diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 5f113c9..4830fca 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,30 +1,11 @@ -# Repo Instructions +# Repository instructions -## Testing +Cover Story is a browser stealth game whose patrols are planned through the published +`dancing-links` npm package. -Any feature addition requires thorough testing. -Use Test-Driven Development (TDD) to guide implementation wherever applicable. -All new code should be accompanied by appropriate unit test. - -## Performance - -Performance is absolutely critical to this project. -If you modify any application logic, you MUST run benchmarks both before and after your changes. -Ensure that performance has not been negatively impacted. -Document benchmark results in your pull request description. - -## Commit Style - -All commits in this repository MUST follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification. -Commits are used to automatically release new versions using `release-it`. - -- If you change repository setup, CI flows, or similar meta-configuration, use the `build:` or `ci:` prefix — this prevents a new release from being triggered. -- The `Initial Plan` commit must be prefixed with `docs:`. - -**Examples:** - -- `feat: add user authentication module` -- `fix: resolve API response error` -- `ci: update workflow for test coverage` -- `build: update dependencies` -- `docs: initial plan` +- Run `npm test`, `npm run lint`, `npm run format:check`, and `npm run build` for changes. +- Document every optimized path in code, including what it does and why it is faster. +- Keep scheduling tied to varied live state; do not cache repeated puzzle answers to manufacture a + benchmark win. +- Test every non-identical fallback explicitly. +- Use Conventional Commits. diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml deleted file mode 100644 index ca43d60..0000000 --- a/.github/workflows/benchmark.yml +++ /dev/null @@ -1,228 +0,0 @@ -name: Benchmark - -on: - pull_request: - branches: [ main, master ] - -jobs: - benchmark: - runs-on: namespace-profile-default - # Only run PR comparison for pull requests - if: github.event_name == 'pull_request' - - strategy: - matrix: - runtime: [node-22, node-24, node-25, bun-latest] - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 # Need full history to find merge-base - - - name: Parse runtime version - id: version - run: echo "value=${RUNTIME#*-}" >> $GITHUB_OUTPUT - env: - RUNTIME: ${{ matrix.runtime }} - - - name: Setup Node.js (node runtime) - if: startsWith(matrix.runtime, 'node-') - uses: actions/setup-node@v4 - with: - node-version: ${{ steps.version.outputs.value }} - cache: 'npm' - - - name: Setup Node.js (bun runtime) - if: startsWith(matrix.runtime, 'bun-') - uses: actions/setup-node@v4 - with: - node-version: 22 - cache: 'npm' - - - name: Setup Bun - if: startsWith(matrix.runtime, 'bun-') - uses: oven-sh/setup-bun@v2 - with: - bun-version: ${{ steps.version.outputs.value }} - - - name: Find merge base - id: merge-base - run: | - git fetch origin ${{ github.base_ref }} - MERGE_BASE=$(git merge-base HEAD origin/${{ github.base_ref }}) - echo "commit=$MERGE_BASE" >> $GITHUB_OUTPUT - echo "Merge base: $MERGE_BASE" - - - name: Benchmark baseline (merge-base) - run: | - echo "Benchmarking merge-base: ${{ steps.merge-base.outputs.commit }}" - git checkout ${{ steps.merge-base.outputs.commit }} - npm ci - - # Check if benchmark:json script exists in package.json - if [ -f package.json ] && grep -q '"benchmark:json"' package.json; then - echo "Found benchmark:json script, running benchmarks..." - # Use appropriate runtime for benchmark - if [[ "${{ matrix.runtime }}" == bun-* ]]; then - BENCHMARK_CMD="bun run benchmark:json" - else - BENCHMARK_CMD="npm run benchmark:json" - fi - - if timeout 900s $BENCHMARK_CMD baseline-results-${{ matrix.runtime }}.json 2>baseline-error-${{ matrix.runtime }}.log; then - echo "Baseline benchmark completed successfully" - else - echo "Baseline benchmark failed or timed out" - echo '[]' > baseline-results-${{ matrix.runtime }}.json - fi - else - echo "benchmark:json script not found in merge-base commit, skipping baseline" - echo "Merge-base does not have benchmark:json script" > baseline-error-${{ matrix.runtime }}.log - echo '[]' > baseline-results-${{ matrix.runtime }}.json - fi - - - name: Benchmark PR branch - run: | - echo "Benchmarking PR: ${{ github.sha }}" - git checkout ${{ github.sha }} - npm ci - - # Use appropriate runtime for benchmark - if [[ "${{ matrix.runtime }}" == bun-* ]]; then - BENCHMARK_CMD="bun run benchmark:json" - else - BENCHMARK_CMD="npm run benchmark:json" - fi - - if timeout 900s $BENCHMARK_CMD pr-results-${{ matrix.runtime }}.json 2>pr-error-${{ matrix.runtime }}.log; then - echo "PR benchmark completed successfully" - else - echo "PR benchmark failed or timed out" - echo '[]' > pr-results-${{ matrix.runtime }}.json - fi - - - name: Compare results - id: comparison - run: | - # Generate comparison markdown (using Node.js since it's not performance-critical) - npm run compare-benchmarks baseline-results-${{ matrix.runtime }}.json pr-results-${{ matrix.runtime }}.json > comparison-${{ matrix.runtime }}.md - - # Add runtime version header - echo "### ${{ matrix.runtime }}" > final-comparison-${{ matrix.runtime }}.md - echo "" >> final-comparison-${{ matrix.runtime }}.md - cat comparison-${{ matrix.runtime }}.md >> final-comparison-${{ matrix.runtime }}.md - echo "" >> final-comparison-${{ matrix.runtime }}.md - - - name: Upload results as artifacts - uses: actions/upload-artifact@v4 - with: - name: benchmark-results-${{ matrix.runtime }} - path: | - baseline-results-${{ matrix.runtime }}.json - pr-results-${{ matrix.runtime }}.json - baseline-error-${{ matrix.runtime }}.log - pr-error-${{ matrix.runtime }}.log - final-comparison-${{ matrix.runtime }}.md - - # Job to collect all runtime results and post PR comment - comment: - runs-on: ubuntu-latest - needs: benchmark - if: github.event_name == 'pull_request' - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 # Need full history to find merge-base - - - name: Find merge base - id: merge-base - run: | - git fetch origin ${{ github.base_ref }} - MERGE_BASE=$(git merge-base HEAD origin/${{ github.base_ref }}) - echo "commit=$MERGE_BASE" >> $GITHUB_OUTPUT - echo "short-commit=${MERGE_BASE:0:7}" >> $GITHUB_OUTPUT - echo "Merge base: $MERGE_BASE" - - - name: Download all benchmark results - uses: actions/download-artifact@v4 - with: - path: benchmark-results - - - name: Combine results and post comment - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - # Combine all runtime results (Node.js and Bun) - echo "" > combined-results.md - echo "# 🚀 Benchmark Results" >> combined-results.md - echo "" >> combined-results.md - echo "Performance comparison against merge-base [\`${{ steps.merge-base.outputs.short-commit }}\`](${{ github.server_url }}/${{ github.repository }}/commit/${{ steps.merge-base.outputs.commit }})" >> combined-results.md - echo "" >> combined-results.md - - # Add results for each runtime (iterate over actual artifacts) - for result_dir in benchmark-results/benchmark-results-*; do - if [ -d "$result_dir" ]; then - # Extract runtime from directory name (benchmark-results-node-22 -> node-22) - runtime=$(basename "$result_dir" | sed 's/benchmark-results-//') - - if [ -f "$result_dir/final-comparison-${runtime}.md" ]; then - cat "$result_dir/final-comparison-${runtime}.md" >> combined-results.md - else - echo "### ${runtime}" >> combined-results.md - echo "âš ī¸ Benchmark failed or timed out" >> combined-results.md - echo "" >> combined-results.md - - # Add error details if available - if [ -f "$result_dir/baseline-error-${runtime}.log" ]; then - echo "
" >> combined-results.md - echo "Baseline Error Log" >> combined-results.md - echo "" >> combined-results.md - echo "\`\`\`" >> combined-results.md - head -20 "$result_dir/baseline-error-${runtime}.log" >> combined-results.md - echo "\`\`\`" >> combined-results.md - echo "
" >> combined-results.md - echo "" >> combined-results.md - fi - - if [ -f "$result_dir/pr-error-${runtime}.log" ]; then - echo "
" >> combined-results.md - echo "PR Error Log" >> combined-results.md - echo "" >> combined-results.md - echo "\`\`\`" >> combined-results.md - head -20 "$result_dir/pr-error-${runtime}.log" >> combined-results.md - echo "\`\`\`" >> combined-results.md - echo "
" >> combined-results.md - echo "" >> combined-results.md - fi - fi - fi - done - - echo "" >> combined-results.md - echo "
" >> combined-results.md - echo "â„šī¸ Benchmark Details" >> combined-results.md - echo "" >> combined-results.md - echo "- **Baseline**: Merge-base commit [\`${{ steps.merge-base.outputs.short-commit }}\`](${{ github.server_url }}/${{ github.repository }}/commit/${{ steps.merge-base.outputs.commit }}) where this PR branched from ${{ github.base_ref }}" >> combined-results.md - echo "- **Comparison**: Current PR head [\`${GITHUB_SHA:0:7}\`](${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }})" >> combined-results.md - echo "- **Timestamp**: $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> combined-results.md - echo "
" >> combined-results.md - - # Find existing comment or create new one - COMMENT_ID=$(gh api "repos/${{ github.repository }}/issues/${{ github.event.number }}/comments" \ - --jq '.[] | select(.body | contains("")) | .id' | head -1) - - if [ -n "$COMMENT_ID" ]; then - echo "Updating existing comment: $COMMENT_ID" - gh api "repos/${{ github.repository }}/issues/comments/$COMMENT_ID" \ - -X PATCH \ - -f body="$(cat combined-results.md)" - else - echo "Creating new comment" - gh api "repos/${{ github.repository }}/issues/${{ github.event.number }}/comments" \ - -X POST \ - -f body="$(cat combined-results.md)" - fi - diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c0d4adf..52ee6d7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,11 +18,11 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 25 + node-version: 24 cache: 'npm' - name: Install dependencies run: npm ci - name: Build project - run: npm run build \ No newline at end of file + run: npm run build diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index fb1100f..14b4469 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -18,7 +18,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 25 + node-version: 24 cache: 'npm' - name: Install dependencies @@ -28,4 +28,4 @@ jobs: run: npm run lint - name: Check formatting - run: npm run format:check \ No newline at end of file + run: npm run format:check diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 1c00395..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,124 +0,0 @@ -name: Release - -on: - push: - branches: [main, master] - -jobs: - # Gate to prevent running CI on release commits - should-run: - runs-on: ubuntu-latest - if: | - !contains(github.event.head_commit.message, 'chore: release') - steps: - - run: echo "Proceeding with CI and release" - - # Call reusable workflows in parallel - lint: - needs: should-run - uses: ./.github/workflows/lint.yml - - test: - needs: should-run - uses: ./.github/workflows/test.yml - - build: - needs: should-run - uses: ./.github/workflows/build.yml - - # Generate release benchmark documentation on consistent Namespace hardware. - # GitHub-hosted CPU performance is too variable for published comparisons. - benchmark-docs: - runs-on: namespace-profile-default - needs: [lint, test, build] - permissions: - contents: read - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - # Preserve the runtime used by the release benchmarks before OIDC - # publishing required the release job itself to use Node.js 24. - node-version: 25 - cache: 'npm' - - - name: Install dependencies - run: npm ci - - - name: Update benchmark documentation - run: npm run update-benchmark-docs -- --quiet - - - name: Upload benchmark documentation - # Pass only non-executable benchmark output into the privileged job. - uses: actions/upload-artifact@v4 - with: - name: release-benchmark-docs-${{ github.sha }} - path: README.md - if-no-files-found: error - retention-days: 1 - - # Release only after all prerequisites complete - release: - # npm trusted publishing currently accepts only GitHub-hosted runners. - runs-on: ubuntu-latest - needs: benchmark-docs - permissions: - contents: write - id-token: write - - steps: - - name: Checkout repository - uses: actions/checkout@v6 - with: - fetch-depth: 0 - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Download benchmark documentation - # Extract outside the checkout so the artifact cannot add package files. - uses: actions/download-artifact@v4 - with: - name: release-benchmark-docs-${{ github.sha }} - path: ${{ runner.temp }}/release-benchmark-docs - - - name: Apply benchmark documentation - run: cp "$RUNNER_TEMP/release-benchmark-docs/README.md" README.md - - - name: Verify benchmark documentation scope - # The trusted job consumes the Namespace result only as README data; - # executable release inputs must still come from the checked-out SHA. - run: git diff --exit-code -- . ':(exclude)README.md' - - - name: Setup Node.js - uses: actions/setup-node@v6 - with: - node-version: 24 - registry-url: 'https://registry.npmjs.org' - package-manager-cache: false - - - name: Install npm with trusted publishing support - # Trusted publishing requires npm >=11.5.1; pin the major so a future - # npm release cannot silently change the privileged release toolchain. - run: npm install --global npm@11 - - - name: Install dependencies - run: npm ci - - - name: Build project - run: npm run build - - - name: Configure Git - run: | - git config --global user.name "github-actions[bot]" - git config --global user.email "github-actions[bot]@users.noreply.github.com" - - - name: Release - # Skip release-it's token-only npm preflight and override only its - # benchmark hook: Namespace already generated the README, so the - # variable GitHub-hosted CPU must not replace those measurements. - run: npm run release -- --ci --npm.skipChecks --hooks.after:bump="npm run format" - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7b0128e..eec0020 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,9 +2,9 @@ name: Test on: push: - branches: [ main, master ] + branches: [main, master] pull_request: - branches: [ main, master ] + branches: [main, master] workflow_call: jobs: @@ -13,57 +13,20 @@ jobs: strategy: matrix: - runtime: [node-22, node-24, node-25, bun-latest] + node: [20, 22, 24] steps: - - name: Checkout repository - uses: actions/checkout@v4 + - name: Checkout repository + uses: actions/checkout@v4 - - name: Parse runtime version - id: version - run: echo "value=${RUNTIME#*-}" >> $GITHUB_OUTPUT - env: - RUNTIME: ${{ matrix.runtime }} + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + cache: npm - - name: Setup Node.js (node runtime) - if: startsWith(matrix.runtime, 'node-') - uses: actions/setup-node@v4 - with: - node-version: ${{ steps.version.outputs.value }} - cache: 'npm' + - name: Install dependencies + run: npm ci - - name: Setup Node.js (bun runtime) - if: startsWith(matrix.runtime, 'bun-') - uses: actions/setup-node@v4 - with: - node-version: 22 - cache: 'npm' - - - name: Setup Bun - if: startsWith(matrix.runtime, 'bun-') - uses: oven-sh/setup-bun@v2 - with: - bun-version: ${{ steps.version.outputs.value }} - - - name: Install dependencies - run: npm ci - - - name: Run tests with coverage (Node.js) - if: startsWith(matrix.runtime, 'node-') - run: npm run cover - - - name: Run tests with coverage (Bun) - if: startsWith(matrix.runtime, 'bun-') - run: bun run cover - - - name: Display coverage summary - run: npx nyc report --reporter=text-summary - - - name: Upload coverage to artifacts - uses: actions/upload-artifact@v4 - if: matrix.runtime == 'node-22' - with: - name: coverage-report - path: | - coverage.lcov - .nyc_output/ \ No newline at end of file + - name: Run behavior tests + run: npm test diff --git a/.gitignore b/.gitignore index ef9e3aa..7375987 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ /.nyc_output /coverage /built +/dist /coverage.lcov profile.cpuprofile diff --git a/.npmignore b/.npmignore deleted file mode 100644 index 7c9149f..0000000 --- a/.npmignore +++ /dev/null @@ -1,31 +0,0 @@ -# Source files (exclude from npm package) -/lib/ -/index.ts -/test/ -/benchmark/ - -# Built test files (not needed in package) -/built/lib/test/ -/built/typings/test/ - -# Configuration files -/tsconfig*.json -/eslint.config.js -/.eslintrc* -/tslint.json -/.prettierrc* -/.release-it.json -/.github/ - -# Development/CI artifacts -/.circleci -/.nyc_output/ -/profile.cpuprofile -/coverage.lcov -/coverage/ - -# Node modules and logs -node_modules/ -npm-debug.log* -yarn-debug.log* -yarn-error.log* diff --git a/.release-it.json b/.release-it.json deleted file mode 100644 index f5caa6d..0000000 --- a/.release-it.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "git": { - "commitMessage": "chore: release v${version}", - "tagName": "v${version}", - "tagAnnotation": "Release v${version}", - "requireCleanWorkingDir": false - }, - "github": { - "release": true, - "releaseName": "Release v${version}" - }, - "npm": { - "publish": true - }, - "plugins": { - "@release-it/conventional-changelog": { - "preset": "angular", - "infile": "CHANGELOG.md" - } - }, - "hooks": { - "after:bump": ["npm run update-benchmark-docs --quiet", "npm run format"], - "before:git:commit": "npm run format" - } -} diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 560ae99..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,310 +0,0 @@ -# Changelog - -## [4.3.9](https://github.com/TimBeyer/dancing-links/compare/v4.3.8...v4.3.9) (2026-07-13) - - -### Bug Fixes - -* preserve reentrant sparse batch semantics ([63eb726](https://github.com/TimBeyer/dancing-links/commit/63eb72685c23e44b01aef96f1d41f1116481d033)) -* resume generators after root-level solutions ([8a07b10](https://github.com/TimBeyer/dancing-links/commit/8a07b10dd08c395834afa12ebcc0d4f97c22d5c0)) -* specialize zero-primary exact covers ([e3a6068](https://github.com/TimBeyer/dancing-links/commit/e3a606839ac14b95a3296ffa4d2fff4aecdef643)) -* widen storage when row indices exceed uint16 ([1315b92](https://github.com/TimBeyer/dancing-links/commit/1315b92ecbe369d57dfc7c2209cc4a4636a96c34)) - - -### Performance Improvements - -* append sparse batches through packed indexed stores ([3ede35d](https://github.com/TimBeyer/dancing-links/commit/3ede35ddda70ad5929e17f17b3a2e1a92272c65d)) -* compact and stabilize dancing links search ([584648f](https://github.com/TimBeyer/dancing-links/commit/584648ffd2299a04dff3e77eb2ef31648bbe40ad)) -* defer template row copies until mutation ([64ecc76](https://github.com/TimBeyer/dancing-links/commit/64ecc76431c5784dc0ac5b07ff049eb619125d2a)) -* keep row construction optimized through return ([093d0b9](https://github.com/TimBeyer/dancing-links/commit/093d0b920687cb32130ba0278126ebe2a80ea4b9)) -* size node metadata by its index domain ([1624168](https://github.com/TimBeyer/dancing-links/commit/1624168d627f6b5a877b4ccdc0f7dcd0a4dfa55e)) - -## [4.3.8](https://github.com/TimBeyer/dancing-links/compare/v4.3.7...v4.3.8) (2026-07-13) - - -### Bug Fixes - -* **ci:** benchmark releases on Namespace ([513d1d5](https://github.com/TimBeyer/dancing-links/commit/513d1d5bd77872608c10ebdb8467a1c4b4d3c2fb)) -* **ci:** publish npm releases through trusted OIDC ([2370620](https://github.com/TimBeyer/dancing-links/commit/2370620edef94f655c0f442ecc2f1ff0ed22ed36)) -* **ci:** sync optional lockfile dependencies ([21f30f4](https://github.com/TimBeyer/dancing-links/commit/21f30f481c4433115fa99263b5563d0d82f31fd1)) - -## [4.3.7](https://github.com/TimBeyer/dancing-links/compare/v4.3.6...v4.3.7) (2026-01-15) - - -### Bug Fixes - -* use type import for SimpleConstraint in tests ([db5ed46](https://github.com/TimBeyer/dancing-links/commit/db5ed46282ab36736b46fff6a88a59b431911d66)) - -## [4.3.6](https://github.com/TimBeyer/dancing-links/compare/v4.3.5...v4.3.6) (2026-01-15) - -## [4.3.5](https://github.com/TimBeyer/dancing-links/compare/v4.3.4...v4.3.5) (2026-01-15) - - -### Bug Fixes - -* increase benchmark timeout from 5 to 15 minutes ([97ad58d](https://github.com/TimBeyer/dancing-links/commit/97ad58d14319582217349d0d835b0b2bf729d09b)) - - -### Performance Improvements - -* configure benchmark options per-test for better control ([de40bd7](https://github.com/TimBeyer/dancing-links/commit/de40bd7f3c13d48f7b5e6c7dc515165f4ddb34fd)) -* increase benchmark sample sizes for more stable results ([d75c3b1](https://github.com/TimBeyer/dancing-links/commit/d75c3b17942125d8db6f37739391e055b81bad3e)) - - -### Reverts - -* remove custom benchmark options, use Benchmark.js defaults ([756652e](https://github.com/TimBeyer/dancing-links/commit/756652e2bfc8c0ce8aa1ae25202900ee06ce68cb)) - -## [4.3.4](https://github.com/TimBeyer/dancing-links/compare/v4.3.3...v4.3.4) (2026-01-15) - - -### Bug Fixes - -* add version parsing step for setup actions ([87bacb5](https://github.com/TimBeyer/dancing-links/commit/87bacb59a5374d367cf54f0617f1a773acedf9c6)) -* correct GitHub Actions expression syntax in workflows ([db351de](https://github.com/TimBeyer/dancing-links/commit/db351dec6378048e6ee24420ab570ddafe7682c4)) -* use matrix includes instead of replace() function ([e0dab4e](https://github.com/TimBeyer/dancing-links/commit/e0dab4e8ff3c54f2e9f83927ffb1fcb304478aff)) - -## [4.3.3](https://github.com/TimBeyer/dancing-links/compare/v4.3.2...v4.3.3) (2026-01-14) - -## [4.3.2](https://github.com/TimBeyer/dancing-links/compare/v4.3.1...v4.3.2) (2025-08-15) - - -### Performance Improvements - -* use switch/case instead of dictionary lookup for state machine ([d695c26](https://github.com/TimBeyer/dancing-links/commit/d695c26a9e11f729e26a55536a2c4e077f78455a)) - -## [4.3.1](https://github.com/TimBeyer/dancing-links/compare/v4.3.0...v4.3.1) (2025-08-08) - -# [4.3.0](https://github.com/TimBeyer/dancing-links/compare/v4.2.2...v4.3.0) (2025-08-07) - - -### Features - -* add fast solver with batch constraint optimization ([317064d](https://github.com/TimBeyer/dancing-links/commit/317064dc7a18f40cb1f1a4b16a15e17dd540c0d9)) - - -### Performance Improvements - -* unify constraint system with efficient ConstraintRow POJOs ([1fefdcb](https://github.com/TimBeyer/dancing-links/commit/1fefdcb8ec8f5625e3bafa118470be84a9bc6ce5)) - -## [4.2.2](https://github.com/TimBeyer/dancing-links/compare/v4.2.1...v4.2.2) (2025-08-07) - -# [4.2.0](https://github.com/TimBeyer/dancing-links/compare/v4.1.0...v4.2.0) (2025-08-06) - - -### Bug Fixes - -* correct path resolution and JSON parsing in benchmark docs script ([d168af8](https://github.com/TimBeyer/dancing-links/commit/d168af8d9dc73a3d83f2e99694019b6b3119e907)) -* eliminate mutable instance state from benchmark solvers ([784d71c](https://github.com/TimBeyer/dancing-links/commit/784d71cc57f06f60f231799ef083c1c0eb0198a4)) -* format ops/sec to 2 decimal places in benchmark results ([442006f](https://github.com/TimBeyer/dancing-links/commit/442006faef2a2367aed633079089b8a4f9179a23)) -* preserve full precision in benchmark results ([ba5deed](https://github.com/TimBeyer/dancing-links/commit/ba5deed10c183b3c12a91eab081cb23f594238d4)) -* properly separate main and dev TypeScript configurations ([488bb50](https://github.com/TimBeyer/dancing-links/commit/488bb50f70fd9419dc5cb0e4cdb6e3e24c4d93d3)) -* replace any type with proper types in template solver ([f83adba](https://github.com/TimBeyer/dancing-links/commit/f83adba9f09f2182ad781a79a3294a8c00d1ed73)) -* round margin percentages to 2 decimal places in benchmark comparisons ([2071d38](https://github.com/TimBeyer/dancing-links/commit/2071d384299361003f034ebac7a16f3c4565f55d)) -* working modular benchmark system ([370e45a](https://github.com/TimBeyer/dancing-links/commit/370e45aa3c671a773c70afa31f92740b23c847c5)) - - -### Features - -* add automated benchmark documentation system ([4534e2a](https://github.com/TimBeyer/dancing-links/commit/4534e2a24976077cfc4c9acb971a2be89b7144e6)) -* implement descriptive solver names with static name property ([ae67510](https://github.com/TimBeyer/dancing-links/commit/ae675104d782f0ab466d7cd0044ca8ccdba64154)) -* include binary solver in competitive benchmarks for fair comparison ([1f7d445](https://github.com/TimBeyer/dancing-links/commit/1f7d44595eee83e38df8760fe245ddb7b8a767af)) -* make benchmark results directly visible in README ([69b6005](https://github.com/TimBeyer/dancing-links/commit/69b60055b061300706f5c0cbe2c1610f901de230)) -* update README benchmarks and add auto-formatting to doc script ([593b713](https://github.com/TimBeyer/dancing-links/commit/593b713f9ffeb1bb5de0585abd44a6ba4e64df9a)) - -# [4.1.0](https://github.com/TimBeyer/dancing-links/compare/v4.0.0...v4.1.0) (2025-08-06) - - -### Bug Fixes - -* add generator benchmark to single pentomino tiling test ([9f01206](https://github.com/TimBeyer/dancing-links/commit/9f0120606794c9bd389e12c8997b82e128f00aed)) - - -### Features - -* add resumable generator interface for streaming solutions ([0b229b3](https://github.com/TimBeyer/dancing-links/commit/0b229b33b29d38d925ea8bd080762863bb575f05)) - -# [4.0.0](https://github.com/TimBeyer/dancing-links/compare/v3.3.0...v4.0.0) (2025-08-05) - - -### Bug Fixes - -* address codebase review issues and improve code quality ([501ce0e](https://github.com/TimBeyer/dancing-links/commit/501ce0e203a510e03f0259646c2cec723d156188)) -* disable commitlint footer line length rule and format code ([15b9888](https://github.com/TimBeyer/dancing-links/commit/15b9888524411f16b4ed1b5b1dae95baa9c092f4)) -* replace any with proper union types in factory methods ([6f30676](https://github.com/TimBeyer/dancing-links/commit/6f306764a0a1fd1688da8a602376f71940150451)) -* resolve benchmark formatting and CI comparison issues ([246fc7a](https://github.com/TimBeyer/dancing-links/commit/246fc7a0480c1f55f0099324e683c2cc4d00dbff)) -* resolve linting errors and improve test coverage ([61d4b4d](https://github.com/TimBeyer/dancing-links/commit/61d4b4db120c397bb1bdc3737a1317f7fe3cf43a)) -* resolve TypeScript compilation error in constraint handlers ([2b37f50](https://github.com/TimBeyer/dancing-links/commit/2b37f50e1d40e2ea0b91104485a89f2c9d1c2c68)) -* support positional filename argument in benchmark JSON mode ([4b9ca83](https://github.com/TimBeyer/dancing-links/commit/4b9ca833cd3fa6ed78cc6b07b1c18960412685dc)) - - -### Code Refactoring - -* remove deprecated legacy API and clean up codebase ([5810ea3](https://github.com/TimBeyer/dancing-links/commit/5810ea3eda4f3da604fef87be35448e72d99dfe5)) - - -### Features - -* add backward compatibility with deprecation notices ([0e0d712](https://github.com/TimBeyer/dancing-links/commit/0e0d712861467f8c1faf7b582b7739fcd52c9050)) -* complete high-performance caching API implementation ([43174b6](https://github.com/TimBeyer/dancing-links/commit/43174b69c29a27637f7156f9c6256e4c5164fe1d)) -* consolidate benchmark system with unified CLI interface ([93592fe](https://github.com/TimBeyer/dancing-links/commit/93592fe38633cee6f325bc298ff1d0e81b6496c7)) -* deprecate remaining legacy API functions ([f2dbc89](https://github.com/TimBeyer/dancing-links/commit/f2dbc89090d76bbd0f208776b537f0d479d44b76)) -* implement dual interface with sparse and binary constraint support ([176e1ef](https://github.com/TimBeyer/dancing-links/commit/176e1efbdc484f3b8740081345c085e386ae6358)) -* implement high-performance constraint caching API ([91a109d](https://github.com/TimBeyer/dancing-links/commit/91a109dcaa8b9216b6eacaaea4d49cdb953bb64a)) -* implement strongly typed factory methods with conditional types ([aae13ce](https://github.com/TimBeyer/dancing-links/commit/aae13ce9d2edf1346f7e960ca8034350550baa19)) -* implement type-safe SolverTemplate with upfront configuration validation ([d822b0b](https://github.com/TimBeyer/dancing-links/commit/d822b0b324106d16394adbb2c35f047f2245b758)) - - -### Performance Improvements - -* add comprehensive benchmarks for new caching API ([00aa7e9](https://github.com/TimBeyer/dancing-links/commit/00aa7e9165d8f485a8e4ad733bc79b521bffeb57)) -* convert Row interface to class for V8 optimization ([7036713](https://github.com/TimBeyer/dancing-links/commit/703671309b09167593106b683c8465bbdf61402f)) -* eliminate unnecessary array copying in sparse constraints ([e498c76](https://github.com/TimBeyer/dancing-links/commit/e498c766d155212b6bb7393a470d9cca5ff1d1aa)) -* implement batch operations with runtime caching optimizations ([7dc2c89](https://github.com/TimBeyer/dancing-links/commit/7dc2c899ee803e9768587ce8cc64c226e3a0186c)) -* implement optional validation for production performance ([fd942ab](https://github.com/TimBeyer/dancing-links/commit/fd942ab6775d1975f29e7347057ba94f16e1bd78)) -* optimize benchmarks to show real-world API usage patterns ([b05d019](https://github.com/TimBeyer/dancing-links/commit/b05d0198010fcf2f2e457361ad08d7b600de755d)) -* optimize constraint handlers and fix misleading parameter naming ([4854099](https://github.com/TimBeyer/dancing-links/commit/48540997fb46fa93140667cc1980b0fcd6911c40)) -* optimize constraint processing with single-pass algorithms ([d1d8ea1](https://github.com/TimBeyer/dancing-links/commit/d1d8ea10ce95b10a8a18d110bbeb71275fd57c2a)) -* replace abstract inheritance with interface delegation pattern ([58c5ad9](https://github.com/TimBeyer/dancing-links/commit/58c5ad940dbdb116d7e2fa349a802e54abb549ac)) - - -### BREAKING CHANGES - -* Legacy functional API (findOne, findAll, find, findRaw) has been removed. Use the new DancingLinks class API instead. - -🤖 Generated with [Claude Code](https://claude.ai/code) - -Co-Authored-By: Claude - -# [3.4.0](https://github.com/TimBeyer/dancing-links/compare/v3.3.0...v3.4.0) (2025-08-02) - - -### Bug Fixes - -* address codebase review issues and improve code quality ([501ce0e](https://github.com/TimBeyer/dancing-links/commit/501ce0e203a510e03f0259646c2cec723d156188)) -* replace any with proper union types in factory methods ([6f30676](https://github.com/TimBeyer/dancing-links/commit/6f306764a0a1fd1688da8a602376f71940150451)) -* resolve benchmark formatting and CI comparison issues ([246fc7a](https://github.com/TimBeyer/dancing-links/commit/246fc7a0480c1f55f0099324e683c2cc4d00dbff)) -* resolve linting errors and improve test coverage ([61d4b4d](https://github.com/TimBeyer/dancing-links/commit/61d4b4db120c397bb1bdc3737a1317f7fe3cf43a)) -* resolve TypeScript compilation error in constraint handlers ([2b37f50](https://github.com/TimBeyer/dancing-links/commit/2b37f50e1d40e2ea0b91104485a89f2c9d1c2c68)) -* support positional filename argument in benchmark JSON mode ([4b9ca83](https://github.com/TimBeyer/dancing-links/commit/4b9ca833cd3fa6ed78cc6b07b1c18960412685dc)) - - -### Features - -* add backward compatibility with deprecation notices ([0e0d712](https://github.com/TimBeyer/dancing-links/commit/0e0d712861467f8c1faf7b582b7739fcd52c9050)) -* complete high-performance caching API implementation ([43174b6](https://github.com/TimBeyer/dancing-links/commit/43174b69c29a27637f7156f9c6256e4c5164fe1d)) -* consolidate benchmark system with unified CLI interface ([93592fe](https://github.com/TimBeyer/dancing-links/commit/93592fe38633cee6f325bc298ff1d0e81b6496c7)) -* deprecate remaining legacy API functions ([f2dbc89](https://github.com/TimBeyer/dancing-links/commit/f2dbc89090d76bbd0f208776b537f0d479d44b76)) -* implement dual interface with sparse and binary constraint support ([176e1ef](https://github.com/TimBeyer/dancing-links/commit/176e1efbdc484f3b8740081345c085e386ae6358)) -* implement high-performance constraint caching API ([91a109d](https://github.com/TimBeyer/dancing-links/commit/91a109dcaa8b9216b6eacaaea4d49cdb953bb64a)) -* implement strongly typed factory methods with conditional types ([aae13ce](https://github.com/TimBeyer/dancing-links/commit/aae13ce9d2edf1346f7e960ca8034350550baa19)) -* implement type-safe SolverTemplate with upfront configuration validation ([d822b0b](https://github.com/TimBeyer/dancing-links/commit/d822b0b324106d16394adbb2c35f047f2245b758)) - - -### Performance Improvements - -* add comprehensive benchmarks for new caching API ([00aa7e9](https://github.com/TimBeyer/dancing-links/commit/00aa7e9165d8f485a8e4ad733bc79b521bffeb57)) -* convert Row interface to class for V8 optimization ([7036713](https://github.com/TimBeyer/dancing-links/commit/703671309b09167593106b683c8465bbdf61402f)) -* eliminate unnecessary array copying in sparse constraints ([e498c76](https://github.com/TimBeyer/dancing-links/commit/e498c766d155212b6bb7393a470d9cca5ff1d1aa)) -* implement batch operations with runtime caching optimizations ([7dc2c89](https://github.com/TimBeyer/dancing-links/commit/7dc2c899ee803e9768587ce8cc64c226e3a0186c)) -* implement optional validation for production performance ([fd942ab](https://github.com/TimBeyer/dancing-links/commit/fd942ab6775d1975f29e7347057ba94f16e1bd78)) -* optimize benchmarks to show real-world API usage patterns ([b05d019](https://github.com/TimBeyer/dancing-links/commit/b05d0198010fcf2f2e457361ad08d7b600de755d)) -* optimize constraint handlers and fix misleading parameter naming ([4854099](https://github.com/TimBeyer/dancing-links/commit/48540997fb46fa93140667cc1980b0fcd6911c40)) -* optimize constraint processing with single-pass algorithms ([d1d8ea1](https://github.com/TimBeyer/dancing-links/commit/d1d8ea10ce95b10a8a18d110bbeb71275fd57c2a)) -* replace abstract inheritance with interface delegation pattern ([58c5ad9](https://github.com/TimBeyer/dancing-links/commit/58c5ad940dbdb116d7e2fa349a802e54abb549ac)) - -# [3.3.0](https://github.com/TimBeyer/dancing-links/compare/v3.2.2...v3.3.0) (2025-08-01) - - -### Bug Fixes - -* add compare-benchmarks npm script and use in workflow ([0d3f986](https://github.com/TimBeyer/dancing-links/commit/0d3f98600a35360935cc1745b3e819d62002f99a)) -* add null checks for strict TypeScript compliance ([a89b6e2](https://github.com/TimBeyer/dancing-links/commit/a89b6e228dafee8f23cacec6a5dcd719f996eb78)) -* address additional Copilot review comments ([cfccc1d](https://github.com/TimBeyer/dancing-links/commit/cfccc1de1cdda1956c596a4f42fdc3b7fae526e3)) -* address Copilot review comments ([c7f3cc9](https://github.com/TimBeyer/dancing-links/commit/c7f3cc9610483c841805405b643e108f12a9c063)) -* calculate merge-base in comment job for proper display ([2ec7983](https://github.com/TimBeyer/dancing-links/commit/2ec7983b983b0cdd98705ea96cb67c1b1b18f6d4)) -* correct direct execution detection in comparison script ([c6066ee](https://github.com/TimBeyer/dancing-links/commit/c6066eeb2c9053811ac29fda4ee4b4eb4e1e21c4)) -* improve benchmark error handling ([fd2a2b0](https://github.com/TimBeyer/dancing-links/commit/fd2a2b0eb33cadb3cf65dc44a447e55d206a3592)) -* include scripts folder in dev TypeScript build ([8a2ebcb](https://github.com/TimBeyer/dancing-links/commit/8a2ebcb71c85ba37b08ac4f38149719dd8e1da8b)) -* output pure JSON by writing to file instead of stdout ([bb819ef](https://github.com/TimBeyer/dancing-links/commit/bb819efe11122f6d8f3a4f17641f0416204f3ea2)) -* parse benchmark sections correctly ([5341f51](https://github.com/TimBeyer/dancing-links/commit/5341f51ca37d02d0ca746391774bfdf020c98b4a)) -* remove old benchmark file ([983049d](https://github.com/TimBeyer/dancing-links/commit/983049d83054e1fcc06fa56bf39d8ea7f2654aad)) -* use direct package.json check for script existence ([56c6769](https://github.com/TimBeyer/dancing-links/commit/56c6769d59a759c5c4b823dbaf9d95d5319755e2)) - - -### Features - -* add PR benchmark comparison with automated comments ([d1efae8](https://github.com/TimBeyer/dancing-links/commit/d1efae8d19272fdbe33cd179f5095c9f276134c8)) -* handle first PR scenario gracefully when baseline unavailable ([2812fc8](https://github.com/TimBeyer/dancing-links/commit/2812fc865f6f43443efd872784ae7c4ae59c1b8b)) -* improve benchmark error reporting and handle missing scripts ([1e8533d](https://github.com/TimBeyer/dancing-links/commit/1e8533db71daebb2ea049c7b97958ce03f8c0eef)) -* structured JSON benchmarks ([ab6c3ce](https://github.com/TimBeyer/dancing-links/commit/ab6c3ce2e7e04ae0460c38b4fedfa06342416e07)) - - -### Performance Improvements - -* remove duplicate build step in benchmark workflow ([a8d8836](https://github.com/TimBeyer/dancing-links/commit/a8d8836f65f6f1fb4cb588c3fbe936d0000f978c)) - -## [3.2.2](https://github.com/TimBeyer/dancing-links/compare/v3.2.1...v3.2.2) (2025-07-31) - -## [3.2.1](https://github.com/TimBeyer/dancing-links/compare/v3.2.0...v3.2.1) (2025-07-31) - - -### Bug Fixes - -* use correct npm script for coverage in test workflow ([335db17](https://github.com/TimBeyer/dancing-links/commit/335db1749ce02ba12e03946fb037dc9b006f5b66)) - -# [3.2.0](https://github.com/TimBeyer/dancing-links/compare/v3.1.0...v3.2.0) (2025-07-31) - -### Bug Fixes - -- correct typo 'sodoku' to 'sudoku' in benchmark output ([6a550e1](https://github.com/TimBeyer/dancing-links/commit/6a550e1c183b19f63e146db8c3241892e4a6bdf6)) -- enable profiler with vscode compatible output format ([84352c7](https://github.com/TimBeyer/dancing-links/commit/84352c7eeb701e321113786774d60f09acb64746)) - -### Features - -- add development benchmark comparing Original AoS vs SoA ([0e4d3fb](https://github.com/TimBeyer/dancing-links/commit/0e4d3fb341b950f0fe9a982844a7a9c7892ed256)) -- implement Struct-of-Arrays data structures for Dancing Links ([89613e6](https://github.com/TimBeyer/dancing-links/commit/89613e6158bb2b2bbb613c7270237226352710ca)) -- separate fast benchmarks from library comparison benchmarks ([37a289b](https://github.com/TimBeyer/dancing-links/commit/37a289b0b5c12d7b6f12cebd1e13ed9673b93856)) -- use classes instead of POJOs for better lookup performance ([584ba0e](https://github.com/TimBeyer/dancing-links/commit/584ba0eaf43221a3d38bd28d0d0feac3fbe7b544)) - -### Performance Improvements - -- complete systematic optimization testing ([085ada8](https://github.com/TimBeyer/dancing-links/commit/085ada8540d6358da5c744f7a0b3ce4a3946660f)) -- phase 1a enhanced column selection heuristic - reverted ([b4e3340](https://github.com/TimBeyer/dancing-links/commit/b4e3340c843936440db378dac62c7b14d4c889cf)) -- phase 1b column length tracking - implementation failed ([f3d9a98](https://github.com/TimBeyer/dancing-links/commit/f3d9a9839c3260b9cafab24825ffe9fcc1dd1fcc)) -- phase 2a unit propagation - kept ([d2d3a84](https://github.com/TimBeyer/dancing-links/commit/d2d3a846fe796ead39c6de5ac76cdc1208a1ebe5)) -- phase 2b memory layout optimization - reverted ([a668d6a](https://github.com/TimBeyer/dancing-links/commit/a668d6aa09ea219bb0b5c7cf5937d3b363861de7)) -- phase 2b memory layout optimization retry - reverted ([bdb4fcf](https://github.com/TimBeyer/dancing-links/commit/bdb4fcfbe419bc6be5d8b2b6a4a8c2285267d005)) -- phase 3a symmetry breaking - conceptual failure ([21f8a47](https://github.com/TimBeyer/dancing-links/commit/21f8a473d1d3471688f0a65e84c6ef2dfd35c622)) -- remaining opt 1 cache warming - reverted ([f546461](https://github.com/TimBeyer/dancing-links/commit/f5464611426cc555a917e65fc42d11b86899a5ff)) -- remaining opt 4 extended unit propagation - reverted ([0acf8bc](https://github.com/TimBeyer/dancing-links/commit/0acf8bc26a41962824ff8fab249a22e47eb835ed)) -- systematic optimization testing - Tests 1-5 complete ([3474482](https://github.com/TimBeyer/dancing-links/commit/34744823807e706f36eb400243ef93ee0cb635c0)) -- test 7 inline forward function - reverted ([b5fa57b](https://github.com/TimBeyer/dancing-links/commit/b5fa57b99e43f6b229d3e304393d7a951e54af66)) -- test 8 local variable caching - reverted ([6248b88](https://github.com/TimBeyer/dancing-links/commit/6248b88c7c1aea93aca3c891ea535247a96d5cbb)) -- test 9 pre-calculate next pointers - kept ([62a78c8](https://github.com/TimBeyer/dancing-links/commit/62a78c8d606202cf45e6dc72866a843a31510a2c)) - -# [3.1.0](https://github.com/TimBeyer/dancing-links/compare/v3.0.0...v3.1.0) (2025-07-15) - -### Bug Fixes - -- add workflow dependency and build step to release workflow ([70aa08f](https://github.com/TimBeyer/dancing-links/commit/70aa08f6cf8d0f7c2e6c520b348361fed8ee83b3)) -- replace custom commitlint logic with wagoid/commitlint-github-action ([837f7ec](https://github.com/TimBeyer/dancing-links/commit/837f7ecf75bac4cfa31c331a30009f9f301d7273)) -- revert CHANGELOG.md formatting and remove commitlint script ([01f4e9a](https://github.com/TimBeyer/dancing-links/commit/01f4e9a88e6f422f86a78b274c0975cefc9e3118)) - -### Features - -- implement release automation formatting and conventional commits improvements ([192a55a](https://github.com/TimBeyer/dancing-links/commit/192a55aaf1dd98ccb61ba60c6abcefcaf2715033)) - -# [3.0.0](https://github.com/TimBeyer/dancing-links/compare/v2.1.1...v3.0.0) (2025-07-15) - -- feat!: require Node.js 20+ and add conventional commits guidelines ([8fab697](https://github.com/TimBeyer/dancing-links/commit/8fab697c82fe8af95ecdf60e3d5575e799d658e2)) - -### Bug Fixes - -- missing Result type ([031e0ca](https://github.com/TimBeyer/dancing-links/commit/031e0ca2a0be3cce77d1f70bed14668be9517e48)) - -### BREAKING CHANGES - -- Node.js 20+ is now required. The minimum supported Node.js version has been increased from 18 to 20 to align with the modernized CI/CD pipeline and take advantage of newer Node.js features. - -Co-authored-by: TimBeyer <2362075+TimBeyer@users.noreply.github.com> diff --git a/CLAUDE.md b/CLAUDE.md index c8c776c..ea6b9e8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,195 +1,24 @@ -# CLAUDE.md +# Cover Story repository guidance -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +Cover Story is a browser stealth prototype driven by real-time exact-cover patrol scheduling. The +published `dancing-links` package is a runtime dependency; do not restore or import the old in-tree +solver implementation. -## Project Overview +## Commands -This is a high-performance JavaScript/TypeScript implementation of Knuth's Dancing Links algorithm (DLX) for solving exact cover problems. The library provides the fastest JS implementation of the algorithm and includes examples for n-queens, pentomino tiling, and sudoku problems. +- `npm run dev` — Vite development server +- `npm test` — game scheduling and fallback tests +- `npm run build` — strict TypeScript check and production build +- `npm run lint` — lint app and tests +- `npm run format:check` — verify formatting -## Development Commands +## Requirements -- `npm run build` - Build TypeScript to JavaScript (cleans first) -- `npm run test` - Run unit tests (alias for test-unit) -- `npm run test-watch` - Run tests in watch mode -- `npm run test-unit` - Run unit tests with Mocha and ts-node -- `npm run lint` - Run ESLint checks -- `npm run lint:fix` - Run ESLint with auto-fix -- `npm run format` - Format code with Prettier -- `npm run format:check` - Check code formatting -- `npm run coverage` - Generate test coverage report with nyc -- `npm run benchmark` - Run internal solver benchmarks for regression testing -- `npm run benchmark:competitive` - Run competitive benchmarks comparing our best solver vs external libraries -- `npm run benchmark:comprehensive` - Run comprehensive analysis across all solver-case combinations -- `npm run profile` - Generate CPU profile for performance analysis +- Document every performance optimization in code with what it does and why it is faster. +- Do not cache solved states merely to improve a repeated-work benchmark. Scheduling must reflect the + live game state. +- Add explicit tests whenever fallback behavior is not identical to the normal path. +- Use Conventional Commits. -## Core Architecture - -### Main Entry Points - -- `index.ts` - Public API exports (DancingLinks factory, ProblemSolver, SolverTemplate) -- `lib/index.ts` - Main library re-exports from organized modules -- `lib/core/algorithm.ts` - Core Dancing Links algorithm implementation using state machine -- `lib/types/interfaces.ts` - TypeScript type definitions and constraint interfaces -- `lib/solvers/factory.ts` - DancingLinks factory class for creating solvers and templates -- `lib/constraints/handlers/` - Constraint handlers for simple and complex modes - -### Algorithm Structure - -The core algorithm (`lib/core/algorithm.ts`) uses a state machine pattern to avoid recursion and implement Knuth's Dancing Links algorithm. The states are: - -- FORWARD: Select next column to cover -- ADVANCE: Try next option for selected column -- BACKUP: Backtrack when no options remain -- RECOVER: Restore previous state when backtracking -- DONE: Solution found or search complete - -### Data Structures - -- `NodeStore` class: Struct-of-Arrays implementation with typed arrays for navigation fields -- `ColumnStore` class: Column headers with length tracking and circular linking -- Constraint types: `SimpleConstraint` (single row) and `ComplexConstraint` (primary + secondary rows) - -### Key Modules - -- State machine logic in `search()` function in `lib/core/algorithm.ts` -- Matrix operations: `cover()` and `uncover()` for constraint satisfaction -- Data structures in `lib/core/data-structures.ts` with NodeStore and ColumnStore classes -- Constraint handlers in `lib/constraints/handlers/` for simple and complex solver modes - -## Performance Requirements - -Performance is critical - always run benchmarks before and after changes using `npm run benchmark`. The library maintains its position as the fastest Dancing Links implementation in JavaScript through systematic optimization. - -See `PERFORMANCE.md` for detailed analysis of optimization work completed. - -## Testing - -All new features require comprehensive unit tests. Use `npm run test` for standard testing, `npm run test-watch` for development. Coverage reports available via `npm run coverage`. - -## Commit Convention - -Must follow Conventional Commits specification: - -- `feat:` - New features (minor version bump) -- `fix:` - Bug fixes (patch version bump) -- `perf:` - Performance improvements -- `test:` - Test additions/changes -- `docs:` - Documentation changes -- `ci:` - CI/build changes (no release) -- `build:` - Build system changes (no release) - -## Project Structure - -- `lib/` - Core library implementation with organized nested modules - - `core/` - Core algorithm and data structures - - `constraints/handlers/` - Constraint handlers for different solver modes - - `solvers/` - Factory, solver, and template classes - - `types/` - TypeScript interfaces and type definitions -- `benchmark/` - Performance testing and example problems (n-queens, pentomino, sudoku) -- `test/unit/` - Unit test suite -- `built/` - Compiled JavaScript output -- TypeScript configuration supports both development (`tsconfig.dev.json`) and production builds - -## Code Quality Standards - -### Code comments - -Make sure to leave relevant and detailed comments on complex parts of the codebase. - -#### Comment Guidelines - -**DO** write detailed comments for: - -- Complex algorithms with multiple steps -- Non-obvious business logic or domain-specific rules -- Areas where refactoring considerations are documented -- Code that cannot be easily simplified due to technical constraints - -**DON'T** write comments for: - -- Self-evident code (obvious function names, simple operations) -- Historical changes or what code "used to do" -- Anything that can be understood from reading the code itself - -When you write complex code, you MUST write documentation explaining the why, not the what. - -### Performance-Critical Code Guidelines - -**DO** use for performance-critical code: - -- `for...of` loops over `.forEach()` -- Manual loops over `.map()` and `.reduce()` for data transformation -- Low-level iteration patterns in hot paths - -**DON'T** use for performance-critical code: - -- Array utility methods (`.map`, `.reduce`, `.forEach`) - provably slower than loops -- Functional programming patterns that create intermediate arrays -- Method chaining that allocates temporary objects - -### Testing Guidelines - -**DO** in tests: - -- Test functionality and behavior -- Focus on input/output verification -- Test edge cases and error conditions - -**DON'T** in tests: - -- Test method existence with `.to.have.property` - TypeScript ensures this -- Test implementation details -- Duplicate type checking that TypeScript already provides - -### Problem-Solving Approach - -**ALWAYS plan together first for complex problems before implementing.** - -When to **PLAN TOGETHER** (not implement immediately): - -- Questions like "Can we think of a better way..." -- "Maybe we can build something better..." -- "Is it a good interface to..." -- Architecture or design discussions -- Performance optimization strategies -- API design questions -- Complex problem exploration - -When to **IMPLEMENT DIRECTLY**: - -- "Can you fix the type issue" -- "Add this specific feature" -- "Run the tests" -- Clear, specific implementation requests -- Bug fixes with known solutions - -**Always use judgment**: If unsure whether to plan or implement, err on the side of planning and discussion first. Implementation can always come after we've explored the problem space together. - -### Refactoring Philosophy - -**BREAK APIs PROPERLY - No Legacy Compatibility Unless Explicitly Requested** - -When refactoring or renaming: - -- **DO** make clean breaks and update everything consistently -- **DO** rename options, functions, and variables everywhere they're used -- **DO** update all documentation, scripts, and references in one go -- **DON'T** keep legacy compatibility layers or deprecated options -- **DON'T** maintain backward compatibility unless explicitly asked - -The codebase should be internally consistent. If you rename something, rename it everywhere. If you break an API, break it completely and update all consumers. Half-measures create technical debt and confusion. - -## Commit Guidelines - -- **ALWAYS run `npm run format` before committing** - Code must be properly formatted -- Commit frequently, ensure tests pass before committing, always ensure that ALL TS types pass -- Always do work in branches and create one if we're not in a branch already. Commit frequently. - -### Pre-Commit Checklist - -Before every commit, ALWAYS run: - -1. `npm run format` - Format code with Prettier -2. `npm run lint` - Check for linting issues -3. `npm run test` - Ensure all tests pass -4. `npm run build` - Verify TypeScript compilation +The live exact-cover model is in `src/schedule.ts`; rendering and game rules are in `src/game.ts`; +world geometry is in `src/world.ts`. diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md deleted file mode 100644 index 923a41a..0000000 --- a/DEVELOPMENT.md +++ /dev/null @@ -1,234 +0,0 @@ -# Development Guide - -This document contains information for developers working on the dancing-links library. - -## Prerequisites - -- Node.js 20 or higher -- npm 8 or higher - -## Setup - -```bash -npm install -``` - -## Development Scripts - -### Building & Testing - -- `npm run build` - Build the TypeScript code to JavaScript -- `npm run build:dev` - Build with development configuration (includes benchmarks and scripts) -- `npm test` - Run the test suite -- `npm run test-watch` - Run tests in watch mode -- `npm run coverage` - Generate test coverage report - -### Code Quality - -- `npm run lint` - Run ESLint code quality checks -- `npm run lint:fix` - Run ESLint with auto-fix -- `npm run format` - Format code with Prettier -- `npm run format:check` - Check code formatting - -### Performance & Benchmarking - -- `npm run benchmark` - Run fast library-only benchmarks (CI mode) -- `npm run benchmark:comparison` - Run comprehensive benchmarks including external libraries -- `npm run benchmark:json` - Generate JSON benchmark output for analysis -- `npm run update-benchmark-docs` - Update README with current benchmark results -- `npm run update-benchmark-docs:dry-run` - Preview benchmark documentation changes -- `npm run profile` - Generate CPU performance profile - -## Performance & Benchmarks - -The benchmarks compare performance across different constraint formats and against other Dancing Links libraries using sudoku and pentomino problems. - -### Running Benchmarks - -```bash -# Fast library-only benchmarks -npm run benchmark - -# Include external library comparisons -npm run benchmark:comparison - -# Generate JSON output -npm run benchmark:json - -# Custom options -node built/benchmark/index.js --external --json=results.json -``` - -### Key Performance Insights - -- **Sparse constraints** reduce parsing overhead compared to binary constraints -- **Template reuse** eliminates constraint preprocessing overhead, especially beneficial for binary constraints which require conversion to sparse format -- **Batch operations** reduce function call overhead when adding many constraints - -Benchmarks consistently show this library outperforms other JavaScript Dancing Links implementations, with sparse constraints and templates providing additional optimizations. - -### Automated Benchmark Documentation - -The project includes automated benchmark documentation that runs during releases: - -- Compares against other JS Dancing Links libraries (dlxlib, dance, dancing-links-algorithm) -- Generates objective performance comparison tables -- Updates README automatically during `npm run release` -- Can be run manually with `npm run update-benchmark-docs` - -## Profiling - -Generate CPU profiles for performance analysis: - -```bash -npm run profile -``` - -This creates `profile.cpuprofile` which can be loaded into Chrome DevTools for detailed performance analysis. - -## Architecture & Implementation - -### Core Algorithm - -The algorithm uses a state machine pattern to avoid recursion and closely follows [Knuth's reference implementation](https://cs.stanford.edu/~knuth/programs/dance.w). The core algorithm is implemented using efficient data structures optimized for the Dancing Links technique. - -### Project Structure - -- `lib/` - Core library implementation with organized nested modules - - `core/` - Core algorithm and data structures - - `constraints/handlers/` - Constraint handlers for different solver modes - - `solvers/` - Factory, solver, and template classes - - `types/` - TypeScript interfaces and type definitions -- `benchmark/` - Performance testing and example problems (n-queens, pentomino, sudoku) -- `test/unit/` - Unit test suite -- `scripts/` - Development and automation scripts -- `built/` - Compiled JavaScript output - -### Algorithm Structure - -The core algorithm (`lib/core/algorithm.ts`) uses a state machine pattern with these states: - -- **FORWARD**: Select next column to cover -- **ADVANCE**: Try next option for selected column -- **BACKUP**: Backtrack when no options remain -- **RECOVER**: Restore previous state when backtracking -- **DONE**: Solution found or search complete - -### Data Structures - -- `NodeStore` class: Struct-of-Arrays implementation with typed arrays for navigation fields -- `ColumnStore` class: Column headers with length tracking and circular linking -- Constraint types: `SimpleConstraint` (single row) and `ComplexConstraint` (primary + secondary rows) - -## Contribution Guidelines - -### Commit Convention - -This project follows [Conventional Commits](https://www.conventionalcommits.org/) specification for automated releases and changelog generation. Please use the following commit message format: - -``` -[optional scope]: - -[optional body] - -[optional footer(s)] -``` - -**Types:** - -- `feat:` - A new feature (triggers minor version bump) -- `fix:` - A bug fix (triggers patch version bump) -- `docs:` - Documentation only changes -- `style:` - Changes that do not affect the meaning of the code (white-space, formatting, etc) -- `refactor:` - A code change that neither fixes a bug nor adds a feature -- `perf:` - A code change that improves performance -- `test:` - Adding missing tests or correcting existing tests -- `chore:` - Changes to the build process or auxiliary tools - -**Breaking Changes:** -To trigger a major version release, include `BREAKING CHANGE:` in the commit footer or add `!` after the type: - -``` -feat!: remove support for Node.js 16 - -BREAKING CHANGE: Node.js 18+ is now required -``` - -### Code Quality Standards - -#### Code Comments - -**DO** write detailed comments for: - -- Complex algorithms with multiple steps -- Non-obvious business logic or domain-specific rules -- Areas where refactoring considerations are documented -- Code that cannot be easily simplified due to technical constraints - -**DON'T** write comments for: - -- Self-evident code (obvious function names, simple operations) -- Historical changes or what code "used to do" -- Anything that can be understood from reading the code itself - -#### Performance-Critical Code Guidelines - -**DO** use for performance-critical code: - -- `for...of` loops over `.forEach()` -- Manual loops over `.map()` and `.reduce()` for data transformation -- Low-level iteration patterns in hot paths - -**DON'T** use for performance-critical code: - -- Array utility methods (`.map`, `.reduce`, `.forEach`) - provably slower than loops -- Functional programming patterns that create intermediate arrays -- Method chaining that allocates temporary objects - -#### Testing Guidelines - -**DO** in tests: - -- Test functionality and behavior -- Focus on input/output verification -- Test edge cases and error conditions - -**DON'T** in tests: - -- Test method existence with `.to.have.property` - TypeScript ensures this -- Test implementation details -- Duplicate type checking that TypeScript already provides - -### Pre-Commit Checklist - -Before every commit, ALWAYS run: - -1. `npm run format` - Format code with Prettier -2. `npm run lint` - Check for linting issues -3. `npm run test` - Ensure all tests pass -4. `npm run build` - Verify TypeScript compilation - -### Performance Requirements - -Performance is critical - always run benchmarks before and after changes using `npm run benchmark`. The library maintains its position as the fastest Dancing Links implementation in JavaScript through systematic optimization. - -See `PERFORMANCE.md` for detailed analysis of optimization work completed. - -## Release Process - -Releases are automated using release-it: - -```bash -npm run release -``` - -This will: - -1. Run automated benchmark documentation updates -2. Format code -3. Generate changelog -4. Create git tag -5. Publish to npm -6. Create GitHub release - -The benchmark documentation is automatically updated during releases to ensure performance claims stay current. diff --git a/PERFORMANCE.md b/PERFORMANCE.md deleted file mode 100644 index f005edd..0000000 --- a/PERFORMANCE.md +++ /dev/null @@ -1,100 +0,0 @@ -# Performance Optimization Process - -This document summarizes the systematic performance optimization work performed on the Dancing Links implementation. - -## Optimization Testing Results - -After systematic testing of **19 individual optimizations**, we identified 3 successful approaches out of 19 attempts. - -## Successful Optimizations (3 out of 19) - -### 1. Early Termination for Impossible Constraints - -When a column has zero remaining options, the current search path cannot lead to a valid solution. Immediately selecting such columns triggers backtracking sooner, avoiding deeper recursion into impossible branches. - -**Result:** Consistent positive performance impact across all benchmarks. - -### 2. Pre-calculated Pointers - -Storing the next loop iteration target before modifying the current node's links reduces data dependencies in cover/uncover operations where linked list traversal is frequent. - -**Result:** Consistent positive performance impact across all benchmarks. - -### 3. Unit Propagation for Forced Moves - -When a column has exactly one remaining option, that option must be selected in any valid solution. Prioritizing these unit constraints reduces the search space by making forced moves immediately rather than exploring them through normal branching. - -**Result:** Significant improvement on constraint problems with cascading effects (like Sudoku), minimal impact on problems without such characteristics (like Pentomino tiling). - -## Failed Optimization Patterns - -### Complex Micro-optimizations (12 failures) - -- **Loop unrolling & fast paths**: Degraded performance -- **Function inlining**: No benefit over existing JavaScript engine optimizations -- **Local variable caching**: No measurable improvement -- **Memory layout optimizations**: Overhead outweighed benefits - -### Advanced Algorithmic Improvements (4 failures) - -- **Enhanced column selection heuristics**: Computation overhead outweighed algorithmic benefits -- **Complex constraint propagation**: Expensive analysis dominated any search space reduction -- **Symmetry breaking**: Post-processing approach provided no search-time benefits - -## Key Insights - -### ✅ What Works - -1. **Simple algorithmic improvements** that reduce search space -2. **Early termination** for impossible/forced cases -3. **Problem-specific optimizations** that match problem characteristics -4. **Working with language runtime** rather than against it - -### ❌ What Doesn't Work - -1. **Manual micro-optimizations** - modern JavaScript engines handle these automatically -2. **Complex memory layouts** - property access overhead often dominates -3. **Manual loop optimizations** - can interfere with engine optimizations -4. **Premature caching** - provides no benefit over built-in optimizations - -## Optimization Methodology - -### Testing Protocol - -Each optimization was implemented in isolation and benchmarked against a stable baseline: - -1. **Implement**: Single, focused change to current implementation -2. **Benchmark**: Run comprehensive benchmarks multiple times, record averages -3. **Compare**: Calculate performance change vs baseline for each test case -4. **Document**: Record results with analysis -5. **Decide**: Keep if net positive across all benchmarks, revert if negative -6. **Clean**: Ensure clean implementation before next test - -### Success Rate - -- **Total optimizations tested**: 19 -- **Successful optimizations**: 3 -- **Pattern**: Simple algorithmic improvements succeed, complex micro-optimizations mostly fail - -## Lessons Learned - -### Current Understanding - -The optimization work demonstrated that: - -- Algorithmic improvements can provide substantial gains when they match problem characteristics -- Unit propagation is effective for constraint problems with cascading effects -- Simple optimizations often outperform complex ones in managed runtime environments - -### Future Approach - -Based on systematic testing: - -1. **Focus on algorithmic improvements** over micro-optimizations -2. **Test systematically** - measure everything, assume nothing about performance -3. **Work with the runtime** - simple patterns often optimize better than complex manual optimizations -4. **Consider problem-specific approaches** for targeted use cases - -## Recommendations - -The systematic optimization effort successfully identified which approaches work and which don't, providing a foundation for future performance work. The current implementation maintains clean, maintainable code while incorporating the optimizations that proved effective through testing. diff --git a/README.md b/README.md index 66c4a9a..55b67c9 100644 --- a/README.md +++ b/README.md @@ -1,225 +1,100 @@ -# dancing-links +# Cover Story -## About +**Cover Story** is a playable stealth-game prototype whose patrol system is a live exact-cover +problem. You are stealing a dossier from a museum while every plausible joint guard schedule is +recomputed, sampled, and drawn around you in real time. -This is an implementation of Knuth's DLX to solve the exact cover problem. -It is a port of [Knuth's literate dancing links implementation](https://cs.stanford.edu/~knuth/programs/dance.w) and supports primary and secondary constraints, and returning custom data in addition to row indices. +This branch intentionally consumes [`dancing-links`](https://www.npmjs.com/package/dancing-links) +`4.3.9` from npm. It does not import or benchmark a local copy of the solver. -There are no external dependencies and there is full TypeScript support. +## Play -It is currently [the fastest](#benchmarks) Dancing Links implementation in JavaScript. - -## Usage - -### Basic Example - -```ts -import { DancingLinks } from 'dancing-links' - -const dlx = new DancingLinks() -const solver = dlx.createSolver({ columns: 3 }) - -solver.addSparseConstraint('row1', [0, 2]) // Constraint active in columns 0 and 2 -solver.addSparseConstraint('row2', [1]) // Constraint active in column 1 -solver.addSparseConstraint('row3', [0, 1]) // Constraint active in columns 0 and 1 - -const solutions = solver.findAll() -// Returns: [[{ data: 'row1', index: 0 }, { data: 'row2', index: 1 }]] +```sh +npm install +npm run dev ``` -### Constraint Formats +Open the local URL printed by Vite and select **Begin infiltration**. -#### Sparse Constraints (Recommended) +| Input | Action | +| -------------------------- | -------------------------------------------------------- | +| WASD / arrow keys | Move and hide behind exhibits | +| Click a nearby patrol node | Throw an echo; exactly one guard must service it | +| E beside a magenta gate | Jam that route for four planning beats | +| Space | Take the dossier at the vault or extract at the entrance | +| Escape | Pause / resume | +| R | Restart | -**Sparse constraints are the most efficient format** - specify only the active column indices instead of full binary arrays. This reduces parsing overhead and memory usage, especially for problems with many columns. +The dossier increases the patrol tempo. Exposure rises only while a guard has an unobstructed view; +breaking line of sight lets it fall. Three blown identities end the run. -```ts -const solver = dlx.createSolver({ columns: 100 }) +## Why this is actually DLX gameplay -// ⚡ EFFICIENT: Only specify active columns -solver.addSparseConstraint('constraint1', [0, 15, 42, 87]) -solver.addSparseConstraint('constraint2', [1, 16, 43, 99]) +Every planning beat generates a four-step route row for each guard. The exact-cover matrix uses: -// Batch operations for better performance -const constraints = [ - { data: 'batch1', columnIndices: [0, 10, 20] }, - { data: 'batch2', columnIndices: [5, 15, 25] }, - { data: 'batch3', columnIndices: [2, 12, 22] } -] -solver.addSparseConstraints(constraints) -``` - -#### Binary Constraints +- one primary column per guard, so exactly one route is selected for every guard; +- one primary column per active duty or echo, so exactly one selected route services each one; +- secondary node/time columns, so two guards cannot occupy the same place on the same beat; and +- secondary undirected edge/time columns, so guards cannot pass through one another head-on. -Use binary constraints when it's more convenient for your encoding logic or when you already have constraint data in binary format: +The game samples up to 128 complete covers and turns their next moves into the colored ghost field. +Thick, bright paths occur in more valid covers. The actual patrol then follows one of those complete +joint schedules. An echo adds a primary column; a jam removes all rows that cross an edge. Both +actions therefore reshape the solution space rather than applying a cosmetic AI modifier. -```ts -const solver = dlx.createSolver({ columns: 4 }) +`128+` is deliberately shown when the search reaches its sampling limit. It means “at least 128,” +not that exactly 128 schedules exist. -// Convenient when encoding naturally produces binary arrays -solver.addBinaryConstraint('row1', [1, 0, 1, 0]) -solver.addBinaryConstraint('row2', [0, 1, 0, 1]) -solver.addBinaryConstraint('row3', [1, 1, 0, 0]) +## Real-world performance, not benchmark shortcuts -// Batch operations -const binaryConstraints = [ - { data: 'batch1', columnValues: [1, 0, 1, 0] }, - { data: 'batch2', columnValues: [0, 1, 0, 1] } -] -solver.addBinaryConstraints(binaryConstraints) -``` +Every beat rebuilds the problem from the current guard positions, outstanding deadlines, and jammed +edges. The prototype does not cache an answer to a repeated puzzle. That makes its workload the one +the interaction creates: varied, stateful, and latency-sensitive. -### Constraint Templates +The hot path is documented inline in [`src/schedule.ts`](src/schedule.ts): -For problems with reusable constraint patterns, templates provide significant performance benefits by pre-processing base constraints. **Templates are especially beneficial when using binary constraints**, as the binary-to-sparse conversion happens once during template creation rather than every time you create a solver: +- route constraints stay sparse instead of allocating mostly-zero binary matrices; +- all prevalidated route rows enter the solver in one batch; +- numeric node, edge, and time indices avoid parsing or per-slot lookup objects; and +- a bounded horizon, route count, and solution sample keep planning latency predictable. -```ts -// Create template with base constraints -const template = dlx.createSolverTemplate({ columns: 20 }) -template.addSparseConstraint('base1', [0, 5, 10]) -template.addSparseConstraint('base2', [1, 6, 11]) +Static node and edge maps in [`src/world.ts`](src/world.ts) are also built once rather than rescanned +for every render frame. These choices reduce work without changing the puzzle or reusing a previous +solution. -// Create multiple solvers from the same template -const solver1 = template.createSolver() -solver1.addSparseConstraint('extra1', [2, 7, 12]) -const solutions1 = solver1.findAll() - -const solver2 = template.createSolver() -solver2.addSparseConstraint('extra2', [3, 8, 13]) -const solutions2 = solver2.findAll() -``` +## Contradiction behavior -### Complex Constraints (Primary + Secondary) +Player input should not crash or freeze the real-time loop. If a newly thrown echo cannot belong to +any cover, the scheduler retries without the newest player duty, reports the fizzle, and refunds its +charge. If a fixed routine duty is contradictory after route changes, it is separately removed while +guard selection and collision constraints remain active. -For problems requiring both primary constraints (must be covered exactly once) and secondary constraints (optional - may be left uncovered, but if covered, allow no collisions): +Those fallbacks are intentionally not behavior-identical, so they have dedicated tests. See +[`test/game/schedule.spec.ts`](test/game/schedule.spec.ts) for collisions, head-on edges, jams, +unreachable duties, both recovery paths, and honest capped-search reporting. -```ts -const solver = dlx.createSolver({ - primaryColumns: 2, // First 2 columns are primary - secondaryColumns: 2 // Next 2 columns are secondary -}) +## Development -// Method 1: Add constraints separately -solver.addSparseConstraint('constraint1', { - primary: [0], // Must cover primary column 0 - secondary: [1] // May cover secondary column 1 (optional, but no conflicts if used) -}) - -// Method 2: Add as binary constraint -solver.addBinaryConstraint('constraint2', { - primaryRow: [0, 1], // Binary values for primary columns - secondaryRow: [1, 0] // Binary values for secondary columns -}) -``` - -**Key difference between primary and secondary constraints:** - -- **Primary**: All primary columns MUST be covered exactly once in any valid solution -- **Secondary**: Secondary columns are optional - they can be left uncovered, but if a secondary column IS covered, only one constraint can cover it (no collisions allowed) - -### Solution Methods - -```ts -// Find one solution -const oneSolution = solver.findOne() - -// Find all solutions -const allSolutions = solver.findAll() - -// Find up to N solutions -const limitedSolutions = solver.find(10) +```sh +npm test # scheduler and fallback behavior +npm run lint # TypeScript linting +npm run build # strict typecheck plus production Vite bundle +npm run format:check ``` -### Generator Interface (Streaming Solutions) - -For large solution spaces or when you need early termination, use the generator interface: - -```ts -// Stream solutions one at a time -const generator = solver.createGenerator() - -let solutionCount = 0 -for (const solution of generator) { - console.log('Found solution:', solution) - - solutionCount++ - if (solutionCount >= 5) { - // Stop after finding 5 solutions - break - } -} - -// Manual iteration for full control -const generator2 = solver.createGenerator() -let result = generator2.next() -while (!result.done) { - processSolution(result.value) - result = generator2.next() -} -``` - -The generator maintains search state between solutions, enabling memory-efficient streaming and early termination without computing all solutions upfront. - -## Examples - -The [benchmark directory](https://github.com/TimBeyer/dancing-links/tree/master/benchmark) contains complete implementations for: - -- **N-Queens Problem**: Classical constraint satisfaction problem -- **Pentomino Tiling**: 2D shape placement with rotation constraints -- **Sudoku Solver**: Number placement with row/column/box constraints - -These examples demonstrate encoding techniques for different problem types and show performance optimization strategies. - -## Benchmarks - -This section contains performance comparisons against other JavaScript Dancing Links libraries, updated automatically during releases. - -All benchmarks run on the same machine with identical test cases. Results show operations per second (higher is better). - -### All solutions to the sudoku - -| Library | Ops/Sec | Relative Performance | Margin of Error | -| ----------------------- | -------- | -------------------- | --------------- | -| dancing-links (sparse) | 35659.62 | **1.00x (fastest)** | ±0.10% | -| dancing-links (binary) | 8297.89 | 0.23x | ±0.13% | -| dance | 2714.39 | 0.08x | ±0.23% | -| dancing-links-algorithm | 1661.14 | 0.05x | ±0.37% | -| dlxlib | 1521.37 | 0.04x | ±0.35% | - -### Finding one pentomino tiling on a 6x10 field - -| Library | Ops/Sec | Relative Performance | Margin of Error | -| ---------------------- | ------- | -------------------- | --------------- | -| dancing-links (sparse) | 831.54 | **1.00x (fastest)** | ±0.29% | -| dancing-links (binary) | 762.37 | 0.92x | ±0.34% | -| dlxlib | 446.27 | 0.54x | ±0.60% | -| dance | 100.90 | 0.12x | ±0.87% | - -### Finding ten pentomino tilings on a 6x10 field - -| Library | Ops/Sec | Relative Performance | Margin of Error | -| ---------------------- | ------- | -------------------- | --------------- | -| dancing-links (sparse) | 117.94 | **1.00x (fastest)** | ±0.57% | -| dancing-links (binary) | 114.12 | 0.97x | ±1.02% | -| dlxlib | 85.77 | 0.73x | ±1.51% | -| dance | 20.07 | 0.17x | ±1.05% | - -### Finding one hundred pentomino tilings on a 6x10 field - -| Library | Ops/Sec | Relative Performance | Margin of Error | -| ---------------------- | ------- | -------------------- | --------------- | -| dancing-links (binary) | 16.00 | **1.00x (fastest)** | ±0.80% | -| dancing-links (sparse) | 15.98 | 1.00x | ±0.63% | -| dlxlib | 11.78 | 0.74x | ±1.47% | -| dance | 2.90 | 0.18x | ±1.21% | +The prototype is deliberately small and framework-free: -**Testing Environment:** +- `src/schedule.ts` builds and solves the live exact-cover matrix; +- `src/game.ts` owns the heist loop, patrol deadlines, detection, equipment, and rendering; +- `src/world.ts` defines the museum graph, exhibits, doors, and collision geometry; and +- `src/audio.ts` creates the procedural feedback sounds. -- Node.js v25.9.0 -- Test cases: Sudoku solving, pentomino tiling (1, 10, 100 solutions) +## Prototype scope -_Last updated: 2026-07-13_ +This is one compact mission tuned for desktop keyboard and pointer controls. There is no persistence +beyond the local best score, no level editor, and no production asset pipeline. The point of the +prototype is to test whether reading and manipulating a solution distribution can feel like a game. -## Contributing +## License -For development information, performance benchmarking, profiling, and contribution guidelines, see [DEVELOPMENT.md](DEVELOPMENT.md). +MIT diff --git a/benchmark/config/cases.ts b/benchmark/config/cases.ts deleted file mode 100644 index 477e72f..0000000 --- a/benchmark/config/cases.ts +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Benchmark case definitions - * Each case defines a specific problem scenario and execution strategy - */ - -import { BenchmarkCase } from '../types.js' - -/** - * All benchmark cases available in the system - * Cases can be selected by groups using their IDs in the matrix configuration - */ -export const cases = { - 'sudoku-hard': { - id: 'sudoku-hard', - name: 'All solutions to the sudoku', - problemType: 'sudoku', - parameters: { - puzzle: '..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9' - }, - executeStrategy: (solver, prepared) => solver.solveAll(prepared) - } satisfies BenchmarkCase<'sudoku'>, - - 'pentomino-1': { - id: 'pentomino-1', - name: 'Finding one pentomino tiling on a 6x10 field', - problemType: 'pentomino', - parameters: {}, - executeStrategy: (solver, prepared) => solver.solveOne(prepared) - } satisfies BenchmarkCase<'pentomino'>, - - 'pentomino-10': { - id: 'pentomino-10', - name: 'Finding ten pentomino tilings on a 6x10 field', - problemType: 'pentomino', - parameters: {}, - executeStrategy: (solver, prepared) => solver.solveCount(prepared, 10) - } satisfies BenchmarkCase<'pentomino'>, - - 'pentomino-100': { - id: 'pentomino-100', - name: 'Finding one hundred pentomino tilings on a 6x10 field', - problemType: 'pentomino', - parameters: {}, - executeStrategy: (solver, prepared) => solver.solveCount(prepared, 100) - } satisfies BenchmarkCase<'pentomino'>, - - 'index-width-16': { - id: 'index-width-16', - name: 'Fresh exhaustive search at 65,535 nodes (Uint16)', - problemType: 'index-width', - parameters: { nodeCount: 65_535 }, - executeStrategy: (solver, prepared) => solver.solveAll(prepared) - } satisfies BenchmarkCase<'index-width'>, - - 'index-width-32': { - id: 'index-width-32', - name: 'Fresh exhaustive search at 65,536 nodes (Int32)', - problemType: 'index-width', - parameters: { nodeCount: 65_536 }, - executeStrategy: (solver, prepared) => solver.solveAll(prepared) - } satisfies BenchmarkCase<'index-width'>, - - 'index-width-mixed': { - id: 'index-width-mixed', - name: 'Fresh sequential Uint16 and Int32 exhaustive searches', - problemType: 'index-width', - parameters: { nodeCount: 65_536 }, - executeStrategy: (solver, prepared) => solver.solveAll(prepared) - } satisfies BenchmarkCase<'index-width'> -} as const - -export type CaseId = keyof typeof cases diff --git a/benchmark/config/groups.ts b/benchmark/config/groups.ts deleted file mode 100644 index 28f80c2..0000000 --- a/benchmark/config/groups.ts +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Benchmark group definitions - * Groups define matrices of case/solver combinations for different benchmark scenarios - */ - -import type { CaseId } from './cases.js' -import type { SolverId } from './solvers.js' -import { - internalSolvers, - externalSolvers, - externalSolversWithoutDancingLinksAlgorithm -} from './solvers.js' - -// Groups intentionally select only relevant cases. Width-boundary regression -// tasks, for example, have no meaningful external-library comparison. -type BenchmarkMatrix = Partial> - -interface BenchmarkGroup { - readonly name: string - readonly description: string - readonly matrix: BenchmarkMatrix -} - -/** - * All benchmark groups available in the system - * Groups are selected via CLI arguments and define explicit solver-case combinations - */ -export const groups = { - internal: { - name: 'internal', - description: - 'Internal solver benchmarks: regression testing across all internal implementations', - matrix: { - 'sudoku-hard': internalSolvers, - 'pentomino-1': internalSolvers, - 'pentomino-10': internalSolvers, - 'pentomino-100': internalSolvers, - 'index-width-16': ['width-fresh'], - 'index-width-32': ['width-fresh'], - 'index-width-mixed': ['width-mixed'] - } - }, - - competitive: { - name: 'competitive', - description: 'Competitive benchmarks: our main solvers vs external libraries', - matrix: { - 'sudoku-hard': ['sparse', 'binary', ...externalSolvers], - 'pentomino-1': ['sparse', 'binary', ...externalSolversWithoutDancingLinksAlgorithm], - 'pentomino-10': ['sparse', 'binary', ...externalSolversWithoutDancingLinksAlgorithm], - 'pentomino-100': ['sparse', 'binary', ...externalSolversWithoutDancingLinksAlgorithm] - } - }, - - comprehensive: { - name: 'comprehensive', - description: - 'Comprehensive benchmarks: detailed analysis across all viable solver-case combinations', - matrix: { - 'sudoku-hard': [...internalSolvers, ...externalSolvers], - 'pentomino-1': [...internalSolvers, ...externalSolversWithoutDancingLinksAlgorithm], - 'pentomino-10': [...internalSolvers, ...externalSolversWithoutDancingLinksAlgorithm], - 'pentomino-100': [...internalSolvers, ...externalSolversWithoutDancingLinksAlgorithm] - } - } -} as const satisfies Record - -export type GroupId = keyof typeof groups - -/** - * Get group by name with error handling - */ -export function getGroup(name: string): BenchmarkGroup | undefined { - return groups[name as GroupId] -} diff --git a/benchmark/config/problems.ts b/benchmark/config/problems.ts deleted file mode 100644 index 2981f2a..0000000 --- a/benchmark/config/problems.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Problem registry - * Central registration of all available problem definitions - */ - -import { ProblemRegistry } from '../types.js' - -// Problem definition imports -import { generateSudokuConstraints } from '../problems/sudoku/definition.js' -import { generatePentominoConstraints } from '../problems/pentomino/definition.js' -import { generateIndexWidthConstraints } from '../problems/index-width/definition.js' - -/** - * Registry of all available problem definitions - * Maps problem type names to their constraint generation functions - */ -export const problems: ProblemRegistry = { - sudoku: generateSudokuConstraints, - pentomino: generatePentominoConstraints, - 'index-width': generateIndexWidthConstraints, - 'n-queens': (() => { - throw new Error('N-Queens not implemented yet') - }) as any // TODO: implement -} - -/** - * Get problem definition by name with type safety - */ -export function getProblem(name: T): ProblemRegistry[T] { - const problem = problems[name] - if (!problem) { - throw new Error(`Problem '${name}' not found in registry`) - } - return problem -} - -/** - * Get all problem names - */ -export function getProblemNames(): string[] { - return Object.keys(problems) -} diff --git a/benchmark/config/solvers.ts b/benchmark/config/solvers.ts deleted file mode 100644 index 94d50d7..0000000 --- a/benchmark/config/solvers.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Solver registry - * Central registration of all available solvers - */ - -// Dancing Links solver imports -import { DancingLinksSparseSolver } from '../solvers/InternalSparseSolver.js' -import { DancingLinksBinarySolver } from '../solvers/InternalBinarySolver.js' -import { DancingLinksTemplateSolver } from '../solvers/InternalTemplateSolver.js' -import { DancingLinksGeneratorSolver } from '../solvers/InternalGeneratorSolver.js' -import { - IndexWidthFreshSolver, - IndexWidthMixedSolver -} from '../solvers/InternalIndexWidthSolver.js' - -// External library solver imports -import { DlxlibSolver } from '../solvers/ExternalDlxlibSolver.js' -import { DanceSolver } from '../solvers/ExternalDanceSolver.js' -import { DancingLinksAlgorithmSolver } from '../solvers/ExternalDancingLinksAlgorithmSolver.js' - -/** - * Registry of all available solver classes - * Maps short IDs to solver classes for matrix configuration - */ -export const solvers = { - sparse: DancingLinksSparseSolver, - binary: DancingLinksBinarySolver, - template: DancingLinksTemplateSolver, - generator: DancingLinksGeneratorSolver, - 'width-fresh': IndexWidthFreshSolver, - 'width-mixed': IndexWidthMixedSolver, - dlxlib: DlxlibSolver, - dance: DanceSolver, - 'dancing-links-algorithm': DancingLinksAlgorithmSolver -} as const - -export type SolverId = keyof typeof solvers - -// Helper arrays for common solver groupings -export const internalSolvers: readonly SolverId[] = ['sparse', 'binary', 'template', 'generator'] -export const externalSolvers: readonly SolverId[] = ['dlxlib', 'dance', 'dancing-links-algorithm'] -export const externalSolversWithoutDancingLinksAlgorithm: readonly SolverId[] = ['dlxlib', 'dance'] diff --git a/benchmark/index.ts b/benchmark/index.ts deleted file mode 100644 index 8209713..0000000 --- a/benchmark/index.ts +++ /dev/null @@ -1,167 +0,0 @@ -/** - * Modular benchmark CLI interface - * Supports dynamic group selection and maintains compatibility with existing CI - */ - -import { writeFileSync } from 'fs' -import { BenchmarkOptions, BenchmarkSection, BenchmarkResult } from './types.js' - -// Re-export types for external scripts -export { BenchmarkOptions, BenchmarkSection, BenchmarkResult } -import { runBenchmarkGroup, getAvailableGroups, getGroupDescription } from './runner.js' - -/** - * Parse command line arguments - */ -function parseArgs(): BenchmarkOptions & { group?: string; help?: boolean } { - const args = process.argv.slice(2) - - // Check for help flag - const help = args.includes('--help') - - // Determine group selection - let group: string | undefined - if (args.includes('--competitive')) { - group = 'competitive' - } else if (args.includes('--comprehensive')) { - group = 'comprehensive' - } else if (args.includes('--internal')) { - group = 'internal' - } - - // Default to 'internal' if no group specified - if (!group && !help) { - group = 'internal' - } - - // Parse other options - const jsonFlag = args.find(arg => arg.startsWith('--json')) - const jsonOutput = !!jsonFlag || args.includes('--json') - const quiet = args.includes('--quiet') - - // Support both --json=filename and positional filename argument - let jsonFile: string | undefined - if (jsonFlag?.includes('=')) { - jsonFile = jsonFlag.split('=')[1] - } else if (jsonOutput) { - // If --json is specified without =filename, look for positional argument - const nonFlagArgs = args.filter(arg => !arg.startsWith('--')) - jsonFile = nonFlagArgs[0] - } - - return { - group, - help, - includeExternal: group === 'comprehensive' || group === 'competitive', - jsonOutput, - jsonFile, - quiet - } -} - -/** - * Output benchmark results - */ -function outputResults(results: BenchmarkSection[], options: BenchmarkOptions): void { - if (options.jsonOutput) { - const jsonOutput = JSON.stringify(results, null, 2) - - if (options.jsonFile) { - writeFileSync(options.jsonFile, jsonOutput) - if (!options.quiet) { - console.log(`Benchmark results written to ${options.jsonFile}`) - } - } else { - console.log(jsonOutput) - } - } -} - -/** - * Show usage information - */ -function showUsage(): void { - const availableGroups = getAvailableGroups() - - console.log(` -Usage: node benchmark/index.js [options] - -Group Options (select one): - --internal Internal benchmarks: all internal solver implementations (default) - --competitive Competitive benchmarks: our best solver vs external libraries - --comprehensive Comprehensive benchmarks: detailed analysis of all combinations - -Output Options: - --json[=file] Output results as JSON (to file if specified) - --quiet Suppress console output during benchmarks - -Other Options: - --help Show this help message - -Available Groups:`) - - for (const groupName of availableGroups) { - const description = getGroupDescription(groupName) - console.log(` ${groupName.padEnd(10)} ${description || ''}`) - } - - console.log(` -Examples: - node benchmark/index.js # Internal benchmarks (default) - node benchmark/index.js --competitive # Competitive benchmarks - node benchmark/index.js --comprehensive # Comprehensive analysis - node benchmark/index.js --internal --json=internal.json # Internal with JSON output - node benchmark/index.js --competitive --quiet # Competitive mode, quiet output -`) -} - -/** - * Main benchmark runner - */ -async function main(): Promise { - const options = parseArgs() - - // Show help if requested - if (options.help) { - showUsage() - return - } - - // Ensure we have a group to run - if (!options.group) { - console.error('No benchmark group specified. Use --help for usage information.') - process.exit(1) - } - - // Display header - if (!options.quiet) { - console.log('============================================================') - console.log('DANCING LINKS PERFORMANCE BENCHMARKS (New System)') - console.log(`Group: ${options.group} (${getGroupDescription(options.group) || 'Custom group'})`) - console.log('============================================================') - console.log() - } - - try { - // Run the specified group - const results = await runBenchmarkGroup(options.group, options) - - // Output results - outputResults(results, options) - - // Display footer - if (!options.quiet && !options.jsonOutput) { - console.log('============================================================') - console.log('BENCHMARK COMPLETE') - console.log('============================================================') - } - } catch (error) { - console.error('Benchmark execution failed:', (error as Error).message) - process.exit(1) - } -} - -// Run main function if this file is executed directly -if (import.meta.url === `file://${process.argv[1]}`) { - main().catch(console.error) -} diff --git a/benchmark/problems/index-width/definition.ts b/benchmark/problems/index-width/definition.ts deleted file mode 100644 index 9960b4b..0000000 --- a/benchmark/problems/index-width/definition.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Exact node-count workloads for the Uint16/Int32 storage boundary. - * - * Column 1 appears only in the final row and is placed last in that row. Search - * must therefore select the matrix's highest-index node, then cover/uncover the - * other 63 columns. The 65,535- and 65,536-node variants differ by one filler - * node, exercising behavior immediately on both sides of the fallback cutoff. - */ - -import { IndexWidthParams, StandardConstraints } from '../../types.js' - -export const INDEX_WIDTH_PRIMARY_COLUMNS = 64 -const HEADER_NODES = INDEX_WIDTH_PRIMARY_COLUMNS + 1 -const PADDING_ROWS = 1_038 -const FORCED_COLUMN = 1 - -export function generateIndexWidthConstraints(params: IndexWidthParams): StandardConstraints { - const paddingRow: number[] = [] - for (let column = 0; column < INDEX_WIDTH_PRIMARY_COLUMNS; column++) { - if (column !== FORCED_COLUMN) { - paddingRow.push(column) - } - } - - const terminalRow = [...paddingRow, FORCED_COLUMN] - const fixedNodes = HEADER_NODES + PADDING_ROWS * paddingRow.length + terminalRow.length - const fillerWidth = params.nodeCount - fixedNodes - if (fillerWidth !== 12 && fillerWidth !== 13) { - throw new Error(`Unsupported index-width node count: ${params.nodeCount}`) - } - - // Reusing one immutable padding array keeps input setup compact. Timed solver - // ingestion still creates every row record and matrix node from scratch. - const primaryConstraints = new Array(PADDING_ROWS + 2) - for (let row = 0; row < PADDING_ROWS; row++) { - primaryConstraints[row] = paddingRow - } - primaryConstraints[PADDING_ROWS] = paddingRow.slice(0, fillerWidth) - primaryConstraints[PADDING_ROWS + 1] = terminalRow - - return { primaryConstraints } -} diff --git a/benchmark/problems/n-queens/encoder.ts b/benchmark/problems/n-queens/encoder.ts deleted file mode 100644 index 2087aac..0000000 --- a/benchmark/problems/n-queens/encoder.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { ComplexConstraint, BinaryNumber } from '../../../index.js' - -function constant(t: T): () => T { - return () => t -} - -function times(n: number, fn: () => T): T[] { - const returnValue: T[] = [] - - for (let i = 0; i < n; i++) { - returnValue.push(fn()) - } - - return returnValue -} - -function oneAt(length: number, index: number): BinaryNumber[] { - let array = times(length, constant(0 as BinaryNumber)) - array[index] = 1 - return array -} - -function getDiagonalIndex( - fieldSize: number, - x: number, - y: number, - reverse: boolean = false -): number { - return reverse ? x + y : fieldSize + x - y - 1 -} - -export function createEncoder(fieldSize: number) { - const primaryRow = function (x: number, y: number): BinaryNumber[] { - const row = oneAt(fieldSize, x) - const column = oneAt(fieldSize, y) - return [...row, ...column] as BinaryNumber[] - } - - const secondaryRow = function (x: number, y: number): BinaryNumber[] { - const numDiagonals = 2 * fieldSize - 1 - const diagonal = oneAt(numDiagonals, getDiagonalIndex(fieldSize, x, y)) - const reverseDiagonal = oneAt(numDiagonals, getDiagonalIndex(fieldSize, x, y, true)) - - return [...diagonal, ...reverseDiagonal] as BinaryNumber[] - } - - return function encodePosition(x: number, y: number): ComplexConstraint { - return { - data: { - position: [x, y] - }, - primaryRow: primaryRow(x, y), - secondaryRow: secondaryRow(x, y) - } - } -} diff --git a/benchmark/problems/n-queens/index.ts b/benchmark/problems/n-queens/index.ts deleted file mode 100644 index 759ce10..0000000 --- a/benchmark/problems/n-queens/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { createEncoder } from './encoder.js' -import { ComplexConstraint } from '../../../index.js' - -export function createConstraints(fieldSize: number): ComplexConstraint[] { - const encode = createEncoder(fieldSize) - const constraints: ComplexConstraint[] = [] - - for (let x = 0; x < fieldSize; x++) { - for (let y = 0; y < fieldSize; y++) { - constraints.push(encode(x, y)) - } - } - - return constraints -} diff --git a/benchmark/problems/pentomino/definition.ts b/benchmark/problems/pentomino/definition.ts deleted file mode 100644 index 0461d7b..0000000 --- a/benchmark/problems/pentomino/definition.ts +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Pentomino problem definition for the benchmark system - */ - -import { StandardConstraints, PentominoParams } from '../../types.js' -import { ALL_CONSTRAINTS, PlacedPentomino } from './field.js' - -/** - * Generate standardized constraints for pentomino tiling - * Pentomino only uses primary constraints - all constraints must be covered exactly once - */ -export function generatePentominoConstraints(_params: PentominoParams): StandardConstraints { - // Use existing constraint generation from pentomino field - // ALL_CONSTRAINTS contains all possible piece placements on a 6x10 field - // The existing constraints are in binary format, convert to sparse - const binaryRows = ALL_CONSTRAINTS.map(constraint => constraint.row) - const primaryConstraints = binaryRows.map(binaryRow => { - const columnIndices = [] - for (let i = 0; i < binaryRow.length; i++) { - if (binaryRow[i] === 1) { - columnIndices.push(i) - } - } - return columnIndices - }) - - return { - primaryConstraints, - // No secondary constraints for pentomino - columnNames: generatePentominoColumnNames() - } -} - -/** - * Generate descriptive column names for pentomino constraints - * Useful for debugging and display purposes - */ -function generatePentominoColumnNames(): string[] { - const names: string[] = [] - - // Piece constraints: Each of the 12 pentomino pieces must be placed exactly once - const pieceNames = ['F', 'I', 'L', 'N', 'P', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] - for (const piece of pieceNames) { - names.push(`piece(${piece})`) - } - - // Position constraints: Each cell on the 6x10 field must be covered exactly once - for (let row = 0; row < 6; row++) { - for (let col = 0; col < 10; col++) { - names.push(`pos(${row},${col})`) - } - } - - return names -} - -/** - * Re-export types from existing pentomino module for convenience - */ -export type { PlacedPentomino } diff --git a/benchmark/problems/pentomino/field.ts b/benchmark/problems/pentomino/field.ts deleted file mode 100644 index 1d5fb57..0000000 --- a/benchmark/problems/pentomino/field.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { Pentomino, NUM_PENTOMINOS, ALL_PENTOMINOS } from './pentomino.js' -import { SimpleConstraint } from '../../../index.js' - -function times(n: number, fn: () => T): T[] { - const returnValue: T[] = [] - - for (let i = 0; i < n; i++) { - returnValue.push(fn()) - } - - return returnValue -} - -function constant(t: T): () => T { - return () => t -} - -function getIndex(x: number, y: number, width: number) { - return y * width + x -} - -export interface PlacedPentomino { - x: number - y: number - p: Pentomino -} - -export class Field { - private width: number - private height: number - - private placedPentominos: PlacedPentomino[] = [] - - constructor(width: number, height: number) { - this.width = width - this.height = height - } - - place(x: number, y: number, p: Pentomino): PlacedPentomino { - const placed = { - x, - y, - p - } - - this.placedPentominos.push(placed) - - return placed - } - - canPlace(x: number, y: number, p: Pentomino) { - const widthFits = x + p.width <= this.width - const heightFits = y + p.height <= this.height - - return widthFits && heightFits - } - - constraintFor(x: number, y: number, p: Pentomino): SimpleConstraint { - // Ensure we can only place one per type including rotations - const typeConstraint = times(NUM_PENTOMINOS, constant(0)) as (1 | 0)[] - typeConstraint[p.type] = 1 - - const placeConstraint = times(this.width * this.height, constant(0)) as (1 | 0)[] - - for (let xBoard = 0; xBoard < this.width; xBoard++) { - for (let yBoard = 0; yBoard < this.height; yBoard++) { - const isInXRange = xBoard >= x && xBoard < x + p.width - const isInYRange = yBoard >= y && yBoard < y + p.height - - if (isInXRange && isInYRange) { - const xP = xBoard - x - const yP = yBoard - y - - const val = p.matrix[getIndex(xP, yP, p.width)] - - placeConstraint[getIndex(xBoard, yBoard, this.width)] = val - } - } - } - - return { - data: { - p, - x, - y - }, - row: [...typeConstraint, ...placeConstraint] - } - } - - printAt(x: number, y: number, p: Pentomino): void { - let printOut = [] - for (let yBoard = 0; yBoard < this.height; yBoard++) { - for (let xBoard = 0; xBoard < this.width; xBoard++) { - const isInXRange = xBoard >= x && xBoard < x + p.width - const isInYRange = yBoard >= y && yBoard < y + p.height - - if (isInXRange && isInYRange) { - const xP = xBoard - x - const yP = yBoard - y - - const val = p.matrix[getIndex(xP, yP, p.width)] - - printOut.push(val) - } else { - printOut.push(0) - } - } - printOut.push('\n') - } - console.log(printOut.join('')) - } - - print(): void { - let printOut = times(this.width * this.height, () => ' ') - - for (let yBoard = 0; yBoard < this.height; yBoard++) { - for (let xBoard = 0; xBoard < this.width; xBoard++) { - for (const { x, y, p } of this.placedPentominos) { - const isInXRange = xBoard >= x && xBoard < x + p.width - const isInYRange = yBoard >= y && yBoard < y + p.height - - if (isInXRange && isInYRange) { - const xP = xBoard - x - const yP = yBoard - y - - const val = p.matrix[getIndex(xP, yP, p.width)] - - if (val) { - printOut[getIndex(xBoard, yBoard, this.width)] = p.id - } - } - } - } - } - - console.log(printOut.join('\n')) - } -} - -const FIELD_WIDTH = 6 -const FIELD_HEIGHT = 10 - -const field = new Field(FIELD_WIDTH, FIELD_HEIGHT) - -export const ALL_CONSTRAINTS: SimpleConstraint[] = [] - -for (const p of ALL_PENTOMINOS) { - for (let x = 0; x < FIELD_WIDTH; x++) { - for (let y = 0; y < FIELD_HEIGHT; y++) { - if (field.canPlace(x, y, p)) { - ALL_CONSTRAINTS.push(field.constraintFor(x, y, p)) - } - } - } -} diff --git a/benchmark/problems/pentomino/pentomino.ts b/benchmark/problems/pentomino/pentomino.ts deleted file mode 100644 index 2d49a54..0000000 --- a/benchmark/problems/pentomino/pentomino.ts +++ /dev/null @@ -1,208 +0,0 @@ -export type BinaryInt = 0 | 1 - -export const NUM_PENTOMINOS = 12 -export enum PentominoType { - F = 0, - I = 1, - L = 2, - N = 3, - P = 4, - T = 5, - U = 6, - V = 7, - W = 8, - X = 9, - Y = 10, - Z = 11 -} - -export interface Pentomino { - type: PentominoType - id: string - width: number - height: number - matrix: BinaryInt[] -} - -const BASE_PENTOMINOS: Pentomino[] = [ - { - type: PentominoType.F, - id: 'F', - width: 3, - height: 3, - matrix: [0, 1, 1, 1, 1, 0, 0, 1, 0] - }, - { - type: PentominoType.I, - id: 'I', - width: 1, - height: 5, - matrix: [1, 1, 1, 1, 1] - }, - { - type: PentominoType.L, - id: 'L', - width: 2, - height: 4, - matrix: [1, 0, 1, 0, 1, 0, 1, 1] - }, - { - type: PentominoType.N, - id: 'N', - width: 2, - height: 4, - matrix: [0, 1, 0, 1, 1, 1, 1, 0] - }, - { - type: PentominoType.P, - id: 'P', - width: 2, - height: 3, - matrix: [1, 1, 1, 1, 1, 0] - }, - { - type: PentominoType.T, - id: 'T', - width: 3, - height: 3, - matrix: [1, 1, 1, 0, 1, 0, 0, 1, 0] - }, - { - type: PentominoType.U, - id: 'U', - width: 3, - height: 2, - matrix: [1, 0, 1, 1, 1, 1] - }, - { - type: PentominoType.V, - id: 'V', - width: 3, - height: 3, - matrix: [1, 0, 0, 1, 0, 0, 1, 1, 1] - }, - { - type: PentominoType.W, - id: 'W', - width: 3, - height: 3, - matrix: [0, 1, 1, 1, 1, 0, 1, 0, 0] - }, - { - type: PentominoType.X, - id: 'X', - width: 3, - height: 3, - matrix: [0, 1, 0, 1, 1, 1, 0, 1, 0] - }, - { - type: PentominoType.Y, - id: 'Y', - width: 2, - height: 4, - matrix: [0, 1, 1, 1, 0, 1, 0, 1] - }, - { - type: PentominoType.Z, - id: 'Z', - width: 3, - height: 3, - matrix: [1, 1, 0, 0, 1, 0, 0, 1, 1] - } -] - -function isEqual(p1: Pentomino, p2: Pentomino): boolean { - if (p1.type !== p2.type) { - return false - } - - if (p1.width !== p2.width) { - return false - } - - if (p1.height !== p2.height) { - return false - } - - // Not the most efficient way of checking whether - // both matrices are equal, but should be OK for the small sizes here - return p1.matrix.join('') === p2.matrix.join('') -} - -function getIndex(x: number, y: number, width: number) { - return y * width + x -} - -export function rotatePentomino(pentomino: Pentomino): Pentomino { - const width = pentomino.height - const height = pentomino.width - - const matrix: BinaryInt[] = [] - - for (let x = 0; x < pentomino.width; x++) { - for (let y = 0; y < pentomino.height; y++) { - const from = getIndex(x, y, pentomino.width) - const to = getIndex(width - y - 1, x, width) - - matrix[to] = pentomino.matrix[from] - } - } - - return { - type: pentomino.type, - id: pentomino.id, - width, - height, - matrix - } -} - -export function mirrorPentomino(pentomino: Pentomino): Pentomino { - const { width, height, type, id } = pentomino - const matrix: BinaryInt[] = [] - - for (let x = 0; x < width; x++) { - for (let y = 0; y < height; y++) { - const from = getIndex(x, y, width) - const to = getIndex(x, height - y - 1, width) - - matrix[to] = pentomino.matrix[from] - } - } - - return { - type, - width, - height, - matrix, - id - } -} - -export const ALL_PENTOMINOS: Pentomino[] = BASE_PENTOMINOS.reduce( - (allPentominos, pentomino) => { - const derivedPentominos: Pentomino[] = [] - - for (let i = 0; i < 4; i++) { - let rotated = pentomino - let mirrorRotated = mirrorPentomino(pentomino) - - for (let rotations = 0; rotations < i; rotations++) { - rotated = rotatePentomino(rotated) - mirrorRotated = rotatePentomino(mirrorRotated) - } - - // Skip redundant rotations - if (!derivedPentominos.some(p => isEqual(p, rotated))) { - derivedPentominos.push(rotated) - } - - if (!derivedPentominos.some(p => isEqual(p, mirrorRotated))) { - derivedPentominos.push(mirrorRotated) - } - } - - return [...allPentominos, ...derivedPentominos] - }, - [] -) diff --git a/benchmark/problems/sudoku/definition.ts b/benchmark/problems/sudoku/definition.ts deleted file mode 100644 index a955f58..0000000 --- a/benchmark/problems/sudoku/definition.ts +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Sudoku problem definition for the benchmark system - */ - -import { StandardConstraints, SudokuParams } from '../../types.js' -import { generateConstraints, parseStringFormat, SudokuInput } from './index.js' - -/** - * Generate standardized constraints for a sudoku puzzle - * Sudoku only uses primary constraints - all constraints must be covered exactly once - */ -export function generateSudokuConstraints(params: SudokuParams): StandardConstraints { - // Parse the string format puzzle into the format expected by existing code - const sudokuField = parseStringFormat(9, params.puzzle) - - // Generate constraints using existing sudoku constraint generation - const constraints = generateConstraints(9, sudokuField) - - // Convert to standardized format - // The existing constraint generation returns binary constraint rows - // We need to convert them to sparse format (column indices) - const binaryRows = constraints.map(constraint => constraint.row) - const primaryConstraints = binaryRows.map(binaryRow => { - const columnIndices = [] - for (let i = 0; i < binaryRow.length; i++) { - if (binaryRow[i] === 1) { - columnIndices.push(i) - } - } - return columnIndices - }) - - return { - primaryConstraints, - // No secondary constraints for sudoku - columnNames: generateSudokuColumnNames() - } -} - -/** - * Generate descriptive column names for sudoku constraints - * Useful for debugging and display purposes - */ -function generateSudokuColumnNames(): string[] { - const names: string[] = [] - - // Position constraints: cell(r,c) for each cell - for (let row = 1; row <= 9; row++) { - for (let col = 1; col <= 9; col++) { - names.push(`cell(${row},${col})`) - } - } - - // Row constraints: row(r,n) for each row and number - for (let row = 1; row <= 9; row++) { - for (let num = 1; num <= 9; num++) { - names.push(`row(${row},${num})`) - } - } - - // Column constraints: col(c,n) for each column and number - for (let col = 1; col <= 9; col++) { - for (let num = 1; num <= 9; num++) { - names.push(`col(${col},${num})`) - } - } - - // Box constraints: box(b,n) for each 3x3 box and number - for (let box = 1; box <= 9; box++) { - for (let num = 1; num <= 9; num++) { - names.push(`box(${box},${num})`) - } - } - - return names -} - -/** - * Re-export types from existing sudoku module for convenience - */ -export type { SudokuInput } diff --git a/benchmark/problems/sudoku/index.ts b/benchmark/problems/sudoku/index.ts deleted file mode 100644 index 1ebac8c..0000000 --- a/benchmark/problems/sudoku/index.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { SimpleConstraint, ConstraintRow, Result } from '../../../index.js' - -type MultiConstraint = SimpleConstraint & ConstraintRow - -export interface SudokuInput { - number: number - rowIndex: number - colIndex: number -} - -function times(n: number, fn: () => T): T[] { - const returnValue: T[] = [] - - for (let i = 0; i < n; i++) { - returnValue.push(fn()) - } - - return returnValue -} - -export function generateConstraints( - size = 9, - inputs: SudokuInput[] = [] -): MultiConstraint[] { - const blockSize = Math.sqrt(size) - // each of the numbers can be in any x|y just once - const numRowColConstraints = size * size - // each of the numbers can be in any row just once - const numRowConstraints = size * size - // each of the numbers can be in any col just once - const numColConstraints = size * size - // each of the numbers can be in any block just once - const numBlockConstraints = size * size - - const constraints: MultiConstraint[] = [] - - const allIndexes = [] - for (let currentRow = 0; currentRow < size; currentRow++) { - for (let currentCol = 0; currentCol < size; currentCol++) { - const matchingInput = inputs.find(i => i.colIndex === currentCol && i.rowIndex === currentRow) - - for (let currentNumber = 0; currentNumber < size; currentNumber++) { - if (matchingInput) { - // Internally we index with zero, but numbers start at 1 - if (matchingInput.number !== currentNumber + 1) { - // If we have an input for this row/col we need to skip all other options - continue - } - } - // The matrix rows go in the order - // [...rowColConstraints, ...rowConstraints, ...colConstraints, ...blockConstraints] - const numberOffset = currentNumber * size - const rowColNumber = size * currentRow + currentCol - const rowColIndex = rowColNumber - - const rowIndex = numRowColConstraints + numberOffset + currentRow - const colIndex = numRowColConstraints + numRowConstraints + numberOffset + currentCol - - const blockRow = Math.floor(currentRow / blockSize) - const blockCol = Math.floor(currentCol / blockSize) - const blockNumber = blockSize * blockRow + blockCol - - const blockIndex = - numRowColConstraints + - numRowConstraints + - numColConstraints + - (numberOffset + blockNumber) - - const row = times( - numRowColConstraints + numRowConstraints + numColConstraints + numBlockConstraints, - () => 0 - ) as (1 | 0)[] - - row[rowColIndex] = 1 - row[rowIndex] = 1 - row[colIndex] = 1 - row[blockIndex] = 1 - - allIndexes[rowColIndex] = 1 - allIndexes[rowIndex] = 1 - allIndexes[colIndex] = 1 - allIndexes[blockIndex] = 1 - - constraints.push({ - row: row, - coveredColumns: [rowColIndex, rowIndex, colIndex, blockIndex], - data: { - number: currentNumber + 1, - rowIndex: currentRow, - colIndex: currentCol - } - }) - } - } - } - - return constraints -} - -export function printBoard(size = 9, inputs: SudokuInput[]): string { - const rows: string[][] = times(size, () => times(size, () => '.')) - - for (let x = 0; x < size; x++) { - for (let y = 0; y < size; y++) { - const field = inputs.find(input => input.colIndex === x && input.rowIndex === y) - rows[y][x] = String((field && field.number) || '.') - } - } - - const joinedRows = rows.map(row => row.join('|')) - const board = joinedRows.join('\n') - - return board -} - -export function parseStringFormat(size = 9, dotFormat: string) { - const inputs: SudokuInput[] = [] - - for (let row = 0; row < size; row++) { - for (let col = 0; col < size; col++) { - const index = size * row + col - const cell = dotFormat[index] - if (cell !== '.' && cell !== '0') { - inputs.push({ - rowIndex: row, - colIndex: col, - number: Number(cell) - }) - } - } - } - - return inputs -} - -export function logResults(size = 9, results: Result[][]) { - console.log( - results - .map(s => s.map(c => c.data)) - .map(s => printBoard(size, s)) - .join('\n\n') - ) -} diff --git a/benchmark/profile.ts b/benchmark/profile.ts deleted file mode 100644 index 9ebb4eb..0000000 --- a/benchmark/profile.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { createWriteStream } from 'fs' -import profiler from 'v8-profiler-next' -import { DancingLinks } from '../index.js' -import { ALL_CONSTRAINTS } from './problems/pentomino/field.js' - -profiler.setGenerateType(1) -profiler.startProfiling('dancing-links', true) - -const dlx = new DancingLinks() -const solver = dlx.createSolver({ columns: 72 }) -for (const constraint of ALL_CONSTRAINTS) { - solver.addBinaryConstraint(constraint.data, constraint.row) -} -solver.findAll() - -const profile = profiler.stopProfiling() - -profile.export().pipe(createWriteStream('profile.cpuprofile')) diff --git a/benchmark/runner.ts b/benchmark/runner.ts deleted file mode 100644 index ab8410a..0000000 --- a/benchmark/runner.ts +++ /dev/null @@ -1,202 +0,0 @@ -/** - * Benchmark execution engine - * Orchestrates running benchmark groups with proper timing and result collection - */ - -import { Bench } from 'tinybench' -import { BenchmarkOptions, BenchmarkSection, BenchmarkResult } from './types.js' - -// Configuration imports -import { cases } from './config/cases.js' -import { groups, getGroup } from './config/groups.js' -import { problems } from './config/problems.js' -import { externalSolvers, solvers } from './config/solvers.js' - -// Track deprecated tests (for compatibility with existing benchmark system) -const deprecatedTests = new Set() - -/** - * Run a specific benchmark group by name - */ -export async function runBenchmarkGroup( - groupName: string, - options: BenchmarkOptions -): Promise { - const group = getGroup(groupName) - if (!group) { - throw new Error(`Benchmark group '${groupName}' not found`) - } - - if (!options.quiet) { - console.log(`Running ${group.name} benchmarks: ${group.description}`) - } - - return runBenchmarksFromMatrix(group.matrix, options) -} - -/** - * Run benchmarks based on a matrix configuration - */ -async function runBenchmarksFromMatrix( - matrix: Record, - options: BenchmarkOptions -): Promise { - const results: BenchmarkSection[] = [] - - for (const [caseId, solverIds] of Object.entries(matrix)) { - const benchmarkCase = cases[caseId as keyof typeof cases] - if (!benchmarkCase) { - if (!options.quiet) { - console.warn(`Case '${caseId}' not found, skipping`) - } - continue - } - - if (!options.quiet) { - console.log(`\nBenchmark: ${benchmarkCase.name}\n`) - } - - // Generate constraints for this case - const problemFn = problems[benchmarkCase.problemType] - if (!problemFn) { - if (!options.quiet) { - console.warn(`Problem type '${benchmarkCase.problemType}' not found, skipping`) - } - continue - } - - const constraints = problemFn(benchmarkCase.parameters as any) // Type assertion needed due to discriminated union - // A benchmark that throws must fail the command. Tinybench otherwise records - // an errored task and continues, which can make a broken implementation look - // fast by silently removing it from the results table. - const bench = new Bench({ throws: true }) - - // Add each solver to the benchmark suite - for (const solverId of solverIds) { - const SolverClass = solvers[solverId as keyof typeof solvers] - if (!SolverClass) { - if (!options.quiet) { - console.warn(`Solver '${solverId}' not found, skipping`) - } - continue - } - - try { - // Create fresh solver instance for this benchmark - const solver = new SolverClass() - - // Setup once per case (outside of timing) - solver.setup?.(constraints) - - // Prepare once per case (outside of timing) - const prepared = solver.prepare(constraints) - - // Add benchmark test - clean execution, no branching! - const testName = SolverClass.name - bench.add(testName, () => { - benchmarkCase.executeStrategy(solver, prepared) - }) - } catch (error) { - // External packages are optional comparison points and may reject a - // problem shape they do not support. Every in-repository solver is a - // required benchmark target, so setup failures must stop validation. - if (!(externalSolvers as readonly string[]).includes(solverId)) { - const message = error instanceof Error ? error.message : String(error) - throw new Error(`Failed to prepare ${solverId} for ${caseId}: ${message}`) - } - if (!options.quiet) { - console.warn(`Skipping ${solverId} for ${caseId}: ${(error as Error).message}`) - } - } - } - - // Run the suite for this case - const sectionResult = await runBench(bench, benchmarkCase.name, options) - results.push(sectionResult) - } - - return results -} - -/** - * Run a tinybench suite and collect results - */ -async function runBench( - bench: Bench, - sectionName: string, - options: BenchmarkOptions -): Promise { - // Set up event listener for cycle events - if (!options.quiet) { - bench.addEventListener('cycle', event => { - const task = event.task - if (task && task.result && task.result.state === 'completed') { - // Format output similar to Benchmark.js - // In tinybench, throughput.mean is operations per second (Hz) - const opsPerSec = task.result.throughput.mean - const margin = task.result.throughput.rme - const runs = task.result.throughput.samplesCount - console.log( - `${task.name} x ${opsPerSec.toLocaleString('en-US', { maximumFractionDigits: 2 })} ops/sec \xb1${margin.toFixed(2)}% (${runs} runs sampled)` - ) - } - }) - } - - // Run the benchmark - await bench.run() - - // Collect results - const sectionResults: BenchmarkResult[] = [] - for (const task of bench.tasks) { - if (task.result && task.result.state === 'completed') { - // In tinybench, throughput.mean is operations per second (Hz equivalent) - sectionResults.push({ - name: task.name, - opsPerSec: task.result.throughput.mean, - margin: task.result.throughput.rme, - runs: task.result.throughput.samplesCount, - deprecated: deprecatedTests.has(task.name) - }) - } - } - - // Keep this guard even with `throws: true`: an aborted or otherwise incomplete - // task has no trustworthy throughput and must not become an empty, successful - // benchmark section. - const incompleteTasks = bench.tasks.filter(task => task.result?.state !== 'completed') - if (incompleteTasks.length > 0) { - const details = incompleteTasks - .map(task => `${task.name} (${task.result?.state ?? 'missing result'})`) - .join(', ') - throw new Error(`Benchmark tasks did not complete: ${details}`) - } - - // Find and display fastest - if (!options.quiet && sectionResults.length > 0) { - const fastest = sectionResults.reduce((prev, current) => - prev.opsPerSec > current.opsPerSec ? prev : current - ) - console.log(`Fastest is ${fastest.name}\n\n`) - } - - return { - benchmarkName: sectionName, - results: sectionResults - } -} - -/** - * Get list of available groups - */ -export function getAvailableGroups(): string[] { - return Object.keys(groups) -} - -/** - * Get group description by name - */ -export function getGroupDescription(groupName: string): string | undefined { - const group = getGroup(groupName) - return group?.description -} diff --git a/benchmark/solvers/ExternalDanceSolver.ts b/benchmark/solvers/ExternalDanceSolver.ts deleted file mode 100644 index cf772e1..0000000 --- a/benchmark/solvers/ExternalDanceSolver.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * External dance solver implementation - * Uses the dance library for Dancing Links solving - */ - -/// - -import { Solver, StandardConstraints } from '../types.js' -import { convertToBinary, validateSecondarySupport } from '../utils/converters.js' -import * as dance from 'dance' - -/** - * External solver using dance library - * Does not support secondary constraints - */ -export class DanceSolver extends Solver { - static readonly name = 'dance' - /** - * Prepare constraints in binary matrix format for dance - * dance expects plain binary arrays (0-indexed) - */ - prepare(constraints: StandardConstraints): number[][] { - // Validate that dance can handle these constraints - validateSecondarySupport(constraints, 'external-dance') - - // Convert to binary matrix format expected by dance - return convertToBinary(constraints) - } - - /** - * Find all solutions using dance - * dance.solve with empty options finds all solutions - */ - solveAll(plainRows: number[][]): unknown { - return dance.solve(plainRows, {}) - } - - /** - * Find one solution using dance - * Uses maxSolutions option to limit results - */ - solveOne(plainRows: number[][]): unknown { - return dance.solve(plainRows, { maxSolutions: 1 }) - } - - /** - * Find a specific number of solutions using dance - * Uses maxSolutions option to limit results - */ - solveCount(plainRows: number[][], count: number): unknown { - return dance.solve(plainRows, { maxSolutions: count }) - } -} diff --git a/benchmark/solvers/ExternalDancingLinksAlgorithmSolver.ts b/benchmark/solvers/ExternalDancingLinksAlgorithmSolver.ts deleted file mode 100644 index 320f5e4..0000000 --- a/benchmark/solvers/ExternalDancingLinksAlgorithmSolver.ts +++ /dev/null @@ -1,60 +0,0 @@ -/** - * External dancing-links-algorithm solver implementation - * Uses the dancing-links-algorithm library for Dancing Links solving - */ - -/// - -import { Solver, StandardConstraints } from '../types.js' -import { convertToBinary, validateSecondarySupport } from '../utils/converters.js' -import * as dancingLinksAlgorithm from 'dancing-links-algorithm' - -/** - * External solver using dancing-links-algorithm library - * Does not support secondary constraints - * Note: This library only supports finding all solutions (no count limiting) - */ -export class DancingLinksAlgorithmSolver extends Solver { - static readonly name = 'dancing-links-algorithm' - /** - * Prepare constraints in binary matrix format for dancing-links-algorithm - * dancing-links-algorithm expects plain binary arrays (0-indexed) - */ - prepare(constraints: StandardConstraints): number[][] { - // Validate that dancing-links-algorithm can handle these constraints - validateSecondarySupport(constraints, 'external-dancing-links-algorithm') - - // Convert to binary matrix format expected by dancing-links-algorithm - return convertToBinary(constraints) - } - - /** - * Find all solutions using dancing-links-algorithm - */ - solveAll(plainRows: number[][]): unknown { - return dancingLinksAlgorithm.solve(plainRows) - } - - /** - * Find one solution using dancing-links-algorithm - * Note: This library doesn't support limiting solutions, so we get all and take first - * This makes it less efficient for single-solution benchmarks - */ - solveOne(plainRows: number[][]): unknown { - const allSolutions = dancingLinksAlgorithm.solve(plainRows) - return Array.isArray(allSolutions) && allSolutions.length > 0 ? [allSolutions[0]] : allSolutions - } - - /** - * Find a specific number of solutions using dancing-links-algorithm - * Note: This library doesn't support limiting solutions, so we get all and slice - * This makes it less efficient for limited-count benchmarks - */ - solveCount(plainRows: number[][], count: number): unknown { - const allSolutions = dancingLinksAlgorithm.solve(plainRows) - if (Array.isArray(allSolutions)) { - return allSolutions.slice(0, count) - } - return allSolutions - } -} diff --git a/benchmark/solvers/ExternalDlxlibSolver.ts b/benchmark/solvers/ExternalDlxlibSolver.ts deleted file mode 100644 index 7418c5c..0000000 --- a/benchmark/solvers/ExternalDlxlibSolver.ts +++ /dev/null @@ -1,52 +0,0 @@ -/** - * External dlxlib solver implementation - * Uses the dlxlib library for Dancing Links solving - */ - -/// - -import { Solver, StandardConstraints } from '../types.js' -import { convertToBinary, validateSecondarySupport } from '../utils/converters.js' -import * as dlxlib from 'dlxlib' - -/** - * External solver using dlxlib library - * Does not support secondary constraints - */ -export class DlxlibSolver extends Solver { - static readonly name = 'dlxlib' - /** - * Prepare constraints in binary matrix format for dlxlib - * dlxlib expects plain binary arrays (0-indexed) - */ - prepare(constraints: StandardConstraints): number[][] { - // Validate that dlxlib can handle these constraints - validateSecondarySupport(constraints, 'external-dlxlib') - - // Convert to binary matrix format expected by dlxlib - return convertToBinary(constraints) - } - - /** - * Find all solutions using dlxlib - */ - solveAll(plainRows: number[][]): unknown { - return dlxlib.solve(plainRows) - } - - /** - * Find one solution using dlxlib - * Uses the fourth parameter to limit solutions - */ - solveOne(plainRows: number[][]): unknown { - return dlxlib.solve(plainRows, null, null, 1) - } - - /** - * Find a specific number of solutions using dlxlib - * Uses the fourth parameter to limit solutions - */ - solveCount(plainRows: number[][], count: number): unknown { - return dlxlib.solve(plainRows, null, null, count) - } -} diff --git a/benchmark/solvers/InternalBinarySolver.ts b/benchmark/solvers/InternalBinarySolver.ts deleted file mode 100644 index f89b268..0000000 --- a/benchmark/solvers/InternalBinarySolver.ts +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Internal binary constraint solver implementation - * Uses the library's binary constraint format - */ - -import { Solver, StandardConstraints } from '../types.js' -import { convertToBinary } from '../utils/converters.js' -import { DancingLinks } from '../../index.js' - -/** - * Format for binary constraints batch operations - */ -interface BinaryConstraintsBatch { - data: unknown - columnValues: (0 | 1)[] -} - -/** - * Prepared constraint data including column count - */ -interface PreparedBinaryConstraints { - numColumns: number - constraints: BinaryConstraintsBatch[] -} - -/** - * Internal solver using binary constraint format - */ -export class DancingLinksBinarySolver extends Solver { - static readonly name = 'dancing-links (binary)' - - /** - * Prepare constraints in binary format for batch operations - * All formatting happens here, outside of benchmark timing - */ - prepare(constraints: StandardConstraints): PreparedBinaryConstraints { - const binaryMatrix = convertToBinary(constraints) - const numColumns = binaryMatrix.length > 0 ? binaryMatrix[0].length : 0 - - // Convert to binary constraint batch format expected by the library - const binaryConstraints = binaryMatrix.map((row, index) => ({ - data: index, // Use row index as data for identification - columnValues: row as (0 | 1)[] - })) - - return { - numColumns, - constraints: binaryConstraints - } - } - - /** - * Find all solutions using binary constraints - */ - solveAll(prepared: PreparedBinaryConstraints): unknown { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: prepared.numColumns }) - solver.addBinaryConstraints(prepared.constraints) - return solver.findAll() - } - - /** - * Find one solution using binary constraints - */ - solveOne(prepared: PreparedBinaryConstraints): unknown { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: prepared.numColumns }) - solver.addBinaryConstraints(prepared.constraints) - return solver.findOne() - } - - /** - * Find a specific number of solutions using binary constraints - */ - solveCount(prepared: PreparedBinaryConstraints, count: number): unknown { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: prepared.numColumns }) - solver.addBinaryConstraints(prepared.constraints) - return solver.find(count) - } -} diff --git a/benchmark/solvers/InternalGeneratorSolver.ts b/benchmark/solvers/InternalGeneratorSolver.ts deleted file mode 100644 index 7e8a3c0..0000000 --- a/benchmark/solvers/InternalGeneratorSolver.ts +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Internal generator-based solver implementation - * Uses the library's generator interface for iterative solution finding - */ - -import { Solver, StandardConstraints } from '../types.js' -import { flattenConstraints } from '../utils/converters.js' -import { DancingLinks } from '../../index.js' - -/** - * Format for sparse constraints batch operations - */ -interface SparseConstraintsBatch { - data: unknown - columnIndices: number[] -} - -/** - * Prepared constraint data including column count - */ -interface PreparedGeneratorConstraints { - numColumns: number - constraints: SparseConstraintsBatch[] -} - -/** - * Internal solver using generator interface - * Provides iterative solution finding with memory efficiency - */ -export class DancingLinksGeneratorSolver extends Solver { - static readonly name = 'dancing-links generator' - - /** - * Prepare constraints in sparse format for generator operations - * All formatting happens here, outside of benchmark timing - */ - prepare(constraints: StandardConstraints): PreparedGeneratorConstraints { - const flattened = flattenConstraints(constraints) - - // Convert to sparse constraint batch format expected by the library - const sparseConstraints = flattened.rows.map((row, index) => ({ - data: index, // Use row index as data for identification - columnIndices: row - })) - - return { - numColumns: flattened.numColumns, - constraints: sparseConstraints - } - } - - /** - * Find all solutions using generator interface - * Collects all solutions by iterating through the generator - */ - solveAll(prepared: PreparedGeneratorConstraints): unknown { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: prepared.numColumns }) - solver.addSparseConstraints(prepared.constraints) - - const solutions = [] - for (const solution of solver.createGenerator()) { - solutions.push(solution) - } - return solutions - } - - /** - * Find one solution using generator interface - * Returns the first solution from the generator - */ - solveOne(prepared: PreparedGeneratorConstraints): unknown { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: prepared.numColumns }) - solver.addSparseConstraints(prepared.constraints) - - const generator = solver.createGenerator() - const result = generator.next() - return result.done ? null : result.value - } - - /** - * Find a specific number of solutions using generator interface - * Iterates through generator until count is reached or exhausted - */ - solveCount(prepared: PreparedGeneratorConstraints, count: number): unknown { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: prepared.numColumns }) - solver.addSparseConstraints(prepared.constraints) - - const solutions = [] - for (const solution of solver.createGenerator()) { - solutions.push(solution) - if (solutions.length >= count) break - } - return solutions - } -} diff --git a/benchmark/solvers/InternalIndexWidthSolver.ts b/benchmark/solvers/InternalIndexWidthSolver.ts deleted file mode 100644 index 947bf12..0000000 --- a/benchmark/solvers/InternalIndexWidthSolver.ts +++ /dev/null @@ -1,176 +0,0 @@ -/** - * Honest end-to-end benchmarks for adaptive 16/32-bit storage. - * - * Prepared input rows live outside timing like the other sparse benchmarks, but - * every measured operation creates a public solver, ingests all constraints, - * builds fresh typed-array stores, and exhaustively searches them. No compiled - * topology or result is reused between operations. - */ - -import { DancingLinks } from '../../index.js' -import { ProblemBuilder } from '../../lib/core/problem-builder.js' -import type { ConstraintRow, SparseConstraintBatch } from '../../lib/types/interfaces.js' -import { - generateIndexWidthConstraints, - INDEX_WIDTH_PRIMARY_COLUMNS -} from '../problems/index-width/definition.js' -import { Solver, StandardConstraints } from '../types.js' - -interface PreparedIndexWidth { - readonly nodeCount: number - readonly constraints: SparseConstraintBatch - readonly rows: ConstraintRow[] -} - -interface PreparedMixedWidths { - readonly uint16: PreparedIndexWidth - readonly int32: PreparedIndexWidth -} - -function prepareRows(constraints: StandardConstraints): PreparedIndexWidth { - const sparse = constraints.primaryConstraints.map((columnIndices, data) => ({ - data, - columnIndices - })) - const rows = sparse.map(({ data, columnIndices }) => ({ - coveredColumns: columnIndices, - data - })) - let rowNodes = 0 - for (const row of rows) { - rowNodes += row.coveredColumns.length - } - const prepared = { - nodeCount: INDEX_WIDTH_PRIMARY_COLUMNS + 1 + rowNodes, - constraints: sparse, - rows - } - verifyWidthAndSearch(prepared) - return prepared -} - -/** Prove once, outside timing, that the intended fallback and hot search path run. */ -function verifyWidthAndSearch(prepared: PreparedIndexWidth): void { - if (prepared.nodeCount !== 0xffff && prepared.nodeCount !== 0x10000) { - throw new Error(`Unexpected index-width matrix size: ${prepared.nodeCount}`) - } - - const context = ProblemBuilder.buildContext({ - numPrimary: INDEX_WIDTH_PRIMARY_COLUMNS, - numSecondary: 0, - rows: prepared.rows - }) - const ExpectedNodeIndexArray = prepared.nodeCount === 0xffff ? Uint16Array : Int32Array - const views: Array< - [ - Int32Array | Uint16Array, - typeof Int32Array | typeof Uint16Array - ] - > = [ - [context.nodes.up, ExpectedNodeIndexArray], - [context.nodes.down, ExpectedNodeIndexArray], - [context.nodes.col, Uint16Array], - [context.nodes.rowIndex, Uint16Array], - [context.nodes.rowStart, ExpectedNodeIndexArray], - [context.columns.len, ExpectedNodeIndexArray], - [context.columns.prev, ExpectedNodeIndexArray], - [context.columns.next, ExpectedNodeIndexArray] - ] - for (const [view, ExpectedArray] of views) { - if (!(view instanceof ExpectedArray)) { - throw new Error(`Matrix ${prepared.nodeCount} selected the wrong integer storage width`) - } - } - - // Root occupies index 0, so primary column 1 has header index 2. It contains - // only the terminal row, whose forced node was deliberately written last. - const highestNode = prepared.nodeCount - 1 - if (context.nodes.down[2] !== highestNode) { - throw new Error(`Search will not select the expected high node ${highestNode}`) - } - - // Exercise the same public batch-ingestion/build/search path used by the timed - // operation once outside timing. This prevents a handler regression from - // producing a fast but incorrect benchmark while the direct builder check - // above still happens to pass. - const solutions = solveFreshAll(prepared) - const terminalRow = prepared.rows.length - 1 - if ( - solutions.length !== 1 || - solutions[0]?.length !== 1 || - solutions[0][0]?.index !== terminalRow - ) { - throw new Error( - `Index-width matrix ${prepared.nodeCount} did not produce its terminal solution` - ) - } -} - -function solveFreshAll(prepared: PreparedIndexWidth) { - const solver = new DancingLinks().createSolver({ - columns: INDEX_WIDTH_PRIMARY_COLUMNS - }) - solver.addSparseConstraints(prepared.constraints) - return solver.findAll() -} - -function solveFreshOne(prepared: PreparedIndexWidth): unknown { - const solver = new DancingLinks().createSolver({ - columns: INDEX_WIDTH_PRIMARY_COLUMNS - }) - solver.addSparseConstraints(prepared.constraints) - return solver.findOne() -} - -function solveFreshCount(prepared: PreparedIndexWidth, count: number): unknown { - const solver = new DancingLinks().createSolver({ - columns: INDEX_WIDTH_PRIMARY_COLUMNS - }) - solver.addSparseConstraints(prepared.constraints) - return solver.find(count) -} - -export class IndexWidthFreshSolver extends Solver { - static readonly name = 'dancing-links (fresh build + exhaustive search)' - - prepare(constraints: StandardConstraints): PreparedIndexWidth { - return prepareRows(constraints) - } - - solveAll(prepared: PreparedIndexWidth): unknown { - return solveFreshAll(prepared) - } - - solveOne(prepared: PreparedIndexWidth): unknown { - return solveFreshOne(prepared) - } - - solveCount(prepared: PreparedIndexWidth, count: number): unknown { - return solveFreshCount(prepared, count) - } -} - -export class IndexWidthMixedSolver extends Solver { - static readonly name = 'dancing-links (fresh Uint16 → Int32 pair)' - - prepare(int32Constraints: StandardConstraints): PreparedMixedWidths { - // The case supplies the 32-bit half. Generate and verify the adjacent 16-bit - // half once so every timed pair alternates the shared kernels across widths. - return { - uint16: prepareRows(generateIndexWidthConstraints({ nodeCount: 0xffff })), - int32: prepareRows(int32Constraints) - } - } - - solveAll(prepared: PreparedMixedWidths): unknown { - return [solveFreshAll(prepared.uint16), solveFreshAll(prepared.int32)] - } - - solveOne(prepared: PreparedMixedWidths): unknown { - return [solveFreshOne(prepared.uint16), solveFreshOne(prepared.int32)] - } - - solveCount(prepared: PreparedMixedWidths, count: number): unknown { - return [solveFreshCount(prepared.uint16, count), solveFreshCount(prepared.int32, count)] - } -} diff --git a/benchmark/solvers/InternalSparseSolver.ts b/benchmark/solvers/InternalSparseSolver.ts deleted file mode 100644 index f276cce..0000000 --- a/benchmark/solvers/InternalSparseSolver.ts +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Internal sparse constraint solver implementation - * Uses the library's sparse constraint format for optimal performance - */ - -import { Solver, StandardConstraints } from '../types.js' -import { flattenConstraints } from '../utils/converters.js' -import { DancingLinks } from '../../index.js' - -/** - * Format for sparse constraints batch operations - */ -interface SparseConstraintsBatch { - data: unknown - columnIndices: number[] -} - -/** - * Prepared constraint data including column count - */ -interface PreparedSparseConstraints { - numColumns: number - constraints: SparseConstraintsBatch[] -} - -/** - * Internal solver using sparse constraint format - * This is typically the fastest interface for our library - */ -export class DancingLinksSparseSolver extends Solver { - static readonly name = 'dancing-links (sparse)' - - /** - * Prepare constraints in sparse format for batch operations - * All formatting happens here, outside of benchmark timing - */ - prepare(constraints: StandardConstraints): PreparedSparseConstraints { - const flattened = flattenConstraints(constraints) - - // Convert to sparse constraint batch format expected by the library - const sparseConstraints = flattened.rows.map((row, index) => ({ - data: index, // Use row index as data for identification - columnIndices: row - })) - - return { - numColumns: flattened.numColumns, - constraints: sparseConstraints - } - } - - /** - * Find all solutions using sparse constraints - */ - solveAll(prepared: PreparedSparseConstraints): unknown { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: prepared.numColumns }) - solver.addSparseConstraints(prepared.constraints) - return solver.findAll() - } - - /** - * Find one solution using sparse constraints - */ - solveOne(prepared: PreparedSparseConstraints): unknown { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: prepared.numColumns }) - solver.addSparseConstraints(prepared.constraints) - return solver.findOne() - } - - /** - * Find a specific number of solutions using sparse constraints - */ - solveCount(prepared: PreparedSparseConstraints, count: number): unknown { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: prepared.numColumns }) - solver.addSparseConstraints(prepared.constraints) - return solver.find(count) - } -} diff --git a/benchmark/solvers/InternalTemplateSolver.ts b/benchmark/solvers/InternalTemplateSolver.ts deleted file mode 100644 index 51394f1..0000000 --- a/benchmark/solvers/InternalTemplateSolver.ts +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Internal template-based solver implementation - * Pre-compiles constraints into a reusable template for maximum performance - */ - -import { Solver, StandardConstraints } from '../types.js' -import { flattenConstraints } from '../utils/converters.js' -import { DancingLinks, SolverTemplate, ProblemSolver } from '../../index.js' - -/** - * Template instance from the Dancing Links library - */ -type DlxSolverTemplate = SolverTemplate - -/** - * Solver instance from a template - */ -type DlxTemplateSolver = ProblemSolver - -/** - * Internal solver using template-based constraint pre-compilation - * Fastest for repeated solving of the same constraint set - */ -export class DancingLinksTemplateSolver extends Solver { - static readonly name = 'dancing-links template' - /** - * Setup template once per case with pre-compiled constraints - * This is the expensive operation done outside of benchmark timing - */ - setup(constraints: StandardConstraints): void { - const flattened = flattenConstraints(constraints) - const dlx = new DancingLinks() - const template = dlx.createSolverTemplate({ columns: flattened.numColumns }) - - // Convert to sparse constraint batch format for template - const sparseConstraints = flattened.rows.map((row, index) => ({ - data: index, - columnIndices: row - })) - - template.addSparseConstraints(sparseConstraints) - this.setupResult = template - } - - /** - * Create a new solver instance from the pre-compiled template - * This is very fast since constraints are already compiled - */ - prepare(_constraints: StandardConstraints): DlxTemplateSolver { - if (!this.setupResult) { - throw new Error('Template not set up - setup() must be called first') - } - return this.setupResult.createSolver() - } - - /** - * Find all solutions using template-based solver - */ - solveAll(solver: DlxTemplateSolver): unknown { - return solver.findAll() - } - - /** - * Find one solution using template-based solver - */ - solveOne(solver: DlxTemplateSolver): unknown { - return solver.findOne() - } - - /** - * Find a specific number of solutions using template-based solver - */ - solveCount(solver: DlxTemplateSolver, count: number): unknown { - return solver.find(count) - } -} diff --git a/benchmark/types.d.ts b/benchmark/types.d.ts deleted file mode 100644 index 24a7814..0000000 --- a/benchmark/types.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -declare module 'dlxlib' { - export function solve( - matrix: number[][], - solution?: any, - options?: any, - maxSolutions?: number - ): any[] -} - -declare module 'dance' { - export function solve(matrix: number[][], options?: { maxSolutions?: number }): any[] -} - -declare module 'dancing-links-algorithm' { - export function solve(matrix: number[][]): any[] -} diff --git a/benchmark/types.ts b/benchmark/types.ts deleted file mode 100644 index 1e1a9d1..0000000 --- a/benchmark/types.ts +++ /dev/null @@ -1,158 +0,0 @@ -/** - * Core type definitions for the modular benchmark system - */ - -/** - * Standardized constraint format that all problems output - */ -export interface StandardConstraints { - primaryConstraints: number[][] // Must be covered exactly once - secondaryConstraints?: number[][] // Can be covered at most once (optional) - columnNames?: string[] // Optional for debugging/display -} - -/** - * Base class for all solver implementations - */ -export abstract class Solver { - static readonly name: string - protected setupResult?: TSetup - - /** - * Optional setup once per case (e.g., template creation) - * Called outside of benchmark timing - */ - setup?(_constraints: StandardConstraints): void { - // Default: no setup needed - } - - /** - * Prepare constraints for this solver's format - * Called once per case, outside of benchmark timing - */ - abstract prepare(constraints: StandardConstraints): TPrepared - - /** - * Find all solutions - */ - abstract solveAll(prepared: TPrepared): unknown - - /** - * Find one solution - */ - abstract solveOne(prepared: TPrepared): unknown - - /** - * Find a specific number of solutions - */ - abstract solveCount(prepared: TPrepared, count: number): unknown -} - -/** - * Problem parameter types - */ -export interface SudokuParams { - puzzle: string -} - -export interface PentominoParams { - // Currently no parameters needed -} - -export interface NQueensParams { - n: number -} - -export interface IndexWidthParams { - nodeCount: 65_535 | 65_536 -} - -/** - * Problem type discriminated union - */ -export type ProblemType = 'sudoku' | 'pentomino' | 'n-queens' | 'index-width' - -/** - * Problem parameters mapped to their types - */ -export type ProblemParameters = T extends 'sudoku' - ? SudokuParams - : T extends 'pentomino' - ? PentominoParams - : T extends 'n-queens' - ? NQueensParams - : T extends 'index-width' - ? IndexWidthParams - : never - -/** - * Benchmark case definition with proper type inference - */ -export interface BenchmarkCase { - id: string - name: string - problemType: T - parameters: ProblemParameters - executeStrategy>( - solver: TSolver, - prepared: TPrepared - ): unknown -} - -/** - * Benchmark group definition - */ -export interface BenchmarkGroup { - name: string - description: string - caseIds: string[] - solverNames: string[] -} - -/** - * Benchmark execution options - */ -export interface BenchmarkOptions { - includeExternal: boolean - jsonOutput: boolean - jsonFile?: string - quiet: boolean -} - -/** - * Individual benchmark result - */ -export interface BenchmarkResult { - name: string - opsPerSec: number - margin: number - runs: number - deprecated?: boolean -} - -/** - * Benchmark section (group of related tests) - */ -export interface BenchmarkSection { - benchmarkName: string - results: BenchmarkResult[] -} - -/** - * Problem definition function type - */ -export type ProblemDefinition = ( - params: ProblemParameters -) => StandardConstraints - -/** - * Solver registry type - */ -export type SolverRegistry = Record - -/** - * Problem registry type with proper typing - */ -export type ProblemRegistry = { - [K in ProblemType]: ProblemDefinition -} diff --git a/benchmark/utils/converters.ts b/benchmark/utils/converters.ts deleted file mode 100644 index d8ff8f8..0000000 --- a/benchmark/utils/converters.ts +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Constraint format conversion utilities - */ - -import { StandardConstraints } from '../types.js' - -/** - * Result of flattening constraints with column assignments - */ -export interface FlattenedConstraints { - numColumns: number - rows: number[][] - primaryColumns: number -} - -/** - * Flatten primary and secondary constraints into a single constraint matrix - * with proper column number assignments - */ -export function flattenConstraints(constraints: StandardConstraints): FlattenedConstraints { - const primaryRows = constraints.primaryConstraints - const secondaryRows = constraints.secondaryConstraints || [] - - // Calculate number of primary columns - const primaryColumns = primaryRows.length > 0 ? Math.max(0, ...primaryRows.flat()) + 1 : 0 - - // Secondary constraints get column numbers starting after primary columns - const secondaryColumnOffset = primaryColumns - const offsetSecondaryRows = secondaryRows.map(row => row.map(col => col + secondaryColumnOffset)) - - // Calculate total number of columns - const secondaryColumns = secondaryRows.length > 0 ? Math.max(0, ...secondaryRows.flat()) + 1 : 0 - const totalColumns = primaryColumns + secondaryColumns - - // Combine all rows - const allRows = [...primaryRows, ...offsetSecondaryRows] - - return { - numColumns: totalColumns, - rows: allRows, - primaryColumns - } -} - -/** - * Convert StandardConstraints to binary matrix format - * Used by external libraries that expect binary constraint matrices - */ -export function convertToBinary(constraints: StandardConstraints): number[][] { - const flattened = flattenConstraints(constraints) - return convertSparseToBinary(flattened.rows, flattened.numColumns) -} - -/** - * Convert sparse constraint rows to binary matrix format - * Helper function for binary conversion - */ -function convertSparseToBinary(sparseRows: number[][], numColumns: number): number[][] { - const matrix = new Array(sparseRows.length) - for (let i = 0; i < sparseRows.length; i++) { - matrix[i] = new Array(numColumns).fill(0) - for (const col of sparseRows[i]) { - matrix[i][col] = 1 - } - } - return matrix -} - -/** - * Validate that a solver supports secondary constraints - * Throws an error if secondary constraints are present but not supported - */ -export function validateSecondarySupport( - constraints: StandardConstraints, - solverName: string -): void { - const hasSecondary = - constraints.secondaryConstraints && constraints.secondaryConstraints.length > 0 - - if (hasSecondary && !SECONDARY_CONSTRAINT_SOLVERS.has(solverName)) { - throw new Error(`Solver ${solverName} does not support secondary constraints`) - } -} - -/** - * Set of solver names that support secondary constraints - * Only our Dancing Links solvers currently support this feature - */ -const SECONDARY_CONSTRAINT_SOLVERS = new Set([ - 'dancing-links (binary)', - 'dancing-links (sparse)', - 'dancing-links template', - 'dancing-links generator' -]) diff --git a/eslint.config.js b/eslint.config.js index 4867355..e1f404c 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -5,26 +5,7 @@ import tsparser from '@typescript-eslint/parser' export default [ js.configs.recommended, { - files: ['**/*.ts'], - languageOptions: { - parser: tsparser, - parserOptions: { - ecmaVersion: 2022, - sourceType: 'module', - project: './tsconfig.json' - } - }, - plugins: { - '@typescript-eslint': tseslint - }, - rules: { - ...tseslint.configs.recommended.rules, - '@typescript-eslint/no-unused-vars': 'error', - '@typescript-eslint/no-explicit-any': 'off' // Allow any for generic library - } - }, - { - files: ['test/**/*.ts'], + files: ['src/**/*.ts', 'test/game/**/*.ts', 'vite.config.ts'], languageOptions: { parser: tsparser, parserOptions: { @@ -33,42 +14,15 @@ export default [ project: './tsconfig.json' }, globals: { + document: 'readonly', + window: 'readonly', + performance: 'readonly', + requestAnimationFrame: 'readonly', + cancelAnimationFrame: 'readonly', + localStorage: 'readonly', + console: 'readonly', describe: 'readonly', - it: 'readonly', - before: 'readonly', - after: 'readonly', - beforeEach: 'readonly', - afterEach: 'readonly' - } - }, - plugins: { - '@typescript-eslint': tseslint - }, - rules: { - ...tseslint.configs.recommended.rules, - '@typescript-eslint/no-unused-vars': 'error', - '@typescript-eslint/no-explicit-any': 'off' // Allow any for generic library - } - }, - { - files: ['**/*.js'], - languageOptions: { - ecmaVersion: 2022, - sourceType: 'module' - } - }, - { - files: ['scripts/**/*.ts'], - languageOptions: { - parser: tsparser, - parserOptions: { - ecmaVersion: 2022, - sourceType: 'module', - project: './tsconfig.dev.json' - }, - globals: { - process: 'readonly', - console: 'readonly' + it: 'readonly' } }, plugins: { @@ -76,11 +30,10 @@ export default [ }, rules: { ...tseslint.configs.recommended.rules, - '@typescript-eslint/no-unused-vars': 'error', - '@typescript-eslint/no-explicit-any': 'off' // Allow any for generic library + '@typescript-eslint/no-unused-vars': 'error' } }, { - ignores: ['built/**', 'node_modules/**', 'benchmark/**', '*.mjs'] + ignores: ['built/**', 'dist/**', 'node_modules/**', 'benchmark/**', 'lib/**', 'test/unit/**'] } ] diff --git a/index.html b/index.html new file mode 100644 index 0000000..2a535ee --- /dev/null +++ b/index.html @@ -0,0 +1,97 @@ + + + + + + + Cover Story · A real-time exact-cover heist + + +
+
+
+ OPERATIVE CONSOLE / 03:17 +

COVER STORY

+
+
+ + LIVE EXACT-COVER ENGINE +
+
+ +
+ + +
+

MISSION

+ Reach the archive +
+ + Find the cyan vault and extract the dossier +
+
+ +
+
+ — + PLAUSIBLE FUTURES +
+
+ SOLVE — + ROWS — + BEAT 00 +
+
+ +
+
EXPOSURE0%
+
+
+ +
+ CLICK ECHO 3 + E JAM 2 + IDENTITIES ● ● ● +
+ +
+ +
+
+

THE HEIST EXISTS IN EVERY PLAUSIBLE FUTURE

+

Rewrite the patrol.

+

+ The ghost paths are every guard move that still belongs to a valid joint schedule. + Manipulate the schedule, slip through the uncertainty, and steal the dossier. +

+
+
+ 01MOVE WASD / ARROWS +
+
+ 02THROW ECHO Click a nearby patrol node +
+
+ 03JAM DOOR Press E beside a magenta gate +
+
+ 04INTERACT Space at the vault and exit +
+
+ +

ESC pauses ¡ R restarts ¡ headphones recommended

+
+
+
+ +
+ GHOST LINES = WEIGHTED MOVES ACROSS THE CURRENT SOLUTION SAMPLE + POWERED BY dancing-links@4.3.9 FROM NPM +
+
+ + + diff --git a/index.ts b/index.ts deleted file mode 100644 index d552401..0000000 --- a/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// High-performance Dancing Links API -export { - DancingLinks, - ProblemSolver, - SolverTemplate, - BinaryConstraint, - SparseConstraint, - SimpleConstraint, - ComplexConstraint, - ConstraintRow, - Result, - BinaryNumber -} from './lib/index.js' diff --git a/lib/constraints/handlers/complex.ts b/lib/constraints/handlers/complex.ts deleted file mode 100644 index 0f87f11..0000000 --- a/lib/constraints/handlers/complex.ts +++ /dev/null @@ -1,163 +0,0 @@ -/** - * Complex constraint handler for primary + secondary columns mode - * - * Zero branching - columnIndices is always { primary: number[], secondary: number[] } - * columnValues is always { primaryRow: BinaryNumber[], secondaryRow: BinaryNumber[] } - */ - -import { - ConstraintRow, - BinaryNumber, - ComplexSolverConfig, - ConstraintHandler, - SparseConstraintBatch, - BinaryConstraintBatch -} from '../../types/interfaces.js' - -export class ComplexConstraintHandler implements ConstraintHandler { - readonly mode = 'complex' as const - private constraints: ConstraintRow[] = [] - private validationEnabled = false - private numPrimary: number - private numSecondary: number - - constructor(private config: ComplexSolverConfig) { - this.numPrimary = config.primaryColumns - this.numSecondary = config.secondaryColumns - } - - validateConstraints(): this { - this.validationEnabled = true - return this - } - - addSparseConstraint(data: T, columnIndices: { primary: number[]; secondary: number[] }): this { - return this.addSparseConstraints([{ data, columnIndices }]) - } - - addSparseConstraints(constraints: SparseConstraintBatch): this { - for (let i = 0; i < constraints.length; i++) { - const { data, columnIndices } = constraints[i] - const { primary, secondary } = columnIndices - - if (this.validationEnabled) { - for (let j = 0; j < primary.length; j++) { - const col = primary[j] - if (col < 0 || col >= this.numPrimary) { - throw new Error( - `Primary column index ${col} exceeds primaryColumns limit of ${this.numPrimary}` - ) - } - } - } - - const coveredColumns: number[] = ([] as number[]).concat(primary) - for (let j = 0; j < secondary.length; j++) { - const col = secondary[j] - if (this.validationEnabled) { - if (col < 0 || col >= this.numSecondary) { - throw new Error( - `Secondary column index ${col} exceeds secondaryColumns limit of ${this.numSecondary}` - ) - } - } - coveredColumns.push(col + this.numPrimary) - } - - this.constraints.push({ coveredColumns, data }) - } - return this - } - - addBinaryConstraint( - data: T, - columnValues: { primaryRow: BinaryNumber[]; secondaryRow: BinaryNumber[] } - ): this { - return this.addBinaryConstraints([{ data, columnValues }]) - } - - addBinaryConstraints(constraints: BinaryConstraintBatch): this { - for (let i = 0; i < constraints.length; i++) { - const { data, columnValues } = constraints[i] - const { primaryRow, secondaryRow } = columnValues - - if (this.validationEnabled) { - if (primaryRow.length !== this.numPrimary) { - throw new Error( - `Primary row length ${primaryRow.length} does not match primaryColumns ${this.numPrimary}` - ) - } - if (secondaryRow.length !== this.numSecondary) { - throw new Error( - `Secondary row length ${secondaryRow.length} does not match secondaryColumns ${this.numSecondary}` - ) - } - } - - const coveredColumns: number[] = [] - - for (let j = 0; j < primaryRow.length; j++) { - if (primaryRow[j] === 1) { - coveredColumns.push(j) - } - } - - for (let j = 0; j < secondaryRow.length; j++) { - if (secondaryRow[j] === 1) { - coveredColumns.push(j + primaryRow.length) - } - } - - this.constraints.push({ coveredColumns, data }) - } - return this - } - - addRow(row: ConstraintRow): this { - this.constraints.push(row) - return this - } - - addRows(rows: ConstraintRow[]): this { - this.constraints.push(...rows) - return this - } - - /** - * Share the compiled immutable row snapshot with a new template handler in - * O(1), while ordinary constructors retain their original monomorphic shape. - * @internal - */ - shareConstraints(constraints: ConstraintRow[]): void { - this.constraints = constraints - } - - /** - * Copy the compiled template's shared row-reference table on first mutation. - * Read-only template solvers avoid that O(number of rows) work entirely, and - * both fresh and template solvers retain this one handler class and hot shape. - */ - detachConstraints(): void { - this.constraints = this.constraints.slice() - } - - getConstraints(): ConstraintRow[] { - return this.constraints - } - - getNumPrimary(): number { - return this.numPrimary - } - - getNumSecondary(): number { - return this.numSecondary - } - - getConfig(): ComplexSolverConfig { - return this.config - } - - isValidationEnabled(): boolean { - return this.validationEnabled - } -} diff --git a/lib/constraints/handlers/simple.ts b/lib/constraints/handlers/simple.ts deleted file mode 100644 index 65892ea..0000000 --- a/lib/constraints/handlers/simple.ts +++ /dev/null @@ -1,145 +0,0 @@ -/** - * Simple constraint handler for columns-only mode - * - * Zero branching - columnIndices is always number[], columnValues is always BinaryNumber[] - */ - -import { - ConstraintRow, - BinaryNumber, - SimpleSolverConfig, - ConstraintHandler, - SparseConstraintBatch, - BinaryConstraintBatch -} from '../../types/interfaces.js' - -export class SimpleConstraintHandler implements ConstraintHandler { - readonly mode = 'simple' as const - private constraints: ConstraintRow[] = [] - private validationEnabled = false - private numColumns: number - - constructor(private config: SimpleSolverConfig) { - this.numColumns = config.columns - } - - validateConstraints(): this { - this.validationEnabled = true - return this - } - - addSparseConstraint(data: T, columnIndices: number[]): this { - return this.addSparseConstraints([{ data, columnIndices }]) - } - - addSparseConstraints(constraints: SparseConstraintBatch): this { - const target = this.constraints - - for (let i = 0; i < constraints.length; i++) { - const { data, columnIndices } = constraints[i] - - if (this.validationEnabled) { - for (let j = 0; j < columnIndices.length; j++) { - const col = columnIndices[j] - if (col < 0 || col >= this.numColumns) { - throw new Error(`Column index ${col} exceeds columns limit of ${this.numColumns}`) - } - } - - // Validation is the behavioral fallback: commit only after this row is - // valid, using the original live-tail append so a later failure keeps - // the already accepted prefix exactly as before. - target.push({ coveredColumns: columnIndices, data }) - continue - } - - // A direct store at the live tail avoids Array#push's generic method call - // while preserving reentrant getter behavior: nested appends advance - // target.length before this row is committed. Growing one slot at a time - // also retains V8's PACKED elements kind; pre-growing length would make - // the shared builder consume a permanently slower HOLEY array. - target[target.length] = { coveredColumns: columnIndices, data } - } - return this - } - - addBinaryConstraint(data: T, columnValues: BinaryNumber[]): this { - return this.addBinaryConstraints([{ data, columnValues }]) - } - - addBinaryConstraints(constraints: BinaryConstraintBatch): this { - for (let i = 0; i < constraints.length; i++) { - const { data, columnValues } = constraints[i] - - if (this.validationEnabled) { - if (columnValues.length !== this.numColumns) { - throw new Error( - `Row length ${columnValues.length} does not match columns ${this.numColumns}` - ) - } - } - - const coveredColumns: number[] = [] - for (let j = 0; j < columnValues.length; j++) { - if (columnValues[j] === 1) { - coveredColumns.push(j) - } - } - - this.constraints.push({ coveredColumns, data }) - } - return this - } - - addRow(row: ConstraintRow): this { - this.constraints.push(row) - return this - } - - addRows(rows: ConstraintRow[]): this { - this.constraints.push(...rows) - return this - } - - /** - * Point a new template handler at the compiled immutable row snapshot in O(1). - * Keeping this out of the constructor leaves ordinary solver construction on - * its original monomorphic call shape and avoids copying every row reference. - * @internal - */ - shareConstraints(constraints: ConstraintRow[]): void { - this.constraints = constraints - } - - /** - * Detach a template solver from its shared immutable row-reference table. - * - * Regular handlers already own their rows and never call this method. A - * template handler starts with the compiled context's array so creation is - * O(1), then its first solver-local mutation pays the same shallow copy that - * used to be paid eagerly by every solver, including read-only instances. - */ - detachConstraints(): void { - this.constraints = this.constraints.slice() - } - - getConstraints(): ConstraintRow[] { - return this.constraints - } - - getNumPrimary(): number { - return this.numColumns - } - - getNumSecondary(): number { - return 0 - } - - getConfig(): SimpleSolverConfig { - return this.config - } - - isValidationEnabled(): boolean { - return this.validationEnabled - } -} diff --git a/lib/constraints/index.ts b/lib/constraints/index.ts deleted file mode 100644 index aab8eee..0000000 --- a/lib/constraints/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Constraint handlers for different solver modes - */ - -export { SimpleConstraintHandler } from './handlers/simple.js' -export { ComplexConstraintHandler } from './handlers/complex.js' diff --git a/lib/core/algorithm.ts b/lib/core/algorithm.ts deleted file mode 100644 index f1b4ee3..0000000 --- a/lib/core/algorithm.ts +++ /dev/null @@ -1,383 +0,0 @@ -/** - * Knuth's Dancing Links Implementation - * - * Implements Knuth's Algorithm X using Dancing Links technique for solving - * exact cover problems. Uses Struct-of-Arrays architecture with typed arrays. - * - * Reference: https://arxiv.org/pdf/cs/0011047.pdf - * Based on: https://github.com/shreevatsa/knuth-literate-programs/blob/master/programs/dance.pdf - * - * ARCHITECTURE: - * - Struct-of-Arrays data layout using adaptive 16/32-bit navigation fields - * - Index-based references with a width-appropriate reserved sentinel - * - Pre-allocated storage based on constraint matrix analysis - * - State machine pattern to avoid recursion and enable goto-like control flow - * - * ALGORITHM OPTIMIZATIONS: - * - Early termination for impossible constraints (columns with 0 options) - * - Unit propagation for forced moves (columns with 1 option) - * - Pre-calculated pointers to reduce data dependencies - * - Local typed-array aliases to avoid repeated object-property loads in hot loops - */ - -import { ConstraintRow, Result } from '../types/interfaces.js' -import { ColumnStore, NodeStore } from './data-structures.js' -import { SearchContext } from './problem-builder.js' - -/** - * Hide a column and every row that intersects it. - * - * Keep this hot operation at module scope so repeated searches share one - * function identity. Creating it inside search causes optimized callers to - * deoptimize when the next search installs a different closure at the same - * call site. - */ -function cover(nodes: NodeStore, columns: ColumnStore, colIndex: number): void { - const { down, up, col, rowIndex, rowStart } = nodes - const { len, prev, next } = columns - const leftColIndex = prev[colIndex] - const rightColIndex = next[colIndex] - next[leftColIndex] = rightColIndex - prev[rightColIndex] = leftColIndex - const colHeadIndex = colIndex - for (let rr = down[colHeadIndex]; rr !== colHeadIndex; ) { - const nextRR = down[rr] - const row = rowIndex[rr] - const firstInRow = rowStart[row] - const afterRow = rowStart[row + 1] - // This pair is the circular right traversal expressed as two contiguous - // ranges. It preserves DLX ordering while removing a dependent pointer load - // from every visited node and exposing linear access to the CPU prefetcher. - for (let nn = rr + 1; nn < afterRow; nn++) { - const uu = up[nn] - const dd = down[nn] - down[uu] = dd - up[dd] = uu - len[col[nn]]-- - } - for (let nn = firstInRow; nn < rr; nn++) { - const uu = up[nn] - const dd = down[nn] - down[uu] = dd - up[dd] = uu - len[col[nn]]-- - } - rr = nextRR - } -} -/** Restore a previously covered column. */ -function uncover(nodes: NodeStore, columns: ColumnStore, colIndex: number): void { - const { down, up, col, rowIndex, rowStart } = nodes - const { len, prev, next } = columns - const colHeadIndex = colIndex - for (let rr = up[colHeadIndex]; rr !== colHeadIndex; ) { - const nextRR = up[rr] - const row = rowIndex[rr] - const firstInRow = rowStart[row] - const afterRow = rowStart[row + 1] - // Reverse the exact contiguous ranges used by cover so vertical links are - // restored in DLX order without a per-node left-pointer dependency. - for (let nn = rr - 1; nn >= firstInRow; nn--) { - const uu = up[nn] - const dd = down[nn] - down[uu] = nn - up[dd] = nn - len[col[nn]]++ - } - for (let nn = afterRow - 1; nn > rr; nn--) { - const uu = up[nn] - const dd = down[nn] - down[uu] = nn - up[dd] = nn - len[col[nn]]++ - } - rr = nextRR - } - const leftColIndex = prev[colIndex] - const rightColIndex = next[colIndex] - next[leftColIndex] = colIndex - prev[rightColIndex] = colIndex -} -/** - * Cover every other column in a chosen row as one hot operation. - * - * A typical exact-cover row touches several columns. Batching them here loads - * the typed-array views once and crosses the JS function boundary once per row, - * rather than once per column, while preserving the circular rightward order. - */ -function coverRow(nodes: NodeStore, columns: ColumnStore, currentNodeIndex: number): void { - const { down, up, col, rowIndex, rowStart } = nodes - const { len, prev, next } = columns - const chosenRow = rowIndex[currentNodeIndex] - const firstChosenNode = rowStart[chosenRow] - const afterChosenRow = rowStart[chosenRow + 1] - let pp = currentNodeIndex + 1 - let afterRange = afterChosenRow - while (true) { - for (; pp < afterRange; pp++) { - const colIndex = col[pp] - const leftColIndex = prev[colIndex] - const rightColIndex = next[colIndex] - next[leftColIndex] = rightColIndex - prev[rightColIndex] = leftColIndex - for (let rr = down[colIndex]; rr !== colIndex; ) { - const nextRR = down[rr] - const row = rowIndex[rr] - const firstInRow = rowStart[row] - const afterRow = rowStart[row + 1] - for (let nn = rr + 1; nn < afterRow; nn++) { - const uu = up[nn] - const dd = down[nn] - down[uu] = dd - up[dd] = uu - len[col[nn]]-- - } - for (let nn = firstInRow; nn < rr; nn++) { - const uu = up[nn] - const dd = down[nn] - down[uu] = dd - up[dd] = uu - len[col[nn]]-- - } - rr = nextRR - } - } - if (afterRange === currentNodeIndex) { - return - } - pp = firstChosenNode - afterRange = currentNodeIndex - } -} -/** Restore a chosen row's other columns in the exact reverse order of coverRow. */ -function uncoverRow(nodes: NodeStore, columns: ColumnStore, currentNodeIndex: number): void { - const { down, up, col, rowIndex, rowStart } = nodes - const { len, prev, next } = columns - const chosenRow = rowIndex[currentNodeIndex] - const firstChosenNode = rowStart[chosenRow] - const afterChosenRow = rowStart[chosenRow + 1] - let pp = currentNodeIndex - 1 - let beforeRange = firstChosenNode - 1 - while (true) { - for (; pp > beforeRange; pp--) { - const colIndex = col[pp] - for (let rr = up[colIndex]; rr !== colIndex; ) { - const nextRR = up[rr] - const row = rowIndex[rr] - const firstInRow = rowStart[row] - const afterRow = rowStart[row + 1] - for (let nn = rr - 1; nn >= firstInRow; nn--) { - const uu = up[nn] - const dd = down[nn] - down[uu] = nn - up[dd] = nn - len[col[nn]]++ - } - for (let nn = afterRow - 1; nn > rr; nn--) { - const uu = up[nn] - const dd = down[nn] - down[uu] = nn - up[dd] = nn - len[col[nn]]++ - } - rr = nextRR - } - const leftColIndex = prev[colIndex] - const rightColIndex = next[colIndex] - next[leftColIndex] = colIndex - prev[rightColIndex] = colIndex - } - if (beforeRange === currentNodeIndex) { - return - } - pp = afterChosenRow - 1 - beforeRange = currentNodeIndex - } -} -/** Select the shortest active primary column. */ -function pickBestColumn(columns: ColumnStore): number { - const rootColIndex = 0 - const { len, next } = columns - const rootNext = next[rootColIndex] - let lowestLen = len[rootNext] - let lowest = rootNext - - // Zero is the absolute lower bound, so an impossible first column makes the - // rest of the minimum-selection scan redundant. - if (lowestLen === 0) { - return lowest - } - - for ( - let curColIndex = next[rootNext]; - curColIndex !== rootColIndex; - curColIndex = next[curColIndex] - ) { - const length = len[curColIndex] - - // A unit column is forced. Prioritizing it propagates that constraint - // immediately and avoids exploring a wider branching column first. - if (length === 1) { - return curColIndex - } - - if (length < lowestLen) { - lowestLen = length - lowest = curColIndex - - // No later column can improve on zero. - if (lowestLen === 0) { - break - } - } - } - - return lowest -} - -/** - * Materialize one solution outside the search loop's optimization unit. - * - * Object creation is rare relative to link updates. Isolating it here keeps - * allocation feedback out of the hot state machine, while the exact-size result - * array avoids dynamic growth for each solution that is returned. - */ -function materializeSolution( - nodes: NodeStore, - rows: ConstraintRow[], - choice: number[], - deepestLevel: number -): Result[] { - const results = new Array>(deepestLevel + 1) - for (let level = 0; level <= deepestLevel; level++) { - const nodeIndex = choice[level]! - results[level] = { - index: nodes.rowIndex[nodeIndex], - data: rows[nodes.rowIndex[nodeIndex]].data - } - } - return results -} - -/** - * State machine states for Dancing Links search algorithm - * - * The algorithm uses explicit state transitions to avoid recursion and enable - * resumable search for generator-style iteration. - */ -enum SearchState { - /** Select next column to cover and prepare for choice iteration */ - FORWARD, - /** Try current choice by covering intersecting columns */ - ADVANCE, - /** Backtrack by uncovering columns when no valid choices remain */ - BACKUP, - /** Restore state after backtracking to try next choice */ - RECOVER, - /** Search completed - either found enough solutions or exhausted search space */ - DONE -} - -/** - * Execute Dancing Links search using SearchContext for resumable state - * - * The context preserves algorithm state between calls, enabling generator-style - * iteration without modifying the core algorithm to use generators directly. - */ -export function search(context: SearchContext, numSolutions: number): Result[][] { - const { nodes, columns } = context - const { down, col } = nodes - const { next } = columns - const solutions: Result[][] = [] - - // Root column is always at index 0 (created by ProblemBuilder) - const rootColIndex = 0 - let currentSearchState: SearchState - - if (!context.hasStarted) { - currentSearchState = SearchState.FORWARD - context.hasStarted = true - } else if (context.level > 0 || next[rootColIndex] === rootColIndex) { - // A limited search can pause immediately after a solution at level 0. In - // that state every primary column is still covered, so the empty root list - // distinguishes a resumable choice from an exhausted root-level search. - currentSearchState = SearchState.RECOVER - } else { - // Must be: hasStarted=true && level=0 (backtracked to root) - /** - * Search exhaustion detection: level 0 with hasStarted=true indicates - * that we've backtracked all the way from the deepest search level back - * to the root, meaning all possible solution branches have been explored. - * - * This state occurs when: - * 1. We've found solutions and backtracked to find more - * 2. We've exhausted all choices at every level - * 3. No more solutions exist in the search space - */ - return [] - } - - // Keep the state transitions in one stable function. Besides avoiding call - // overhead, this prevents V8 from deoptimizing on fresh nested-function - // identities every time a new problem is solved. - while (true) { - switch (currentSearchState as SearchState) { - case SearchState.FORWARD: { - const bestColIndex = pickBestColumn(columns) - context.bestColIndex = bestColIndex - cover(nodes, columns, bestColIndex) - - const currentNodeIndex = down[bestColIndex] - context.currentNodeIndex = currentNodeIndex - context.choice[context.level] = currentNodeIndex - currentSearchState = SearchState.ADVANCE - break - } - case SearchState.ADVANCE: { - const currentNodeIndex = context.currentNodeIndex - if (currentNodeIndex === context.bestColIndex) { - currentSearchState = SearchState.BACKUP - break - } - - coverRow(nodes, columns, currentNodeIndex) - - if (next[rootColIndex] === rootColIndex) { - solutions.push(materializeSolution(nodes, context.rows, context.choice, context.level)) - - currentSearchState = - solutions.length === numSolutions ? SearchState.DONE : SearchState.RECOVER - break - } - - context.level++ - currentSearchState = SearchState.FORWARD - break - } - case SearchState.BACKUP: - uncover(nodes, columns, context.bestColIndex) - - if (context.level === 0) { - currentSearchState = SearchState.DONE - break - } - - context.level-- - context.currentNodeIndex = context.choice[context.level]! - context.bestColIndex = col[context.currentNodeIndex] - currentSearchState = SearchState.RECOVER - break - case SearchState.RECOVER: { - const currentNodeIndex = context.currentNodeIndex - uncoverRow(nodes, columns, currentNodeIndex) - const nextNodeIndex = down[currentNodeIndex] - context.currentNodeIndex = nextNodeIndex - context.choice[context.level] = nextNodeIndex - currentSearchState = SearchState.ADVANCE - break - } - default: - return solutions - } - } -} diff --git a/lib/core/data-structures.ts b/lib/core/data-structures.ts deleted file mode 100644 index 4c5b946..0000000 --- a/lib/core/data-structures.ts +++ /dev/null @@ -1,172 +0,0 @@ -/** - * Struct-of-Arrays (SoA) data structures for Dancing Links - * - * Implementation using typed arrays for better memory efficiency. - * - * ARCHITECTURE: - * - NodeStore: Contains node data in separate integer typed-array fields - * - ColumnStore: Contains column data in separate integer typed-array fields - * - Index-based references: Uses array indices and a width-appropriate sentinel - * - Pre-allocated storage: Fixed-size arrays determined by constraint matrix analysis - * - * DESIGN CONSIDERATIONS: - * - Setup cost: Requires capacity estimation during initialization - * - Memory pattern: Fixed allocation vs dynamic growth - * - Access pattern: Array indexing with bounds checking - * - Code style: Index-based operations throughout algorithms - */ - -const NULL_INDEX = -1 -const UINT16_SENTINEL = 0xffff - -type IndexArray = Int32Array | Uint16Array - -function alignOffset(offset: number, bytesPerElement: number): number { - return Math.ceil(offset / bytesPerElement) * bytesPerElement -} - -export class NodeStore { - readonly size: number - private readonly maxRows: number - private readonly maxColumns: number - private readonly buffer: ArrayBuffer - - readonly up: IndexArray - readonly down: IndexArray - readonly col: IndexArray // Column indices (sentinel for headers) - readonly rowIndex: IndexArray // Original row index from input - readonly rowStart: IndexArray // Contiguous node boundaries for each row - - constructor( - maxNodes: number, - maxRows: number, - maxColumns: number, - sourceBuffer?: ArrayBuffer, - immutableSource?: NodeStore - ) { - this.size = maxNodes - this.maxRows = maxRows - this.maxColumns = maxColumns - // Each field follows the domain of the values it stores. A large node table - // needs 32-bit navigation and row boundaries, but its column IDs and row IDs - // often still fit in 16 bits. Keeping those metadata streams narrow halves - // their search bandwidth and keeps the shared kernels' col/rowIndex load - // sites monomorphic when only navigation crosses the node-width boundary. - const NodeIndexArray = maxNodes <= UINT16_SENTINEL ? Uint16Array : Int32Array - const ColumnIndexArray = maxColumns <= UINT16_SENTINEL ? Uint16Array : Int32Array - const RowIndexArray = maxRows <= UINT16_SENTINEL ? Uint16Array : Int32Array - const nodeFieldBytes = maxNodes * NodeIndexArray.BYTES_PER_ELEMENT - const mutableBytes = nodeFieldBytes * 2 - - let colOffset = mutableBytes - let rowIndexOffset = mutableBytes - let rowStartOffset = mutableBytes - let bufferBytes = mutableBytes - if (!immutableSource) { - // Mixed-width views still share one allocation. Aligning only where a - // wider constructor requires it avoids separate buffers and their extra - // allocator/GC bookkeeping while adding at most a few padding bytes. - colOffset = alignOffset(bufferBytes, ColumnIndexArray.BYTES_PER_ELEMENT) - bufferBytes = colOffset + maxNodes * ColumnIndexArray.BYTES_PER_ELEMENT - rowIndexOffset = alignOffset(bufferBytes, RowIndexArray.BYTES_PER_ELEMENT) - bufferBytes = rowIndexOffset + maxNodes * RowIndexArray.BYTES_PER_ELEMENT - rowStartOffset = alignOffset(bufferBytes, NodeIndexArray.BYTES_PER_ELEMENT) - bufferBytes = rowStartOffset + (maxRows + 1) * NodeIndexArray.BYTES_PER_ELEMENT - } - this.buffer = sourceBuffer ?? new ArrayBuffer(bufferBytes) - - // ProblemBuilder writes every used slot directly. Typed arrays already - // arrive zeroed, so sentinel fills would add redundant full memory passes - // before the useful construction writes begin. One backing allocation also - // reduces allocator/GC bookkeeping and keeps the navigation tables within a - // compact virtual-memory range while retaining the SoA access pattern. - this.up = new NodeIndexArray(this.buffer, 0, maxNodes) - this.down = new NodeIndexArray(this.buffer, nodeFieldBytes, maxNodes) - if (immutableSource) { - // Search writes only up/down. Template clones share every read-only view, - // so native copying remains limited to navigation bytes even when metadata - // uses an independently narrower width. The private template owns the - // shared views' lifetime and is never searched. - this.col = immutableSource.col - this.rowIndex = immutableSource.rowIndex - this.rowStart = immutableSource.rowStart - } else { - this.col = new ColumnIndexArray(this.buffer, colOffset, maxNodes) - this.rowIndex = new RowIndexArray(this.buffer, rowIndexOffset, maxNodes) - this.rowStart = new NodeIndexArray(this.buffer, rowStartOffset, maxRows + 1) - } - } - - clone(): NodeStore { - // The mutable navigation views occupy the buffer's leading contiguous range, - // so one native slice copies exactly the state a fresh search can modify. - const mutableBytes = this.up.byteLength + this.down.byteLength - return new NodeStore( - this.size, - this.maxRows, - this.maxColumns, - this.buffer.slice(0, mutableBytes), - this - ) - } -} - -export class ColumnStore { - readonly size: number - private readonly maxNodes: number - private readonly buffer: ArrayBuffer - - readonly len: IndexArray // Column lengths - readonly prev: IndexArray // Previous column indices (sentinel for null) - readonly next: IndexArray // Next column indices (sentinel for null) - - constructor(maxColumns: number, maxNodes: number, sourceBuffer?: ArrayBuffer) { - this.size = maxColumns - this.maxNodes = maxNodes - // Column lengths cannot exceed the total node count, so the node-width - // decision safely applies to all three column fields as well. - const IndexArrayConstructor = maxNodes <= UINT16_SENTINEL ? Uint16Array : Int32Array - const fieldBytes = maxColumns * IndexArrayConstructor.BYTES_PER_ELEMENT - this.buffer = sourceBuffer ?? new ArrayBuffer(fieldBytes * 3) - this.len = new IndexArrayConstructor(this.buffer, 0, maxColumns) - this.prev = new IndexArrayConstructor(this.buffer, fieldBytes, maxColumns) - this.next = new IndexArrayConstructor(this.buffer, fieldBytes * 2, maxColumns) - } - - clone(): ColumnStore { - return new ColumnStore(this.size, this.maxNodes, this.buffer.slice(0)) - } -} - -/** - * Internal constraint interface for capacity calculation - * Unifies ConstraintRow and sparse constraint formats - */ -interface ConstraintWithColumns { - coveredColumns: number[] -} - -/** - * Calculate required capacity for stores based on constraints - * Uses for...of loops for performance and readability - */ -export function calculateCapacity( - numPrimary: number, - numSecondary: number, - constraints: Array -): { numNodes: number; numColumns: number } { - // Count row nodes with for...of loop for performance - let rowNodes = 0 - for (const constraint of constraints) { - rowNodes += constraint.coveredColumns.length - } - - // Count column head nodes: 1 root + numPrimary + numSecondary - const headNodes = 1 + numPrimary + numSecondary - - const numNodes = rowNodes + headNodes - const numColumns = numPrimary + numSecondary + 1 // +1 for root column - return { numNodes, numColumns } -} - -export { NULL_INDEX } diff --git a/lib/core/problem-builder.ts b/lib/core/problem-builder.ts deleted file mode 100644 index 6ae2f53..0000000 --- a/lib/core/problem-builder.ts +++ /dev/null @@ -1,209 +0,0 @@ -/** - * Problem Builder - Constructs Dancing Links matrix from constraint rows - * - * Converts constraint data into optimized Struct-of-Arrays format for algorithm execution. - * Pre-allocates storage based on matrix analysis to avoid dynamic resizing during search. - */ - -import { ConstraintRow } from '../types/interfaces.js' -import { NodeStore, ColumnStore, calculateCapacity, NULL_INDEX } from './data-structures.js' - -/** - * Search context for resumable Dancing Links algorithm execution - * - * Captures the algorithm state needed to pause and resume search operations. - * This enables generator-style iteration without modifying the core algorithm - * to use generators directly. - */ -export interface SearchContext { - /** Current depth in the search tree */ - level: number - - /** Stack of node indices chosen at each search level */ - choice: number[] - - /** Column selected for covering at current level */ - bestColIndex: number - - /** Current node being tried in the selected column */ - currentNodeIndex: number - - /** Whether this context has been used for search before */ - hasStarted: boolean - - /** Constraint matrix nodes with their current link state */ - nodes: NodeStore - - /** Column headers with their current lengths and links */ - columns: ColumnStore - - /** - * Original rows, indexed by each node's rowIndex. One reference per input row - * avoids duplicating the generic data payload on every matrix node. - */ - rows: ConstraintRow[] -} - -/** - * Configuration for building a problem structure - */ -export interface ProblemConfig { - numPrimary: number - numSecondary: number - rows: ConstraintRow[] -} - -const ROOT_COLUMN_OFFSET = 1 - -/** - * Write the once-per-matrix row boundary outside buildRows' hot optimization unit. - * - * V8 can enter buildRows through on-stack replacement before this final keyed - * store has type feedback, then deoptimize the entire construction loop when it - * reaches the store. This stable helper gathers feedback independently and lets - * the row-building loop stay optimized through its return. - */ -function writeFinalRowBoundary(nodes: NodeStore, rowCount: number, nextNodeIndex: number): void { - nodes.rowStart[rowCount] = nextNodeIndex -} - -/** - * Builds Dancing Links data structures from constraint rows - */ -export class ProblemBuilder { - /** - * Build SearchContext for resumable search from constraint configuration - */ - static buildContext(config: ProblemConfig): SearchContext { - const { numPrimary, numSecondary, rows } = config - - // Calculate required capacity and pre-allocate stores - const { numNodes, numColumns } = calculateCapacity(numPrimary, numSecondary, rows) - const nodes = new NodeStore(numNodes, rows.length, numColumns) - const columns = new ColumnStore(numColumns, numNodes) - - // Build column structure - this.buildColumns(nodes, columns, numPrimary, numSecondary) - - // Build row structure - const nextNodeIndex = this.buildRows(nodes, columns, rows) - writeFinalRowBoundary(nodes, rows.length, nextNodeIndex) - - return { - level: 0, - choice: [], - bestColIndex: 0, - currentNodeIndex: 0, - hasStarted: false, - nodes, - columns, - rows - } - } - - /** - * Clone an immutable, fully linked problem layout for a fresh search. - * - * Mutable node links and column state occupy contiguous backing regions, so - * this path is two native memory copies regardless of matrix shape. Immutable - * node metadata remains shared. Reusable templates therefore avoid rebuilding - * thousands of links in JavaScript and avoid copying bytes search cannot write. - */ - static cloneContext(template: SearchContext): SearchContext { - return { - level: 0, - choice: [], - bestColIndex: 0, - currentNodeIndex: 0, - hasStarted: false, - nodes: template.nodes.clone(), - columns: template.columns.clone(), - rows: template.rows - } - } - - /** - * Create column headers and linking structure - */ - private static buildColumns( - nodes: NodeStore, - columns: ColumnStore, - numPrimary: number, - numSecondary: number - ): void { - const { up, down, col, rowIndex } = nodes - const { prev, next } = columns - - // Header nodes are the first nodes and are allocated in column order. This - // identity layout removes a column-to-header lookup from every cover and - // uncover operation. Direct bulk writes also avoid allocation checks and - // small linking-method calls while the matrix is being constructed. - for (let colIndex = 0; colIndex < columns.size; colIndex++) { - up[colIndex] = colIndex - down[colIndex] = colIndex - col[colIndex] = NULL_INDEX - rowIndex[colIndex] = NULL_INDEX - } - - // Only primary columns participate in the root's circular list. - if (numPrimary === 0) { - prev[0] = NULL_INDEX - next[0] = NULL_INDEX - } else { - prev[0] = numPrimary - next[0] = 1 - for (let colIndex = 1; colIndex <= numPrimary; colIndex++) { - prev[colIndex] = colIndex - 1 - next[colIndex] = colIndex === numPrimary ? 0 : colIndex + 1 - } - } - - // Secondary columns are absent from the root list but retain self-links so - // cover/uncover can use the same branch-free pointer updates for both kinds. - const firstSecondary = numPrimary + ROOT_COLUMN_OFFSET - for (let colIndex = firstSecondary; colIndex < firstSecondary + numSecondary; colIndex++) { - prev[colIndex] = colIndex - next[colIndex] = colIndex - } - } - - /** - * Create row nodes and link them into the column structure - */ - private static buildRows( - nodes: NodeStore, - columns: ColumnStore, - rows: ConstraintRow[] - ): number { - const { up, down, col, rowIndex, rowStart } = nodes - const { len } = columns - let nextNodeIndex = columns.size - - for (let i = 0; i < rows.length; i++) { - const coveredColumns = rows[i].coveredColumns - const rowLength = coveredColumns.length - const rowStartIndex = nextNodeIndex - rowStart[i] = rowStartIndex - - // Rows never change horizontally, so their contiguous boundaries replace - // per-node left/right pointers. Sequential scans avoid pointer chasing, - // save two arrays, and give the CPU predictable adjacent memory accesses. - for (let j = 0; j < rowLength; j++) { - const nodeIndex = nextNodeIndex++ - const colIndex = coveredColumns[j] + ROOT_COLUMN_OFFSET - const lastInColIndex = up[colIndex] - - up[nodeIndex] = lastInColIndex - down[nodeIndex] = colIndex - col[nodeIndex] = colIndex - rowIndex[nodeIndex] = i - - down[lastInColIndex] = nodeIndex - up[colIndex] = nodeIndex - len[colIndex]++ - } - } - - return nextNodeIndex - } -} diff --git a/lib/index.ts b/lib/index.ts deleted file mode 100644 index ba03736..0000000 --- a/lib/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Dancing Links - High-performance exact cover solver - * - * Main library exports - */ - -// Factory class for creating solvers and templates -export { DancingLinks } from './solvers/factory.js' - -// Individual solver classes (for advanced usage) -export { ProblemSolver } from './solvers/solver.js' -export { SolverTemplate } from './solvers/template.js' - -// Core interfaces and types -export { - BinaryConstraint, - SparseConstraint, - SimpleConstraint, - ComplexConstraint, - ConstraintRow, - Result, - BinaryNumber -} from './types/interfaces.js' diff --git a/lib/solvers/factory.ts b/lib/solvers/factory.ts deleted file mode 100644 index d5430f9..0000000 --- a/lib/solvers/factory.ts +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Dancing Links Factory - * - * Factory class for creating Dancing Links solvers and templates with type safety. - * - * @example - * ```typescript - * // Simple solver for one-time use - * const dlx = new DancingLinks() - * const solver = dlx.createSolver({ columns: 3 }) - * solver.addSparseConstraint('row1', [0, 2]) - * const solutions = solver.findAll() - * - * // Template for reusing constraint patterns - * const template = dlx.createSolverTemplate({ columns: 3 }) - * template.addSparseConstraint('base', [0, 1]) - * const solver1 = template.createSolver() - * const solver2 = template.createSolver() - * ``` - */ - -import { - SolverConfig, - SimpleSolverConfig, - ComplexSolverConfig, - isComplexSolverConfig -} from '../types/interfaces.js' -import { SimpleConstraintHandler, ComplexConstraintHandler } from '../constraints/index.js' -import { ProblemSolver, createZeroPrimaryProblemSolver } from './solver.js' -import { SolverTemplate } from './template.js' - -/** - * Factory class for creating Dancing Links solvers and templates with type safety. - * - * @template T The type of data associated with constraints - * - * @example - * ```typescript - * const dlx = new DancingLinks() - * const solver = dlx.createSolver({ columns: 3 }) - * const template = dlx.createSolverTemplate({ primaryColumns: 2, secondaryColumns: 1 }) - * ``` - */ -export class DancingLinks { - /** - * Create a new problem solver for a single problem instance. - * - * @param config - Solver configuration (simple or complex mode) - * @returns Type-safe problem solver instance - * - * @example - * ```typescript - * // Simple mode (columns only) - * const solver = dlx.createSolver({ columns: 3 }) - * - * // Complex mode (primary + secondary columns) - * const solver = dlx.createSolver({ - * primaryColumns: 2, - * secondaryColumns: 1 - * }) - * ``` - */ - createSolver(config: SimpleSolverConfig): ProblemSolver - createSolver(config: ComplexSolverConfig): ProblemSolver - createSolver(config: SolverConfig): ProblemSolver | ProblemSolver { - if (isComplexSolverConfig(config)) { - const handler = new ComplexConstraintHandler(config) - // Zero-primary exact covers take a cold O(1) solution path. Selecting it - // once here keeps an extra root-empty branch out of every normal search. - if (config.primaryColumns === 0) { - return createZeroPrimaryProblemSolver(handler) - } - return new ProblemSolver(handler) - } else { - const handler = new SimpleConstraintHandler(config) - if (config.columns === 0) { - return createZeroPrimaryProblemSolver(handler) - } - return new ProblemSolver(handler) - } - } - - /** - * Create a solver template for reusing constraint patterns across multiple problems. - * - * @param config - Solver configuration (simple or complex mode) - * @returns Type-safe solver template instance - * - * @example - * ```typescript - * const template = dlx.createSolverTemplate({ columns: 3 }) - * template.addSparseConstraint('base', [0, 1]) - * - * // Create multiple solvers from the same template - * const solver1 = template.createSolver() - * const solver2 = template.createSolver() - * ``` - */ - createSolverTemplate(config: SimpleSolverConfig): SolverTemplate - createSolverTemplate(config: ComplexSolverConfig): SolverTemplate - createSolverTemplate( - config: SolverConfig - ): SolverTemplate | SolverTemplate { - if (isComplexSolverConfig(config)) { - const handler = new ComplexConstraintHandler(config) - return new SolverTemplate(handler) - } else { - const handler = new SimpleConstraintHandler(config) - return new SolverTemplate(handler) - } - } -} diff --git a/lib/solvers/solver.ts b/lib/solvers/solver.ts deleted file mode 100644 index b8b8106..0000000 --- a/lib/solvers/solver.ts +++ /dev/null @@ -1,270 +0,0 @@ -/** - * Problem solver for Dancing Links exact cover problems. - * - * Provides methods to add constraints and find solutions with type safety - * and automatic validation. - * - * @template T The type of data associated with constraints - * @template Mode Either 'simple' or 'complex' solver mode - * - * @example - * ```typescript - * const solver = dlx.createSolver({ columns: 3 }) - * solver.addSparseConstraint('row1', [0, 2]) - * solver.addSparseConstraint('row2', [1]) - * solver.addSparseConstraint('row3', [0, 1]) - * - * const solutions = solver.findAll() - * console.log(`Found ${solutions.length} solutions`) - * ``` - */ - -import { - Result, - ConstraintRow, - SolverMode, - ConstraintHandler, - SparseColumnIndices, - BinaryColumnValues, - SparseConstraintBatch, - BinaryConstraintBatch -} from '../types/interfaces.js' -import { search } from '../core/algorithm.js' -import { ProblemBuilder, type SearchContext } from '../core/problem-builder.js' - -export class ProblemSolver { - constructor( - private handler: ConstraintHandler, - /** Optional immutable layout supplied only by the explicit reusable-template API. */ - private contextTemplate?: SearchContext - ) {} - - validateConstraints(): this { - this.handler.validateConstraints() - return this - } - - addSparseConstraint(data: T, columnIndices: SparseColumnIndices): this { - this.detachContextTemplate() - this.handler.addSparseConstraint(data, columnIndices) - return this - } - - addSparseConstraints(constraints: SparseConstraintBatch): this { - // Keep this rare detach inline: batches are the hot ingestion API, so fresh - // solvers pay only one predictable branch before the branch-free handler. - if (this.contextTemplate) { - this.handler.detachConstraints() - this.contextTemplate = undefined - } - this.handler.addSparseConstraints(constraints) - return this - } - - addBinaryConstraint(data: T, columnValues: BinaryColumnValues): this { - this.detachContextTemplate() - this.handler.addBinaryConstraint(data, columnValues) - return this - } - - addBinaryConstraints(constraints: BinaryConstraintBatch): this { - // Match the sparse batch fast path; binary conversion is still performed by - // the ordinary monomorphic handler after one predictable detach check. - if (this.contextTemplate) { - this.handler.detachConstraints() - this.contextTemplate = undefined - } - this.handler.addBinaryConstraints(constraints) - return this - } - - /** - * Add a pre-built constraint row (used internally by templates). - * - * @param row - Pre-processed constraint row - * @returns This instance for method chaining - * @internal - */ - addRow(row: ConstraintRow): this { - this.detachContextTemplate() - this.handler.addRow(row) - return this - } - - addRows(rows: ConstraintRow[]): this { - this.detachContextTemplate() - this.handler.addRows(rows) - return this - } - - /** - * Find one solution to the exact cover problem. - * - * @returns Array containing at most one solution - * - * @example - * ```typescript - * const solutions = solver.findOne() - * if (solutions.length > 0) { - * console.log('Found solution:', solutions[0]) - * } - * ``` - */ - findOne(): Result[][] { - return this.solve(1) - } - - /** - * Find all solutions to the exact cover problem. - * - * @returns Array of all solutions found - * - * @example - * ```typescript - * const solutions = solver.findAll() - * solutions.forEach((solution, index) => { - * console.log(`Solution ${index}:`, solution) - * }) - * ``` - */ - findAll(): Result[][] { - return this.solve(Infinity) - } - - /** - * Find up to the specified number of solutions. - * - * @param numSolutions - Maximum number of solutions to find - * @returns Array of solutions (may be fewer than requested) - * - * @example - * ```typescript - * const solutions = solver.find(5) // Find at most 5 solutions - * ``` - */ - find(numSolutions: number): Result[][] { - return this.solve(numSolutions) - } - - /** - * Create a generator that yields solutions one at a time. - * - * This provides a streaming interface for iterating over solutions. - * The generator builds problem structures once and yields solutions - * from the complete solution set. - * - * **Performance Note**: This implementation computes all solutions upfront, - * so it's only beneficial when you plan to iterate through many (but not - * necessarily all) solutions. For single solutions, use `findOne()` instead. - * - * @returns Generator that yields individual solutions - * - * @example - * ```typescript - * const generator = solver.createGenerator() - * for (const solution of generator) { - * console.log('Found solution:', solution) - * if (shouldStop) break // Early termination - * } - * ``` - */ - *createGenerator(): Generator[], void, unknown> { - const constraints = this.handler.getConstraints() - if (constraints.length === 0) { - throw new Error('Cannot solve problem with no constraints') - } - - const context = this.createSearchContext(constraints) - - // Keep calling search with numSolutions: 1 until exhausted - while (true) { - const solutions = search(context, 1) - if (solutions.length === 0) break - yield solutions[0] - } - } - - private solve(numSolutions: number): Result[][] { - const constraints = this.handler.getConstraints() - if (constraints.length === 0) { - throw new Error('Cannot solve problem with no constraints') - } - - const context = this.createSearchContext(constraints) - - // Execute search on context - return search(context, numSolutions) - } - - private createSearchContext(constraints: ConstraintRow[]): SearchContext { - if (this.contextTemplate) { - // The compiled template remains immutable; each solve mutates only its two - // native-copied buffers, preserving solver independence without rebuilding. - return ProblemBuilder.cloneContext(this.contextTemplate) - } - - return ProblemBuilder.buildContext({ - numPrimary: this.handler.getNumPrimary(), - numSecondary: this.handler.getNumSecondary(), - rows: constraints - }) - } - - /** - * Detach template rows only when a solver actually adds local rows. - * - * Template creation used to copy the entire row-reference table for every - * solver even though read-only solvers search the compiled context directly. - * Deferring that O(number of template rows) copy makes the common read-only - * path O(1). The handler class and hot solve path remain identical for fresh - * and template solvers, avoiding mixed-workload JIT polymorphism. - */ - private detachContextTemplate(): void { - if (this.contextTemplate) { - this.handler.detachConstraints() - this.contextTemplate = undefined - } - } -} - -/** - * Cold exact-cover specialization for configurations with no primary columns. - * - * The empty row selection is their one solution; secondary-only rows remain - * optional. Handling this at solver construction keeps root-empty checks out of - * the ordinary search state machine, where they measurably slow every normal - * solve. Inherited mutation methods still provide validation and template COW. - * @internal - */ -export function createZeroPrimaryProblemSolver( - handler: ConstraintHandler, - contextTemplate?: SearchContext -): ProblemSolver { - // Construct the regular class directly and replace methods only on this cold - // instance. A derived class gives ProblemSolver multiple constructor targets - // in V8 and measurably slows short ordinary solves; own methods keep its hot - // construction site monomorphic while preserving instanceof ProblemSolver. - const solver = new ProblemSolver(handler, contextTemplate) - - const assertHasConstraints = (): void => { - if (handler.getConstraints().length === 0) { - throw new Error('Cannot solve problem with no constraints') - } - } - const emptySolution = (): Result[][] => { - assertHasConstraints() - return [[]] - } - - // The public find limit is intentionally ignored: this domain has exactly one - // solution under the existing find(0) convention, so no count work is needed. - solver.findOne = emptySolution - solver.findAll = emptySolution - solver.find = emptySolution - solver.createGenerator = function* (): Generator[], void, unknown> { - assertHasConstraints() - yield [] - } - - return solver -} diff --git a/lib/solvers/template.ts b/lib/solvers/template.ts deleted file mode 100644 index 6b5440a..0000000 --- a/lib/solvers/template.ts +++ /dev/null @@ -1,187 +0,0 @@ -/** - * Template for reusable constraint sets. - * - * Use this when you want to solve multiple similar problems that share - * common constraint patterns. - * - * @template T The type of data associated with constraints - * @template Mode Either 'simple' or 'complex' solver mode - * - * @example - * ```typescript - * const template = dlx.createSolverTemplate({ columns: 3 }) - * template.addSparseConstraint('common', [0, 1]) - * - * const solver1 = template.createSolver() - * solver1.addSparseConstraint('specific1', [2]) - * - * const solver2 = template.createSolver() - * solver2.addSparseConstraint('specific2', [1, 2]) - * ``` - */ - -import { - ConstraintRow, - SolverMode, - ConstraintHandler, - SparseColumnIndices, - BinaryColumnValues, - SparseConstraintBatch, - BinaryConstraintBatch, - SimpleSolverConfig, - ComplexSolverConfig -} from '../types/interfaces.js' -import { SimpleConstraintHandler, ComplexConstraintHandler } from '../constraints/index.js' -import { ProblemBuilder, type SearchContext } from '../core/problem-builder.js' -import { ProblemSolver, createZeroPrimaryProblemSolver } from './solver.js' - -/** - * Freeze the constraint topology used by a compiled template. - * - * Row payloads and handler-owned row objects remain references, but each column - * array is copied once at compilation. Solver-local copy-on-write rebuilds - * therefore use the exact topology that produced the cached links, even if a - * caller later mutates an input array. - */ -function snapshotRows(constraints: ConstraintRow[]): ConstraintRow[] { - // Native slice preserves the packed array kind used by ordinary handlers. A - // pre-sized-and-filled array remains holey in V8 and would deoptimize the row - // loops when a process switches between template and fresh solvers. - const snapshot = constraints.slice() - for (let i = 0; i < constraints.length; i++) { - const row = constraints[i] - // The handler owns the row object, so detach only its caller-owned array. - // Reusing the original allocation-site map avoids wrong-map deopts when - // template and fresh rows pass through the same builder/search functions. - const mutableRow = row as { coveredColumns: number[]; data: T } - mutableRow.coveredColumns = row.coveredColumns.slice() - } - return snapshot -} - -export class SolverTemplate { - /** Immutable compiled layout; every constraint mutation invalidates it. */ - private contextTemplate?: SearchContext - - constructor(private handler: ConstraintHandler) {} - - validateConstraints(): this { - this.handler.validateConstraints() - return this - } - - addSparseConstraint(data: T, columnIndices: SparseColumnIndices): this { - this.contextTemplate = undefined - this.handler.addSparseConstraint(data, columnIndices) - return this - } - - addSparseConstraints(constraints: SparseConstraintBatch): this { - this.contextTemplate = undefined - this.handler.addSparseConstraints(constraints) - return this - } - - addBinaryConstraint(data: T, columnValues: BinaryColumnValues): this { - this.contextTemplate = undefined - this.handler.addBinaryConstraint(data, columnValues) - return this - } - - addBinaryConstraints(constraints: BinaryConstraintBatch): this { - this.contextTemplate = undefined - this.handler.addBinaryConstraints(constraints) - return this - } - - addRow(row: ConstraintRow): this { - this.contextTemplate = undefined - this.handler.addRow(row) - return this - } - - addRows(rows: ConstraintRow[]): this { - this.contextTemplate = undefined - this.handler.addRows(rows) - return this - } - - /** - * Create a new solver instance with this template's constraints pre-loaded. - * - * @returns New problem solver with template constraints - * - * @example - * ```typescript - * const solver = template.createSolver() - * solver.addSparseConstraint('additional', [2]) - * const solutions = solver.findAll() - * ``` - */ - createSolver(): ProblemSolver { - // Get constraints once for batch operation - const constraints = this.handler.getConstraints() - - // Check if template has validation enabled - const templateValidationEnabled = this.handler.isValidationEnabled() - const contextTemplate = this.getContextTemplate(constraints) - - // Share the compiled context's immutable row table. ProblemSolver detaches - // it only on first local mutation, making read-only solver creation O(1) - // while retaining the same handler class and hot shape as fresh solvers. - // Use explicit mode detection instead of inferring from getNumSecondary() - if (this.handler.mode === 'complex') { - const config = this.handler.getConfig() as ComplexSolverConfig - const newHandler = new ComplexConstraintHandler(config) - newHandler.shareConstraints(contextTemplate.rows) - - // Propagate validation setting from template - if (templateValidationEnabled) { - newHandler.validateConstraints() - } - - // Match fresh solvers' cold specialization without putting a root-empty - // check in the shared search loop. Passing the compiled context retains - // the same O(1) row sharing and first-mutation copy-on-write behavior. - if (config.primaryColumns === 0) { - // The handler mode check above proves this generic Mode cast at runtime. - return createZeroPrimaryProblemSolver( - newHandler, - contextTemplate - ) as unknown as ProblemSolver - } - return new ProblemSolver(newHandler, contextTemplate) as ProblemSolver - } else { - const config = this.handler.getConfig() as SimpleSolverConfig - const newHandler = new SimpleConstraintHandler(config) - newHandler.shareConstraints(contextTemplate.rows) - - // Propagate validation setting from template - if (templateValidationEnabled) { - newHandler.validateConstraints() - } - - if (config.columns === 0) { - // The handler mode check above proves this generic Mode cast at runtime. - return createZeroPrimaryProblemSolver( - newHandler, - contextTemplate - ) as unknown as ProblemSolver - } - return new ProblemSolver(newHandler, contextTemplate) as ProblemSolver - } - } - - private getContextTemplate(constraints: ConstraintRow[]): SearchContext { - if (!this.contextTemplate) { - // Compile one immutable snapshot. Later template additions cannot alter - // solvers already created from it, while future creates reuse the work. - this.contextTemplate = ProblemBuilder.buildContext({ - numPrimary: this.handler.getNumPrimary(), - numSecondary: this.handler.getNumSecondary(), - rows: snapshotRows(constraints) - }) - } - return this.contextTemplate - } -} diff --git a/lib/types/interfaces.ts b/lib/types/interfaces.ts deleted file mode 100644 index a147a17..0000000 --- a/lib/types/interfaces.ts +++ /dev/null @@ -1,136 +0,0 @@ -/** - * Unified constraint row interface - * Efficient POJO approach for constraint data - */ -export interface ConstraintRow { - readonly coveredColumns: number[] - readonly data: T -} - -export interface Result { - data: T - index: number -} - -export type BinaryNumber = 0 | 1 - -// SearchConfig removed - now handled by ProblemBuilder interface - -export interface SimpleConstraint { - row: BinaryNumber[] - data: T -} - -export interface ComplexConstraint { - primaryRow: BinaryNumber[] - secondaryRow: BinaryNumber[] - data: T -} - -/** - * Sparse constraint format (RECOMMENDED for performance) - * 2-4x faster than binary format, better caching performance - */ -export interface SparseConstraint { - data: T - columns: number[] -} - -/** - * Binary constraint format (for compatibility) - */ -export type BinaryConstraint = SimpleConstraint | ComplexConstraint - -/** - * Solver configuration interfaces - */ -export interface SimpleSolverConfig { - columns: number -} - -export interface ComplexSolverConfig { - primaryColumns: number - secondaryColumns: number -} - -export type SolverConfig = SimpleSolverConfig | ComplexSolverConfig - -/** - * Type guards for solver configurations - */ -export function isComplexSolverConfig(config: SolverConfig): config is ComplexSolverConfig { - return 'secondaryColumns' in config -} - -/** - * Complex constraint formats for type-safe solvers - */ -export interface ComplexSparseConstraint { - data: T - primary: number[] - secondary: number[] -} - -export interface ComplexBinaryConstraint { - data: T - primaryRow: BinaryNumber[] - secondaryRow: BinaryNumber[] -} - -/** - * Solver mode type definition - */ -export type SolverMode = 'simple' | 'complex' - -/** - * Mode-dependent type definitions for clean, descriptive API signatures - */ -export type SparseColumnIndices = Mode extends 'complex' - ? { primary: number[]; secondary: number[] } - : number[] - -export type BinaryColumnValues = Mode extends 'complex' - ? { primaryRow: BinaryNumber[]; secondaryRow: BinaryNumber[] } - : BinaryNumber[] - -/** - * Mode-dependent config type mapping - */ -export type ConfigForMode = Mode extends 'complex' - ? ComplexSolverConfig - : SimpleSolverConfig - -/** - * Batch constraint types for clean API signatures - */ -export type SparseConstraintBatch = Array<{ - data: T - columnIndices: SparseColumnIndices -}> - -export type BinaryConstraintBatch = Array<{ - data: T - columnValues: BinaryColumnValues -}> - -/** - * Interface for constraint handling with type-safe operations - * Provides zero runtime branching through delegation pattern - */ -export interface ConstraintHandler { - readonly mode: Mode - validateConstraints(): this - addSparseConstraint(data: T, columnIndices: SparseColumnIndices): this - addSparseConstraints(constraints: SparseConstraintBatch): this - addBinaryConstraint(data: T, columnValues: BinaryColumnValues): this - addBinaryConstraints(constraints: BinaryConstraintBatch): this - addRow(row: ConstraintRow): this - addRows(rows: ConstraintRow[]): this - /** @internal Copy a compiled template's shared row-reference table before mutation. */ - detachConstraints(): void - getConstraints(): ConstraintRow[] - getNumPrimary(): number - getNumSecondary(): number - getConfig(): ConfigForMode - isValidationEnabled(): boolean -} diff --git a/package-lock.json b/package-lock.json index cadf20a..179434a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,65 +1,47 @@ { - "name": "dancing-links", - "version": "4.3.9", + "name": "cover-story-prototype", + "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "dancing-links", - "version": "4.3.9", - "license": "MIT", + "name": "cover-story-prototype", + "version": "0.1.0", + "dependencies": { + "dancing-links": "^4.3.9" + }, "devDependencies": { "@commitlint/cli": "^19.8.1", "@commitlint/config-conventional": "^19.8.1", - "@release-it/conventional-changelog": "^10.0.1", + "@eslint/js": "^9.18.0", "@types/chai": "^5.2.2", "@types/mocha": "^10.0.10", "@types/node": "^22.10.4", "@typescript-eslint/eslint-plugin": "^8.18.2", "@typescript-eslint/parser": "^8.18.2", "chai": "^5.2.1", - "dance": "^0.1.0", - "dancing-links-algorithm": "^1.0.1", - "dlxlib": "^1.0.3", "eslint": "^9.18.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.2.1", "mocha": "^11.7.5", - "nyc": "^17.1.0", "prettier": "^3.4.2", - "release-it": "^19.0.4", "rimraf": "^6.0.1", - "tinybench": "^6.0.0", "ts-node": "^10.9.2", "typescript": "^5.7.3", - "v8-profiler-next": "^1.10.0" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" + "vite": "^8.1.4" }, "engines": { - "node": ">=6.0.0" + "node": ">=20.19.0" } }, "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -67,255 +49,12 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/compat-data": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", - "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", - "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.6", - "@babel/parser": "^7.28.0", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.0", - "@babel/types": "^7.28.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", - "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.0", - "@babel/types": "^7.28.0", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", - "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", - "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.27.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", - "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", - "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.0", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.0", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.28.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.1.tgz", - "integrity": "sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, "engines": { "node": ">=6.9.0" } @@ -356,19 +95,6 @@ "node": ">=v18" } }, - "node_modules/@commitlint/config-conventional/node_modules/conventional-changelog-conventionalcommits": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz", - "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==", - "dev": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/@commitlint/config-validator": { "version": "19.8.1", "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-19.8.1.tgz", @@ -384,9 +110,9 @@ } }, "node_modules/@commitlint/config-validator/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, "license": "MIT", "dependencies": { @@ -450,9 +176,9 @@ } }, "node_modules/@commitlint/format/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, "license": "MIT", "engines": { @@ -515,9 +241,9 @@ } }, "node_modules/@commitlint/load/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, "license": "MIT", "engines": { @@ -552,51 +278,6 @@ "node": ">=v18" } }, - "node_modules/@commitlint/parse/node_modules/conventional-changelog-angular": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", - "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@commitlint/parse/node_modules/conventional-commits-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", - "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-text-path": "^2.0.0", - "JSONStream": "^1.3.5", - "meow": "^12.0.1", - "split2": "^4.0.0" - }, - "bin": { - "conventional-commits-parser": "cli.mjs" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@commitlint/parse/node_modules/meow": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", - "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16.10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@commitlint/read": { "version": "19.8.1", "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-19.8.1.tgz", @@ -614,37 +295,6 @@ "node": ">=v18" } }, - "node_modules/@commitlint/read/node_modules/git-raw-commits": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", - "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "dargs": "^8.0.0", - "meow": "^12.0.1", - "split2": "^4.0.0" - }, - "bin": { - "git-raw-commits": "cli.mjs" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@commitlint/read/node_modules/meow": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", - "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16.10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@commitlint/resolve-extends": { "version": "19.8.1", "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-19.8.1.tgz", @@ -789,9 +439,9 @@ } }, "node_modules/@commitlint/top-level/node_modules/yocto-queue": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", - "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", "dev": true, "license": "MIT", "engines": { @@ -816,9 +466,9 @@ } }, "node_modules/@commitlint/types/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, "license": "MIT", "engines": { @@ -828,32 +478,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@conventional-changelog/git-client": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@conventional-changelog/git-client/-/git-client-1.0.1.tgz", - "integrity": "sha512-PJEqBwAleffCMETaVm/fUgHldzBE35JFk3/9LL6NUA5EXa3qednu+UT6M7E5iBu3zIQZCULYIiZ90fBYHt6xUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/semver": "^7.5.5", - "semver": "^7.5.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "conventional-commits-filter": "^5.0.0", - "conventional-commits-parser": "^6.0.0" - }, - "peerDependenciesMeta": { - "conventional-commits-filter": { - "optional": true - }, - "conventional-commits-parser": { - "optional": true - } - } - }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -878,21 +502,55 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "node_modules/@emnapi/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", + "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } @@ -993,13 +651,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -1021,19 +672,6 @@ "node": ">= 4" } }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -1084,13 +722,6 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true, - "license": "MIT" - }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -1157,6609 +788,2773 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@hutson/parse-repository-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-5.0.0.tgz", - "integrity": "sha512-e5+YUKENATs1JgYHMzTr2MW/NDcXGfYFAuOQU8gJgF/kEh4EqKgfGrfLI67bMD4tbhZVlkigz/9YYwWcbOFthg==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@inquirer/checkbox": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.2.0.tgz", - "integrity": "sha512-fdSw07FLJEU5vbpOPzXo5c6xmMGDzbZE2+niuDHX5N6mc6V0Ebso/q3xiHra4D73+PMsC8MJmcaZKuAAoaQsSA==", + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/figures": "^1.0.13", - "@inquirer/type": "^3.0.8", - "ansi-escapes": "^4.3.2", - "yoctocolors-cjs": "^2.1.2" - }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": "20 || >=22" } }, - "node_modules/@inquirer/confirm": { - "version": "5.1.14", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.14.tgz", - "integrity": "sha512-5yR4IBfe0kXe59r1YCTG8WXkUbl7Z35HK87Sw+WUyGD8wNUx7JvY7laahzeytyE1oLn74bQnL7hstctQxisQ8Q==", + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/type": "^3.0.8" + "@isaacs/balanced-match": "^4.0.1" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": "20 || >=22" } }, - "node_modules/@inquirer/core": { - "version": "10.1.15", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.15.tgz", - "integrity": "sha512-8xrp836RZvKkpNbVvgWUlxjT4CraKk2q+I3Ksy+seI2zkcE+y6wNs1BVhgcv8VyImFecUhdQrYLdW32pAjwBdA==", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@inquirer/figures": "^1.0.13", - "@inquirer/type": "^3.0.8", - "ansi-escapes": "^4.3.2", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": ">=12" } }, - "node_modules/@inquirer/core/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=6.0.0" } }, - "node_modules/@inquirer/core/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", "dev": true, "license": "MIT" }, - "node_modules/@inquirer/core/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz", + "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@tybys/wasm-util": "^0.10.3" }, - "engines": { - "node": ">=8" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" } }, - "node_modules/@inquirer/core/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/@inquirer/core/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/@inquirer/editor": { - "version": "4.2.15", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.15.tgz", - "integrity": "sha512-wst31XT8DnGOSS4nNJDIklGKnf+8shuauVrWzgKegWUe28zfCftcWZ2vktGdzJgcylWSS2SrDnYUb6alZcwnCQ==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/type": "^3.0.8", - "external-editor": "^3.1.0" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": ">= 8" } }, - "node_modules/@inquirer/expand": { - "version": "4.0.17", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.17.tgz", - "integrity": "sha512-PSqy9VmJx/VbE3CT453yOfNa+PykpKg/0SYP7odez1/NWBGuDXgPhp4AeGYYKjhLn5lUUavVS/JbeYMPdH50Mw==", + "node_modules/@oxc-project/types": { + "version": "0.139.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz", + "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==", "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/type": "^3.0.8", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/Boshen" } }, - "node_modules/@inquirer/figures": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.13.tgz", - "integrity": "sha512-lGPVU3yO9ZNqA7vTYz26jny41lE7yoQansmqdMLBEfqaGsmdg7V3W9mK9Pvb5IL4EVZ9GnSDGMO/cJXud5dMaw==", + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, "license": "MIT", + "optional": true, "engines": { - "node": ">=18" + "node": ">=14" } }, - "node_modules/@inquirer/input": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.2.1.tgz", - "integrity": "sha512-tVC+O1rBl0lJpoUZv4xY+WGWY8V5b0zxU1XDsMsIHYregdh7bN5X5QnIONNBAl0K765FYlAfNHS2Bhn7SSOVow==", + "node_modules/@pkgr/core": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.7.tgz", + "integrity": "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==", "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/type": "^3.0.8" - }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "funding": { + "url": "https://opencollective.com/pkgr" } }, - "node_modules/@inquirer/number": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.17.tgz", - "integrity": "sha512-GcvGHkyIgfZgVnnimURdOueMk0CztycfC8NZTiIY9arIAkeOgt6zG57G+7vC59Jns3UX27LMkPKnKWAOF5xEYg==", + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz", + "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/type": "^3.0.8" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@inquirer/password": { - "version": "4.0.17", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.17.tgz", - "integrity": "sha512-DJolTnNeZ00E1+1TW+8614F7rOJJCM4y4BAGQ3Gq6kQIG+OJ4zr3GLjIjVVJCbKsk2jmkmv6v2kQuN/vriHdZA==", + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz", + "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/type": "^3.0.8", - "ansi-escapes": "^4.3.2" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@inquirer/prompts": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.8.0.tgz", - "integrity": "sha512-JHwGbQ6wjf1dxxnalDYpZwZxUEosT+6CPGD9Zh4sm9WXdtUp9XODCQD3NjSTmu+0OAyxWXNOqf0spjIymJa2Tw==", + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz", + "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/checkbox": "^4.2.0", - "@inquirer/confirm": "^5.1.14", - "@inquirer/editor": "^4.2.15", - "@inquirer/expand": "^4.0.17", - "@inquirer/input": "^4.2.1", - "@inquirer/number": "^3.0.17", - "@inquirer/password": "^4.0.17", - "@inquirer/rawlist": "^4.1.5", - "@inquirer/search": "^3.1.0", - "@inquirer/select": "^4.3.1" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@inquirer/rawlist": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.5.tgz", - "integrity": "sha512-R5qMyGJqtDdi4Ht521iAkNqyB6p2UPuZUbMifakg1sWtu24gc2Z8CJuw8rP081OckNDMgtDCuLe42Q2Kr3BolA==", + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz", + "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/type": "^3.0.8", - "yoctocolors-cjs": "^2.1.2" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@inquirer/search": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.1.0.tgz", - "integrity": "sha512-PMk1+O/WBcYJDq2H7foV0aAZSmDdkzZB9Mw2v/DmONRJopwA/128cS9M/TXWLKKdEQKZnKwBzqu2G4x/2Nqx8Q==", + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz", + "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/figures": "^1.0.13", - "@inquirer/type": "^3.0.8", - "yoctocolors-cjs": "^2.1.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@inquirer/select": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.3.1.tgz", - "integrity": "sha512-Gfl/5sqOF5vS/LIrSndFgOh7jgoe0UXEizDqahFRkq5aJBLegZ6WjuMh/hVEJwlFQjyLq1z9fRtvUMkb7jM1LA==", + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz", + "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/figures": "^1.0.13", - "@inquirer/type": "^3.0.8", - "ansi-escapes": "^4.3.2", - "yoctocolors-cjs": "^2.1.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@inquirer/type": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.8.tgz", - "integrity": "sha512-lg9Whz8onIHRthWaN1Q9EGLa/0LFJjyM8mEUbL1eTi6yMGvBf8gvyDLtxSXztQsxMvhxxNpJYrwa1YHdq+w4Jw==", + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz", + "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@isaacs/balanced-match": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", - "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz", + "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "20 || >=22" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@isaacs/brace-expansion": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", - "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz", + "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==", + "cpu": [ + "s390x" + ], "dev": true, "license": "MIT", - "dependencies": { - "@isaacs/balanced-match": "^4.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "20 || >=22" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz", + "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz", + "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz", + "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": ">=8" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz", + "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==", + "cpu": [ + "wasm32" + ], "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "p-locate": "^4.1.0" + "@emnapi/core": "1.11.1", + "@emnapi/runtime": "1.11.1", + "@napi-rs/wasm-runtime": "^1.1.6" }, "engines": { - "node": ">=8" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz", + "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz", + "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", - "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } + "license": "MIT" }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } + "license": "MIT" }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", - "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true, "license": "MIT" }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.29", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", - "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "tslib": "^2.4.0" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@types/chai": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", + "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", "dev": true, "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" + "@types/deep-eql": "*" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@types/conventional-commits-parser": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.2.tgz", + "integrity": "sha512-BgT2szDXnVypgpNxOK8aL5SGjUdaQbC++WZNjF1Qge3Og2+zhHj+RWhmehLhYyvQwqAmvezruVfOf8+3m74W+g==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 8" + "dependencies": { + "@types/node": "*" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } + "license": "MIT" }, - "node_modules/@nodeutils/defaults-deep": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@nodeutils/defaults-deep/-/defaults-deep-1.1.0.tgz", - "integrity": "sha512-gG44cwQovaOFdSR02jR9IhVRpnDP64VN6JdjYJTfNz4J4fWn7TQnmrf22nSjRqlwlxPcW8PL/L3KbJg3tdwvpg==", + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, - "license": "ISC", - "dependencies": { - "lodash": "^4.15.0" - } + "license": "MIT" }, - "node_modules/@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true, - "license": "ISC", - "dependencies": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } + "license": "MIT" }, - "node_modules/@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", + "node_modules/@types/mocha": { + "version": "10.0.10", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", + "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.16.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.16.3.tgz", + "integrity": "sha512-sr4Xz74KOUeYadexo1r8imhRtlVXcs+j3XK3TcoiYk7B1t3YRVJgtaD3cwX73NYb71pmVuMLNRhJ9XKdoDB74g==", "dev": true, "license": "MIT", "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "undici-types": "~6.21.0" } }, - "node_modules/@npmcli/move-file/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.36.0.tgz", + "integrity": "sha512-lZNihHUVB6ZZiPBNgOQGSxUASI7UJWhT8nHyUGCnaQ28XFCw98IfrMCG3rUl1uwUWoAvodJQby2KTs79UTcrAg==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.36.0", + "@typescript-eslint/type-utils": "8.36.0", + "@typescript-eslint/utils": "8.36.0", + "@typescript-eslint/visitor-keys": "8.36.0", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.36.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@npmcli/move-file/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/@typescript-eslint/parser": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.36.0.tgz", + "integrity": "sha512-FuYgkHwZLuPbZjQHzJXrtXreJdFMKl16BFYyRrLxDhWr6Qr7Kbcu2s1Yhu8tsiMXw1S0W1pjfFfYEt+R604s+Q==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "@typescript-eslint/scope-manager": "8.36.0", + "@typescript-eslint/types": "8.36.0", + "@typescript-eslint/typescript-estree": "8.36.0", + "@typescript-eslint/visitor-keys": "8.36.0", + "debug": "^4.3.4" }, "engines": { - "node": "*" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@npmcli/move-file/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@typescript-eslint/project-service": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.36.0.tgz", + "integrity": "sha512-JAhQFIABkWccQYeLMrHadu/fhpzmSQ1F1KXkpzqiVxA/iYI6UnRt2trqXHt1sYEcw1mxLnB9rKMsOxXPxowN/g==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "@typescript-eslint/tsconfig-utils": "^8.36.0", + "@typescript-eslint/types": "^8.36.0", + "debug": "^4.3.4" }, "engines": { - "node": "*" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@npmcli/move-file/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.36.0.tgz", + "integrity": "sha512-wCnapIKnDkN62fYtTGv2+RY8FlnBYA3tNm0fm91kc2BjPhV2vIjwwozJ7LToaLAyb1ca8BxrS7vT+Pvvf7RvqA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "glob": "^7.1.3" + "@typescript-eslint/types": "8.36.0", + "@typescript-eslint/visitor-keys": "8.36.0" }, - "bin": { - "rimraf": "bin.js" + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@octokit/auth-token": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz", - "integrity": "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==", + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.36.0.tgz", + "integrity": "sha512-Nhh3TIEgN18mNbdXpd5Q8mSCBnrZQeY9V7Ca3dqYvNDStNIGRmJA6dmrIPMJ0kow3C7gcQbpsG2rPzy1Ks/AnA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@octokit/core": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.6.tgz", - "integrity": "sha512-kIU8SLQkYWGp3pVKiYzA5OSaNF5EE03P/R8zEmmrG6XwOg5oBjXyQVVIauQ0dgau4zYhpZEhJrvIYt6oM+zZZA==", + "node_modules/@typescript-eslint/type-utils": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.36.0.tgz", + "integrity": "sha512-5aaGYG8cVDd6cxfk/ynpYzxBRZJk7w/ymto6uiyUFtdCozQIsQWh7M28/6r57Fwkbweng8qAzoMCPwSJfWlmsg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@octokit/auth-token": "^5.0.0", - "@octokit/graphql": "^8.2.2", - "@octokit/request": "^9.2.3", - "@octokit/request-error": "^6.1.8", - "@octokit/types": "^14.0.0", - "before-after-hook": "^3.0.2", - "universal-user-agent": "^7.0.0" + "@typescript-eslint/typescript-estree": "8.36.0", + "@typescript-eslint/utils": "8.36.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" }, "engines": { - "node": ">= 18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@octokit/endpoint": { - "version": "10.1.4", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.4.tgz", - "integrity": "sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA==", + "node_modules/@typescript-eslint/types": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.36.0.tgz", + "integrity": "sha512-xGms6l5cTJKQPZOKM75Dl9yBfNdGeLRsIyufewnxT4vZTrjC0ImQT4fj8QmtJK84F58uSh5HVBSANwcfiXxABQ==", "dev": true, "license": "MIT", - "dependencies": { - "@octokit/types": "^14.0.0", - "universal-user-agent": "^7.0.2" - }, "engines": { - "node": ">= 18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@octokit/graphql": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.2.tgz", - "integrity": "sha512-Yi8hcoqsrXGdt0yObxbebHXFOiUA+2v3n53epuOg1QUgOB6c4XzvisBNVXJSl8RYA5KrDuSL2yq9Qmqe5N0ryA==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.36.0.tgz", + "integrity": "sha512-JaS8bDVrfVJX4av0jLpe4ye0BpAaUW7+tnS4Y4ETa3q7NoZgzYbN9zDQTJ8kPb5fQ4n0hliAt9tA4Pfs2zA2Hg==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/request": "^9.2.3", - "@octokit/types": "^14.0.0", - "universal-user-agent": "^7.0.0" + "@typescript-eslint/project-service": "8.36.0", + "@typescript-eslint/tsconfig-utils": "8.36.0", + "@typescript-eslint/types": "8.36.0", + "@typescript-eslint/visitor-keys": "8.36.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" }, "engines": { - "node": ">= 18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@octokit/openapi-types": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz", - "integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "11.6.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.6.0.tgz", - "integrity": "sha512-n5KPteiF7pWKgBIBJSk8qzoZWcUkza2O6A0za97pMGVrGfPdltxrfmfF5GucHYvHGZD8BdaZmmHGz5cX/3gdpw==", + "node_modules/@typescript-eslint/utils": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.36.0.tgz", + "integrity": "sha512-VOqmHu42aEMT+P2qYjylw6zP/3E/HvptRwdn/PZxyV27KhZg2IOszXod4NcXisWzPAGSS4trE/g4moNj6XmH2g==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/types": "^13.10.0" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.36.0", + "@typescript-eslint/types": "8.36.0", + "@typescript-eslint/typescript-estree": "8.36.0" }, "engines": { - "node": ">= 18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@octokit/core": ">=6" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", - "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", - "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.36.0.tgz", + "integrity": "sha512-vZrhV2lRPWDuGoxcmrzRZyxAggPL+qp3WzUrlZD+slFueDiYHxeBa34dUXPuC0RmGKzl4lS5kFJYvKCq9cnNDA==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "@typescript-eslint/types": "8.36.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@octokit/plugin-request-log": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz", - "integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==", + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">= 18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "@octokit/core": ">=6" + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "13.5.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.5.0.tgz", - "integrity": "sha512-9Pas60Iv9ejO3WlAX3maE1+38c5nqbJXV5GrncEfkndIpZrJ/WPMRd2xYDcPPEt5yzpxcjw9fWNoPhsSGzqKqw==", + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "dependencies": { - "@octokit/types": "^13.10.0" + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": ">=6" + "node": ">=0.4.0" } }, - "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", - "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", - "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^24.2.0" + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@octokit/request": { - "version": "9.2.4", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.4.tgz", - "integrity": "sha512-q8ybdytBmxa6KogWlNa818r0k1wlqzNC+yNkcQDECHvQo8Vmstrg18JwqJHdJdUiHD2sjlwBgSm9kHkOKe2iyA==", + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/endpoint": "^10.1.4", - "@octokit/request-error": "^6.1.8", - "@octokit/types": "^14.0.0", - "fast-content-type-parse": "^2.0.0", - "universal-user-agent": "^7.0.2" + "acorn": "^8.11.0" }, "engines": { - "node": ">= 18" + "node": ">=0.4.0" } }, - "node_modules/@octokit/request-error": { - "version": "6.1.8", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.8.tgz", - "integrity": "sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==", + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/types": "^14.0.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">= 18" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@octokit/rest": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.1.1.tgz", - "integrity": "sha512-sTQV7va0IUVZcntzy1q3QqPm/r8rWtDCqpRAmb8eXXnKkjoQEtFe3Nt5GTVsHft+R6jJoHeSiVLcgcvhtue/rg==", + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "license": "MIT", - "dependencies": { - "@octokit/core": "^6.1.4", - "@octokit/plugin-paginate-rest": "^11.4.2", - "@octokit/plugin-request-log": "^5.3.1", - "@octokit/plugin-rest-endpoint-methods": "^13.3.0" - }, "engines": { - "node": ">= 18" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@octokit/types": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz", - "integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==", + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^25.1.0" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@phun-ky/typeof": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@phun-ky/typeof/-/typeof-1.2.8.tgz", - "integrity": "sha512-7J6ca1tK0duM2BgVB+CuFMh3idlIVASOP2QvOCbNWDc6JnvjtKa9nufPoJQQ4xrwBonwgT1TIhRRcEtzdVgWsA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^20.9.0 || >=22.0.0", - "npm": ">=10.8.2" - }, - "funding": { - "url": "https://github.com/phun-ky/typeof?sponsor=1" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } + "license": "MIT" }, - "node_modules/@pkgr/core": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.7.tgz", - "integrity": "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==", + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/pkgr" - } + "license": "Python-2.0" }, - "node_modules/@release-it/conventional-changelog": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@release-it/conventional-changelog/-/conventional-changelog-10.0.1.tgz", - "integrity": "sha512-Qp+eyMGCPyq5xiWoNK91cWVIR/6HD1QAUNeG6pV2G4kxotWl81k/KDQqDNvrNVmr9+zDp53jI7pVVYQp6mi4zA==", + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", "dev": true, - "license": "MIT", - "dependencies": { - "concat-stream": "^2.0.0", - "conventional-changelog": "^6.0.0", - "conventional-recommended-bump": "^10.0.0", - "git-semver-tags": "^8.0.0", - "semver": "^7.6.3" - }, - "engines": { - "node": "^20.9.0 || >=22.0.0" - }, - "peerDependencies": { - "release-it": "^18.0.0 || ^19.0.0" - } + "license": "MIT" }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 10" + "node": ">=12" } }, - "node_modules/@tootallnate/quickjs-emscripten": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, "license": "MIT" }, - "node_modules/@types/chai": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", - "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/deep-eql": "*" + "balanced-match": "^1.0.0" } }, - "node_modules/@types/conventional-commits-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.1.tgz", - "integrity": "sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==", + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*" + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/deep-eql": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", - "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/mocha": { - "version": "10.0.10", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", - "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/@types/node": { - "version": "22.16.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.16.3.tgz", - "integrity": "sha512-sr4Xz74KOUeYadexo1r8imhRtlVXcs+j3XK3TcoiYk7B1t3YRVJgtaD3cwX73NYb71pmVuMLNRhJ9XKdoDB74g==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "undici-types": "~6.21.0" + "engines": { + "node": ">=6" } }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/parse-path": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@types/parse-path/-/parse-path-7.0.3.tgz", - "integrity": "sha512-LriObC2+KYZD3FzCrgWGv/qufdUy4eXrxcLgQMfYXgPbLIecKIsVBaQgUPmxSSLcjmYbDTQbMgr6qr6l/eb7Bg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/semver": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz", - "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.36.0.tgz", - "integrity": "sha512-lZNihHUVB6ZZiPBNgOQGSxUASI7UJWhT8nHyUGCnaQ28XFCw98IfrMCG3rUl1uwUWoAvodJQby2KTs79UTcrAg==", + "node_modules/chai": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.1.tgz", + "integrity": "sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.36.0", - "@typescript-eslint/type-utils": "8.36.0", - "@typescript-eslint/utils": "8.36.0", - "@typescript-eslint/visitor-keys": "8.36.0", - "graphemer": "^1.4.0", - "ignore": "^7.0.0", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.1.0" + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.36.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "node": ">=18" } }, - "node_modules/@typescript-eslint/parser": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.36.0.tgz", - "integrity": "sha512-FuYgkHwZLuPbZjQHzJXrtXreJdFMKl16BFYyRrLxDhWr6Qr7Kbcu2s1Yhu8tsiMXw1S0W1pjfFfYEt+R604s+Q==", + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.36.0", - "@typescript-eslint/types": "8.36.0", - "@typescript-eslint/typescript-estree": "8.36.0", - "@typescript-eslint/visitor-keys": "8.36.0", - "debug": "^4.3.4" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.36.0.tgz", - "integrity": "sha512-JAhQFIABkWccQYeLMrHadu/fhpzmSQ1F1KXkpzqiVxA/iYI6UnRt2trqXHt1sYEcw1mxLnB9rKMsOxXPxowN/g==", + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.36.0", - "@typescript-eslint/types": "^8.36.0", - "debug": "^4.3.4" - }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "node": ">= 16" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.36.0.tgz", - "integrity": "sha512-wCnapIKnDkN62fYtTGv2+RY8FlnBYA3tNm0fm91kc2BjPhV2vIjwwozJ7LToaLAyb1ca8BxrS7vT+Pvvf7RvqA==", + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.36.0", - "@typescript-eslint/visitor-keys": "8.36.0" + "readdirp": "^4.0.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">= 14.16.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.36.0.tgz", - "integrity": "sha512-Nhh3TIEgN18mNbdXpd5Q8mSCBnrZQeY9V7Ca3dqYvNDStNIGRmJA6dmrIPMJ0kow3C7gcQbpsG2rPzy1Ks/AnA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.36.0.tgz", - "integrity": "sha512-5aaGYG8cVDd6cxfk/ynpYzxBRZJk7w/ymto6uiyUFtdCozQIsQWh7M28/6r57Fwkbweng8qAzoMCPwSJfWlmsg==", + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@typescript-eslint/typescript-estree": "8.36.0", - "@typescript-eslint/utils": "8.36.0", - "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "node": ">=12" } }, - "node_modules/@typescript-eslint/types": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.36.0.tgz", - "integrity": "sha512-xGms6l5cTJKQPZOKM75Dl9yBfNdGeLRsIyufewnxT4vZTrjC0ImQT4fj8QmtJK84F58uSh5HVBSANwcfiXxABQ==", + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=8" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.36.0.tgz", - "integrity": "sha512-JaS8bDVrfVJX4av0jLpe4ye0BpAaUW7+tnS4Y4ETa3q7NoZgzYbN9zDQTJ8kPb5fQ4n0hliAt9tA4Pfs2zA2Hg==", + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.36.0", - "@typescript-eslint/tsconfig-utils": "8.36.0", - "@typescript-eslint/types": "8.36.0", - "@typescript-eslint/visitor-keys": "8.36.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "node": ">=8" } }, - "node_modules/@typescript-eslint/utils": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.36.0.tgz", - "integrity": "sha512-VOqmHu42aEMT+P2qYjylw6zP/3E/HvptRwdn/PZxyV27KhZg2IOszXod4NcXisWzPAGSS4trE/g4moNj6XmH2g==", + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.36.0", - "@typescript-eslint/types": "8.36.0", - "@typescript-eslint/typescript-estree": "8.36.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "node": ">=8" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.36.0.tgz", - "integrity": "sha512-vZrhV2lRPWDuGoxcmrzRZyxAggPL+qp3WzUrlZD+slFueDiYHxeBa34dUXPuC0RmGKzl4lS5kFJYvKCq9cnNDA==", + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.36.0", - "eslint-visitor-keys": "^4.2.1" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" }, - "funding": { - "url": "https://opencollective.com/eslint" + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@xprofiler/node-pre-gyp": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@xprofiler/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-kNFT4XscrA+Hjh+jSHs49PiG/YGf08a6eNDo16qjSnCaT4B5ngrKDcNtEJ6CnS0sDP/1oZmHCBYECB6wGKP7lg==", + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "detect-libc": "^1.0.3", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.5", - "node-gyp": "9.3.1", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } + "license": "MIT" }, - "node_modules/@xprofiler/node-pre-gyp/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", "dev": true, "license": "MIT", "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" } }, - "node_modules/@xprofiler/node-pre-gyp/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "license": "MIT" }, - "node_modules/@xprofiler/node-pre-gyp/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/conventional-changelog-angular": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", + "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", "dev": true, "license": "ISC", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "compare-func": "^2.0.0" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=16" } }, - "node_modules/@xprofiler/node-pre-gyp/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "node_modules/conventional-changelog-conventionalcommits": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz", + "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "agent-base": "6", - "debug": "4" + "compare-func": "^2.0.0" }, "engines": { - "node": ">= 6" + "node": ">=16" } }, - "node_modules/@xprofiler/node-pre-gyp/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "is-text-path": "^2.0.0", + "JSONStream": "^1.3.5", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.mjs" }, "engines": { - "node": "*" + "node": ">=16" } }, - "node_modules/@xprofiler/node-pre-gyp/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", + "node_modules/cosmiconfig": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.2.tgz", + "integrity": "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "glob": "^7.1.3" + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" }, - "bin": { - "rimraf": "bin.js" + "engines": { + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true, - "license": "ISC" - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "node_modules/cosmiconfig-typescript-loader": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-6.3.0.tgz", + "integrity": "sha512-Akr82WH1Wfqatyiqpj8HDkO2o2KmJRu1FhKfSNJP3K4IdXwHfEyL7MOb62i1AGQVLtIQM+iCE9CGOtrfhR+mmA==", "dev": true, "license": "MIT", "dependencies": { - "acorn": "^8.11.0" + "jiti": "2.6.1" }, "engines": { - "node": ">=0.4.0" + "node": ">=v18" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=9", + "typescript": ">=5" } }, - "node_modules/add-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", - "integrity": "sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==", + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true, "license": "MIT" }, - "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/agentkeepalive": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", - "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "node": ">= 8" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, + "node_modules/dancing-links": { + "version": "4.3.9", + "resolved": "https://registry.npmjs.org/dancing-links/-/dancing-links-4.3.9.tgz", + "integrity": "sha512-l9+B0BJyanecY5L2CNbfRc9BcpmvnxOowjMryyqKi9GI45e8EMBbR5z3KjgJ1MyqiS1N73jgarbCy9biMDSl+w==", "license": "MIT", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=20.0.0" } }, - "node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "node_modules/dargs": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz", + "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==", "dev": true, "license": "MIT", "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "ms": "^2.1.3" }, "engines": { - "node": ">=8" + "node": ">=6.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/append-transform": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", - "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, "license": "MIT", - "dependencies": { - "default-require-extensions": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/aproba": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", - "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", - "dev": true, - "license": "ISC" - }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", - "dev": true, - "license": "MIT" - }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, "engines": { - "node": ">=10" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "license": "MIT" - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" + "node": ">=6" } }, - "node_modules/array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, "license": "MIT" }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "engines": { - "node": ">=12" + "node": ">=0.3.1" } }, - "node_modules/ast-types": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", - "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.0.1" + "is-obj": "^2.0.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/async-retry": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", - "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "retry": "0.13.1" + "node": ">=8" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true, "license": "MIT" }, - "node_modules/basic-ftp": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", - "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/before-after-hook": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", - "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } + "license": "MIT" }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true, "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true, - "license": "ISC" - }, - "node_modules/browserslist": { - "version": "4.25.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", - "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "caniuse-lite": "^1.0.30001726", - "electron-to-chromium": "^1.5.173", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/bundle-name": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", - "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "run-applescript": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/c12": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", - "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": "^4.0.3", - "confbox": "^0.2.2", - "defu": "^6.1.4", - "dotenv": "^16.6.1", - "exsolve": "^1.0.7", - "giget": "^2.0.0", - "jiti": "^2.4.2", - "ohash": "^2.0.11", - "pathe": "^2.0.3", - "perfect-debounce": "^1.0.0", - "pkg-types": "^2.2.0", - "rc9": "^2.1.2" - }, - "peerDependencies": { - "magicast": "^0.3.5" - }, - "peerDependenciesMeta": { - "magicast": { - "optional": true - } - } - }, - "node_modules/cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/cacache/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/cacache/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cacache/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacache/node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cacache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cacache/node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/cacache/node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cacache/node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/cacache/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/caching-transform": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", - "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasha": "^5.0.0", - "make-dir": "^3.0.0", - "package-hash": "^4.0.0", - "write-file-atomic": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001727", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz", - "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chai": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.1.tgz", - "integrity": "sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A==", - "dev": true, - "license": "MIT", - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true, - "license": "MIT" - }, - "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - } - }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/ci-info": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", - "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/citty": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", - "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "consola": "^3.2.3" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 12" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "license": "ISC", - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true, - "license": "MIT" - }, - "node_modules/compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "dev": true, - "engines": [ - "node >= 6.0" - ], - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/confbox": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", - "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/consola": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", - "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.18.0 || >=16.10.0" - } - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/conventional-changelog": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-6.0.0.tgz", - "integrity": "sha512-tuUH8H/19VjtD9Ig7l6TQRh+Z0Yt0NZ6w/cCkkyzUbGQTnUEmKfGtkC9gGfVgCfOL1Rzno5NgNF4KY8vR+Jo3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "conventional-changelog-angular": "^8.0.0", - "conventional-changelog-atom": "^5.0.0", - "conventional-changelog-codemirror": "^5.0.0", - "conventional-changelog-conventionalcommits": "^8.0.0", - "conventional-changelog-core": "^8.0.0", - "conventional-changelog-ember": "^5.0.0", - "conventional-changelog-eslint": "^6.0.0", - "conventional-changelog-express": "^5.0.0", - "conventional-changelog-jquery": "^6.0.0", - "conventional-changelog-jshint": "^5.0.0", - "conventional-changelog-preset-loader": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-changelog-angular": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.0.0.tgz", - "integrity": "sha512-CLf+zr6St0wIxos4bmaKHRXWAcsCXrJU6F4VdNDrGRK3B8LDLKoX3zuMV5GhtbGkVR/LohZ6MT6im43vZLSjmA==", - "dev": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-changelog-atom": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-5.0.0.tgz", - "integrity": "sha512-WfzCaAvSCFPkznnLgLnfacRAzjgqjLUjvf3MftfsJzQdDICqkOOpcMtdJF3wTerxSpv2IAAjX8doM3Vozqle3g==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-changelog-codemirror": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-5.0.0.tgz", - "integrity": "sha512-8gsBDI5Y3vrKUCxN6Ue8xr6occZ5nsDEc4C7jO/EovFGozx8uttCAyfhRrvoUAWi2WMm3OmYs+0mPJU7kQdYWQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-changelog-conventionalcommits": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-8.0.0.tgz", - "integrity": "sha512-eOvlTO6OcySPyyyk8pKz2dP4jjElYunj9hn9/s0OB+gapTO8zwS9UQWrZ1pmF2hFs3vw1xhonOLGcGjy/zgsuA==", - "dev": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-changelog-core": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-8.0.0.tgz", - "integrity": "sha512-EATUx5y9xewpEe10UEGNpbSHRC6cVZgO+hXQjofMqpy+gFIrcGvH3Fl6yk2VFKh7m+ffenup2N7SZJYpyD9evw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@hutson/parse-repository-url": "^5.0.0", - "add-stream": "^1.0.0", - "conventional-changelog-writer": "^8.0.0", - "conventional-commits-parser": "^6.0.0", - "git-raw-commits": "^5.0.0", - "git-semver-tags": "^8.0.0", - "hosted-git-info": "^7.0.0", - "normalize-package-data": "^6.0.0", - "read-package-up": "^11.0.0", - "read-pkg": "^9.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-changelog-ember": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-5.0.0.tgz", - "integrity": "sha512-RPflVfm5s4cSO33GH/Ey26oxhiC67akcxSKL8CLRT3kQX2W3dbE19sSOM56iFqUJYEwv9mD9r6k79weWe1urfg==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-changelog-eslint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-6.0.0.tgz", - "integrity": "sha512-eiUyULWjzq+ybPjXwU6NNRflApDWlPEQEHvI8UAItYW/h22RKkMnOAtfCZxMmrcMO1OKUWtcf2MxKYMWe9zJuw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-changelog-express": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-5.0.0.tgz", - "integrity": "sha512-D8Q6WctPkQpvr2HNCCmwU5GkX22BVHM0r4EW8vN0230TSyS/d6VQJDAxGb84lbg0dFjpO22MwmsikKL++Oo/oQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-changelog-jquery": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-6.0.0.tgz", - "integrity": "sha512-2kxmVakyehgyrho2ZHBi90v4AHswkGzHuTaoH40bmeNqUt20yEkDOSpw8HlPBfvEQBwGtbE+5HpRwzj6ac2UfA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-changelog-jshint": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-5.0.0.tgz", - "integrity": "sha512-gGNphSb/opc76n2eWaO6ma4/Wqu3tpa2w7i9WYqI6Cs2fncDSI2/ihOfMvXveeTTeld0oFvwMVNV+IYQIk3F3g==", - "dev": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-changelog-preset-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-5.0.0.tgz", - "integrity": "sha512-SetDSntXLk8Jh1NOAl1Gu5uLiCNSYenB5tm0YVeZKePRIgDW9lQImromTwLa3c/Gae298tsgOM+/CYT9XAl0NA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-changelog-writer": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-8.2.0.tgz", - "integrity": "sha512-Y2aW4596l9AEvFJRwFGJGiQjt2sBYTjPD18DdvxX9Vpz0Z7HQ+g1Z+6iYDAm1vR3QOJrDBkRHixHK/+FhkR6Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "conventional-commits-filter": "^5.0.0", - "handlebars": "^4.7.7", - "meow": "^13.0.0", - "semver": "^7.5.2" - }, - "bin": { - "conventional-changelog-writer": "dist/cli/index.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-commits-filter": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-5.0.0.tgz", - "integrity": "sha512-tQMagCOC59EVgNZcC5zl7XqO30Wki9i9J3acbUvkaosCT6JX3EeFwJD7Qqp4MCikRnzS18WXV3BLIQ66ytu6+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-commits-parser": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-6.2.0.tgz", - "integrity": "sha512-uLnoLeIW4XaoFtH37qEcg/SXMJmKF4vi7V0H2rnPueg+VEtFGA/asSCNTcq4M/GQ6QmlzchAEtOoDTtKqWeHag==", - "dev": true, - "license": "MIT", - "dependencies": { - "meow": "^13.0.0" - }, - "bin": { - "conventional-commits-parser": "dist/cli/index.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-recommended-bump": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-10.0.0.tgz", - "integrity": "sha512-RK/fUnc2btot0oEVtrj3p2doImDSs7iiz/bftFCDzels0Qs1mxLghp+DFHMaOC0qiCI6sWzlTDyBFSYuot6pRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@conventional-changelog/git-client": "^1.0.0", - "conventional-changelog-preset-loader": "^5.0.0", - "conventional-commits-filter": "^5.0.0", - "conventional-commits-parser": "^6.0.0", - "meow": "^13.0.0" - }, - "bin": { - "conventional-recommended-bump": "dist/cli/index.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true, - "license": "MIT" - }, - "node_modules/cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/cosmiconfig-typescript-loader": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-6.1.0.tgz", - "integrity": "sha512-tJ1w35ZRUiM5FeTzT7DtYWAFFv37ZLqSRkGi2oeCK1gPhvaWjkAtfXvLmvE1pRfxxp9aQo6ba/Pvg1dKj05D4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "jiti": "^2.4.1" - }, - "engines": { - "node": ">=v18" - }, - "peerDependencies": { - "@types/node": "*", - "cosmiconfig": ">=9", - "typescript": ">=5" - } - }, - "node_modules/cosmiconfig/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/cosmiconfig/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/cosmiconfig/node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/dance": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dance/-/dance-0.1.0.tgz", - "integrity": "sha512-8DrK6yWkBm+p7NxZZGtDqVM38b8Oenyq6tN6ON7LJmogt0KDq3NrCQ1p2RSsV3xT3nosdKoMBQGhMzhO2fEZDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/dancing-links-algorithm": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dancing-links-algorithm/-/dancing-links-algorithm-1.0.1.tgz", - "integrity": "sha512-qaAVAJElYZQ4URgaNW8xvOnaftrVnsbMoZ390yfnv3hlXjzFkPtqUQLigASdooXUb8CSOTA2Ta3Se8ovDjMY9g==", - "dev": true, - "license": "ISC" - }, - "node_modules/dargs": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz", - "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/data-uri-to-buffer": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", - "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/default-browser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", - "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", - "dev": true, - "license": "MIT", - "dependencies": { - "bundle-name": "^4.1.0", - "default-browser-id": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", - "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-require-extensions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", - "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", - "dev": true, - "license": "MIT", - "dependencies": { - "strip-bom": "^4.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defu": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", - "dev": true, - "license": "MIT" - }, - "node_modules/degenerator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", - "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ast-types": "^0.13.4", - "escodegen": "^2.1.0", - "esprima": "^4.0.1" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/destr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", - "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", - "dev": true, - "license": "MIT" - }, - "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "detect-libc": "bin/detect-libc.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/diff": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", - "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dlxlib": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dlxlib/-/dlxlib-1.0.3.tgz", - "integrity": "sha512-cX4v+hUgjn/Gl9gGKfl/4Ravl779nvf00DnfY4iEUM2JUZNI6ZAvUUylNpEAQm8H1XcmP7ppwZRgnNAFmytitQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.182", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.182.tgz", - "integrity": "sha512-Lv65Btwv9W4J9pyODI6EWpdnhfvrve/us5h1WspW8B2Fb0366REPtY3hX7ounk1CkV/TBjWCEvCBBbYbmV0qCA==", - "dev": true, - "license": "ISC" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true, - "license": "MIT" - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/eslint": { - "version": "9.31.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.31.0.tgz", - "integrity": "sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.0", - "@eslint/core": "^0.15.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.31.0", - "@eslint/plugin-kit": "^0.3.1", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.1.tgz", - "integrity": "sha512-dobTkHT6XaEVOo8IO90Q4DOSxnm3Y151QxPJlM/vKC0bVy+d6cVWQZLlFiuZPP0wS6vZwSKeJgKkcS+KfMBlRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.11.7" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", - "prettier": ">=3.0.0" - }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eta": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/eta/-/eta-3.5.0.tgz", - "integrity": "sha512-e3x3FBvGzeCIHhF+zhK8FZA2vC5uFn6b4HJjegUbIWrDb4mJ7JjTGMJY9VGIbRVpmSwHopNiaJibhjIr+HfLug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "url": "https://github.com/eta-dev/eta?sponsor=1" - } - }, - "node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/execa/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/execa/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/exsolve": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", - "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", - "dev": true, - "license": "MIT" - }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "license": "MIT", - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/fast-content-type-parse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz", - "integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "license": "MIT", - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-up-simple": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", - "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "license": "BSD-3-Clause", - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true, - "license": "ISC" - }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fromentries": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs-minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/gauge/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/gauge/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/gauge/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", - "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-uri": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", - "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "basic-ftp": "^5.0.2", - "data-uri-to-buffer": "^6.0.2", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/giget": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", - "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "citty": "^0.1.6", - "consola": "^3.4.0", - "defu": "^6.1.4", - "node-fetch-native": "^1.6.6", - "nypm": "^0.6.0", - "pathe": "^2.0.3" - }, - "bin": { - "giget": "dist/cli.mjs" - } - }, - "node_modules/git-raw-commits": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-5.0.0.tgz", - "integrity": "sha512-I2ZXrXeOc0KrCvC7swqtIFXFN+rbjnC7b2T943tvemIOVNl+XP8YnA9UVwqFhzzLClnSA60KR/qEjLpXzs73Qg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@conventional-changelog/git-client": "^1.0.0", - "meow": "^13.0.0" - }, - "bin": { - "git-raw-commits": "src/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/git-semver-tags": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-8.0.0.tgz", - "integrity": "sha512-N7YRIklvPH3wYWAR2vysaqGLPRcpwQ0GKdlqTiVN5w1UmCdaeY3K8s6DMKRCh54DDdzyt/OAB6C8jgVtb7Y2Fg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@conventional-changelog/git-client": "^1.0.0", - "meow": "^13.0.0" - }, - "bin": { - "git-semver-tags": "src/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/git-up": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/git-up/-/git-up-8.1.1.tgz", - "integrity": "sha512-FDenSF3fVqBYSaJoYy1KSc2wosx0gCvKP+c+PRBht7cAaiCeQlBtfBDX9vgnNOHmdePlSFITVcn4pFfcgNvx3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-ssh": "^1.4.0", - "parse-url": "^9.2.0" - } - }, - "node_modules/git-url-parse": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-16.1.0.tgz", - "integrity": "sha512-cPLz4HuK86wClEW7iDdeAKcCVlWXmrLpb2L+G9goW0Z1dtpNS6BXXSOckUTlJT/LDQViE1QZKstNORzHsLnobw==", - "dev": true, - "license": "MIT", - "dependencies": { - "git-up": "^8.1.0" - } - }, - "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/global-directory": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", - "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ini": "4.1.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/hasha": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", - "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-stream": "^2.0.0", - "type-fest": "^0.8.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "license": "MIT", - "bin": { - "he": "bin/he" - } - }, - "node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true, - "license": "MIT" - }, - "node_modules/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=16.17.0" - } - }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.0.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-meta-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", - "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/index-to-position": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.1.0.tgz", - "integrity": "sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true, - "license": "ISC" - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/ini": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", - "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/inquirer": { - "version": "12.7.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-12.7.0.tgz", - "integrity": "sha512-KKFRc++IONSyE2UYw9CJ1V0IWx5yQKomwB+pp3cWomWs+v2+ZsG11G2OVfAjFS6WWCppKw+RfKmpqGfSzD5QBQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.14", - "@inquirer/prompts": "^7.6.0", - "@inquirer/type": "^3.0.7", - "ansi-escapes": "^4.3.2", - "mute-stream": "^2.0.0", - "run-async": "^4.0.4", - "rxjs": "^7.8.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/ip-address/node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-interactive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", - "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-ssh": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.1.tgz", - "integrity": "sha512-JNeu1wQsHjyHgn9NcWTaXq6zWSR6hqE0++zhfZlkFBbScNkyvxCdeV8sRkSBaeLKxmbpR21brail63ACNxJ0Tg==", - "dev": true, - "license": "MIT", - "dependencies": { - "protocols": "^2.0.1" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-text-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", - "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "text-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-inside-container": "^1.0.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/issue-parser": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-7.0.1.tgz", - "integrity": "sha512-3YZcUUR2Wt1WsapF+S/WiA2WmlW0cWAoPccMqne7AxEBhCdFeTPjfv/Axb8V2gyCgY3nRw+ksZ3xSUX+R47iAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash.capitalize": "^4.2.1", - "lodash.escaperegexp": "^4.1.2", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.uniqby": "^4.7.0" - }, - "engines": { - "node": "^18.17 || >=20.6.1" - } - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-hook": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", - "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "append-transform": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-processinfo": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", - "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", - "dev": true, - "license": "ISC", - "dependencies": { - "archy": "^1.0.0", - "cross-spawn": "^7.0.3", - "istanbul-lib-coverage": "^3.2.0", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-processinfo/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/istanbul-lib-processinfo/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/istanbul-lib-processinfo/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/istanbul-lib-processinfo/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jiti": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", - "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "dev": true, - "license": "MIT" - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "license": "MIT" - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT" - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.capitalize": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", - "integrity": "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.escaperegexp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", - "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.mergewith": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", - "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.startcase": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", - "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.uniqby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", - "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.upperfirst": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", - "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", - "dev": true, - "license": "MIT" - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/loupe": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.4.tgz", - "integrity": "sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==", - "dev": true, - "license": "MIT" - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/macos-release": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-3.4.0.tgz", - "integrity": "sha512-wpGPwyg/xrSp4H4Db4xYSeAr6+cFQGHfspHzDUdYxswDnUW0L5Ov63UuJiSr8NMSpyaChO4u1n0MXUvVPtrN6A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true, - "license": "ISC" + "node": ">=6" + } }, - "node_modules/make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "is-arrayish": "^0.2.1" } }, - "node_modules/make-fetch-happen/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", - "dependencies": { - "debug": "4" - }, "engines": { - "node": ">= 6.0.0" + "node": ">=6" } }, - "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, "engines": { - "node": ">= 6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/make-fetch-happen/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "node_modules/eslint": { + "version": "9.31.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.31.0.tgz", + "integrity": "sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "6", - "debug": "4" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.0", + "@eslint/core": "^0.15.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.31.0", + "@eslint/plugin-kit": "^0.3.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">= 6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "node_modules/make-fetch-happen/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/eslint-plugin-prettier": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.1.tgz", + "integrity": "sha512-dobTkHT6XaEVOo8IO90Q4DOSxnm3Y151QxPJlM/vKC0bVy+d6cVWQZLlFiuZPP0wS6vZwSKeJgKkcS+KfMBlRw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.11.7" }, "engines": { - "node": ">=8" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/make-fetch-happen/node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">= 10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/make-fetch-happen/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/meow": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", - "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 8" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, + "license": "Apache-2.0", "engines": { - "node": ">=8.6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 4" } }, - "node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "mime-db": "^1.54.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 0.6" + "node": "*" } }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, - "license": "ISC", + "license": "BSD-3-Clause", "dependencies": { - "brace-expansion": "^2.0.1" + "estraverse": "^5.1.0" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10" } }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "license": "ISC", + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=4.0" } }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, + "license": "BSD-2-Clause", "engines": { - "node": ">= 8" + "node": ">=4.0" } }, - "node_modules/minipass-collect/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, + "license": "BSD-2-Clause", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/minipass-collect/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "license": "MIT", "dependencies": { - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" + "node": ">=8.6.0" } }, - "node_modules/minipass-fetch/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "license": "ISC", "dependencies": { - "yallist": "^4.0.0" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/minipass-fetch/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, - "license": "ISC" + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.3.tgz", + "integrity": "sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, "license": "ISC", "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" + "reusify": "^1.0.4" } }, - "node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "flat-cache": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=16.0.0" } }, - "node_modules/minipass-flush/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "minipass": "^3.0.0" + "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minipass-pipeline/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, - "license": "ISC" + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "minipass": "^3.0.0" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, "engines": { - "node": ">=8" + "node": ">=16" } }, - "node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, "license": "ISC", "dependencies": { - "yallist": "^4.0.0" + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">=8" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/minipass-sized/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 8" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/minizlib/node_modules/yallist": { + "node_modules/git-raw-commits": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", + "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==", + "deprecated": "Deprecated and no longer maintained. Use @conventional-changelog/git-client instead.", "dev": true, "license": "MIT", + "dependencies": { + "dargs": "^8.0.0", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, "bin": { - "mkdirp": "bin/cmd.js" + "git-raw-commits": "cli.mjs" }, "engines": { - "node": ">=10" + "node": ">=16" } }, - "node_modules/mocha": { - "version": "11.7.5", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", - "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "browser-stdout": "^1.3.1", - "chokidar": "^4.0.1", - "debug": "^4.3.5", - "diff": "^7.0.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^10.4.5", - "he": "^1.2.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^9.0.5", - "ms": "^2.1.3", - "picocolors": "^1.1.1", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^9.2.0", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1", - "yargs-unparser": "^2.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" + "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "argparse": "^2.0.1" + "is-glob": "^4.0.3" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=10.13.0" } }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/global-directory": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", + "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "ini": "4.1.1" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "license": "ISC", + "license": "MIT", "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nan": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.23.0.tgz", - "integrity": "sha512-1UxuyYGdoQHcGg87Lkqm3FzefucTa0NAiOcuRsDmysep3c1LVCRK2krrUDafMWtjSG04htvAmvg96+SDknOmgQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/natural-compare": { + "node_modules/graphemer": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, "license": "MIT" }, - "node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, - "license": "MIT" + "license": "MIT", + "bin": { + "he": "bin/he" + } }, - "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4.0" + "node": ">= 4" } }, - "node_modules/new-github-release-url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/new-github-release-url/-/new-github-release-url-2.0.0.tgz", - "integrity": "sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ==", + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "license": "MIT", "dependencies": { - "type-fest": "^2.5.1" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/new-github-release-url/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=12.20" - }, + "license": "MIT", "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "node": ">=0.8.19" + } + }, + "node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/node-fetch-native": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", - "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true, "license": "MIT" }, - "node_modules/node-gyp": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.1.tgz", - "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, "engines": { - "node": "^12.13 || ^14.13 || >=16" + "node": ">=0.10.0" } }, - "node_modules/node-gyp/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/node-gyp/node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "deprecated": "This package is no longer supported.", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=0.10.0" } }, - "node_modules/node-gyp/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/node-gyp/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-gyp/node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=0.12.0" } }, - "node_modules/node-gyp/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, + "license": "MIT", "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=8" } }, - "node_modules/node-gyp/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/node-gyp/node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, - "license": "ISC", - "dependencies": { - "abbrev": "^1.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, + "license": "MIT", "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=8" } }, - "node_modules/node-gyp/node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "deprecated": "This package is no longer supported.", + "node_modules/is-text-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", + "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" + "text-extensions": "^2.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=8" } }, - "node_modules/node-gyp/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "license": "MIT", + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/node-gyp/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, "license": "ISC" }, - "node_modules/node-gyp/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/node-gyp/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "ansi-regex": "^5.0.1" + "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/node-preload": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", - "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "dev": true, "license": "MIT", - "dependencies": { - "process-on-spawn": "^1.0.0" - }, - "engines": { - "node": ">=8" + "bin": { + "jiti": "lib/jiti-cli.mjs" } }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true, "license": "MIT" }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "node_modules/js-yaml": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", + "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", "dev": true, - "license": "ISC", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", "dependencies": { - "abbrev": "1" + "argparse": "^2.0.1" }, "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/normalize-package-data": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", - "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^7.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } + "license": "MIT" }, - "node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "license": "MIT" }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "license": "MIT" }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "deprecated": "This package is no longer supported.", + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, - "license": "ISC", - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } + "license": "MIT" }, - "node_modules/nyc": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-17.1.0.tgz", - "integrity": "sha512-U42vQ4czpKa0QdI1hu950XuNhYqgoM+ZF1HT+VuUHL9hPfDPVvNQyltmMqdE9bUHMVa+8yNbc3QKTj8zQhlVxQ==", + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", "dev": true, - "license": "ISC", + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "license": "(MIT OR Apache-2.0)", "dependencies": { - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "caching-transform": "^4.0.0", - "convert-source-map": "^1.7.0", - "decamelize": "^1.2.0", - "find-cache-dir": "^3.2.0", - "find-up": "^4.1.0", - "foreground-child": "^3.3.0", - "get-package-type": "^0.1.0", - "glob": "^7.1.6", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^6.0.2", - "istanbul-lib-processinfo": "^2.0.2", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "make-dir": "^3.0.0", - "node-preload": "^0.2.1", - "p-map": "^3.0.0", - "process-on-spawn": "^1.0.0", - "resolve-from": "^5.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "spawn-wrap": "^2.0.0", - "test-exclude": "^6.0.0", - "yargs": "^15.0.2" + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" }, "bin": { - "nyc": "bin/nyc.js" + "JSONStream": "bin.js" }, "engines": { - "node": ">=18" + "node": "*" } }, - "node_modules/nyc/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "json-buffer": "3.0.1" } }, - "node_modules/nyc/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/nyc/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", "dev": true, - "license": "ISC", + "license": "MPL-2.0", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/nyc/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/nyc/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=8" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/nyc/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "*" + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/nyc/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/nyc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "*" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/nyc/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6" + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/nyc/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/nyc/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/nyc/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/nyc/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/nyc/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/nyc/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/lightningcss/node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, + "license": "Apache-2.0", "engines": { "node": ">=8" } }, - "node_modules/nyc/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nyc/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/nyc/node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/nyc/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } + "license": "MIT" }, - "node_modules/nypm": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.1.tgz", - "integrity": "sha512-hlacBiRiv1k9hZFiphPUkfSQ/ZfQzZDzC+8z0wL3lvDAOUu/2NnChkKuMoMjNur/9OpKuz2QsIeiPVN0xM5Q0w==", + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, - "license": "MIT", - "dependencies": { - "citty": "^0.1.6", - "consola": "^3.4.2", - "pathe": "^2.0.3", - "pkg-types": "^2.2.0", - "tinyexec": "^1.0.1" - }, - "bin": { - "nypm": "dist/cli.mjs" - }, - "engines": { - "node": "^14.16.0 || >=16.10.0" - } + "license": "MIT" + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "dev": true, + "license": "MIT" }, - "node_modules/object-assign": { + "node_modules/lodash.snakecase": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, - "node_modules/ohash": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", - "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "node_modules/lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", "dev": true, "license": "MIT" }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } + "license": "MIT" }, - "node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "node_modules/lodash.upperfirst": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", + "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "license": "MIT", "dependencies": { - "mimic-function": "^5.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { - "node": ">=18" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/open": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", - "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "node_modules/loupe": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.4.tgz", + "integrity": "sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==", + "dev": true, + "license": "MIT" + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", "dev": true, "license": "MIT", - "dependencies": { - "default-browser": "^5.2.1", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "wsl-utils": "^0.1.0" - }, "engines": { - "node": ">=18" + "node": ">=16.10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, "engines": { - "node": ">= 0.8.0" + "node": ">= 8" } }, - "node_modules/ora": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", - "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^5.3.0", - "cli-cursor": "^5.0.0", - "cli-spinners": "^2.9.2", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^2.0.0", - "log-symbols": "^6.0.0", - "stdin-discarder": "^0.2.2", - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8.6" } }, - "node_modules/ora/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/ora/node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, - "license": "MIT" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/ora/node_modules/is-unicode-supported": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", - "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, - "license": "MIT", + "license": "ISC", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/ora/node_modules/log-symbols": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", - "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "node_modules/mocha": { + "version": "11.7.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", + "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^5.3.0", - "is-unicode-supported": "^1.3.0" + "browser-stdout": "^1.3.1", + "chokidar": "^4.0.1", + "debug": "^4.3.5", + "diff": "^7.0.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^9.0.5", + "ms": "^2.1.3", + "picocolors": "^1.1.1", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "yargs-unparser": "^2.0.0" }, - "engines": { - "node": ">=18" + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", - "dev": true, - "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/ora/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=18" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/os-name": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-6.1.0.tgz", - "integrity": "sha512-zBd1G8HkewNd2A8oQ8c6BN/f/c9EId7rSUueOLGu28govmUctXmM+3765GwsByv9nYUdrLqHphXlYIc86saYsg==", + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.16", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", + "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", - "dependencies": { - "macos-release": "^3.3.0", - "windows-release": "^6.1.0" + "bin": { + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, "node_modules/p-limit": { @@ -7794,79 +3589,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/pac-proxy-agent": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", - "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tootallnate/quickjs-emscripten": "^0.23.0", - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "get-uri": "^6.0.1", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.6", - "pac-resolver": "^7.0.1", - "socks-proxy-agent": "^8.0.5" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-resolver": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", - "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", - "dev": true, - "license": "MIT", - "dependencies": { - "degenerator": "^5.0.0", - "netmask": "^2.0.2" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/package-hash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", - "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "graceful-fs": "^4.1.15", - "hasha": "^5.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -7888,60 +3610,24 @@ } }, "node_modules/parse-json": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", - "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "index-to-position": "^1.1.0", - "type-fest": "^4.39.1" - }, - "engines": { - "node": ">=18" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-json/node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=16" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse-path": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.1.0.tgz", - "integrity": "sha512-EuCycjZtfPcjWk7KTksnJ5xPMvWGA/6i4zrLYhRG0hGvC3GPU/jGUj3Cy+ZR0v30duV3e23R95T1lE2+lsndSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "protocols": "^2.0.0" - } - }, - "node_modules/parse-url": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-9.2.0.tgz", - "integrity": "sha512-bCgsFI+GeGWPAvAiUv63ZorMeif3/U0zaXABGJbOWt5OH2KCaPHF6S+0ok4aqM9RuIPGyZdx9tR9l13PsW4AYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/parse-path": "^7.0.0", - "parse-path": "^7.0.0" - }, - "engines": { - "node": ">=14.13.0" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -7952,16 +3638,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -7996,13 +3672,6 @@ "dev": true, "license": "ISC" }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, "node_modules/pathval": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", @@ -8013,13 +3682,6 @@ "node": ">= 14.16" } }, - "node_modules/perfect-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", - "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", - "dev": true, - "license": "MIT" - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -8040,85 +3702,33 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/postcss": { + "version": "8.5.19", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.19.tgz", + "integrity": "sha512-Mz8SaolMd8nB+G13WkORcxQKHZ/NE4xXevtkJHVuG+guo9/wYKlIMTKAqGdEmYOXR2ijPjTYNHssizdaVSUNdQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.2.0.tgz", - "integrity": "sha512-2SM/GZGAEkPp3KWORxQZns4M+WSeXbC2HEvmOIJe3Cmiv6ieAJvdVhDldtHqM5J1Y7MrR1XhkBT/rMlhh9FdqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "confbox": "^0.2.2", - "exsolve": "^1.0.7", - "pathe": "^2.0.3" + "node": "^10 || ^12 || >=14" } }, "node_modules/prelude-ls": { @@ -8137,118 +3747,29 @@ "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", - "peer": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/process-on-spawn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.1.0.tgz", - "integrity": "sha512-JOnOPQ/8TZgjs1JIH/m9ni7FfimjNa/PRx7y/Wb5qdItsnhO0jE4AT7fC0HjC28DUQWDr50dwSYZLdRMlqDq3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "fromentries": "^1.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/promise-retry/node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, "engines": { - "node": ">= 4" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/protocols": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.2.tgz", - "integrity": "sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/proxy-agent": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", - "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.1", - "https-proxy-agent": "^7.0.6", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.1.0", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.5" + "fast-diff": "^1.1.2" }, "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" + "node": ">=6.0.0" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true, - "license": "MIT" - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -8290,96 +3811,6 @@ "safe-buffer": "^5.1.0" } }, - "node_modules/rc9": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", - "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", - "dev": true, - "license": "MIT", - "dependencies": { - "defu": "^6.1.4", - "destr": "^2.0.3" - } - }, - "node_modules/read-package-up": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz", - "integrity": "sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up-simple": "^1.0.0", - "read-pkg": "^9.0.0", - "type-fest": "^4.6.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-package-up/node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", - "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/normalize-package-data": "^2.4.3", - "normalize-package-data": "^6.0.0", - "parse-json": "^8.0.0", - "type-fest": "^4.6.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -8394,68 +3825,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/release-it": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/release-it/-/release-it-19.0.4.tgz", - "integrity": "sha512-W9A26FW+l1wy5fDg9BeAknZ19wV+UvHUDOC4D355yIOZF/nHBOIhjDwutKd4pikkjvL7CpKeF+4zLxVP9kmVEw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/webpro" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/webpro" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "@nodeutils/defaults-deep": "1.1.0", - "@octokit/rest": "21.1.1", - "@phun-ky/typeof": "1.2.8", - "async-retry": "1.3.3", - "c12": "3.1.0", - "ci-info": "^4.3.0", - "eta": "3.5.0", - "git-url-parse": "16.1.0", - "inquirer": "12.7.0", - "issue-parser": "7.0.1", - "lodash.merge": "4.6.2", - "mime-types": "3.0.1", - "new-github-release-url": "2.0.0", - "open": "10.2.0", - "ora": "8.2.0", - "os-name": "6.1.0", - "proxy-agent": "6.5.0", - "semver": "7.7.2", - "tinyglobby": "0.2.14", - "undici": "6.21.3", - "url-join": "5.0.0", - "wildcard-match": "5.1.4", - "yargs-parser": "21.1.1" - }, - "bin": { - "release-it": "bin/release-it.js" - }, - "engines": { - "node": "^20.12.0 || >=22.0.0" - } - }, - "node_modules/release-zalgo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", - "dev": true, - "license": "ISC", - "dependencies": { - "es6-error": "^4.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -8476,13 +3845,6 @@ "node": ">=0.10.0" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true, - "license": "ISC" - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -8493,33 +3855,6 @@ "node": ">=4" } }, - "node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -8634,27 +3969,38 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/run-applescript": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", - "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "node_modules/rolldown": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz", + "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=18" + "dependencies": { + "@oxc-project/types": "=0.139.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-async": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-4.0.5.tgz", - "integrity": "sha512-oN9GTgxUNDBumHTTDmQ8dep6VIJbgj9S3dPP+9XylVLIK4xB9XTXtKWROd5pnhdXR9k0EgO1JRcNh0T+Ny2FsA==", - "dev": true, - "license": "MIT", "engines": { - "node": ">=0.12.0" + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.1.5", + "@rolldown/binding-darwin-arm64": "1.1.5", + "@rolldown/binding-darwin-x64": "1.1.5", + "@rolldown/binding-freebsd-x64": "1.1.5", + "@rolldown/binding-linux-arm-gnueabihf": "1.1.5", + "@rolldown/binding-linux-arm64-gnu": "1.1.5", + "@rolldown/binding-linux-arm64-musl": "1.1.5", + "@rolldown/binding-linux-ppc64-gnu": "1.1.5", + "@rolldown/binding-linux-s390x-gnu": "1.1.5", + "@rolldown/binding-linux-x64-gnu": "1.1.5", + "@rolldown/binding-linux-x64-musl": "1.1.5", + "@rolldown/binding-openharmony-arm64": "1.1.5", + "@rolldown/binding-wasm32-wasi": "1.1.5", + "@rolldown/binding-win32-arm64-msvc": "1.1.5", + "@rolldown/binding-win32-x64-msvc": "1.1.5" } }, "node_modules/run-parallel": { @@ -8681,16 +4027,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/rxjs": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", - "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -8712,13 +4048,6 @@ ], "license": "MIT" }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "license": "MIT" - }, "node_modules/semver": { "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", @@ -8727,253 +4056,67 @@ "license": "ISC", "bin": { "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true, - "license": "ISC" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.6.tgz", - "integrity": "sha512-pe4Y2yzru68lXCb38aAqRf5gvN8YdjP1lok5o0J7BOHljkyCGKVz7H3vpVIXKD27rj2giOJ7DwVyk/GWrPHDWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", - "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/spawn-wrap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", - "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^2.0.0", - "is-windows": "^1.0.2", - "make-dir": "^3.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "which": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/spawn-wrap/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + }, + "engines": { + "node": ">=10" } }, - "node_modules/spawn-wrap/node_modules/foreground-child": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, - "license": "ISC", + "license": "BSD-3-Clause", "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8.0.0" + "randombytes": "^2.1.0" } }, - "node_modules/spawn-wrap/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "shebang-regex": "^3.0.0" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=8" } }, - "node_modules/spawn-wrap/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/spawn-wrap/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "engines": { + "node": ">=14" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/spawn-wrap/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.21", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", - "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", - "dev": true, - "license": "CC0-1.0" - }, "node_modules/split2": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", @@ -8984,69 +4127,6 @@ "node": ">= 10.x" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/ssri/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ssri/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/stdin-discarder": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", - "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -9151,29 +4231,6 @@ "node": ">=8" } }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -9216,102 +4273,6 @@ "url": "https://opencollective.com/synckit" } }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=8" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/text-extensions": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", @@ -9332,80 +4293,14 @@ "dev": true, "license": "MIT" }, - "node_modules/tinybench": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-6.0.0.tgz", - "integrity": "sha512-BWlWpVbbZXaYjRV0twGLNQO00Zj4HA/sjLOQP2IvzQqGwRGp+2kh7UU3ijyJ3ywFRogYDRbiHDMrUOfaMnN56g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20.0.0" - } - }, "node_modules/tinyexec": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", - "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyglobby": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", - "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.6", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", - "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", "dev": true, "license": "MIT", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, "engines": { - "node": ">=0.6.0" + "node": ">=18" } }, "node_modules/to-regex-range": { @@ -9421,13 +4316,6 @@ "node": ">=8.0" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true, - "license": "MIT" - }, "node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -9500,46 +4388,20 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, - "license": "0BSD" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true, - "license": "MIT" + "license": "0BSD", + "optional": true }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", "dependencies": { - "is-typedarray": "^1.0.0" + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" } }, "node_modules/typescript": { @@ -9548,7 +4410,6 @@ "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -9557,30 +4418,6 @@ "node": ">=14.17" } }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", - "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/undici": { - "version": "6.21.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz", - "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.17" - } - }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", @@ -9601,70 +4438,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "dev": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/universal-user-agent": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", - "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", - "dev": true, - "license": "ISC" - }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -9675,33 +4448,6 @@ "punycode": "^2.1.0" } }, - "node_modules/url-join": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", - "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -9709,146 +4455,146 @@ "dev": true, "license": "MIT" }, - "node_modules/v8-profiler-next": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/v8-profiler-next/-/v8-profiler-next-1.10.0.tgz", - "integrity": "sha512-HME7CR3V8gkBEAutcMyGS0vK0XH2hFQhF5SvSdrF/mdjWIGoaiY+WH3RpY7ePY7J7vNDbQfP+Ikefdi1z/mJXg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@xprofiler/node-pre-gyp": "^1.0.9", - "nan": "^2.18.0" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "node_modules/vite": { + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.4.tgz", + "integrity": "sha512-bTT9PsdWO+MQMNG9ZXIP/qM9wGh37DFxTV/sPq9cFpHr3w4jkgef032PkAL9jAqhk3Nz8NQw3O8n6/xFkqO4QQ==", "dev": true, "license": "MIT", "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" + "lightningcss": "^1.32.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.16", + "rolldown": "~1.1.4", + "tinyglobby": "^0.2.17" }, "bin": { - "node-which": "bin/node-which" + "vite": "bin/vite.js" }, "engines": { - "node": ">= 8" - } - }, - "node_modules/which-module": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.3.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } } }, - "node_modules/wide-align/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/wide-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/wide-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "dev": true, "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/vite/node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "fdir": "^6.5.0", + "picomatch": "^4.0.4" }, "engines": { - "node": ">=8" + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/wildcard-match": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/wildcard-match/-/wildcard-match-5.1.4.tgz", - "integrity": "sha512-wldeCaczs8XXq7hj+5d/F38JE2r7EXgb6WQDM84RVwxy81T/sxB5e9+uZLK9Q9oNz1mlvjut+QtvgaOQFPVq/g==", - "dev": true, - "license": "ISC" - }, - "node_modules/windows-release": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-6.1.0.tgz", - "integrity": "sha512-1lOb3qdzw6OFmOzoY0nauhLG72TpWtb5qgYPiSh/62rjc1XidBSDio2qw0pwHh17VINF217ebIkZJdFLZFn9SA==", + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "execa": "^8.0.1" + "isexe": "^2.0.0" }, - "engines": { - "node": ">=18" + "bin": { + "node-which": "bin/node-which" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">= 8" } }, "node_modules/word-wrap": { @@ -9861,13 +4607,6 @@ "node": ">=0.10.0" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true, - "license": "MIT" - }, "node_modules/workerpool": { "version": "9.3.3", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.3.tgz", @@ -9970,49 +4709,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/write-file-atomic/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/wsl-utils": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", - "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-wsl": "^3.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -10023,13 +4719,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -10168,19 +4857,6 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/yoctocolors-cjs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", - "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } } } } diff --git a/package.json b/package.json index 410d42c..2d76b61 100644 --- a/package.json +++ b/package.json @@ -1,104 +1,44 @@ { - "name": "dancing-links", - "version": "4.3.9", - "description": "Fastest JS solver for exact cover problems using Dancing Links", - "author": "Tim Beyer", - "license": "MIT", - "homepage": "https://github.com/TimBeyer/dancing-links", - "repository": { - "type": "git", - "url": "https://github.com/TimBeyer/dancing-links.git" - }, - "bugs": { - "url": "https://github.com/TimBeyer/dancing-links/issues" - }, + "name": "cover-story-prototype", + "version": "0.1.0", + "private": true, + "description": "A real-time stealth game driven by the live solution space of an exact-cover problem", "type": "module", - "main": "built/lib/index.js", - "types": "built/typings/index.d.ts", - "exports": { - ".": { - "types": "./built/typings/index.d.ts", - "import": "./built/lib/index.js" - } - }, "engines": { - "node": ">=20.0.0" - }, - "directories": { - "test": "test" + "node": ">=20.19.0" }, - "keywords": [ - "dlx", - "dancing links", - "algorithm x", - "exact cover", - "knuth" - ], "scripts": { - "clean": "rimraf built", - "build": "npm run clean && tsc", - "prepare": "npm run build", - "test": "npm run test-unit", - "test-watch": "npm run test-unit -- --watch", - "test-unit": "NODE_ENV=test mocha --loader=ts-node/esm 'test/unit/**/*.spec.ts'", - "cover": "nyc npm run test-unit", - "coverage": "npm run cover && nyc report --reporter=text-lcov > coverage.lcov", - "lint": "eslint --ext .ts .", - "lint:fix": "eslint --ext .ts . --fix", - "format": "prettier --write '**/*.{ts,js,json,md}' '!CHANGELOG.md'", - "format:check": "prettier --check '**/*.{ts,js,json,md}' '!CHANGELOG.md'", - "build:dev": "npm run clean && tsc -p tsconfig.dev.json", - "benchmark": "npm run build:dev && node built/benchmark/index.js --internal", - "benchmark:json": "npm run build:dev && node built/benchmark/index.js --internal --json", - "benchmark:competitive": "npm run build:dev && node built/benchmark/index.js --competitive", - "benchmark:comprehensive": "npm run build:dev && node built/benchmark/index.js --comprehensive", - "compare-benchmarks": "npm run build:dev && node built/scripts/compare-benchmarks.js", - "update-benchmark-docs": "npm run build:dev && node built/scripts/update-benchmark-docs.js", - "update-benchmark-docs:dry-run": "npm run build:dev && node built/scripts/update-benchmark-docs.js --dry-run", - "profile": "npm run build:dev && node built/benchmark/profile.js", - "release": "release-it" + "dev": "vite", + "clean": "rimraf dist", + "build": "npm run clean && tsc --noEmit && vite build", + "test": "NODE_ENV=test mocha --loader=ts-node/esm 'test/game/**/*.spec.ts'", + "test:watch": "npm test -- --watch", + "lint": "eslint src test/game vite.config.ts", + "lint:fix": "npm run lint -- --fix", + "format": "prettier --write 'src/**/*.{ts,css}' 'test/game/**/*.ts' 'index.html' 'README.md' 'package.json' 'vite.config.ts'", + "format:check": "prettier --check 'src/**/*.{ts,css}' 'test/game/**/*.ts' 'index.html' 'README.md' 'package.json' 'vite.config.ts'" }, - "nyc": { - "per-file": true, - "include": [ - "index.ts", - "lib/**/*.ts" - ], - "exclude": [ - "test/**/*.spec.ts", - "test/**/*.ts", - "node_modules/**/*" - ], - "extension": [ - ".ts" - ], - "all": true, - "sourceMap": true + "dependencies": { + "dancing-links": "^4.3.9" }, "devDependencies": { "@commitlint/cli": "^19.8.1", "@commitlint/config-conventional": "^19.8.1", - "@release-it/conventional-changelog": "^10.0.1", + "@eslint/js": "^9.18.0", "@types/chai": "^5.2.2", "@types/mocha": "^10.0.10", "@types/node": "^22.10.4", "@typescript-eslint/eslint-plugin": "^8.18.2", "@typescript-eslint/parser": "^8.18.2", "chai": "^5.2.1", - "dance": "^0.1.0", - "dancing-links-algorithm": "^1.0.1", - "dlxlib": "^1.0.3", "eslint": "^9.18.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.2.1", "mocha": "^11.7.5", - "nyc": "^17.1.0", "prettier": "^3.4.2", - "release-it": "^19.0.4", "rimraf": "^6.0.1", - "tinybench": "^6.0.0", "ts-node": "^10.9.2", "typescript": "^5.7.3", - "v8-profiler-next": "^1.10.0" + "vite": "^8.1.4" } } diff --git a/scripts/compare-benchmarks.ts b/scripts/compare-benchmarks.ts deleted file mode 100755 index 09f85e5..0000000 --- a/scripts/compare-benchmarks.ts +++ /dev/null @@ -1,302 +0,0 @@ -#!/usr/bin/env node - -/** - * Benchmark Comparison Script - * - * Compares benchmark results between baseline and PR branches. - * Parsing logic is abstracted to easily switch from text to structured data. - */ - -import { readFileSync } from 'fs' - -interface BenchmarkResult { - name: string - benchmarkName: string - libraryName: string - opsPerSec: number - margin: number - runs?: number - deprecated?: boolean -} - -interface BenchmarkSection { - benchmarkName: string - results: Array<{ - name: string - opsPerSec: number - margin: number - runs: number - deprecated?: boolean - }> -} - -interface ComparisonResult { - name: string - baseline: BenchmarkResult - pr: BenchmarkResult - percentChange: number -} - -/** - * Parser interface for benchmark results - * Abstract away parsing logic to easily replace with structured data parser - */ -class BenchmarkParser { - /** - * Parse structured JSON benchmark output - */ - static parse(output: string): BenchmarkResult[] { - try { - const benchmarkSections: BenchmarkSection[] = JSON.parse(output) - const results: BenchmarkResult[] = [] - - for (const section of benchmarkSections) { - const { benchmarkName, results: sectionResults } = section - - for (const result of sectionResults) { - results.push({ - name: `${benchmarkName} | ${result.name}`, - benchmarkName: benchmarkName, - libraryName: result.name, - opsPerSec: result.opsPerSec, - margin: result.margin, - runs: result.runs, - deprecated: result.deprecated || false - }) - } - } - - return results - } catch (error) { - console.error('Failed to parse benchmark JSON:', error) - console.error('Output length:', output.length, 'characters') - console.error( - 'Output preview:', - output.substring(0, 100).replace(/[^\x20-\x7E]/g, '?') + '...' - ) - return [] - } - } -} - -/** - * Compare benchmark results and generate comparison report - */ -class BenchmarkComparator { - private baselineResults: BenchmarkResult[] - private prResults: BenchmarkResult[] - - constructor(baselineResults: BenchmarkResult[], prResults: BenchmarkResult[]) { - this.baselineResults = baselineResults - this.prResults = prResults - } - - /** - * Generate markdown comparison table - */ - generateMarkdown(): string { - const comparisons = this.calculateComparisons() - - if (this.baselineResults.length === 0 && this.prResults.length === 0) { - return '❌ Both baseline and PR benchmarks failed to run.' - } - - if (this.baselineResults.length === 0) { - return '❌ Baseline benchmark failed to run. Cannot compare results.' - } - - if (this.prResults.length === 0) { - return '❌ PR benchmark failed to run. Cannot compare results.' - } - - let markdown = '## 🚀 Benchmark Results\n\n' - - // Show comparisons for matched results - if (comparisons.length > 0) { - const groupedComparisons = this.groupComparisonsByBenchmark(comparisons) - - for (const [benchmarkName, benchmarkComparisons] of Object.entries(groupedComparisons)) { - markdown += `### ${benchmarkName}\n\n` - markdown += '| Library | Baseline (ops/sec) | PR (ops/sec) | Change | Performance |\n' - markdown += '|---------|-------------------|--------------|---------|-------------|\n' - - for (const comp of benchmarkComparisons) { - const changeSign = comp.percentChange >= 0 ? '+' : '' - const performanceIcon = this.getPerformanceIcon(comp.percentChange) - const libraryName = comp.pr.deprecated - ? `${comp.pr.libraryName} (deprecated)` - : comp.pr.libraryName - - markdown += `| ${libraryName} ` - markdown += `| ${comp.baseline.opsPerSec.toLocaleString()} Âą${comp.baseline.margin.toFixed(2)}% ` - markdown += `| ${comp.pr.opsPerSec.toLocaleString()} Âą${comp.pr.margin.toFixed(2)}% ` - markdown += `| ${changeSign}${comp.percentChange.toFixed(2)}% ` - markdown += `| ${performanceIcon} |\n` - } - - markdown += '\n' - } - } - - // Show raw results for unmatched items - const unmatchedResults = this.getUnmatchedResults(comparisons) - if (unmatchedResults.baselineOnly.length > 0 || unmatchedResults.prOnly.length > 0) { - markdown += '### Unmatched Results\n\n' - - if (unmatchedResults.baselineOnly.length > 0) { - markdown += '#### Baseline Only\n\n' - markdown += this.generateRawResultsTable(unmatchedResults.baselineOnly) - } - - if (unmatchedResults.prOnly.length > 0) { - markdown += '#### PR Only\n\n' - markdown += this.generateRawResultsTable(unmatchedResults.prOnly) - } - } - - // If no comparisons at all, show everything as raw - if (comparisons.length === 0) { - markdown += 'âš ī¸ No matching benchmark names found between baseline and PR.\n\n' - markdown += '### Raw Baseline Results\n\n' - markdown += this.generateRawResultsTable(this.baselineResults) - markdown += '\n### Raw PR Results\n\n' - markdown += this.generateRawResultsTable(this.prResults) - } - - markdown += `*Updated: ${new Date().toISOString()}*\n` - - return markdown - } - - /** - * Group comparisons by benchmark type for cleaner display - */ - groupComparisonsByBenchmark(comparisons: ComparisonResult[]): Record { - const grouped: Record = {} - - for (const comp of comparisons) { - const benchmarkName = comp.pr.benchmarkName - if (!grouped[benchmarkName]) { - grouped[benchmarkName] = [] - } - grouped[benchmarkName].push(comp) - } - - // Sort libraries within each benchmark for consistency - for (const benchmarkName of Object.keys(grouped)) { - grouped[benchmarkName].sort((a, b) => a.pr.libraryName.localeCompare(b.pr.libraryName)) - } - - return grouped - } - - /** - * Get unmatched results from baseline and PR - */ - getUnmatchedResults(comparisons: ComparisonResult[]) { - const matchedNames = new Set(comparisons.map(c => c.name)) - - const baselineOnly = this.baselineResults.filter(b => !matchedNames.has(b.name)) - const prOnly = this.prResults.filter(p => !matchedNames.has(p.name)) - - return { baselineOnly, prOnly } - } - - /** - * Calculate performance comparisons between baseline and PR - */ - calculateComparisons(): ComparisonResult[] { - const comparisons: ComparisonResult[] = [] - - for (const prResult of this.prResults) { - const baselineResult = this.baselineResults.find(b => b.name === prResult.name) - - if (baselineResult) { - const percentChange = - ((prResult.opsPerSec - baselineResult.opsPerSec) / baselineResult.opsPerSec) * 100 - - comparisons.push({ - name: prResult.name, - baseline: baselineResult, - pr: prResult, - percentChange - }) - } - } - - return comparisons - } - - /** - * Generate raw results table when no comparisons are possible - */ - generateRawResultsTable(results: BenchmarkResult[]): string { - if (results.length === 0) { - return '*No results available*\n' - } - - let markdown = '| Benchmark | Library | ops/sec | Margin | Runs |\n' - markdown += '|-----------|---------|---------|--------|------|\n' - - for (const result of results) { - const libraryName = result.deprecated - ? `${result.libraryName} (deprecated)` - : result.libraryName - markdown += `| ${result.benchmarkName} | ${libraryName} ` - markdown += `| ${result.opsPerSec.toLocaleString()} | Âą${result.margin.toFixed(2)}% ` - markdown += `| ${result.runs || 'N/A'} |\n` - } - - return markdown + '\n' - } - - /** - * Get performance indicator icon based on percentage change - */ - getPerformanceIcon(percentChange: number): string { - if (percentChange >= 10) return '🚀 Significant improvement' - if (percentChange >= 2) return '✅ Improvement' - if (percentChange >= -2) return 'âžĄī¸ No significant change' - if (percentChange >= -10) return 'âš ī¸ Minor regression' - return '🔴 Significant regression' - } -} - -/** - * Main function - */ -function main(): void { - const args = process.argv.slice(2) - - if (args.length !== 2) { - console.error('Usage: node compare-benchmarks.ts ') - process.exit(1) - } - - const [baselineFile, prFile] = args - - try { - // Read benchmark output files - const baselineOutput = readFileSync(baselineFile, 'utf8') - const prOutput = readFileSync(prFile, 'utf8') - - // Parse results using abstracted parser - const baselineResults = BenchmarkParser.parse(baselineOutput) - const prResults = BenchmarkParser.parse(prOutput) - - // Generate comparison report - const comparator = new BenchmarkComparator(baselineResults, prResults) - const markdown = comparator.generateMarkdown() - - // Output markdown for GitHub comment - console.log(markdown) - } catch (error) { - console.error('Error comparing benchmarks:', (error as Error).message) - process.exit(1) - } -} - -// Run if called directly -if (process.argv[1] && process.argv[1].endsWith('compare-benchmarks.js')) { - main() -} diff --git a/scripts/update-benchmark-docs.ts b/scripts/update-benchmark-docs.ts deleted file mode 100644 index 23da747..0000000 --- a/scripts/update-benchmark-docs.ts +++ /dev/null @@ -1,381 +0,0 @@ -#!/usr/bin/env node - -/** - * Automated Benchmark Documentation Updater - * - * Runs comprehensive benchmarks, compares against other JS Dancing Links libraries, - * and updates the README with performance comparison tables. - * - * Integrates into the release process to ensure benchmark documentation stays current. - */ - -import { exec } from 'child_process' -import { readFile, writeFile } from 'fs/promises' -import { join, dirname } from 'path' -import { fileURLToPath } from 'url' -import { promisify } from 'util' -import type { BenchmarkResult, BenchmarkSection } from '../benchmark/index.js' - -const execAsync = promisify(exec) - -/** - * Configuration for script execution - */ -interface UpdateOptions { - quiet: boolean - dryRun: boolean - benchmarkTimeout: number -} - -/** - * Processed results for documentation generation - */ -interface ProcessedResult extends BenchmarkResult { - libraryName: string - relativePerformance: number - isFastest: boolean -} - -interface ProcessedSection { - benchmarkName: string - results: ProcessedResult[] - fastestResult: ProcessedResult -} - -/** - * Main benchmark documentation updater class - */ -class BenchmarkDocUpdater { - private options: UpdateOptions - private projectRoot: string - - constructor(options: Partial = {}) { - this.options = { - quiet: false, - dryRun: false, - benchmarkTimeout: 300000, // 5 minutes - ...options - } - - const __filename = fileURLToPath(import.meta.url) - const __dirname = dirname(__filename) - - // When running the compiled script, we need to go up two levels: built/scripts -> built -> project root - this.projectRoot = __dirname.endsWith('/built/scripts') - ? join(__dirname, '..', '..') // from built/scripts to project root - : join(__dirname, '..') // from scripts to project root (when running TypeScript directly) - } - - /** - * Run the complete benchmark documentation update process - */ - async updateBenchmarkDocs(): Promise { - try { - this.log('Starting benchmark documentation update...') - - // Step 1: Run benchmarks and get JSON results - const benchmarkData = await this.runBenchmarks() - - // Step 2: Process results for documentation - const processedSections = this.processBenchmarkData(benchmarkData) - - // Step 3: Generate markdown tables - const benchmarkMarkdown = this.generateBenchmarkMarkdown(processedSections) - - // Step 4: Update README - await this.updateReadme(benchmarkMarkdown) - - this.log('Benchmark documentation update completed successfully') - } catch (error) { - const errorMessage = error instanceof Error ? error.message : 'Unknown error' - throw new Error(`Failed to update benchmark documentation: ${errorMessage}`) - } - } - - /** - * Run comprehensive benchmarks with external library comparisons - */ - protected async runBenchmarks(): Promise { - this.log('Running comprehensive benchmarks with external library comparisons...') - - try { - // First ensure dev build is up to date - this.log('Building development version...') - await execAsync('npm run build:dev', { - cwd: this.projectRoot, - timeout: 60000, // 1 minute for build - encoding: 'utf8' - }) - - // Then run benchmarks directly to get clean JSON output - const benchmarkPath = join(this.projectRoot, 'built', 'benchmark', 'index.js') - const benchmarkCommand = `node "${benchmarkPath}" --competitive --json --quiet` - - const { stdout, stderr } = await execAsync(benchmarkCommand, { - cwd: this.projectRoot, - timeout: this.options.benchmarkTimeout, - encoding: 'utf8' - }) - - if (stderr) { - this.log(`Benchmark warnings: ${stderr}`) - } - - // Parse clean JSON output - const benchmarkData: BenchmarkSection[] = JSON.parse(stdout.trim()) - - this.log(`Successfully completed benchmarks: ${benchmarkData.length} sections`) - return benchmarkData - } catch (error) { - if (error instanceof Error) { - // Handle specific error cases - if ('code' in error && (error as any).code === 'ETIMEDOUT') { - throw new Error(`Benchmarks timed out after ${this.options.benchmarkTimeout / 1000}s`) - } - - if ('stderr' in error && (error as any).stderr) { - throw new Error(`Benchmark execution failed: ${(error as any).stderr}`) - } - } - - throw new Error(`Failed to run benchmarks: ${error}`) - } - } - - /** - * Process benchmark data to calculate relative performance metrics - */ - protected processBenchmarkData(sections: BenchmarkSection[]): ProcessedSection[] { - return sections.map(section => { - // Find the fastest result in this section - const fastestResult = section.results.reduce((fastest, current) => - current.opsPerSec > fastest.opsPerSec ? current : fastest - ) - - // Process all results with relative performance - const processedResults: ProcessedResult[] = section.results.map(result => ({ - ...result, - libraryName: result.name, - relativePerformance: result.opsPerSec / fastestResult.opsPerSec, - isFastest: result.opsPerSec === fastestResult.opsPerSec - })) - - // Sort by performance (fastest first) - processedResults.sort((a, b) => b.opsPerSec - a.opsPerSec) - - return { - benchmarkName: section.benchmarkName, - results: processedResults, - fastestResult: processedResults[0] - } - }) - } - - /** - * Generate markdown tables for benchmark results - */ - protected generateBenchmarkMarkdown(sections: ProcessedSection[]): string { - const timestamp = new Date().toISOString().split('T')[0] - - let markdown = `## Benchmarks - -This section contains performance comparisons against other JavaScript Dancing Links libraries, updated automatically during releases. - -` - - // Add benchmark content directly - markdown += `All benchmarks run on the same machine with identical test cases. Results show operations per second (higher is better). - -` - - // Generate tables for each benchmark type - for (const section of sections) { - markdown += `### ${section.benchmarkName} - -| Library | Ops/Sec | Relative Performance | Margin of Error | -|---------|---------|---------------------|-----------------| -` - - for (const result of section.results) { - const relativeFormatted = result.isFastest - ? '**1.00x (fastest)**' - : `${result.relativePerformance.toFixed(2)}x` - - markdown += `| ${result.libraryName} | ${result.opsPerSec.toFixed(2)} | ${relativeFormatted} | Âą${result.margin.toFixed(2)}% |\n` - } - - markdown += '\n' - } - - // Add footnotes and metadata - markdown += `**Testing Environment:** -- Node.js ${process.version} -- Test cases: Sudoku solving, pentomino tiling (1, 10, 100 solutions) - -*Last updated: ${timestamp}* - -` - - return markdown - } - - /** - * Update README.md with new benchmark section - */ - private async updateReadme(benchmarkMarkdown: string): Promise { - const readmePath = join(this.projectRoot, 'README.md') - - try { - let readmeContent = await readFile(readmePath, 'utf8') - - // Define markers for the benchmark section - const startMarker = '## Benchmarks' - const endMarker = '## Contributing' - - // Check if benchmark section already exists - const startIndex = readmeContent.indexOf(startMarker) - const endIndex = readmeContent.indexOf(endMarker) - - if (startIndex === -1) { - // No existing benchmark section - add before Contributing - if (endIndex === -1) { - // No Contributing section - add at the end - readmeContent += '\n' + benchmarkMarkdown - } else { - // Insert before Contributing - readmeContent = - readmeContent.slice(0, endIndex) + - benchmarkMarkdown + - '\n' + - readmeContent.slice(endIndex) - } - } else { - // Replace existing benchmark section - if (endIndex === -1 || endIndex < startIndex) { - // Benchmark section exists but no end marker - replace to end of file - readmeContent = readmeContent.slice(0, startIndex) + benchmarkMarkdown - } else { - // Replace section between markers - readmeContent = - readmeContent.slice(0, startIndex) + benchmarkMarkdown + readmeContent.slice(endIndex) - } - } - - if (this.options.dryRun) { - this.log('DRY RUN: Would update README.md with new benchmark section') - this.log(`New benchmark section length: ${benchmarkMarkdown.length} characters`) - } else { - await writeFile(readmePath, readmeContent) - this.log('Successfully updated README.md with new benchmark results') - - // Format the README.md file to ensure consistent formatting - await this.formatReadme() - } - } catch (error) { - throw new Error(`Failed to update README.md: ${error}`) - } - } - - /** - * Format the README.md file using Prettier - */ - private async formatReadme(): Promise { - try { - this.log('Formatting README.md with Prettier...') - - await execAsync('npm run format -- README.md', { - cwd: this.projectRoot, - timeout: 30000, // 30 seconds for formatting - encoding: 'utf8' - }) - - this.log('Successfully formatted README.md') - } catch (error) { - // Don't fail the whole process if formatting fails, just warn - this.log(`Warning: Failed to format README.md: ${error}`) - } - } - - /** - * Log message (respects quiet mode) - */ - protected log(message: string): void { - if (!this.options.quiet) { - console.log(`[benchmark-docs] ${message}`) - } - } -} - -/** - * Parse command line arguments - */ -function parseArgs(): UpdateOptions & { help?: boolean } { - const args = process.argv.slice(2) - - return { - quiet: args.includes('--quiet'), - dryRun: args.includes('--dry-run'), - help: args.includes('--help') || args.includes('-h'), - benchmarkTimeout: 300000 // 5 minutes default - } -} - -/** - * Show usage information - */ -function showUsage(): void { - console.log(` -Usage: node scripts/update-benchmark-docs.js [options] - -Updates README.md with current benchmark results comparing against other -JavaScript Dancing Links libraries. - -Options: - --quiet Suppress progress output - --dry-run Show what would be changed without modifying files - --help, -h Show this help message - -Examples: - node built/scripts/update-benchmark-docs.js # Update with progress output - node built/scripts/update-benchmark-docs.js --quiet # Update silently - node built/scripts/update-benchmark-docs.js --dry-run # Preview changes only - -The script runs comprehensive benchmarks including external library comparisons -and automatically updates the README with formatted comparison tables. -`) -} - -/** - * Main execution function - */ -async function main(): Promise { - const options = parseArgs() - - if (options.help) { - showUsage() - process.exit(0) - } - - try { - const updater = new BenchmarkDocUpdater(options) - await updater.updateBenchmarkDocs() - - if (!options.quiet) { - console.log('✅ Benchmark documentation update completed successfully') - } - } catch (error) { - const message = error instanceof Error ? error.message : 'Unknown error occurred' - console.error(`❌ ${message}`) - process.exit(1) - } -} - -// Run if called directly -if (process.argv[1] && process.argv[1].endsWith('update-benchmark-docs.js')) { - main().catch(error => { - console.error('Unhandled error:', error) - process.exit(1) - }) -} - -export { BenchmarkDocUpdater, type UpdateOptions } diff --git a/src/audio.ts b/src/audio.ts new file mode 100644 index 0000000..d0a1ace --- /dev/null +++ b/src/audio.ts @@ -0,0 +1,60 @@ +export class AudioDirector { + private context?: AudioContext + + unlock(): void { + if (!this.context) this.context = new window.AudioContext() + void this.context.resume() + } + + step(): void { + this.tone(155, 0.035, 'sine', 0.018) + } + + echo(): void { + this.tone(620, 0.08, 'sine', 0.055, 0) + this.tone(930, 0.12, 'sine', 0.025, 0.06) + } + + jam(): void { + this.tone(105, 0.16, 'square', 0.045) + } + + pickup(): void { + this.tone(420, 0.12, 'triangle', 0.045, 0) + this.tone(680, 0.18, 'triangle', 0.045, 0.1) + this.tone(980, 0.24, 'triangle', 0.035, 0.21) + } + + alert(): void { + this.tone(125, 0.28, 'sawtooth', 0.07, 0) + this.tone(92, 0.3, 'sawtooth', 0.06, 0.2) + } + + success(): void { + for (let index = 0; index < 4; index += 1) { + this.tone(360 + index * 145, 0.24, 'triangle', 0.04, index * 0.11) + } + } + + private tone( + frequency: number, + duration: number, + type: OscillatorType, + volume: number, + delay = 0 + ): void { + if (!this.context) return + const startedAt = this.context.currentTime + delay + const oscillator = this.context.createOscillator() + const gain = this.context.createGain() + oscillator.type = type + oscillator.frequency.setValueAtTime(frequency, startedAt) + gain.gain.setValueAtTime(0.0001, startedAt) + gain.gain.exponentialRampToValueAtTime(volume, startedAt + 0.012) + gain.gain.exponentialRampToValueAtTime(0.0001, startedAt + duration) + oscillator.connect(gain) + gain.connect(this.context.destination) + oscillator.start(startedAt) + oscillator.stop(startedAt + duration + 0.03) + } +} diff --git a/src/game.ts b/src/game.ts new file mode 100644 index 0000000..1ac7c15 --- /dev/null +++ b/src/game.ts @@ -0,0 +1,904 @@ +import { AudioDirector } from './audio.js' +import { + createSchedule, + type RoutePlan, + type ScheduleDuty, + type ScheduleResult +} from './schedule.js' +import { + clamp, + distanceSquared, + DOOR_EDGE_IDS, + EDGE_BY_ID, + ENTRY_NODE, + EXHIBITS, + GAME_GRAPH, + lineOfSightClear, + moveWithCollisions, + nearestNode, + NODE_BY_ID, + ROUTINE_NODES, + VAULT_NODE, + WORLD_HEIGHT, + WORLD_WIDTH +} from './world.js' + +interface Player { + x: number + y: number + facing: number + heat: number + hasDossier: boolean +} + +interface GuardActor { + readonly id: string + readonly name: string + readonly color: string + readonly startNode: number + node: number + fromNode: number + targetNode: number + x: number + y: number + facing: number +} + +interface ActiveDuty extends ScheduleDuty { + readonly createdBeat: number +} + +type GameMode = 'title' | 'playing' | 'paused' | 'won' | 'lost' + +const PLAYER_RADIUS = 12 +const PLAYER_SPEED = 205 +const ECHO_RANGE = 275 +const DOOR_RANGE = 74 +const MAX_ECHOES = 3 +const MAX_JAMS = 2 +const GUARD_VISION_RANGE = 205 +const GUARD_VISION_HALF_ANGLE = 0.58 +const GUARD_STARTS = [0, 9, 13] as const + +export class CoverStoryGame { + private readonly context: CanvasRenderingContext2D + private readonly keys = new Set() + private readonly audio = new AudioDirector() + private readonly objective = requiredElement('objective') + private readonly objectiveDetail = requiredElement('objective-detail') + private readonly objectiveDot = requiredElement('objective-dot') + private readonly futureCount = requiredElement('future-count') + private readonly solveTime = requiredElement('solve-time') + private readonly routeCount = requiredElement('route-count') + private readonly beatCount = requiredElement('beat-count') + private readonly heatValue = requiredElement('heat-value') + private readonly heatFill = requiredElement('heat-fill') + private readonly echoCount = requiredElement('echo-count') + private readonly jamCount = requiredElement('jam-count') + private readonly lifeCount = requiredElement('life-count') + private readonly toastElement = requiredElement('toast') + private readonly overlay = requiredElement('overlay') + private readonly overlayTitle = requiredElement('overlay-title') + private readonly overlayCopy = requiredElement('overlay-copy') + private readonly tutorial = requiredElement('tutorial') + private readonly startButton = requiredElement('start-button') + + private mode: GameMode = 'title' + private player: Player = { x: 80, y: 630, facing: 0, heat: 0, hasDossier: false } + private guards: GuardActor[] = [] + private duties: ActiveDuty[] = [] + private schedule?: ScheduleResult + private chosenPlans = new Map() + private jammedDoors = new Map() + private beatProgress = 0 + private beatNumber = 0 + private routineCursor = 0 + private echoCharges = MAX_ECHOES + private jamCharges = MAX_JAMS + private lives = 3 + private alerts = 0 + private elapsedSeconds = 0 + private lastFrame = performance.now() + private toastUntil = 0 + private immunityUntil = 0 + private caughtFlash = 0 + private cursor = { x: 600, y: 360, inside: false } + private lastFootstep = 0 + + constructor(private readonly canvas: HTMLCanvasElement) { + const context = canvas.getContext('2d') + if (!context) throw new Error('Canvas 2D is required to run Cover Story') + this.context = context + this.bindInput() + this.startButton.addEventListener('click', () => { + if (this.mode === 'paused') this.togglePause() + else this.start() + }) + requestAnimationFrame(time => this.frame(time)) + } + + private start(): void { + this.audio.unlock() + this.lives = 3 + this.alerts = 0 + this.elapsedSeconds = 0 + this.caughtFlash = 0 + this.resetPatrol() + this.mode = 'playing' + this.overlay.classList.add('hidden') + this.toast('Read the futures. Move between them.', '#65e8ff') + } + + private resetPatrol(): void { + const entry = NODE_BY_ID.get(ENTRY_NODE) + if (!entry) throw new Error('Missing entry node') + this.player = { x: entry.x, y: entry.y, facing: 0, heat: 0, hasDossier: false } + this.echoCharges = MAX_ECHOES + this.jamCharges = MAX_JAMS + this.beatProgress = 0 + this.beatNumber = 0 + this.routineCursor = 0 + this.duties = [] + this.jammedDoors.clear() + this.guards = [ + this.createGuard('amber', 'AMBER', '#ffd36b', GUARD_STARTS[0]), + this.createGuard('violet', 'VIOLET', '#c780ff', GUARD_STARTS[1]), + this.createGuard('red', 'RED', '#ff657c', GUARD_STARTS[2]) + ] + this.addRoutineDuty() + this.planBeat() + this.immunityUntil = performance.now() + 900 + } + + private createGuard(id: string, name: string, color: string, startNode: number): GuardActor { + const node = NODE_BY_ID.get(startNode) + if (!node) throw new Error(`Missing guard start node ${startNode}`) + return { + id, + name, + color, + startNode, + node: startNode, + fromNode: startNode, + targetNode: startNode, + x: node.x, + y: node.y, + facing: 0 + } + } + + private bindInput(): void { + window.addEventListener('keydown', event => { + const key = event.key.toLowerCase() + this.keys.add(key) + if (['arrowup', 'arrowdown', 'arrowleft', 'arrowright', ' '].includes(key)) { + event.preventDefault() + } + + if ( + key === 'enter' && + (this.mode === 'title' || this.mode === 'won' || this.mode === 'lost') + ) { + this.start() + } else if (key === 'escape' && (this.mode === 'playing' || this.mode === 'paused')) { + this.togglePause() + } else if (key === 'r' && this.mode !== 'title') { + this.start() + } else if (key === 'e' && this.mode === 'playing') { + this.tryJamDoor() + } else if (key === ' ' && this.mode === 'playing') { + this.tryInteract() + } + }) + window.addEventListener('keyup', event => this.keys.delete(event.key.toLowerCase())) + window.addEventListener('blur', () => this.keys.clear()) + + this.canvas.addEventListener('pointermove', event => { + this.cursor = { ...this.toWorldPosition(event), inside: true } + }) + this.canvas.addEventListener('pointerleave', () => { + this.cursor.inside = false + }) + this.canvas.addEventListener('pointerdown', event => { + if (event.button !== 0 || this.mode !== 'playing') return + this.audio.unlock() + this.throwEcho(this.toWorldPosition(event)) + }) + } + + private toWorldPosition(event: PointerEvent): { x: number; y: number } { + const bounds = this.canvas.getBoundingClientRect() + return { + x: ((event.clientX - bounds.left) / bounds.width) * WORLD_WIDTH, + y: ((event.clientY - bounds.top) / bounds.height) * WORLD_HEIGHT + } + } + + private togglePause(): void { + this.mode = this.mode === 'playing' ? 'paused' : 'playing' + if (this.mode === 'paused') { + this.showOverlay('SIGNAL PAUSED', 'The patrol futures are frozen.', 'RESUME', false) + } else { + this.overlay.classList.add('hidden') + this.lastFrame = performance.now() + } + } + + private frame(time: number): void { + const delta = Math.min((time - this.lastFrame) / 1000, 0.05) + this.lastFrame = time + if (this.mode === 'playing') this.update(delta, time) + this.render(time) + this.updateHud(time) + requestAnimationFrame(nextTime => this.frame(nextTime)) + } + + private update(delta: number, time: number): void { + this.elapsedSeconds += delta + this.updatePlayer(delta, time) + this.updatePatrol(delta) + this.updateDetection(delta, time) + this.caughtFlash = Math.max(0, this.caughtFlash - delta * 1.8) + } + + private updatePlayer(delta: number, time: number): void { + let dx = 0 + let dy = 0 + if (this.keys.has('a') || this.keys.has('arrowleft')) dx -= 1 + if (this.keys.has('d') || this.keys.has('arrowright')) dx += 1 + if (this.keys.has('w') || this.keys.has('arrowup')) dy -= 1 + if (this.keys.has('s') || this.keys.has('arrowdown')) dy += 1 + if (dx === 0 && dy === 0) return + + const length = Math.hypot(dx, dy) + dx /= length + dy /= length + this.player.facing = Math.atan2(dy, dx) + const next = moveWithCollisions( + this.player.x, + this.player.y, + dx * PLAYER_SPEED * delta, + dy * PLAYER_SPEED * delta, + PLAYER_RADIUS + ) + this.player.x = next.x + this.player.y = next.y + + if (time - this.lastFootstep > 310) { + this.lastFootstep = time + this.audio.step() + } + } + + private updatePatrol(delta: number): void { + const beatDuration = this.player.hasDossier ? 0.82 : 1.02 + this.beatProgress += delta / beatDuration + const interpolation = smoothstep(clamp(this.beatProgress, 0, 1)) + for (const guard of this.guards) { + const from = NODE_BY_ID.get(guard.fromNode) + const target = NODE_BY_ID.get(guard.targetNode) + if (!from || !target) continue + guard.x = from.x + (target.x - from.x) * interpolation + guard.y = from.y + (target.y - from.y) * interpolation + if (from.id !== target.id) guard.facing = Math.atan2(target.y - from.y, target.x - from.x) + } + + if (this.beatProgress < 1) return + for (const guard of this.guards) { + guard.node = guard.targetNode + guard.fromNode = guard.node + const node = NODE_BY_ID.get(guard.node) + if (node) { + guard.x = node.x + guard.y = node.y + } + } + + this.advanceDuties() + this.advanceDoorJams() + this.beatNumber += 1 + if (!this.duties.some(duty => duty.source === 'routine')) this.addRoutineDuty() + this.planBeat() + } + + private advanceDuties(): void { + const remaining: ActiveDuty[] = [] + for (const duty of this.duties) { + if (duty.slot === 1) continue + remaining.push({ ...duty, slot: duty.slot - 1 }) + } + this.duties = remaining + } + + private advanceDoorJams(): void { + for (const [edgeId, beats] of this.jammedDoors) { + if (beats <= 1) this.jammedDoors.delete(edgeId) + else this.jammedDoors.set(edgeId, beats - 1) + } + } + + private addRoutineDuty(): void { + const node = ROUTINE_NODES[this.routineCursor % ROUTINE_NODES.length] + this.routineCursor += 1 + if (node === undefined) return + this.duties.push({ + id: `routine-${this.beatNumber}-${this.routineCursor}`, + node, + slot: 3, + source: 'routine', + createdBeat: this.beatNumber + }) + } + + private planBeat(): void { + const result = createSchedule({ + graph: GAME_GRAPH, + guards: this.guards.map(guard => ({ id: guard.id, node: guard.node })), + duties: this.duties, + blockedEdgeIds: new Set(this.jammedDoors.keys()), + horizon: 4, + maxSolutions: 128, + maxRoutesPerGuard: 384 + }) + this.schedule = result + this.beatProgress = 0 + + if (result.droppedDutyIds.length > 0) this.recoverDroppedDuties(result) + const selected = result.solutions[Math.floor(Math.random() * result.solutions.length)] + if (!selected) throw new Error('The route-only patrol must always have a solution') + this.chosenPlans = new Map(selected.map(plan => [plan.guardId, plan])) + for (const guard of this.guards) { + guard.fromNode = guard.node + guard.targetNode = this.chosenPlans.get(guard.id)?.nodes[1] ?? guard.node + } + } + + private recoverDroppedDuties(result: ScheduleResult): void { + const dropped = new Set(result.droppedDutyIds) + let refundedEchoes = 0 + for (const duty of this.duties) { + if (dropped.has(duty.id) && duty.source === 'player') refundedEchoes += 1 + } + this.duties = this.duties.filter(duty => !dropped.has(duty.id)) + this.echoCharges = Math.min(MAX_ECHOES, this.echoCharges + refundedEchoes) + if (result.recovery === 'dropped-player-duty') { + this.toast('No valid patrol could hear that echo — charge refunded.', '#ffd36b') + } else { + this.toast('Patrol directive contradicted. Autonomous routes restored.', '#ff657c') + } + } + + private throwEcho(position: { x: number; y: number }): void { + if (this.echoCharges <= 0) { + this.toast('No echo charges left.', '#ff657c') + return + } + if (distanceSquared(this.player.x, this.player.y, position.x, position.y) > ECHO_RANGE ** 2) { + this.toast('That patrol node is out of throwing range.', '#ffd36b') + return + } + + const node = nearestNode(position.x, position.y) + if (distanceSquared(position.x, position.y, node.x, node.y) > 88 ** 2) { + this.toast('Aim closer to a glowing patrol node.', '#ffd36b') + return + } + if (this.duties.some(duty => duty.source === 'player' && duty.node === node.id)) { + this.toast('An echo is already ringing there.', '#ffd36b') + return + } + + this.echoCharges -= 1 + this.duties.push({ + id: `echo-${this.beatNumber}-${performance.now().toFixed(0)}`, + node: node.id, + slot: 2, + source: 'player', + createdBeat: this.beatNumber + }) + this.audio.echo() + this.toast('Echo queued. Watch the next patrol futures bend.', '#65e8ff') + } + + private tryJamDoor(): void { + if (this.jamCharges <= 0) { + this.toast('No gate spikes left.', '#ff657c') + return + } + + let closest: { id: string; distance: number } | undefined + for (const edgeId of DOOR_EDGE_IDS) { + const edge = EDGE_BY_ID.get(edgeId) + const a = edge ? NODE_BY_ID.get(edge.a) : undefined + const b = edge ? NODE_BY_ID.get(edge.b) : undefined + if (!a || !b) continue + const midpointX = (a.x + b.x) / 2 + const midpointY = (a.y + b.y) / 2 + const candidateDistance = distanceSquared(this.player.x, this.player.y, midpointX, midpointY) + if (!closest || candidateDistance < closest.distance) { + closest = { id: edgeId, distance: candidateDistance } + } + } + + if (!closest || closest.distance > DOOR_RANGE ** 2) { + this.toast('Move beside a magenta gate to jam it.', '#ffd36b') + return + } + if (this.jammedDoors.has(closest.id)) { + this.toast('That gate is already jammed.', '#ffd36b') + return + } + + this.jamCharges -= 1 + this.jammedDoors.set(closest.id, 4) + this.audio.jam() + this.toast('Gate jammed for four planning beats.', '#ff70d7') + } + + private tryInteract(): void { + const vault = NODE_BY_ID.get(VAULT_NODE) + const entry = NODE_BY_ID.get(ENTRY_NODE) + if (!vault || !entry) return + + if ( + !this.player.hasDossier && + distanceSquared(this.player.x, this.player.y, vault.x, vault.y) < 52 ** 2 + ) { + this.player.hasDossier = true + this.player.heat = Math.max(this.player.heat, 12) + this.audio.pickup() + this.toast('DOSSIER ACQUIRED — patrol tempo increased.', '#65e8ff') + return + } + if ( + this.player.hasDossier && + distanceSquared(this.player.x, this.player.y, entry.x, entry.y) < 55 ** 2 + ) { + this.win() + return + } + this.toast('Nothing here responds to your cipher.', '#8ea0b5') + } + + private updateDetection(delta: number, time: number): void { + let seen = false + let closestDistance = Number.POSITIVE_INFINITY + for (const guard of this.guards) { + const dx = this.player.x - guard.x + const dy = this.player.y - guard.y + const distance = Math.hypot(dx, dy) + if (distance < 25 && time > this.immunityUntil) { + this.getCaught() + return + } + if (distance > GUARD_VISION_RANGE) continue + const angle = Math.atan2(dy, dx) + if (Math.abs(normalizeAngle(angle - guard.facing)) > GUARD_VISION_HALF_ANGLE) continue + if (!lineOfSightClear(guard.x, guard.y, this.player.x, this.player.y)) continue + seen = true + closestDistance = Math.min(closestDistance, distance) + } + + if (seen && time > this.immunityUntil) { + const proximity = 1 - closestDistance / GUARD_VISION_RANGE + const pressure = this.player.hasDossier ? 58 : 43 + this.player.heat += delta * pressure * (1 + proximity * 0.9) + } else { + this.player.heat -= delta * (this.player.hasDossier ? 20 : 30) + } + this.player.heat = clamp(this.player.heat, 0, 100) + if (this.player.heat >= 100) this.getCaught() + } + + private getCaught(): void { + this.audio.alert() + this.alerts += 1 + this.lives -= 1 + this.caughtFlash = 1 + if (this.lives <= 0) { + this.mode = 'lost' + this.showOverlay( + 'ALL STORIES COLLAPSED', + `The patrol resolved your identity in ${formatTime(this.elapsedSeconds)}.`, + 'TRY ANOTHER FUTURE', + false + ) + return + } + this.resetPatrol() + this.toast('COVER BLOWN — new identity inserted at the entrance.', '#ff657c') + } + + private win(): void { + this.mode = 'won' + const score = Math.max( + 0, + Math.round( + 12000 - + this.elapsedSeconds * 75 - + this.alerts * 1500 + + this.lives * 500 + + (this.echoCharges + this.jamCharges) * 250 + ) + ) + const best = Math.max(Number(localStorage.getItem('cover-story-best') ?? 0), score) + localStorage.setItem('cover-story-best', String(best)) + this.audio.success() + this.showOverlay( + 'THE COVER HOLDS', + `Dossier extracted in ${formatTime(this.elapsedSeconds)} ¡ ${this.alerts} blown ${ + this.alerts === 1 ? 'identity' : 'identities' + } ¡ score ${score.toLocaleString()} ¡ best ${best.toLocaleString()}`, + 'RUN IT AGAIN', + false + ) + } + + private showOverlay(title: string, copy: string, button: string, showTutorial: boolean): void { + this.overlayTitle.textContent = title + this.overlayCopy.textContent = copy + this.startButton.textContent = button + this.tutorial.classList.toggle('hidden', !showTutorial) + this.overlay.classList.remove('hidden') + } + + private toast(message: string, color: string): void { + this.toastElement.textContent = message + this.toastElement.style.setProperty('--toast-color', color) + this.toastElement.classList.add('visible') + this.toastUntil = performance.now() + 2600 + } + + private updateHud(time: number): void { + const sample = this.schedule?.sampledSolutions ?? 0 + this.futureCount.textContent = this.schedule?.solutionLimitReached + ? `${sample}+` + : String(sample) + this.solveTime.textContent = this.schedule ? `${this.schedule.solveMs.toFixed(2)}ms` : '—' + this.routeCount.textContent = String(this.schedule?.candidateRoutes ?? '—') + this.beatCount.textContent = String(this.beatNumber + 1).padStart(2, '0') + this.heatValue.textContent = `${Math.round(this.player.heat)}%` + this.heatFill.style.width = `${this.player.heat}%` + this.heatFill.classList.toggle('danger', this.player.heat > 66) + this.echoCount.textContent = String(this.echoCharges) + this.jamCount.textContent = String(this.jamCharges) + this.lifeCount.textContent = Array.from({ length: 3 }, (_, index) => + index < this.lives ? '●' : '○' + ).join(' ') + + if (this.player.hasDossier) { + this.objective.textContent = 'Extract the dossier' + this.objectiveDetail.textContent = 'Return to the green insertion point' + this.objectiveDot.classList.add('active') + } else { + this.objective.textContent = 'Reach the archive' + this.objectiveDetail.textContent = 'Press Space inside the cyan vault' + this.objectiveDot.classList.remove('active') + } + if (time > this.toastUntil) this.toastElement.classList.remove('visible') + } + + private render(time: number): void { + const context = this.context + context.clearRect(0, 0, WORLD_WIDTH, WORLD_HEIGHT) + this.drawFloor(context) + this.drawGraph(context) + this.drawFutureField(context, time) + this.drawExhibits(context) + this.drawDoors(context, time) + this.drawObjectives(context, time) + this.drawDuties(context, time) + this.drawGuards(context) + this.drawPlayer(context, time) + this.drawCursor(context, time) + + if (this.caughtFlash > 0) { + context.fillStyle = `rgba(255, 50, 82, ${this.caughtFlash * 0.28})` + context.fillRect(0, 0, WORLD_WIDTH, WORLD_HEIGHT) + } + } + + private drawFloor(context: CanvasRenderingContext2D): void { + const gradient = context.createLinearGradient(0, 0, WORLD_WIDTH, WORLD_HEIGHT) + gradient.addColorStop(0, '#0a1220') + gradient.addColorStop(0.55, '#08101b') + gradient.addColorStop(1, '#10101d') + context.fillStyle = gradient + context.fillRect(0, 0, WORLD_WIDTH, WORLD_HEIGHT) + + context.strokeStyle = 'rgba(103, 232, 255, 0.035)' + context.lineWidth = 1 + for (let x = 40; x < WORLD_WIDTH; x += 40) { + context.beginPath() + context.moveTo(x, 0) + context.lineTo(x, WORLD_HEIGHT) + context.stroke() + } + for (let y = 40; y < WORLD_HEIGHT; y += 40) { + context.beginPath() + context.moveTo(0, y) + context.lineTo(WORLD_WIDTH, y) + context.stroke() + } + + context.strokeStyle = 'rgba(127, 154, 180, 0.3)' + context.lineWidth = 3 + context.strokeRect(32, 32, WORLD_WIDTH - 64, WORLD_HEIGHT - 64) + } + + private drawGraph(context: CanvasRenderingContext2D): void { + context.save() + context.strokeStyle = 'rgba(119, 168, 190, 0.11)' + context.lineWidth = 2 + context.setLineDash([4, 12]) + for (const edge of GAME_GRAPH.edges) { + const a = NODE_BY_ID.get(edge.a) + const b = NODE_BY_ID.get(edge.b) + if (!a || !b) continue + context.beginPath() + context.moveTo(a.x, a.y) + context.lineTo(b.x, b.y) + context.stroke() + } + context.setLineDash([]) + for (const node of GAME_GRAPH.nodes) { + context.fillStyle = 'rgba(101, 232, 255, 0.22)' + context.beginPath() + context.arc(node.x, node.y, 3, 0, Math.PI * 2) + context.fill() + } + context.restore() + } + + private drawFutureField(context: CanvasRenderingContext2D, time: number): void { + if (!this.schedule) return + context.save() + context.globalCompositeOperation = 'lighter' + for (const guard of this.guards) { + const moves = this.schedule.nextMoves[guard.id] ?? [] + for (const move of moves) { + const destination = NODE_BY_ID.get(move.node) + const origin = NODE_BY_ID.get(guard.fromNode) + if (!destination || !origin) continue + const pulse = 0.8 + Math.sin(time * 0.004 + move.node) * 0.2 + context.strokeStyle = colorWithAlpha(guard.color, (0.1 + move.probability * 0.4) * pulse) + context.lineWidth = 1 + move.probability * 7 + context.setLineDash(move.node === guard.fromNode ? [2, 7] : [9, 7]) + context.lineDashOffset = -time * 0.018 + context.beginPath() + context.moveTo(origin.x, origin.y) + context.lineTo(destination.x, destination.y) + context.stroke() + + context.fillStyle = colorWithAlpha(guard.color, 0.08 + move.probability * 0.28) + context.beginPath() + context.arc(destination.x, destination.y, 8 + move.probability * 13, 0, Math.PI * 2) + context.fill() + } + } + context.restore() + } + + private drawExhibits(context: CanvasRenderingContext2D): void { + for (const exhibit of EXHIBITS) { + context.save() + context.shadowColor = exhibit.accent + context.shadowBlur = 16 + context.fillStyle = '#111927' + context.strokeStyle = colorWithAlpha(exhibit.accent, 0.42) + context.lineWidth = 2 + context.beginPath() + context.roundRect(exhibit.x, exhibit.y, exhibit.width, exhibit.height, 8) + context.fill() + context.stroke() + context.shadowBlur = 0 + + const inner = context.createLinearGradient( + exhibit.x, + exhibit.y, + exhibit.x + exhibit.width, + exhibit.y + exhibit.height + ) + inner.addColorStop(0, colorWithAlpha(exhibit.accent, 0.22)) + inner.addColorStop(1, 'rgba(4, 9, 16, 0.15)') + context.fillStyle = inner + context.fillRect(exhibit.x + 10, exhibit.y + 10, exhibit.width - 20, exhibit.height - 38) + context.fillStyle = 'rgba(221, 237, 245, 0.52)' + context.font = '9px ui-monospace, SFMono-Regular, Menlo, monospace' + context.fillText(exhibit.title, exhibit.x + 10, exhibit.y + exhibit.height - 12) + context.restore() + } + } + + private drawDoors(context: CanvasRenderingContext2D, time: number): void { + for (const edgeId of DOOR_EDGE_IDS) { + const edge = EDGE_BY_ID.get(edgeId) + const a = edge ? NODE_BY_ID.get(edge.a) : undefined + const b = edge ? NODE_BY_ID.get(edge.b) : undefined + if (!a || !b) continue + const x = (a.x + b.x) / 2 + const y = (a.y + b.y) / 2 + const angle = Math.atan2(b.y - a.y, b.x - a.x) + Math.PI / 2 + const jammed = this.jammedDoors.get(edgeId) + const length = 34 + context.save() + context.translate(x, y) + context.rotate(angle) + context.shadowColor = jammed ? '#ff405f' : '#ff70d7' + context.shadowBlur = jammed ? 18 + Math.sin(time * 0.015) * 6 : 8 + context.strokeStyle = jammed ? '#ff405f' : '#ff70d7' + context.lineWidth = jammed ? 6 : 3 + context.beginPath() + context.moveTo(-length, 0) + context.lineTo(length, 0) + context.stroke() + context.shadowBlur = 0 + context.fillStyle = '#09111c' + context.font = 'bold 9px ui-monospace, SFMono-Regular, Menlo, monospace' + context.textAlign = 'center' + context.fillText(jammed ? `${jammed}▮` : 'GATE', 0, -7) + context.restore() + } + } + + private drawObjectives(context: CanvasRenderingContext2D, time: number): void { + const vault = NODE_BY_ID.get(VAULT_NODE) + const entry = NODE_BY_ID.get(ENTRY_NODE) + if (!vault || !entry) return + const pulse = 1 + Math.sin(time * 0.005) * 0.12 + + context.save() + context.shadowBlur = 22 + context.shadowColor = this.player.hasDossier ? '#526476' : '#65e8ff' + context.fillStyle = this.player.hasDossier ? '#18202c' : '#65e8ff' + context.beginPath() + context.arc(vault.x, vault.y, 17 * pulse, 0, Math.PI * 2) + context.fill() + context.shadowColor = '#78ffa8' + context.fillStyle = this.player.hasDossier ? '#78ffa8' : '#244536' + context.beginPath() + context.arc(entry.x, entry.y, 20 * pulse, 0, Math.PI * 2) + context.fill() + context.shadowBlur = 0 + context.fillStyle = '#071019' + context.font = 'bold 10px ui-monospace, SFMono-Regular, Menlo, monospace' + context.textAlign = 'center' + context.fillText(this.player.hasDossier ? 'EMPTY' : 'VAULT', vault.x, vault.y + 4) + context.fillText(this.player.hasDossier ? 'EXIT' : 'IN', entry.x, entry.y + 4) + context.restore() + } + + private drawDuties(context: CanvasRenderingContext2D, time: number): void { + for (const duty of this.duties) { + const node = NODE_BY_ID.get(duty.node) + if (!node) continue + const color = duty.source === 'player' ? '#65e8ff' : '#ffd36b' + const radius = 23 + ((time * 0.06 + duty.createdBeat * 17) % 28) + context.save() + context.strokeStyle = colorWithAlpha(color, 1 - (radius - 23) / 32) + context.lineWidth = 2 + context.beginPath() + context.arc(node.x, node.y, radius, 0, Math.PI * 2) + context.stroke() + context.fillStyle = color + context.font = 'bold 10px ui-monospace, SFMono-Regular, Menlo, monospace' + context.textAlign = 'center' + context.fillText( + duty.source === 'player' ? `ECHO ${duty.slot}` : `DUTY ${duty.slot}`, + node.x, + node.y - 29 + ) + context.restore() + } + } + + private drawGuards(context: CanvasRenderingContext2D): void { + for (const guard of this.guards) { + const range = GUARD_VISION_RANGE + context.save() + context.translate(guard.x, guard.y) + context.rotate(guard.facing) + const cone = context.createRadialGradient(0, 0, 5, 0, 0, range) + cone.addColorStop(0, colorWithAlpha(guard.color, 0.23)) + cone.addColorStop(0.72, colorWithAlpha(guard.color, 0.09)) + cone.addColorStop(1, colorWithAlpha(guard.color, 0)) + context.fillStyle = cone + context.beginPath() + context.moveTo(0, 0) + context.arc(0, 0, range, -GUARD_VISION_HALF_ANGLE, GUARD_VISION_HALF_ANGLE) + context.closePath() + context.fill() + context.restore() + + context.save() + context.translate(guard.x, guard.y) + context.rotate(guard.facing) + context.shadowColor = guard.color + context.shadowBlur = 14 + context.fillStyle = guard.color + context.beginPath() + context.moveTo(16, 0) + context.lineTo(-10, 11) + context.lineTo(-6, 0) + context.lineTo(-10, -11) + context.closePath() + context.fill() + context.shadowBlur = 0 + context.restore() + + // Keep identity labels in screen space. Rotating them with the actor made + // half the patrol names upside-down and slowed recognition during play. + context.fillStyle = 'rgba(235, 246, 252, 0.74)' + context.font = 'bold 9px ui-monospace, SFMono-Regular, Menlo, monospace' + context.textAlign = 'center' + context.fillText(guard.name, guard.x, guard.y - 20) + } + } + + private drawPlayer(context: CanvasRenderingContext2D, time: number): void { + context.save() + context.translate(this.player.x, this.player.y) + context.shadowColor = this.player.hasDossier ? '#ffffff' : '#65e8ff' + context.shadowBlur = 16 + Math.sin(time * 0.008) * 4 + context.fillStyle = '#ecfbff' + context.beginPath() + context.arc(0, 0, PLAYER_RADIUS, 0, Math.PI * 2) + context.fill() + context.shadowBlur = 0 + context.rotate(this.player.facing) + context.fillStyle = '#071019' + context.beginPath() + context.moveTo(11, 0) + context.lineTo(-3, 5) + context.lineTo(-3, -5) + context.closePath() + context.fill() + if (this.player.hasDossier) { + context.strokeStyle = '#65e8ff' + context.lineWidth = 2 + context.strokeRect(-7, -7, 14, 14) + } + context.restore() + } + + private drawCursor(context: CanvasRenderingContext2D, time: number): void { + if (!this.cursor.inside || this.mode !== 'playing') return + const node = nearestNode(this.cursor.x, this.cursor.y) + const inRange = distanceSquared(this.player.x, this.player.y, node.x, node.y) <= ECHO_RANGE ** 2 + context.save() + context.strokeStyle = inRange ? '#65e8ff' : '#ff657c' + context.globalAlpha = 0.55 + Math.sin(time * 0.01) * 0.2 + context.lineWidth = 2 + context.beginPath() + context.arc(node.x, node.y, 13, 0, Math.PI * 2) + context.stroke() + context.restore() + } +} + +function requiredElement(id: string): T { + const element = document.getElementById(id) + if (!element) throw new Error(`Missing required element #${id}`) + return element as T +} + +function smoothstep(value: number): number { + return value * value * (3 - 2 * value) +} + +function normalizeAngle(angle: number): number { + return Math.atan2(Math.sin(angle), Math.cos(angle)) +} + +function colorWithAlpha(hex: string, alpha: number): string { + const red = Number.parseInt(hex.slice(1, 3), 16) + const green = Number.parseInt(hex.slice(3, 5), 16) + const blue = Number.parseInt(hex.slice(5, 7), 16) + return `rgba(${red}, ${green}, ${blue}, ${clamp(alpha, 0, 1)})` +} + +function formatTime(seconds: number): string { + const minutes = Math.floor(seconds / 60) + const remainder = Math.floor(seconds % 60) + return `${minutes}:${String(remainder).padStart(2, '0')}` +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..4f66869 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,7 @@ +import './styles.css' +import { CoverStoryGame } from './game.js' + +const canvas = document.getElementById('game') +if (!(canvas instanceof HTMLCanvasElement)) throw new Error('Missing game canvas') + +new CoverStoryGame(canvas) diff --git a/src/schedule.ts b/src/schedule.ts new file mode 100644 index 0000000..277c771 --- /dev/null +++ b/src/schedule.ts @@ -0,0 +1,395 @@ +import { DancingLinks } from 'dancing-links' + +export interface NavigationNode { + readonly id: number + readonly x: number + readonly y: number +} + +export interface NavigationEdge { + readonly id: string + readonly a: number + readonly b: number +} + +export interface NavigationGraph { + readonly nodes: readonly NavigationNode[] + readonly edges: readonly NavigationEdge[] +} + +export interface GuardState { + readonly id: string + readonly node: number +} + +export interface ScheduleDuty { + readonly id: string + readonly node: number + readonly slot: number + readonly source: 'routine' | 'player' +} + +export interface RoutePlan { + readonly id: string + readonly guardId: string + /** Includes the guard's current node at index zero. */ + readonly nodes: readonly number[] + readonly coveredDutyIds: readonly string[] +} + +export interface NextMoveWeight { + readonly node: number + readonly count: number + readonly probability: number +} + +export interface ExactScheduleResult { + readonly solutions: readonly (readonly RoutePlan[])[] + readonly nextMoves: Readonly> + readonly sampledSolutions: number + /** True means search stopped at the limit, so more solutions may exist. */ + readonly solutionLimitReached: boolean + readonly candidateRoutes: number + readonly solveMs: number +} + +export interface ScheduleResult extends ExactScheduleResult { + readonly recovery: 'none' | 'dropped-player-duty' | 'dropped-routine-duty' + readonly droppedDutyIds: readonly string[] +} + +export interface ScheduleInput { + readonly graph: NavigationGraph + readonly guards: readonly GuardState[] + readonly duties?: readonly ScheduleDuty[] + readonly blockedEdgeIds?: ReadonlySet + readonly horizon?: number + readonly maxSolutions?: number + readonly maxRoutesPerGuard?: number + readonly random?: () => number +} + +interface RouteConstraint { + readonly data: RoutePlan + readonly columnIndices: { + readonly primary: number[] + readonly secondary: number[] + } +} + +interface Neighbor { + readonly node: number + readonly edgeIndex: number + readonly edgeId: string +} + +const DEFAULT_HORIZON = 4 +const DEFAULT_MAX_SOLUTIONS = 128 +const DEFAULT_MAX_ROUTES_PER_GUARD = 384 + +/** + * Solve the guards' complete joint future as an exact-cover problem. + * + * Primary columns choose exactly one route per guard and service each duty + * exactly once. Secondary columns reserve node/time and undirected edge/time + * pairs at most once, preventing guards from overlapping or crossing through + * one another between planning beats. + */ +export function solveExactSchedule(input: ScheduleInput): ExactScheduleResult { + const startedAt = performance.now() + const horizon = input.horizon ?? DEFAULT_HORIZON + const maxSolutions = input.maxSolutions ?? DEFAULT_MAX_SOLUTIONS + const maxRoutes = input.maxRoutesPerGuard ?? DEFAULT_MAX_ROUTES_PER_GUARD + const duties = input.duties ?? [] + const random = input.random ?? Math.random + + validateInput(input, horizon, maxSolutions, maxRoutes) + + const nodeIndex = new Map(input.graph.nodes.map((node, index) => [node.id, index])) + const edgeIndex = new Map(input.graph.edges.map((edge, index) => [edge.id, index])) + const adjacency = createAdjacency(input.graph, input.blockedEdgeIds ?? new Set()) + const constraints: RouteConstraint[] = [] + + for (let guardIndex = 0; guardIndex < input.guards.length; guardIndex += 1) { + const guard = input.guards[guardIndex] + if (!guard) continue + + const plans = enumerateRoutes(guard, adjacency, duties, horizon, maxRoutes, random) + for (const plan of plans) { + const primary = [guardIndex] + for (let dutyIndex = 0; dutyIndex < duties.length; dutyIndex += 1) { + const duty = duties[dutyIndex] + if (duty && plan.nodes[duty.slot] === duty.node) { + primary.push(input.guards.length + dutyIndex) + } + } + + const secondary: number[] = [] + for (let slot = 1; slot <= horizon; slot += 1) { + const currentNode = plan.nodes[slot] + const previousNode = plan.nodes[slot - 1] + if (currentNode === undefined || previousNode === undefined) continue + + const currentIndex = nodeIndex.get(currentNode) + if (currentIndex === undefined) continue + secondary.push((slot - 1) * input.graph.nodes.length + currentIndex) + + if (currentNode !== previousNode) { + const traversedEdge = findEdge(adjacency, previousNode, currentNode) + const traversedIndex = traversedEdge ? edgeIndex.get(traversedEdge.edgeId) : undefined + if (traversedIndex !== undefined) { + secondary.push( + input.graph.nodes.length * horizon + + (slot - 1) * input.graph.edges.length + + traversedIndex + ) + } + } + } + + constraints.push({ data: plan, columnIndices: { primary, secondary } }) + } + } + + const dlx = new DancingLinks() + const solver = dlx.createSolver({ + primaryColumns: input.guards.length + duties.length, + secondaryColumns: horizon * input.graph.nodes.length + horizon * input.graph.edges.length + }) + + // Route rows are already validated while they are built. Feeding the sparse + // rows as one batch avoids dense zero-filled matrices and repeated public API + // calls; that is the published library's fastest normal ingestion path. + solver.addSparseConstraints(constraints) + const rawSolutions = solver.find(maxSolutions) + const guardOrder = new Map(input.guards.map((guard, index) => [guard.id, index])) + const solutions = rawSolutions.map(solution => + solution + .map(result => result.data) + .sort((a, b) => (guardOrder.get(a.guardId) ?? 0) - (guardOrder.get(b.guardId) ?? 0)) + ) + + return { + solutions, + nextMoves: summarizeNextMoves(input.guards, solutions), + sampledSolutions: solutions.length, + solutionLimitReached: solutions.length === maxSolutions, + candidateRoutes: constraints.length, + solveMs: performance.now() - startedAt + } +} + +/** + * Keep a bad player input from breaking the real-time loop. + * + * The ordinary case performs exactly one solve. Only after a contradiction do + * we retry, newest player duties first, and report every removed duty so the UI + * can fizzle/refund it. If the fixed patrol itself is contradictory, routine + * duties are removed as a final safety valve while collision constraints and + * one-route-per-guard remain intact. + */ +export function createSchedule(input: ScheduleInput): ScheduleResult { + let totalSolveMs = 0 + let result = solveExactSchedule(input) + totalSolveMs += result.solveMs + if (result.solutions.length > 0) { + return withRecovery(result, 'none', [], totalSolveMs) + } + + const duties = [...(input.duties ?? [])] + const droppedDutyIds: string[] = [] + for (let index = duties.length - 1; index >= 0; index -= 1) { + const duty = duties[index] + if (!duty || duty.source !== 'player') continue + + duties.splice(index, 1) + droppedDutyIds.push(duty.id) + result = solveExactSchedule({ ...input, duties }) + totalSolveMs += result.solveMs + if (result.solutions.length > 0) { + return withRecovery(result, 'dropped-player-duty', droppedDutyIds, totalSolveMs) + } + } + + const routineDutyIds = duties.filter(duty => duty.source === 'routine').map(duty => duty.id) + result = solveExactSchedule({ ...input, duties: [] }) + totalSolveMs += result.solveMs + return withRecovery( + result, + 'dropped-routine-duty', + [...droppedDutyIds, ...routineDutyIds], + totalSolveMs + ) +} + +function withRecovery( + result: ExactScheduleResult, + recovery: ScheduleResult['recovery'], + droppedDutyIds: readonly string[], + solveMs: number +): ScheduleResult { + return { ...result, recovery, droppedDutyIds, solveMs } +} + +function validateInput( + input: ScheduleInput, + horizon: number, + maxSolutions: number, + maxRoutes: number +): void { + if (input.guards.length === 0) throw new Error('At least one guard is required') + if (!Number.isInteger(horizon) || horizon < 1) + throw new Error('Horizon must be a positive integer') + if (!Number.isInteger(maxSolutions) || maxSolutions < 1) { + throw new Error('maxSolutions must be a positive integer') + } + if (!Number.isInteger(maxRoutes) || maxRoutes < 1) { + throw new Error('maxRoutesPerGuard must be a positive integer') + } + + const nodeIds = new Set(input.graph.nodes.map(node => node.id)) + const guardIds = new Set() + const occupiedNodes = new Set() + for (const guard of input.guards) { + if (!nodeIds.has(guard.node)) throw new Error(`Guard ${guard.id} starts outside the graph`) + if (guardIds.has(guard.id)) throw new Error(`Duplicate guard id: ${guard.id}`) + if (occupiedNodes.has(guard.node)) throw new Error('Guards must start on distinct nodes') + guardIds.add(guard.id) + occupiedNodes.add(guard.node) + } + + const dutyIds = new Set() + for (const duty of input.duties ?? []) { + if (!nodeIds.has(duty.node)) throw new Error(`Duty ${duty.id} is outside the graph`) + if (duty.slot < 1 || duty.slot > horizon) { + throw new Error(`Duty ${duty.id} falls outside the planning horizon`) + } + if (dutyIds.has(duty.id)) throw new Error(`Duplicate duty id: ${duty.id}`) + dutyIds.add(duty.id) + } +} + +function createAdjacency( + graph: NavigationGraph, + blockedEdgeIds: ReadonlySet +): ReadonlyMap { + const adjacency = new Map() + for (const node of graph.nodes) adjacency.set(node.id, []) + + for (let index = 0; index < graph.edges.length; index += 1) { + const edge = graph.edges[index] + if (!edge || blockedEdgeIds.has(edge.id)) continue + adjacency.get(edge.a)?.push({ node: edge.b, edgeIndex: index, edgeId: edge.id }) + adjacency.get(edge.b)?.push({ node: edge.a, edgeIndex: index, edgeId: edge.id }) + } + return adjacency +} + +function enumerateRoutes( + guard: GuardState, + adjacency: ReadonlyMap, + duties: readonly ScheduleDuty[], + horizon: number, + maxRoutes: number, + random: () => number +): RoutePlan[] { + const paths: number[][] = [] + const path = [guard.node] + + const visit = (slot: number): void => { + if (paths.length >= maxRoutes) return + if (slot > horizon) { + paths.push([...path]) + return + } + + const current = path[path.length - 1] + if (current === undefined) return + const previous = path[path.length - 2] + let options = [...(adjacency.get(current) ?? [])] + + // Immediate reversals add many visually redundant A-B-A futures. When + // another exit exists, omitting them shrinks the row set before DLX sees it; + // dead ends retain reversal so route generation never strands a guard. + if (previous !== undefined && previous !== current && options.length > 1) { + options = options.filter(option => option.node !== previous) + } + + shuffleInPlace(options, random) + const justWaited = previous === current + if (!justWaited || options.length === 0) { + options.push({ node: current, edgeIndex: -1, edgeId: '' }) + } + + for (const option of options) { + path.push(option.node) + visit(slot + 1) + path.pop() + if (paths.length >= maxRoutes) break + } + } + + visit(1) + + const holdingPath = Array.from({ length: horizon + 1 }, () => guard.node) + if (!paths.some(candidate => candidate.every((node, index) => node === holdingPath[index]))) { + paths.push(holdingPath) + } + + // Numeric ids and indices are carried through the hot path. Avoiding string + // parsing and lookup objects per time slot materially reduces allocation when + // the schedule is rebuilt every beat. + return paths.map((nodes, routeIndex) => { + const coveredDutyIds = duties + .filter(duty => nodes[duty.slot] === duty.node) + .map(duty => duty.id) + return { + id: `${guard.id}:${routeIndex}`, + guardId: guard.id, + nodes, + coveredDutyIds + } + }) +} + +function shuffleInPlace(items: T[], random: () => number): void { + for (let index = items.length - 1; index > 0; index -= 1) { + const other = Math.floor(random() * (index + 1)) + const item = items[index] + const replacement = items[other] + if (item === undefined || replacement === undefined) continue + items[index] = replacement + items[other] = item + } +} + +function findEdge( + adjacency: ReadonlyMap, + from: number, + to: number +): Neighbor | undefined { + return adjacency.get(from)?.find(neighbor => neighbor.node === to) +} + +function summarizeNextMoves( + guards: readonly GuardState[], + solutions: readonly (readonly RoutePlan[])[] +): Readonly> { + const summary: Record = {} + for (const guard of guards) { + const counts = new Map() + for (const solution of solutions) { + const plan = solution.find(candidate => candidate.guardId === guard.id) + const next = plan?.nodes[1] + if (next !== undefined) counts.set(next, (counts.get(next) ?? 0) + 1) + } + summary[guard.id] = [...counts] + .map(([node, count]) => ({ + node, + count, + probability: solutions.length === 0 ? 0 : count / solutions.length + })) + .sort((a, b) => b.count - a.count) + } + return summary +} diff --git a/src/styles.css b/src/styles.css new file mode 100644 index 0000000..a015910 --- /dev/null +++ b/src/styles.css @@ -0,0 +1,562 @@ +:root { + color-scheme: dark; + font-family: + Inter, + ui-sans-serif, + system-ui, + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + sans-serif; + background: #050910; + color: #e8f7fb; + font-synthesis: none; + --cyan: #65e8ff; + --magenta: #ff70d7; + --amber: #ffd36b; + --red: #ff657c; + --muted: #8ea0b5; +} + +* { + box-sizing: border-box; +} + +html, +body { + min-width: 320px; + min-height: 100%; + margin: 0; +} + +body { + min-height: 100vh; + overflow-x: hidden; + background: + radial-gradient(circle at 30% -10%, rgba(58, 124, 152, 0.2), transparent 42rem), + radial-gradient(circle at 90% 90%, rgba(117, 37, 103, 0.17), transparent 38rem), #050910; +} + +button, +kbd { + font: inherit; +} + +#app { + width: min(1480px, 100%); + margin: 0 auto; + padding: 20px clamp(12px, 3vw, 46px) 24px; +} + +.masthead, +footer { + display: flex; + align-items: flex-end; + justify-content: space-between; + gap: 24px; +} + +.masthead { + margin-bottom: 12px; +} + +.eyebrow { + margin: 0 0 4px; + color: var(--muted); + font: + 600 10px/1.2 ui-monospace, + SFMono-Regular, + Menlo, + monospace; + letter-spacing: 0.22em; +} + +h1 { + margin: 0; + font-size: clamp(26px, 4vw, 48px); + font-weight: 900; + line-height: 0.95; + letter-spacing: -0.055em; +} + +h1 span { + color: transparent; + -webkit-text-stroke: 1px var(--cyan); + text-shadow: 0 0 24px rgba(101, 232, 255, 0.4); +} + +.solver-badge { + display: flex; + align-items: center; + gap: 9px; + padding: 8px 11px; + border: 1px solid rgba(101, 232, 255, 0.2); + color: var(--cyan); + background: rgba(9, 22, 32, 0.7); + font: + 700 9px/1 ui-monospace, + SFMono-Regular, + Menlo, + monospace; + letter-spacing: 0.12em; +} + +.solver-pulse { + width: 7px; + height: 7px; + border-radius: 50%; + background: var(--cyan); + box-shadow: 0 0 12px var(--cyan); + animation: pulse 1.4s ease-in-out infinite; +} + +.game-shell { + position: relative; + overflow: hidden; + border: 1px solid rgba(114, 163, 186, 0.22); + background: #08101b; + box-shadow: + 0 30px 80px rgba(0, 0, 0, 0.5), + 0 0 0 1px rgba(101, 232, 255, 0.04) inset; +} + +.game-shell::after { + position: absolute; + inset: 0; + z-index: 8; + pointer-events: none; + content: ''; + background: + linear-gradient(rgba(255, 255, 255, 0.016) 50%, transparent 50%) 0 0 / 100% 4px, + radial-gradient(ellipse at center, transparent 55%, rgba(0, 0, 0, 0.42) 100%); + mix-blend-mode: screen; +} + +canvas { + display: block; + width: 100%; + height: auto; + aspect-ratio: 5 / 3; + cursor: crosshair; +} + +.hud, +.heat-panel, +.loadout { + position: absolute; + z-index: 4; + pointer-events: none; + border: 1px solid rgba(130, 176, 197, 0.17); + background: linear-gradient(135deg, rgba(5, 12, 21, 0.88), rgba(8, 17, 28, 0.68)); + backdrop-filter: blur(7px); +} + +.hud { + top: 16px; + min-height: 75px; + padding: 12px 14px; +} + +.hud-left { + left: 16px; + width: min(320px, 32%); +} + +.hud-right { + right: 16px; + display: flex; + align-items: stretch; + gap: 16px; +} + +.hud-label { + margin: 0 0 5px; + color: var(--cyan); + font: + 700 8px/1 ui-monospace, + SFMono-Regular, + Menlo, + monospace; + letter-spacing: 0.2em; +} + +.hud-left strong { + display: block; + overflow: hidden; + font-size: clamp(12px, 1.4vw, 18px); + text-overflow: ellipsis; + white-space: nowrap; +} + +.objective-line { + display: flex; + align-items: center; + gap: 7px; + margin-top: 6px; + color: var(--muted); + font-size: clamp(8px, 0.85vw, 11px); +} + +#objective-dot { + flex: 0 0 auto; + width: 6px; + height: 6px; + border-radius: 50%; + background: var(--cyan); + box-shadow: 0 0 9px var(--cyan); +} + +#objective-dot.active { + background: #78ffa8; + box-shadow: 0 0 9px #78ffa8; +} + +.telemetry-primary { + display: flex; + min-width: 112px; + flex-direction: column; + justify-content: center; + border-right: 1px solid rgba(120, 165, 186, 0.18); +} + +.telemetry-primary span { + color: var(--cyan); + font: + 800 clamp(22px, 2.7vw, 34px) / 0.9 ui-monospace, + SFMono-Regular, + Menlo, + monospace; + text-shadow: 0 0 14px rgba(101, 232, 255, 0.35); +} + +.telemetry-primary small, +.telemetry-grid { + color: var(--muted); + font: + 700 7px/1.4 ui-monospace, + SFMono-Regular, + Menlo, + monospace; + letter-spacing: 0.12em; +} + +.telemetry-primary small { + margin-top: 6px; +} + +.telemetry-grid { + display: grid; + min-width: 95px; + align-content: center; + gap: 4px; +} + +.telemetry-grid b { + float: right; + margin-left: 12px; + color: #e8f7fb; +} + +.heat-panel { + bottom: 18px; + left: 16px; + width: min(280px, 31%); + padding: 10px 12px; +} + +.heat-label { + display: flex; + justify-content: space-between; + margin-bottom: 6px; + color: var(--muted); + font: + 700 8px/1 ui-monospace, + SFMono-Regular, + Menlo, + monospace; + letter-spacing: 0.14em; +} + +.heat-label b { + color: #eefcff; +} + +.heat-track { + height: 5px; + overflow: hidden; + background: rgba(133, 167, 182, 0.13); +} + +#heat-fill { + width: 0; + height: 100%; + background: linear-gradient(90deg, var(--cyan), var(--amber)); + box-shadow: 0 0 10px var(--cyan); + transition: width 70ms linear; +} + +#heat-fill.danger { + background: linear-gradient(90deg, var(--amber), var(--red)); + box-shadow: 0 0 12px var(--red); +} + +.loadout { + right: 16px; + bottom: 18px; + display: flex; + gap: clamp(10px, 2vw, 24px); + padding: 10px 12px; + color: var(--muted); + font: + 700 clamp(7px, 0.75vw, 9px) / 1 ui-monospace, + SFMono-Regular, + Menlo, + monospace; + letter-spacing: 0.08em; +} + +.loadout b { + margin-left: 4px; + color: #eefcff; +} + +kbd { + padding: 2px 4px; + border: 1px solid rgba(101, 232, 255, 0.34); + color: var(--cyan); + background: rgba(101, 232, 255, 0.07); + font-size: inherit; +} + +.toast { + --toast-color: var(--cyan); + position: absolute; + bottom: 72px; + left: 50%; + z-index: 9; + max-width: 70%; + padding: 9px 14px; + transform: translate(-50%, 8px); + border: 1px solid color-mix(in srgb, var(--toast-color), transparent 58%); + opacity: 0; + color: var(--toast-color); + background: rgba(4, 10, 17, 0.9); + box-shadow: 0 0 22px color-mix(in srgb, var(--toast-color), transparent 85%); + font: + 700 clamp(8px, 0.9vw, 11px) / 1.3 ui-monospace, + SFMono-Regular, + Menlo, + monospace; + letter-spacing: 0.06em; + pointer-events: none; + transition: 180ms ease; +} + +.toast.visible { + transform: translate(-50%, 0); + opacity: 1; +} + +.overlay { + position: absolute; + inset: 0; + z-index: 12; + display: grid; + place-items: center; + padding: 24px; + background: + linear-gradient(90deg, rgba(4, 9, 16, 0.88), rgba(4, 9, 16, 0.66)), + radial-gradient(circle at 68% 32%, rgba(101, 232, 255, 0.16), transparent 24rem); + backdrop-filter: blur(7px); + transition: opacity 220ms ease; +} + +.overlay.hidden { + visibility: hidden; + opacity: 0; + pointer-events: none; +} + +.overlay-card { + width: min(690px, 92%); + padding: clamp(22px, 4vw, 48px); + border: 1px solid rgba(101, 232, 255, 0.28); + background: linear-gradient(145deg, rgba(8, 19, 31, 0.96), rgba(8, 12, 23, 0.92)); + box-shadow: + 24px 24px 70px rgba(0, 0, 0, 0.5), + -2px 0 30px rgba(101, 232, 255, 0.06); +} + +.overlay h2 { + margin: 14px 0 12px; + font-size: clamp(30px, 5vw, 62px); + line-height: 0.95; + letter-spacing: -0.055em; +} + +.overlay-copy { + max-width: 570px; + margin: 0; + color: #aabac8; + font-size: clamp(12px, 1.3vw, 16px); + line-height: 1.65; +} + +.tutorial { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 1px; + margin: 28px 0; + background: rgba(120, 161, 181, 0.13); +} + +.tutorial.hidden { + display: none; +} + +.tutorial div { + display: flex; + align-items: center; + gap: 13px; + min-height: 61px; + padding: 10px 13px; + background: #0b1421; +} + +.tutorial b { + color: var(--cyan); + font: + 800 18px/1 ui-monospace, + SFMono-Regular, + Menlo, + monospace; +} + +.tutorial span { + color: var(--muted); + font: + 600 9px/1.45 ui-monospace, + SFMono-Regular, + Menlo, + monospace; +} + +.tutorial strong { + display: block; + color: #eaf8fc; + letter-spacing: 0.08em; +} + +#start-button { + min-width: 220px; + padding: 13px 18px; + border: 1px solid var(--cyan); + color: #061016; + background: var(--cyan); + box-shadow: 0 0 26px rgba(101, 232, 255, 0.25); + font: + 900 10px/1 ui-monospace, + SFMono-Regular, + Menlo, + monospace; + letter-spacing: 0.13em; + cursor: pointer; + transition: 150ms ease; +} + +#start-button:hover, +#start-button:focus-visible { + transform: translateY(-2px); + background: #b5f5ff; + box-shadow: 0 8px 34px rgba(101, 232, 255, 0.35); +} + +.overlay-footnote { + margin: 12px 0 0; + color: #66798c; + font: + 600 8px/1.3 ui-monospace, + SFMono-Regular, + Menlo, + monospace; + letter-spacing: 0.09em; +} + +footer { + padding: 10px 2px 0; + color: #5d7183; + font: + 600 8px/1.4 ui-monospace, + SFMono-Regular, + Menlo, + monospace; + letter-spacing: 0.1em; +} + +footer b { + color: #8ea9b6; +} + +@keyframes pulse { + 0%, + 100% { + transform: scale(0.75); + opacity: 0.55; + } + + 50% { + transform: scale(1); + opacity: 1; + } +} + +@media (max-width: 760px) { + #app { + padding-inline: 7px; + } + + .solver-badge, + footer span:first-child, + .objective-line, + .telemetry-grid, + .loadout span:last-child { + display: none; + } + + .hud { + min-height: auto; + padding: 8px; + } + + .hud-left { + width: 42%; + } + + .hud-right { + gap: 0; + } + + .telemetry-primary { + min-width: 78px; + border: 0; + } + + .heat-panel { + width: 35%; + padding: 7px; + } + + .loadout { + gap: 8px; + padding: 7px; + } + + .tutorial { + grid-template-columns: 1fr; + margin: 16px 0; + } + + .tutorial div { + min-height: 45px; + } +} diff --git a/src/world.ts b/src/world.ts new file mode 100644 index 0000000..9e5c8e5 --- /dev/null +++ b/src/world.ts @@ -0,0 +1,180 @@ +import type { NavigationEdge, NavigationGraph, NavigationNode } from './schedule.js' + +export const WORLD_WIDTH = 1200 +export const WORLD_HEIGHT = 720 + +export interface Rectangle { + readonly x: number + readonly y: number + readonly width: number + readonly height: number + readonly title: string + readonly accent: string +} + +const nodes: NavigationNode[] = [ + { id: 0, x: 80, y: 90 }, + { id: 1, x: 340, y: 90 }, + { id: 2, x: 600, y: 90 }, + { id: 3, x: 860, y: 90 }, + { id: 4, x: 1120, y: 90 }, + { id: 5, x: 80, y: 360 }, + { id: 6, x: 340, y: 360 }, + { id: 7, x: 600, y: 360 }, + { id: 8, x: 860, y: 360 }, + { id: 9, x: 1120, y: 360 }, + { id: 10, x: 80, y: 630 }, + { id: 11, x: 340, y: 630 }, + { id: 12, x: 600, y: 630 }, + { id: 13, x: 860, y: 630 }, + { id: 14, x: 1120, y: 630 } +] + +function edge(a: number, b: number): NavigationEdge { + return { id: `${Math.min(a, b)}-${Math.max(a, b)}`, a, b } +} + +const edges: NavigationEdge[] = [ + edge(0, 1), + edge(1, 2), + edge(2, 3), + edge(3, 4), + edge(5, 6), + edge(6, 7), + edge(7, 8), + edge(8, 9), + edge(10, 11), + edge(11, 12), + edge(12, 13), + edge(13, 14), + edge(0, 5), + edge(5, 10), + edge(1, 6), + edge(6, 11), + edge(2, 7), + edge(7, 12), + edge(3, 8), + edge(8, 13), + edge(4, 9), + edge(9, 14) +] + +export const GAME_GRAPH: NavigationGraph = { nodes, edges } + +export const EXHIBITS: readonly Rectangle[] = [ + { x: 145, y: 165, width: 130, height: 120, title: 'RED STUDY', accent: '#ff546f' }, + { x: 405, y: 165, width: 130, height: 120, title: 'GLASS MEMORY', accent: '#65e8ff' }, + { x: 665, y: 165, width: 130, height: 120, title: 'FALSE SUN', accent: '#ffd36b' }, + { x: 925, y: 165, width: 130, height: 120, title: 'VOID / 7', accent: '#c780ff' }, + { x: 145, y: 435, width: 130, height: 120, title: 'BLUE NOISE', accent: '#65e8ff' }, + { x: 405, y: 435, width: 130, height: 120, title: 'AFTERIMAGE', accent: '#c780ff' }, + { x: 665, y: 435, width: 130, height: 120, title: 'SOFT MACHINE', accent: '#ff546f' }, + { x: 925, y: 435, width: 130, height: 120, title: 'NIGHT BLOOM', accent: '#ffd36b' } +] + +export const DOOR_EDGE_IDS = ['1-2', '6-7', '7-8', '12-13'] as const +export const ROUTINE_NODES = [2, 6, 8, 12, 3, 11, 7, 9, 1, 13] as const +export const ENTRY_NODE = 10 +export const VAULT_NODE = 4 + +// These maps are created once because rendering, hit-testing, and patrol +// interpolation all query them every frame. Rebuilding either map at 60 fps +// would repeat identical array scans without changing gameplay behavior. +export const NODE_BY_ID = new Map(GAME_GRAPH.nodes.map(node => [node.id, node])) +export const EDGE_BY_ID = new Map(GAME_GRAPH.edges.map(item => [item.id, item])) + +export function distanceSquared(ax: number, ay: number, bx: number, by: number): number { + const dx = ax - bx + const dy = ay - by + return dx * dx + dy * dy +} + +export function nearestNode(x: number, y: number): NavigationNode { + let nearest = GAME_GRAPH.nodes[0] + let bestDistance = Number.POSITIVE_INFINITY + for (const node of GAME_GRAPH.nodes) { + const candidateDistance = distanceSquared(x, y, node.x, node.y) + if (candidateDistance < bestDistance) { + nearest = node + bestDistance = candidateDistance + } + } + if (!nearest) throw new Error('The museum requires at least one patrol node') + return nearest +} + +export function lineOfSightClear(ax: number, ay: number, bx: number, by: number): boolean { + return !EXHIBITS.some(obstacle => segmentIntersectsRectangle(ax, ay, bx, by, obstacle, 5)) +} + +export function moveWithCollisions( + x: number, + y: number, + dx: number, + dy: number, + radius: number +): { x: number; y: number } { + let nextX = clamp(x + dx, 34 + radius, WORLD_WIDTH - 34 - radius) + if (EXHIBITS.some(obstacle => circleIntersectsRectangle(nextX, y, radius, obstacle))) { + nextX = x + } + + let nextY = clamp(y + dy, 34 + radius, WORLD_HEIGHT - 34 - radius) + if (EXHIBITS.some(obstacle => circleIntersectsRectangle(nextX, nextY, radius, obstacle))) { + nextY = y + } + return { x: nextX, y: nextY } +} + +function circleIntersectsRectangle( + x: number, + y: number, + radius: number, + rectangle: Rectangle +): boolean { + const nearestX = clamp(x, rectangle.x, rectangle.x + rectangle.width) + const nearestY = clamp(y, rectangle.y, rectangle.y + rectangle.height) + return distanceSquared(x, y, nearestX, nearestY) < radius * radius +} + +function segmentIntersectsRectangle( + ax: number, + ay: number, + bx: number, + by: number, + rectangle: Rectangle, + padding: number +): boolean { + const left = rectangle.x - padding + const right = rectangle.x + rectangle.width + padding + const top = rectangle.y - padding + const bottom = rectangle.y + rectangle.height + padding + + return ( + segmentsIntersect(ax, ay, bx, by, left, top, right, top) || + segmentsIntersect(ax, ay, bx, by, right, top, right, bottom) || + segmentsIntersect(ax, ay, bx, by, right, bottom, left, bottom) || + segmentsIntersect(ax, ay, bx, by, left, bottom, left, top) + ) +} + +function segmentsIntersect( + ax: number, + ay: number, + bx: number, + by: number, + cx: number, + cy: number, + dx: number, + dy: number +): boolean { + const denominator = (ax - bx) * (cy - dy) - (ay - by) * (cx - dx) + if (Math.abs(denominator) < 0.0001) return false + const t = ((ax - cx) * (cy - dy) - (ay - cy) * (cx - dx)) / denominator + const u = -((ax - bx) * (ay - cy) - (ay - by) * (ax - cx)) / denominator + return t >= 0 && t <= 1 && u >= 0 && u <= 1 +} + +export function clamp(value: number, minimum: number, maximum: number): number { + return Math.max(minimum, Math.min(maximum, value)) +} diff --git a/test/game/schedule.spec.ts b/test/game/schedule.spec.ts new file mode 100644 index 0000000..975e548 --- /dev/null +++ b/test/game/schedule.spec.ts @@ -0,0 +1,138 @@ +import { expect } from 'chai' +import { + createSchedule, + solveExactSchedule, + type NavigationGraph, + type ScheduleInput +} from '../../src/schedule.js' + +const lineGraph: NavigationGraph = { + nodes: [ + { id: 0, x: 0, y: 0 }, + { id: 1, x: 1, y: 0 }, + { id: 2, x: 2, y: 0 } + ], + edges: [ + { id: '0-1', a: 0, b: 1 }, + { id: '1-2', a: 1, b: 2 } + ] +} + +const baseInput: ScheduleInput = { + graph: lineGraph, + guards: [ + { id: 'amber', node: 0 }, + { id: 'violet', node: 2 } + ], + horizon: 1, + maxSolutions: 32, + random: () => 0.5 +} + +describe('real-time patrol scheduling', () => { + it('chooses exactly one route per guard and services a duty once', () => { + const result = solveExactSchedule({ + ...baseInput, + duties: [{ id: 'noise', node: 1, slot: 1, source: 'player' }] + }) + + expect(result.solutions.length).to.be.greaterThan(0) + for (const solution of result.solutions) { + expect(solution.map(plan => plan.guardId)).to.have.members(['amber', 'violet']) + expect(solution.filter(plan => plan.nodes[1] === 1)).to.have.length(1) + expect(solution.flatMap(plan => plan.coveredDutyIds)).to.deep.equal(['noise']) + } + }) + + it('uses edge/time constraints to prevent head-on swaps', () => { + const graph: NavigationGraph = { + nodes: [ + { id: 0, x: 0, y: 0 }, + { id: 1, x: 1, y: 0 } + ], + edges: [{ id: 'door', a: 0, b: 1 }] + } + const result = solveExactSchedule({ + graph, + guards: [ + { id: 'left', node: 0 }, + { id: 'right', node: 1 } + ], + horizon: 1, + maxSolutions: 16, + random: () => 0.5 + }) + + for (const solution of result.solutions) { + const left = solution.find(plan => plan.guardId === 'left') + const right = solution.find(plan => plan.guardId === 'right') + expect(left?.nodes[1] === 1 && right?.nodes[1] === 0).to.equal(false) + } + }) + + it('removes jammed edges before candidate routes reach the solver', () => { + const result = solveExactSchedule({ + graph: lineGraph, + guards: [{ id: 'amber', node: 0 }], + blockedEdgeIds: new Set(['0-1']), + horizon: 2, + maxSolutions: 16, + random: () => 0.5 + }) + + expect(result.solutions.length).to.be.greaterThan(0) + for (const solution of result.solutions) { + expect(solution[0]?.nodes).to.deep.equal([0, 0, 0]) + } + }) + + it('reports a contradiction when a required duty is unreachable', () => { + const result = solveExactSchedule({ + graph: lineGraph, + guards: [{ id: 'amber', node: 0 }], + blockedEdgeIds: new Set(['0-1']), + duties: [{ id: 'impossible', node: 1, slot: 1, source: 'player' }], + horizon: 1, + random: () => 0.5 + }) + + expect(result.solutions).to.have.length(0) + }) + + it('drops and reports an impossible player duty, preserving a playable patrol', () => { + const result = createSchedule({ + graph: lineGraph, + guards: [{ id: 'amber', node: 0 }], + blockedEdgeIds: new Set(['0-1']), + duties: [{ id: 'bad-throw', node: 1, slot: 1, source: 'player' }], + horizon: 1, + random: () => 0.5 + }) + + expect(result.recovery).to.equal('dropped-player-duty') + expect(result.droppedDutyIds).to.deep.equal(['bad-throw']) + expect(result.solutions.length).to.be.greaterThan(0) + }) + + it('separately identifies the non-identical routine-duty fallback', () => { + const result = createSchedule({ + graph: lineGraph, + guards: [{ id: 'amber', node: 0 }], + blockedEdgeIds: new Set(['0-1']), + duties: [{ id: 'bad-patrol', node: 1, slot: 1, source: 'routine' }], + horizon: 1, + random: () => 0.5 + }) + + expect(result.recovery).to.equal('dropped-routine-duty') + expect(result.droppedDutyIds).to.deep.equal(['bad-patrol']) + expect(result.solutions[0]?.[0]?.nodes).to.deep.equal([0, 0]) + }) + + it('labels a full sample without claiming that it is the exhaustive count', () => { + const result = solveExactSchedule({ ...baseInput, maxSolutions: 1 }) + + expect(result.sampledSolutions).to.equal(1) + expect(result.solutionLimitReached).to.equal(true) + }) +}) diff --git a/test/unit/complex-constraints.spec.ts b/test/unit/complex-constraints.spec.ts deleted file mode 100644 index da6809f..0000000 --- a/test/unit/complex-constraints.spec.ts +++ /dev/null @@ -1,246 +0,0 @@ -/** - * Comprehensive tests for complex constraint behavior - * - * Complex constraints have: - * - Primary constraints: MUST be covered exactly once - * - Secondary constraints: MAY be covered, but if covered, only once (no collisions) - */ - -import { expect } from 'chai' -import { DancingLinks } from '../../lib/solvers/factory.js' -import type { Result } from '../../lib/types/interfaces.js' - -describe('Complex Constraints', () => { - describe('Basic Complex Constraint Behavior', () => { - it('should handle primary constraints that must be covered exactly once', () => { - // 2 primary, 1 secondary constraint - const dlx = new DancingLinks() - const solver = dlx.createSolver({ primaryColumns: 2, secondaryColumns: 1 }) - - // Row 1: covers primary [0,1], secondary [] - solver.addSparseConstraint('row1', { primary: [0, 1], secondary: [] }) - - // Should find exactly one solution since all primaries are covered - const solutions = solver.findAll() - expect(solutions).to.have.length(1) - expect(solutions[0]).to.have.length(1) - expect(solutions[0][0].data).to.equal('row1') - }) - - it('should allow secondary constraints to be left uncovered', () => { - // 1 primary, 2 secondary constraints - const dlx = new DancingLinks() - const solver = dlx.createSolver({ primaryColumns: 1, secondaryColumns: 2 }) - - // Row 1: covers primary [0], ignores both secondaries - solver.addSparseConstraint('row1', { primary: [0], secondary: [] }) - - // Should find solution even though secondaries are uncovered - const solutions = solver.findAll() - expect(solutions).to.have.length(1) - expect(solutions[0][0].data).to.equal('row1') - }) - - it('should prevent collisions in secondary constraints', () => { - // 2 primary, 1 secondary constraint - const dlx = new DancingLinks() - const solver = dlx.createSolver({ primaryColumns: 2, secondaryColumns: 1 }) - - // Row 1: covers primary [0], secondary [0] - solver.addSparseConstraint('row1', { primary: [0], secondary: [0] }) - - // Row 2: covers primary [1], secondary [0] - COLLISION on secondary [0] - solver.addSparseConstraint('row2', { primary: [1], secondary: [0] }) - - // Row 3: covers primary [1], secondary [] - alternative for primary [1] - solver.addSparseConstraint('row3', { primary: [1], secondary: [] }) - - const solutions = solver.findAll() - - // Should find only 1 solution: [row1, row3] - // Cannot use [row1, row2] due to secondary collision on column 0 - expect(solutions).to.have.length(1) - expect(solutions[0]).to.have.length(2) - - const solutionData = solutions[0].map(row => row.data).sort() - expect(solutionData).to.deep.equal(['row1', 'row3']) - }) - - it('should demonstrate actual secondary constraint collision prevention', () => { - // Test case: 2 primary constraints, 1 secondary constraint - // This will show that two rows cannot both cover the same secondary constraint - const dlx = new DancingLinks() - const solver = dlx.createSolver({ primaryColumns: 2, secondaryColumns: 1 }) - - // Both rows want to use the same secondary constraint [0] - solver.addSparseConstraint('rowA', { primary: [0], secondary: [0] }) - solver.addSparseConstraint('rowB', { primary: [1], secondary: [0] }) - - const solutions = solver.findAll() - - // Should find NO solutions because: - // - Primary [0] requires rowA or some alternative (only rowA available) - // - Primary [1] requires rowB or some alternative (only rowB available) - // - But rowA and rowB both want secondary [0], creating a collision - expect(solutions).to.have.length(0) - }) - }) - - describe('Complex Multi-Row Scenarios', () => { - it('should handle mixed primary/secondary constraint scenarios', () => { - // 2 primary (must cover), 2 secondary (optional, no conflicts) - const dlx = new DancingLinks() - const solver = dlx.createSolver({ primaryColumns: 2, secondaryColumns: 2 }) - - // Row 1: primary [0], secondary [0] - solver.addSparseConstraint('A', { primary: [0], secondary: [0] }) - - // Row 2: primary [1], secondary [1] - solver.addSparseConstraint('B', { primary: [1], secondary: [1] }) - - // Row 3: primary [0,1], secondary [] (covers both primaries, no secondaries) - solver.addSparseConstraint('C', { primary: [0, 1], secondary: [] }) - - const solutions = solver.findAll() - - // Should find 2 solutions: - // Solution 1: Rows A + B (covers all primaries, uses both secondaries) - // Solution 2: Row C only (covers all primaries, leaves secondaries unused) - expect(solutions).to.have.length(2) - - const solutionData = solutions - .map((sol: Result[]) => sol.map((row: Result) => row.data).sort()) - .sort((a: string[], b: string[]) => a.length - b.length) - - expect(solutionData[0]).to.deep.equal(['C']) - expect(solutionData[1]).to.deep.equal(['A', 'B']) - }) - - it('should solve constraint satisfaction with optional secondaries', () => { - // Simulate a simple constraint satisfaction problem: - // Primary: 3 tasks that must be assigned - // Secondary: 2 resources that can be used but aren't required - - const dlx = new DancingLinks() - const solver = dlx.createSolver({ primaryColumns: 3, secondaryColumns: 2 }) - - // Task assignments with optional resource usage - solver.addSparseConstraint('task1_with_resource1', { primary: [0], secondary: [0] }) - solver.addSparseConstraint('task1_no_resource', { primary: [0], secondary: [] }) - solver.addSparseConstraint('task2_with_resource2', { primary: [1], secondary: [1] }) - solver.addSparseConstraint('task2_no_resource', { primary: [1], secondary: [] }) - solver.addSparseConstraint('task3_no_resource', { primary: [2], secondary: [] }) - - const solutions = solver.findAll() - - // Should find multiple valid solutions - expect(solutions.length).to.be.greaterThan(1) - - // Each solution should cover all 3 primary constraints exactly once - for (const solution of solutions) { - expect(solution).to.have.length(3) // One choice per primary constraint - - // Verify each solution has valid structure - for (const row of solution) { - expect(row.data).to.be.a('string') - } - } - }) - }) - - describe('Edge Cases and Error Scenarios', () => { - it('should handle empty secondary constraints', () => { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ primaryColumns: 1, secondaryColumns: 2 }) - - solver.addSparseConstraint('row1', { primary: [0], secondary: [] }) - - const solutions = solver.findAll() - expect(solutions).to.have.length(1) - expect(solutions[0][0].data).to.equal('row1') - }) - - it('should handle empty primary constraints', () => { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ primaryColumns: 1, secondaryColumns: 1 }) - - // Row with no primary coverage - this should not contribute to solutions - // since primary [0] would remain uncovered - solver.addSparseConstraint('secondary_only', { primary: [], secondary: [0] }) - solver.addSparseConstraint('covers_primary', { primary: [0], secondary: [] }) - - const solutions = solver.findAll() - expect(solutions).to.have.length(1) - expect(solutions[0]).to.have.length(1) - expect(solutions[0][0].data).to.equal('covers_primary') - }) - - it('should return one empty solution when there are no primary columns', () => { - const solver = new DancingLinks().createSolver({ - primaryColumns: 0, - secondaryColumns: 2 - }) - solver.addSparseConstraints([ - { data: 'optional-a', columnIndices: { primary: [], secondary: [0] } }, - { data: 'optional-b', columnIndices: { primary: [], secondary: [1] } } - ]) - - // Secondary columns are optional, so choosing no rows is the one exact - // cover. Optional-only rows must not create additional solutions. - expect(solver.findOne()).to.deep.equal([[]]) - expect(solver.find(5)).to.deep.equal([[]]) - expect(solver.findAll()).to.deep.equal([[]]) - expect([...solver.createGenerator()]).to.deep.equal([[]]) - }) - - it('should retain validation in the zero-primary specialization', () => { - const solver = new DancingLinks() - .createSolver({ primaryColumns: 0, secondaryColumns: 1 }) - .validateConstraints() - - expect(() => solver.addSparseConstraint('invalid', { primary: [], secondary: [1] })).to.throw( - 'Secondary column index 1 exceeds secondaryColumns limit of 1' - ) - }) - - it('should handle scenarios with no valid solutions', () => { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ primaryColumns: 2, secondaryColumns: 1 }) - - // Only cover primary [0], leaving primary [1] uncovered - solver.addSparseConstraint('incomplete', { primary: [0], secondary: [0] }) - - const solutions = solver.findAll() - expect(solutions).to.have.length(0) // No solutions since primary [1] uncovered - }) - }) - - describe('Binary Constraint Format Compatibility', () => { - it('should produce identical results for binary and sparse complex constraints', () => { - // Test same problem with both formats - const dlx1 = new DancingLinks() - const sparseSolver = dlx1.createSolver({ primaryColumns: 2, secondaryColumns: 1 }) - - const dlx2 = new DancingLinks() - const binarySolver = dlx2.createSolver({ primaryColumns: 2, secondaryColumns: 1 }) - - // Sparse format - sparseSolver.addSparseConstraint('A', { primary: [0], secondary: [0] }) - sparseSolver.addSparseConstraint('B', { primary: [1], secondary: [] }) - - // Binary format (equivalent) - binarySolver.addBinaryConstraint('A', { primaryRow: [1, 0], secondaryRow: [1] }) - binarySolver.addBinaryConstraint('B', { primaryRow: [0, 1], secondaryRow: [0] }) - - const sparseSolutions = sparseSolver.findAll() - const binarySolutions = binarySolver.findAll() - - expect(sparseSolutions).to.have.length(binarySolutions.length) - expect(sparseSolutions).to.have.length(1) - - // Both should find same solution structure - expect(sparseSolutions[0]).to.have.length(2) - expect(binarySolutions[0]).to.have.length(2) - }) - }) -}) diff --git a/test/unit/constraint-formats.spec.ts b/test/unit/constraint-formats.spec.ts deleted file mode 100644 index 189c364..0000000 --- a/test/unit/constraint-formats.spec.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { expect } from 'chai' -import { DancingLinks } from '../../index.js' - -describe('Constraint Formats', function () { - it('should support sparse constraint format', function () { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: 3 }) - - // Add constraints using sparse format (recommended) - solver.addSparseConstraint(0, [0]) // covers column 0 - solver.addSparseConstraint(1, [1]) // covers column 1 - solver.addSparseConstraint(2, [2]) // covers column 2 - solver.addSparseConstraint(3, [0, 2]) // covers columns 0 and 2 - - const solutions = solver.findAll() - expect(solutions).to.have.length(2) - - const solutionData = [] - for (const solution of solutions) { - const data = [] - for (const result of solution) { - data.push(result.data) - } - data.sort() - solutionData.push(data) - } - - expect(solutionData).to.deep.include([0, 1, 2]) - expect(solutionData).to.deep.include([1, 3]) - }) - - it('should append unchecked sparse batches without overwriting or leaving gaps', function () { - const emptySolver = new DancingLinks().createSolver({ columns: 1 }) - emptySolver.addSparseConstraints([]) - expect(() => emptySolver.findAll()).to.throw('Cannot solve problem with no constraints') - - const solver = new DancingLinks().createSolver({ columns: 3 }) - solver.addSparseConstraint('zero', [0]) - solver.addSparseConstraints([]) - solver.addSparseConstraints([ - { data: 'one', columnIndices: [1] }, - { data: 'two', columnIndices: [2] } - ]) - - const solutions = solver.findAll() - expect(solutions).to.have.length(1) - expect(solutions[0]!.slice().sort((a, b) => a.index - b.index)).to.deep.equal([ - { index: 0, data: 'zero' }, - { index: 1, data: 'one' }, - { index: 2, data: 'two' } - ]) - }) - - it('should commit only completed unchecked rows when reading a later row throws', function () { - const solver = new DancingLinks().createSolver({ columns: 2 }) - const throwingConstraint = { - data: 'invalid', - get columnIndices(): number[] { - throw new Error('input access failed') - } - } - - expect(() => - solver.addSparseConstraints([ - { data: 'kept', columnIndices: [0] }, - throwingConstraint, - { data: 'later', columnIndices: [1] } - ]) - ).to.throw('input access failed') - - solver.addSparseConstraint('replacement', [1]) - const solutions = solver.findAll() - expect(solutions).to.have.length(1) - expect(solutions[0]!.slice().sort((a, b) => a.index - b.index)).to.deep.equal([ - { index: 0, data: 'kept' }, - { index: 1, data: 'replacement' } - ]) - }) - - it('should append after rows added reentrantly by an input getter', function () { - const solver = new DancingLinks().createSolver({ columns: 3 }) - const reentrantConstraint = { - data: 'outer', - get columnIndices(): number[] { - solver.addSparseConstraint('nested', [1]) - return [0] - } - } - - solver.addSparseConstraints([reentrantConstraint, { data: 'later', columnIndices: [2] }]) - - const solutions = solver.findAll() - expect(solutions).to.have.length(1) - expect(solutions[0]!.slice().sort((a, b) => a.index - b.index)).to.deep.equal([ - { index: 0, data: 'nested' }, - { index: 1, data: 'outer' }, - { index: 2, data: 'later' } - ]) - }) - - it('should support binary constraint format for compatibility', function () { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: 3 }) - - // Add constraints using binary format (for compatibility) - solver.addBinaryConstraint(0, [1, 0, 0]) - solver.addBinaryConstraint(1, [0, 1, 0]) - solver.addBinaryConstraint(2, [0, 0, 1]) - solver.addBinaryConstraint(3, [1, 0, 1]) - - const solutions = solver.findAll() - expect(solutions).to.have.length(2) - - const solutionData = [] - for (const solution of solutions) { - const data = [] - for (const result of solution) { - data.push(result.data) - } - data.sort() - solutionData.push(data) - } - - expect(solutionData).to.deep.include([0, 1, 2]) - expect(solutionData).to.deep.include([1, 3]) - }) - - it('should produce identical results for sparse and binary formats', function () { - const dlx = new DancingLinks() - - const sparseSolver = dlx.createSolver({ columns: 3 }) - sparseSolver.addSparseConstraint('s0', [0]) - sparseSolver.addSparseConstraint('s1', [1]) - sparseSolver.addSparseConstraint('s2', [2]) - - const binarySolver = dlx.createSolver({ columns: 3 }) - binarySolver.addBinaryConstraint('b0', [1, 0, 0]) - binarySolver.addBinaryConstraint('b1', [0, 1, 0]) - binarySolver.addBinaryConstraint('b2', [0, 0, 1]) - - const sparseSolutions = sparseSolver.findAll() - const binarySolutions = binarySolver.findAll() - - expect(sparseSolutions).to.have.length(binarySolutions.length) - expect(sparseSolutions[0]).to.have.length(binarySolutions[0]!.length) - }) - - it('should support templates with both constraint formats', function () { - const dlx = new DancingLinks() - const template = dlx.createSolverTemplate({ columns: 3 }) - - // Mix sparse and binary constraints in template - template.addSparseConstraint('sparse-base', [0]) - template.addBinaryConstraint('binary-base', [0, 1, 0]) - - const solver = template.createSolver() - solver.addSparseConstraint('sparse-extra', [2]) - - const solutions = solver.findAll() - expect(solutions).to.have.length.greaterThan(0) - }) -}) diff --git a/test/unit/dancing-links.spec.ts b/test/unit/dancing-links.spec.ts deleted file mode 100644 index a57e9d5..0000000 --- a/test/unit/dancing-links.spec.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { expect } from 'chai' -import { DancingLinks } from '../../index.js' - -describe('DancingLinks Factory', function () { - it('should create a DancingLinks instance', function () { - const dlx = new DancingLinks() - expect(dlx).to.be.instanceOf(DancingLinks) - }) - - it('should create a ProblemSolver', function () { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: 1 }) - - // Add a simple constraint and verify it works - solver.addBinaryConstraint(0, [1]) - expect(() => solver.findAll()).to.not.throw() - }) - - it('should create a SolverTemplate', function () { - const dlx = new DancingLinks() - const template = dlx.createSolverTemplate({ columns: 1 }) - - // Just verify we can create solver from template - expect(() => template.createSolver()).to.not.throw() - }) -}) diff --git a/test/unit/problem-solver.spec.ts b/test/unit/problem-solver.spec.ts deleted file mode 100644 index 4ab8928..0000000 --- a/test/unit/problem-solver.spec.ts +++ /dev/null @@ -1,410 +0,0 @@ -import { expect } from 'chai' -import { DancingLinks } from '../../index.js' -import type { SimpleConstraint } from '../../index.js' -import { search } from '../../lib/core/algorithm.js' -import { ProblemBuilder } from '../../lib/core/problem-builder.js' - -describe('ProblemSolver', function () { - it('should solve a simple exact cover problem', function () { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: 3 }) - - const constraints: SimpleConstraint[] = [ - { data: 0, row: [1, 0, 0] }, - { data: 1, row: [0, 1, 0] }, - { data: 2, row: [0, 0, 1] }, - { data: 3, row: [1, 0, 1] } - ] - - for (const c of constraints) { - solver.addBinaryConstraint(c.data, c.row) - } - - const solutions = solver.findAll() - - expect(solutions).to.have.length(2) - - const solutionData = [] - for (const solution of solutions) { - const data = [] - for (const result of solution) { - data.push(result.data) - } - data.sort() - solutionData.push(data) - } - - expect(solutionData).to.deep.include([0, 1, 2]) - expect(solutionData).to.deep.include([1, 3]) - }) - - it('should support fluent interface for adding constraints', function () { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: 3 }) - - const result = solver - .addBinaryConstraint(0, [1, 0, 0]) - .addBinaryConstraint(1, [0, 1, 0]) - .addBinaryConstraint(2, [0, 0, 1]) - - expect(result).to.equal(solver) - }) - - it('should support findOne, findAll, and find with specific count', function () { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: 3 }) - - solver - .addBinaryConstraint(0, [1, 0, 0]) - .addBinaryConstraint(1, [0, 1, 0]) - .addBinaryConstraint(2, [0, 0, 1]) - .addBinaryConstraint(3, [1, 0, 1]) - - const oneSolution = solver.findOne() - const twoSolutions = solver.find(2) - const allSolutions = solver.findAll() - - expect(oneSolution).to.have.length(1) - expect(twoSolutions).to.have.length(2) - expect(allSolutions).to.have.length(2) - }) - - it('should return the one empty cover when there are no columns', function () { - const solver = new DancingLinks().createSolver({ columns: 0 }) - solver.addSparseConstraint('empty-row', []) - - // With no required columns, choosing no rows is the unique exact cover. - expect(solver.findOne()).to.deep.equal([[]]) - expect(solver.find(0)).to.deep.equal([[]]) - expect(solver.find(5)).to.deep.equal([[]]) - expect(solver.findAll()).to.deep.equal([[]]) - }) - - it('should preserve the no-constraints error for a zero-column solver', function () { - const solver = new DancingLinks().createSolver({ columns: 0 }) - - expect(() => solver.findAll()).to.throw('Cannot solve problem with no constraints') - - // Generator bodies are lazy, so the same guard runs on the first advance. - const generator = solver.createGenerator() - expect(() => generator.next()).to.throw('Cannot solve problem with no constraints') - }) - - it('should process identical constraints across different solvers', function () { - const dlx = new DancingLinks() - - const constraint1 = { data: 'test1', row: [1, 0, 1] as (0 | 1)[] } - const constraint2 = { data: 'test2', row: [1, 0, 1] as (0 | 1)[] } - - const solver1 = dlx.createSolver({ columns: 3 }) - const solver2 = dlx.createSolver({ columns: 3 }) - - solver1.addBinaryConstraint(constraint1.data, constraint1.row) - solver2.addBinaryConstraint(constraint2.data, constraint2.row) - - expect(() => solver1.findAll()).to.not.throw() - expect(() => solver2.findAll()).to.not.throw() - }) - - it('should preserve behavior when the matrix requires 32-bit indices', function () { - this.timeout(10_000) - - const solver = new DancingLinks().createSolver({ columns: 1 }) - const constraints = Array.from({ length: 65_536 }, (_, data) => ({ - data, - columnIndices: [0] - })) - - solver.addSparseConstraints(constraints) - - // The column length itself exceeds Uint16 capacity, so this exercises both - // the node-index and column-length fallbacks rather than only the threshold. - const solutions = solver.findOne() - expect(solutions).to.have.length(1) - expect(solutions[0]).to.have.length(1) - }) - - it('should preserve row data when only row indices require 32 bits', function () { - this.timeout(10_000) - - const solver = new DancingLinks().createSolver({ columns: 1 }) - const constraints = Array.from({ length: 65_536 }, (_, data) => ({ - data, - columnIndices: [] as number[] - })) - constraints.push({ data: 65_536, columnIndices: [0] }) - - const context = ProblemBuilder.buildContext({ - numPrimary: 1, - numSecondary: 0, - rows: constraints.map(({ data, columnIndices }) => ({ coveredColumns: columnIndices, data })) - }) - // A high row index no longer widens unrelated node and column domains. Only - // rowIndex needs Int32, while navigation and metadata remain compact. - expect(context.nodes.rowIndex).to.be.instanceOf(Int32Array) - for (const view of [ - context.nodes.up, - context.nodes.down, - context.nodes.col, - context.nodes.rowStart, - context.columns.len, - context.columns.prev, - context.columns.next - ]) { - expect(view).to.be.instanceOf(Uint16Array) - } - - solver.addSparseConstraints(constraints) - - // Empty rows add no nodes, so this crosses only the row-index boundary. - // The selected row must still point at its high-index input payload. - const solutions = solver.findOne() - expect(solutions).to.have.length(1) - expect(solutions[0]).to.deep.equal([{ index: 65_536, data: 65_536 }]) - }) - - it('should align independently widened node and row index views', function () { - this.timeout(10_000) - - // One empty row followed by 65,535 single-node rows creates an odd 65,537 - // node count and a row index of 65,535. The mixed 32/16/32-bit layout needs - // padding between col and rowIndex, so this also guards the shared buffer's - // alignment fallback rather than testing only even-sized cutoff matrices. - const rows = Array.from({ length: 65_536 }, (_, data) => ({ - coveredColumns: data === 0 ? [] : [0], - data - })) - const context = ProblemBuilder.buildContext({ numPrimary: 1, numSecondary: 0, rows }) - - expect(context.nodes.size).to.equal(65_537) - expect(context.nodes.up).to.be.instanceOf(Int32Array) - expect(context.nodes.down).to.be.instanceOf(Int32Array) - expect(context.nodes.rowStart).to.be.instanceOf(Int32Array) - expect(context.nodes.col).to.be.instanceOf(Uint16Array) - expect(context.nodes.rowIndex).to.be.instanceOf(Int32Array) - expect(context.nodes.rowIndex[65_536]).to.equal(65_535) - }) - - it('should widen column IDs before the Uint16 sentinel becomes a valid ID', function () { - this.timeout(10_000) - - const context = ProblemBuilder.buildContext({ - numPrimary: 65_535, - numSecondary: 0, - rows: [{ coveredColumns: [65_534], data: 'highest-column' }] - }) - - // Root + 65,535 columns makes 65,535 a real header index, so col must - // widen instead of confusing that value with Uint16's reserved sentinel. - // The odd node count also exercises padding before the 32-bit rowStart view. - expect(context.nodes.size).to.equal(65_537) - expect(context.nodes.col).to.be.instanceOf(Int32Array) - expect(context.nodes.col[65_536]).to.equal(65_535) - expect(context.nodes.rowIndex).to.be.instanceOf(Uint16Array) - expect(context.nodes.rowStart).to.be.instanceOf(Int32Array) - expect(context.nodes.rowStart[0]).to.equal(65_536) - expect(context.nodes.rowStart[1]).to.equal(65_537) - }) - - it('should search the highest node on both sides of the storage-width cutoff', function () { - this.timeout(10_000) - - const padding = Array.from({ length: 64 }, (_, column) => column).filter(column => column !== 1) - - for (const nodeCount of [65_535, 65_536] as const) { - const rows = Array.from({ length: 1_038 }, (_, data) => ({ - coveredColumns: padding, - data - })) - rows.push({ coveredColumns: padding.slice(0, nodeCount === 65_535 ? 12 : 13), data: 1_038 }) - rows.push({ coveredColumns: [...padding, 1], data: 1_039 }) - - const context = ProblemBuilder.buildContext({ - numPrimary: 64, - numSecondary: 0, - rows - }) - const ExpectedNodeIndexArray = nodeCount === 65_535 ? Uint16Array : Int32Array - const views: Array< - [ - Int32Array | Uint16Array, - typeof Int32Array | typeof Uint16Array - ] - > = [ - [context.nodes.up, ExpectedNodeIndexArray], - [context.nodes.down, ExpectedNodeIndexArray], - [context.nodes.col, Uint16Array], - [context.nodes.rowIndex, Uint16Array], - [context.nodes.rowStart, ExpectedNodeIndexArray], - [context.columns.len, ExpectedNodeIndexArray], - [context.columns.prev, ExpectedNodeIndexArray], - [context.columns.next, ExpectedNodeIndexArray] - ] - for (const [view, ExpectedArray] of views) { - expect(view instanceof ExpectedArray).to.equal(true) - } - - const clonedContext = ProblemBuilder.cloneContext(context) - expect(clonedContext.nodes.up).to.not.equal(context.nodes.up) - expect(clonedContext.nodes.down).to.not.equal(context.nodes.down) - expect(clonedContext.nodes.col).to.equal(context.nodes.col) - expect(clonedContext.nodes.rowIndex).to.equal(context.nodes.rowIndex) - expect(clonedContext.nodes.rowStart).to.equal(context.nodes.rowStart) - const clonedViews = [ - clonedContext.nodes.up, - clonedContext.nodes.down, - clonedContext.nodes.col, - clonedContext.nodes.rowIndex, - clonedContext.nodes.rowStart, - clonedContext.columns.len, - clonedContext.columns.prev, - clonedContext.columns.next - ] - for (let i = 0; i < views.length; i++) { - expect(clonedViews[i]!.constructor).to.equal(views[i]![0].constructor) - } - - // Primary column 1 has header index 2 and only the terminal row. Keeping - // its node last proves search traverses index 65,534/65,535, rather than - // merely allocating the width-specific store without exercising it. - expect(context.nodes.size).to.equal(nodeCount) - expect(context.nodes.down[2]).to.equal(nodeCount - 1) - expect(search(clonedContext, Infinity)).to.deep.equal([[{ index: 1_039, data: 1_039 }]]) - // Search through the public batch-ingestion path as well as inspecting the - // direct builder context, so the fallback test covers the same behavior - // users and the end-to-end width benchmarks execute. - const solver = new DancingLinks().createSolver({ columns: 64 }) - solver.addSparseConstraints( - rows.map(({ coveredColumns, data }) => ({ columnIndices: coveredColumns, data })) - ) - const solutions = solver.findAll() - expect(solutions).to.deep.equal([[{ index: 1_039, data: 1_039 }]]) - } - }) - - describe('Generator Interface', function () { - it('should yield solutions that match findAll() results', function () { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: 3 }) - - solver - .addBinaryConstraint(0, [1, 0, 0]) - .addBinaryConstraint(1, [0, 1, 0]) - .addBinaryConstraint(2, [0, 0, 1]) - .addBinaryConstraint(3, [1, 0, 1]) - - const allSolutions = solver.findAll() - const generatorSolutions = [] - - for (const solution of solver.createGenerator()) { - generatorSolutions.push(solution) - } - - expect(generatorSolutions).to.have.length(2) - - const normalizeAndSort = (solutions: typeof allSolutions) => - solutions - .map(solution => solution.map(r => r.data).sort()) - .sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b))) - - expect(normalizeAndSort(generatorSolutions)).to.deep.equal(normalizeAndSort(allSolutions)) - }) - - it('should resume after a solution found at the root search level', function () { - const solver = new DancingLinks().createSolver({ columns: 1 }) - solver.addSparseConstraints([ - { data: 'first', columnIndices: [0] }, - { data: 'second', columnIndices: [0] } - ]) - - // Both solutions are direct choices in the root column. The resumable - // search must recover the first row before advancing to the second. - expect([...solver.createGenerator()]).to.deep.equal([ - [{ index: 0, data: 'first' }], - [{ index: 1, data: 'second' }] - ]) - }) - - it('should yield a zero-column solution once and then exhaust', function () { - const solver = new DancingLinks().createSolver({ columns: 0 }) - solver.addSparseConstraint('empty-row', []) - - const generator = solver.createGenerator() - expect(generator.next()).to.deep.equal({ value: [], done: false }) - expect(generator.next()).to.deep.equal({ value: undefined, done: true }) - - // Each generator owns its one-yield state; exhausting one cannot consume - // the solution that an independently created generator must expose. - expect([...solver.createGenerator()]).to.deep.equal([[]]) - expect([...solver.createGenerator()]).to.deep.equal([[]]) - }) - - it('should support early termination', function () { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: 3 }) - - solver - .addBinaryConstraint(0, [1, 0, 0]) - .addBinaryConstraint(1, [0, 1, 0]) - .addBinaryConstraint(2, [0, 0, 1]) - .addBinaryConstraint(3, [1, 0, 1]) - - const solutions = [] - for (const solution of solver.createGenerator()) { - solutions.push(solution) - if (solutions.length === 1) break - } - - expect(solutions).to.have.length(1) - }) - - it('should handle problems with no solutions', function () { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: 2 }) - - solver.addBinaryConstraint(0, [1, 0]).addBinaryConstraint(1, [1, 0]) - - const solutions = [] - for (const solution of solver.createGenerator()) { - solutions.push(solution) - } - - expect(solutions).to.have.length(0) - }) - - it('should handle empty constraint set', function () { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: 3 }) - - expect(() => { - const gen = solver.createGenerator() - gen.next() // Generator functions are lazy, need to call next() to execute - }).to.throw('Cannot solve problem with no constraints') - }) - - it('should create independent generators', function () { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: 2 }) - - solver.addBinaryConstraint(1, [1, 0]).addBinaryConstraint(2, [0, 1]) - - const solutions1 = [] - for (const solution of solver.createGenerator()) { - solutions1.push(solution) - } - - const solutions2 = [] - for (const solution of solver.createGenerator()) { - solutions2.push(solution) - } - - expect(solutions1).to.have.length(1) - expect(solutions2).to.have.length(1) - - const data1 = solutions1[0]!.map(r => r.data).sort() - const data2 = solutions2[0]!.map(r => r.data).sort() - expect(data1).to.deep.equal([1, 2]) - expect(data2).to.deep.equal([1, 2]) - }) - }) -}) diff --git a/test/unit/solver-configurations.spec.ts b/test/unit/solver-configurations.spec.ts deleted file mode 100644 index fbe1046..0000000 --- a/test/unit/solver-configurations.spec.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { expect } from 'chai' -import { DancingLinks } from '../../index.js' - -describe('Solver Configurations', function () { - describe('Simple Solver Configuration', function () { - it('should create solver with simple configuration', function () { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: 3 }) - - solver.addSparseConstraint('test1', [0]) - solver.addSparseConstraint('test2', [1]) - solver.addBinaryConstraint('test3', [0, 0, 1]) - - const solutions = solver.findAll() - expect(solutions).to.have.length.greaterThan(0) - }) - - it('should validate sparse constraint column indices', function () { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: 3 }).validateConstraints() - - expect(() => solver.addSparseConstraint('test', [0, 3])).to.throw( - 'Column index 3 exceeds columns limit of 3' - ) - expect(() => solver.addSparseConstraint('test', [-1])).to.throw( - 'Column index -1 exceeds columns limit of 3' - ) - }) - - it('should preserve the valid prefix of a sparse batch when validation fails', function () { - const solver = new DancingLinks().createSolver({ columns: 2 }).validateConstraints() - - expect(() => - solver.addSparseConstraints([ - { data: 'kept', columnIndices: [0] }, - { data: 'invalid', columnIndices: [2] }, - { data: 'later', columnIndices: [1] } - ]) - ).to.throw('Column index 2 exceeds columns limit of 2') - - solver.addSparseConstraint('replacement', [1]) - const solutions = solver.findAll() - expect(solutions).to.have.length(1) - expect(solutions[0]!.slice().sort((a, b) => a.index - b.index)).to.deep.equal([ - { index: 0, data: 'kept' }, - { index: 1, data: 'replacement' } - ]) - }) - - it('should honor validation enabled reentrantly while reading a batch', function () { - const solver = new DancingLinks().createSolver({ columns: 2 }) - const enablingConstraint = { - data: 'kept', - get columnIndices(): number[] { - solver.validateConstraints() - return [0] - } - } - - expect(() => - solver.addSparseConstraints([ - enablingConstraint, - { data: 'invalid', columnIndices: [2] }, - { data: 'later', columnIndices: [1] } - ]) - ).to.throw('Column index 2 exceeds columns limit of 2') - - solver.addSparseConstraint('replacement', [1]) - const solutions = solver.findAll() - expect(solutions).to.have.length(1) - expect(solutions[0]!.slice().sort((a, b) => a.index - b.index)).to.deep.equal([ - { index: 0, data: 'kept' }, - { index: 1, data: 'replacement' } - ]) - }) - - it('should validate binary constraint row length', function () { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ columns: 3 }).validateConstraints() - - expect(() => solver.addBinaryConstraint('test', [1, 0])).to.throw( - 'Row length 2 does not match columns 3' - ) - expect(() => solver.addBinaryConstraint('test', [1, 0, 1, 0])).to.throw( - 'Row length 4 does not match columns 3' - ) - }) - }) - - describe('Complex Solver Configuration', function () { - it('should create solver with complex configuration', function () { - const dlx = new DancingLinks() - const solver = dlx.createSolver({ primaryColumns: 2, secondaryColumns: 2 }) - - solver.addSparseConstraint('test1', { primary: [0], secondary: [] }) - solver.addSparseConstraint('test2', { primary: [1], secondary: [] }) - solver.addBinaryConstraint('test3', { primaryRow: [0, 0], secondaryRow: [1, 0] }) - solver.addBinaryConstraint('test4', { primaryRow: [0, 0], secondaryRow: [0, 1] }) - - const solutions = solver.findAll() - expect(solutions).to.have.length.greaterThan(0) - }) - - it('should validate complex sparse constraint column indices', function () { - const dlx = new DancingLinks() - const solver = dlx - .createSolver({ primaryColumns: 2, secondaryColumns: 2 }) - .validateConstraints() - - expect(() => solver.addSparseConstraint('test', { primary: [2], secondary: [] })).to.throw( - 'Primary column index 2 exceeds primaryColumns limit of 2' - ) - - expect(() => solver.addSparseConstraint('test', { primary: [], secondary: [2] })).to.throw( - 'Secondary column index 2 exceeds secondaryColumns limit of 2' - ) - }) - - it('should validate complex binary constraint row lengths', function () { - const dlx = new DancingLinks() - const solver = dlx - .createSolver({ primaryColumns: 2, secondaryColumns: 2 }) - .validateConstraints() - - expect(() => - solver.addBinaryConstraint('test', { primaryRow: [1], secondaryRow: [0, 1] }) - ).to.throw('Primary row length 1 does not match primaryColumns 2') - - expect(() => - solver.addBinaryConstraint('test', { primaryRow: [1, 0], secondaryRow: [1] }) - ).to.throw('Secondary row length 1 does not match secondaryColumns 2') - }) - }) -}) diff --git a/test/unit/solver-template.spec.ts b/test/unit/solver-template.spec.ts deleted file mode 100644 index 4ff20bb..0000000 --- a/test/unit/solver-template.spec.ts +++ /dev/null @@ -1,513 +0,0 @@ -import { expect } from 'chai' -import { DancingLinks } from '../../index.js' - -describe('SolverTemplate', function () { - it('should create solvers with template constraints pre-loaded', function () { - const dlx = new DancingLinks() - const template = dlx.createSolverTemplate({ columns: 3 }) - - template.addBinaryConstraint(0, [1, 0, 0]).addBinaryConstraint(1, [0, 1, 0]) - - const solver = template.createSolver() - solver.addBinaryConstraint(2, [0, 0, 1]) - - const solutions = solver.findAll() - expect(solutions).to.have.length(1) - - const resultData = [] - for (const result of solutions[0]!) { - resultData.push(result.data) - } - resultData.sort() - - expect(resultData).to.deep.equal([0, 1, 2]) - }) - - it('should enable constraint reuse across multiple solvers', function () { - const dlx = new DancingLinks() - const template = dlx.createSolverTemplate({ columns: 2 }) - - template.addBinaryConstraint('base1', [1, 0]).addBinaryConstraint('base2', [0, 1]) - - const solver1 = template.createSolver() - const solver2 = template.createSolver() - - const solutions1 = solver1.findAll() - const solutions2 = solver2.findAll() - - expect(solutions1).to.have.length(1) - expect(solutions2).to.have.length(1) - - const data1 = [] - for (const result of solutions1[0]!) { - data1.push(result.data) - } - data1.sort() - - const data2 = [] - for (const result of solutions2[0]!) { - data2.push(result.data) - } - data2.sort() - - expect(data1).to.deep.equal(['base1', 'base2']) - expect(data2).to.deep.equal(['base1', 'base2']) - }) - - it('should support fluent interface for adding constraints', function () { - const dlx = new DancingLinks() - const template = dlx.createSolverTemplate({ columns: 3 }) - - const result = template.addBinaryConstraint(0, [1, 0, 0]).addBinaryConstraint(1, [0, 1, 0]) - - expect(result).to.equal(template) - }) - - it('should validate template constraints at creation time', function () { - const dlx = new DancingLinks() - const template = dlx.createSolverTemplate({ columns: 3 }).validateConstraints() - - // Should validate constraints when adding to template - expect(() => template.addSparseConstraint('test', [0, 3])).to.throw( - 'Column index 3 exceeds columns limit of 3' - ) - expect(() => template.addBinaryConstraint('test', [1, 0])).to.throw( - 'Row length 2 does not match columns 3' - ) - }) - - describe('Solver Independence & Side Effects', function () { - it('should maintain solver independence when adding constraints', function () { - const dlx = new DancingLinks() - const template = dlx.createSolverTemplate({ columns: 3 }) - - // Add base constraints to template - template.addSparseConstraint('base1', [0]) - template.addSparseConstraint('base2', [1]) - - const solver1 = template.createSolver() - const solver2 = template.createSolver() - - // Add extra constraint only to solver1 - solver1.addSparseConstraint('extra1', [2]) - - // solver2 should not see extra1 - const solutions1 = solver1.findAll() - const solutions2 = solver2.findAll() - - // solver1 should have all three constraints - expect(solutions1).to.have.length(1) - const data1 = solutions1[0]!.map(r => r.data).sort() - expect(data1).to.deep.equal(['base1', 'base2', 'extra1']) - - // solver2 should only have base constraints - expect(solutions2).to.have.length(0) // No solution with only base1, base2 - }) - - it('should maintain solver independence after solving', function () { - const dlx = new DancingLinks() - const template = dlx.createSolverTemplate({ columns: 3 }) - - template.addSparseConstraint('base1', [0]) - template.addSparseConstraint('base2', [1]) - template.addSparseConstraint('base3', [2]) - - const solver1 = template.createSolver() - const solver2 = template.createSolver() - - // Solve with solver1 (this mutates internal search state) - const solutions1 = solver1.findAll() - expect(solutions1).to.have.length(1) - - // solver2 should still work correctly after solver1 was used - const solutions2 = solver2.findAll() - expect(solutions2).to.have.length(1) - expect(solutions2[0]!.map(r => r.data).sort()).to.deep.equal(['base1', 'base2', 'base3']) - }) - - it('should support concurrent solving from same template', function () { - const dlx = new DancingLinks() - const template = dlx.createSolverTemplate({ columns: 2 }) - - // Create a problem with exactly one solution - template.addBinaryConstraint(1, [1, 0]) - template.addBinaryConstraint(2, [0, 1]) - - const solver1 = template.createSolver() - const solver2 = template.createSolver() - const solver3 = template.createSolver() - - // All should find the same solution independently - const solutions1 = solver1.findAll() - const solutions2 = solver2.findAll() - const solutions3 = solver3.findAll() - - expect(solutions1).to.have.length(1) - expect(solutions2).to.have.length(1) - expect(solutions3).to.have.length(1) - - // All should have identical solutions - const data1 = solutions1[0]!.map(r => r.data).sort() - const data2 = solutions2[0]!.map(r => r.data).sort() - const data3 = solutions3[0]!.map(r => r.data).sort() - - expect(data1).to.deep.equal([1, 2]) - expect(data2).to.deep.equal([1, 2]) - expect(data3).to.deep.equal([1, 2]) - }) - }) - - describe('Template State Isolation', function () { - it('should isolate a local row in a zero-column template', function () { - const template = new DancingLinks().createSolverTemplate({ columns: 0 }) - const changedSolver = template.createSolver() - const untouchedSolver = template.createSolver() - - changedSolver.addSparseConstraint('local-empty-row', []) - - expect(changedSolver.findAll()).to.deep.equal([[]]) - expect(() => untouchedSolver.findAll()).to.throw('Cannot solve problem with no constraints') - expect(() => template.createSolver().findAll()).to.throw( - 'Cannot solve problem with no constraints' - ) - - const generator = untouchedSolver.createGenerator() - expect(() => generator.next()).to.throw('Cannot solve problem with no constraints') - }) - - it('should isolate and share complex zero-primary template rows with validation', function () { - const template = new DancingLinks() - .createSolverTemplate({ primaryColumns: 0, secondaryColumns: 1 }) - .validateConstraints() - - const changedSolver = template.createSolver() - const untouchedSolver = template.createSolver() - changedSolver.addSparseConstraint('local-optional', { primary: [], secondary: [0] }) - - // A local row makes only the detached solver solvable; the empty shared - // snapshot still triggers the established no-constraints error. - expect(changedSolver.findAll()).to.deep.equal([[]]) - expect(() => untouchedSolver.findAll()).to.throw('Cannot solve problem with no constraints') - expect(() => template.createSolver().findAll()).to.throw( - 'Cannot solve problem with no constraints' - ) - - expect(() => - changedSolver.addSparseConstraint('invalid', { primary: [], secondary: [1] }) - ).to.throw('Secondary column index 1 exceeds secondaryColumns limit of 1') - - // Once the template owns a valid optional row, multiple solvers share its - // snapshot and independently expose the one empty exact cover. - template.addSparseConstraint('template-optional', { primary: [], secondary: [0] }) - expect(template.createSolver().findAll()).to.deep.equal([[]]) - expect(template.createSolver().findAll()).to.deep.equal([[]]) - }) - - it('should rebuild solver-local changes from the compiled topology snapshot', function () { - const template = new DancingLinks().createSolverTemplate({ columns: 2 }) - const callerOwnedColumns = [0] - - template.addSparseConstraint('left', callerOwnedColumns) - const solver = template.createSolver() - - // Compiled links already describe [0]. Mutating the caller's source array - // must not change the rows used when this solver detaches and rebuilds. - callerOwnedColumns.push(1) - solver.addSparseConstraint('right', [1]) - - const solutions = solver.findAll() - expect(solutions).to.have.length(1) - expect(solutions[0]!.map(result => result.data).sort()).to.deep.equal(['left', 'right']) - }) - - it('should detach complex template rows before a solver-local mutation', function () { - const template = new DancingLinks().createSolverTemplate({ - primaryColumns: 2, - secondaryColumns: 1 - }) - - template.addSparseConstraint('left', { primary: [0], secondary: [0] }) - const changedSolver = template.createSolver() - const untouchedSolver = template.createSolver() - - changedSolver.addSparseConstraint('right', { primary: [1], secondary: [] }) - - const changedSolutions = changedSolver.findAll() - expect(changedSolutions).to.have.length(1) - expect(changedSolutions[0]!.map(result => result.data).sort()).to.deep.equal([ - 'left', - 'right' - ]) - expect(untouchedSolver.findAll()).to.have.length(0) - }) - - it('should isolate a validated solver after a partially accepted local batch', function () { - const template = new DancingLinks() - .createSolverTemplate({ columns: 3 }) - .validateConstraints() - template.addSparseConstraint('base', [0]) - - const changedSolver = template.createSolver() - expect(() => - changedSolver.addSparseConstraints([ - { data: 'local', columnIndices: [1] }, - { data: 'invalid', columnIndices: [3] }, - { data: 'later', columnIndices: [2] } - ]) - ).to.throw('Column index 3 exceeds columns limit of 3') - - changedSolver.addSparseConstraint('replacement', [2]) - const changedSolutions = changedSolver.findAll() - expect(changedSolutions).to.have.length(1) - expect(changedSolutions[0]!.slice().sort((a, b) => a.index - b.index)).to.deep.equal([ - { index: 0, data: 'base' }, - { index: 1, data: 'local' }, - { index: 2, data: 'replacement' } - ]) - - // The throwing batch detached before mutation, so neither its accepted - // prefix nor an empty slot can leak back into the compiled template. - expect(template.createSolver().findAll()).to.have.length(0) - }) - - it('should invalidate the compiled layout when the template changes', function () { - const template = new DancingLinks().createSolverTemplate({ columns: 2 }) - - template.addSparseConstraint('left', [0]).addSparseConstraint('right', [1]) - - // Creating this solver compiles the original template layout. - const originalSolver = template.createSolver() - - // This row creates a second solution and must invalidate that layout. - template.addSparseConstraint('combined', [0, 1]) - const updatedSolver = template.createSolver() - - const originalSolutions = originalSolver.findAll() - const updatedSolutions = updatedSolver.findAll() - - expect( - originalSolutions.map(solution => solution.map(result => result.data).sort()) - ).to.deep.equal([['left', 'right']]) - expect(updatedSolutions.map(solution => solution.map(result => result.data))).to.deep.include( - ['combined'] - ) - expect(updatedSolutions).to.have.length(2) - }) - - it('should isolate template modifications from existing solvers', function () { - const dlx = new DancingLinks() - const template = dlx.createSolverTemplate({ columns: 3 }) - - template.addSparseConstraint('base1', [0]) - template.addSparseConstraint('base2', [1]) - - // Create solver from template - const solver1 = template.createSolver() - solver1.addSparseConstraint('solver1-extra', [2]) - - // Modify template after creating solver (add constraint for column 2) - template.addSparseConstraint('template-new', [2]) - - // Create new solver from modified template - const solver2 = template.createSolver() - - const solutions1 = solver1.findAll() - const solutions2 = solver2.findAll() - - // solver1 should have original template + its extra (no template-new) - expect(solutions1).to.have.length(1) - const data1 = solutions1[0]!.map(r => r.data).sort() - expect(data1).to.deep.equal(['base1', 'base2', 'solver1-extra']) - - // solver2 should have modified template constraints (including template-new) - expect(solutions2).to.have.length(1) - const data2 = solutions2[0]!.map(r => r.data).sort() - expect(data2).to.deep.equal(['base1', 'base2', 'template-new']) - }) - - it('should never modify existing solver constraints when template changes', function () { - const dlx = new DancingLinks() - const template = dlx.createSolverTemplate({ columns: 4 }) - - // Step 1: Create template with initial constraints - template.addSparseConstraint('template-base-1', [0]) - template.addSparseConstraint('template-base-2', [1]) - - // Step 2: Create solver1 from template snapshot - const solver1 = template.createSolver() - - // Step 3: Add more constraints to template AFTER creating solver1 - template.addSparseConstraint('template-added-later', [2]) - - // Step 4: Create solver2 from updated template - const solver2 = template.createSolver() - - // Step 5: Complete both solvers with their own constraints - solver1.addSparseConstraint('solver1-specific', [2, 3]) - solver2.addSparseConstraint('solver2-specific', [3]) - - // Step 6: Test the core invariant - solver1 should NOT see 'template-added-later' - const solutions1 = solver1.findAll() - const solutions2 = solver2.findAll() - - expect(solutions1).to.have.length(1) - const data1 = solutions1[0]!.map(r => r.data).sort() - expect(data1).to.deep.equal(['solver1-specific', 'template-base-1', 'template-base-2']) - - // solver1 should NOT have 'template-added-later' even though it was added to template - expect(data1).to.not.include('template-added-later') - - expect(solutions2).to.have.length(1) - const data2 = solutions2[0]!.map(r => r.data).sort() - expect(data2).to.deep.equal([ - 'solver2-specific', - 'template-added-later', - 'template-base-1', - 'template-base-2' - ]) - - // solver2 SHOULD have 'template-added-later' because it was created after the addition - expect(data2).to.include('template-added-later') - }) - - it('should not corrupt template state when solving', function () { - const dlx = new DancingLinks() - const template = dlx.createSolverTemplate({ columns: 3 }) - - template.addSparseConstraint('base1', [0]) - template.addSparseConstraint('base2', [1]) - template.addSparseConstraint('base3', [2]) - - // Create and solve multiple times - const solver1 = template.createSolver() - solver1.findAll() - solver1.findOne() - solver1.find(5) - - // Template should still work for new solvers - const solver2 = template.createSolver() - const solutions = solver2.findAll() - - expect(solutions).to.have.length(1) - const data = solutions[0]!.map(r => r.data).sort() - expect(data).to.deep.equal(['base1', 'base2', 'base3']) - }) - }) - - describe('Complex Reuse Patterns', function () { - it('should work with empty template and solver-specific constraints', function () { - const dlx = new DancingLinks() - const emptyTemplate = dlx.createSolverTemplate({ columns: 3 }) - - const solver1 = emptyTemplate.createSolver() - solver1.addSparseConstraint('s1-1', [0]) - solver1.addSparseConstraint('s1-2', [1]) - solver1.addSparseConstraint('s1-3', [2]) - - const solver2 = emptyTemplate.createSolver() - solver2.addBinaryConstraint('s2-1', [1, 1, 0]) - solver2.addBinaryConstraint('s2-2', [0, 0, 1]) - - const solutions1 = solver1.findAll() - const solutions2 = solver2.findAll() - - expect(solutions1).to.have.length(1) - expect(solutions1[0]!.map(r => r.data).sort()).to.deep.equal(['s1-1', 's1-2', 's1-3']) - - expect(solutions2).to.have.length(1) - expect(solutions2[0]!.map(r => r.data).sort()).to.deep.equal(['s2-1', 's2-2']) - }) - - it('should handle mixed constraint types in templates', function () { - const dlx = new DancingLinks() - const template = dlx.createSolverTemplate({ columns: 4 }) - - // Mix sparse and binary constraints in template - template.addSparseConstraint('sparse1', [0, 1]) - template.addBinaryConstraint('binary1', [0, 0, 1, 1]) - - const solver = template.createSolver() - const solutions = solver.findAll() - - expect(solutions).to.have.length(1) - const data = solutions[0]!.map(r => r.data).sort() - expect(data).to.deep.equal(['binary1', 'sparse1']) - }) - - it('should maintain performance after heavy template reuse', function () { - const dlx = new DancingLinks() - const template = dlx.createSolverTemplate({ columns: 5 }) - - // Add multiple constraints to template - template.addBinaryConstraint(1, [1, 0, 0, 0, 0]) - template.addBinaryConstraint(2, [0, 1, 0, 0, 0]) - template.addBinaryConstraint(3, [0, 0, 1, 0, 0]) - template.addBinaryConstraint(4, [0, 0, 0, 1, 0]) - template.addBinaryConstraint(5, [0, 0, 0, 0, 1]) - - // Create many solvers and solve them - for (let i = 0; i < 10; i++) { - const solver = template.createSolver() - const solutions = solver.findAll() - expect(solutions).to.have.length(1) - expect(solutions[0]!).to.have.length(5) - } - }) - }) - - describe('Edge Cases', function () { - it('should handle template with no solutions', function () { - const dlx = new DancingLinks() - const template = dlx.createSolverTemplate({ columns: 2 }) - - // Create impossible constraints (column 0 must be covered twice) - template.addSparseConstraint('impossible1', [0]) - template.addSparseConstraint('impossible2', [0]) - - const solver1 = template.createSolver() - const solver2 = template.createSolver() - - const solutions1 = solver1.findAll() - const solutions2 = solver2.findAll() - - expect(solutions1).to.have.length(0) - expect(solutions2).to.have.length(0) - }) - - it('should propagate template validation to created solvers', function () { - const dlx = new DancingLinks() - const template = dlx.createSolverTemplate({ columns: 3 }).validateConstraints() - - template.addSparseConstraint('base', [0]) - - const solver = template.createSolver() - - // Solver should inherit validation from template - expect(() => solver.addSparseConstraint('invalid', [5])).to.throw( - 'Column index 5 exceeds columns limit of 3' - ) - }) - - it('should work with large templates', function () { - const dlx = new DancingLinks() - const template = dlx.createSolverTemplate({ columns: 20 }) - - // Add many constraints to template - for (let i = 0; i < 20; i++) { - const constraint = new Array(20).fill(0) - constraint[i] = 1 - template.addBinaryConstraint(i, constraint) - } - - const solver = template.createSolver() - const solutions = solver.findAll() - - expect(solutions).to.have.length(1) - expect(solutions[0]!).to.have.length(20) - - // Verify all numbers 0-19 are present - const data = solutions[0]!.map(r => r.data).sort((a, b) => a - b) - expect(data).to.deep.equal(Array.from({ length: 20 }, (_, i) => i)) - }) - }) -}) diff --git a/tsconfig.dev.json b/tsconfig.dev.json deleted file mode 100644 index ee9a935..0000000 --- a/tsconfig.dev.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./built" - }, - "include": ["./index.ts", "./lib/**/*", "./test/**/*", "./benchmark/**/*", "./scripts/**/*"], - "exclude": ["node_modules", "built"] -} diff --git a/tsconfig.json b/tsconfig.json index 3df2b07..b3721a3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,29 +1,22 @@ { "compilerOptions": { "target": "ES2022", + "useDefineForClassFields": true, "module": "ESNext", - "moduleResolution": "Node", - "outDir": "./built/lib", - "declarationDir": "./built/typings", - "lib": ["ES2022", "DOM"], - "sourceMap": true, - "declaration": true, + "moduleResolution": "Bundler", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "allowImportingTsExtensions": false, + "resolveJsonModule": true, + "isolatedModules": true, "esModuleInterop": true, - "allowSyntheticDefaultImports": true, "forceConsistentCasingInFileNames": true, - - // Strict Type Checking - reduced from full strict mode "strict": true, - "noImplicitAny": true, - "strictNullChecks": true, - "strictFunctionTypes": true, + "noUncheckedIndexedAccess": true, "noImplicitReturns": true, "noUnusedLocals": true, - "noUnusedParameters": true + "noUnusedParameters": true, + "skipLibCheck": true, + "types": ["node", "mocha"] }, - "include": ["./index.ts", "./lib/**/*", "./test/**/*"], - "exclude": ["node_modules", "built", "benchmark", "scripts"], - "ts-node": { - "esm": true - } + "include": ["src", "test/game", "vite.config.ts"] } diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..4a18e80 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'vite' + +export default defineConfig({ + server: { + host: '127.0.0.1', + port: 4173 + }, + preview: { + host: '127.0.0.1', + port: 4173 + } +})