diff --git a/.cargo/config.toml b/.cargo/config.toml index 4b9d04449b34..102cb942d530 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -29,6 +29,7 @@ documentation = """ -p biome_markup \ -p biome_rowan -p biome_string_case \ + -p biome_configuration \ --no-deps """ format = "fmt --all --verbose" diff --git a/.gitattributes b/.gitattributes index bc4e9d87d8bf..edc3d5acb547 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8,8 +8,8 @@ crates/biome_js_analyze/src/assists/*.rs linguist-generated=true text=auto eol=l crates/biome_js_analyze/src/semantic_analyzers.rs linguist-generated=true text=auto eol=lf crates/biome_js_analyze/src/semantic_analyzers/*.rs linguist-generated=true text=auto eol=lf crates/biome_js_analyze/src/registry.rs linguist-generated=true text=auto eol=lf -crates/biome_service/src/configuration/linter/rules.rs linguist-generated=true text=auto eol=lf -crates/biome_service/src/configuration/parse/json/rules.rs linguist-generated=true text=auto eol=lf +crates/biome_configuration/linter/rules.rs linguist-generated=true text=auto eol=lf +crates/biome_configuration/parse/json/rules.rs linguist-generated=true text=auto eol=lf crates/biome_unicode_table/src/tables.rs linguist-generated=true text=auto eol=lf packages/@biomejs/backend-jsonrpc/src/workspace.ts linguist-generated=true text=auto eol=lf packages/@biomejs/biome/configuration_schema.json linguist-generated=true text=auto eol=lf diff --git a/.github/labeler.yml b/.github/labeler.yml index 5ff76e1a5eed..d4a3a7899f90 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,69 +1,100 @@ # See https://github.com/actions/labeler A-Cli: - - crates/biome_cli/** - - crates/biome_fs/** - - crates/biome_console/** +- changed-files: + - any-glob-to-any-file: + - crates/biome_cli/** + - crates/biome_fs/** + - crates/biome_console/** A-Core: - - crates/biome_deserializer/** - - crates/biome_fs/** - - crates/biome_rowan/** - - crates/biome_text_edit/** - - crates/biome_text_size/** - - crates/biome_suppression/** - - crates/biome_markup/** +- changed-files: + - any-glob-to-any-file: + - crates/biome_deserializer/** + - crates/biome_fs/** + - crates/biome_rowan/** + - crates/biome_text_edit/** + - crates/biome_text_size/** + - crates/biome_suppression/** + - crates/biome_markup/** A-Project: - - crates/biome_service/** +- changed-files: + - any-glob-to-any-file: + - crates/biome_service/** + - crates/biome_configuration/** A-Linter: - - crates/biome_analyze/** - - crates/biome_js_analyze/** - - crates/biome_json_analyze/** +- changed-files: + - any-glob-to-any-file: + - crates/biome_analyze/** + - crates/biome_js_analyze/** + - crates/biome_json_analyze/** A-Parser: - - crates/biome_parser/** - - crates/biome_js_parser/** - - crates/biome_js_syntax/** - - crates/biome_json_parser/** - - crates/biome_json_syntax/** - - crates/biome_css_parser/** - - crates/biome_css_syntax/** +- changed-files: + - any-glob-to-any-file: + - crates/biome_parser/** + - crates/biome_js_parser/** + - crates/biome_js_syntax/** + - crates/biome_json_parser/** + - crates/biome_json_syntax/** + - crates/biome_css_parser/** + - crates/biome_css_syntax/** A-Formatter: - - crates/biome_formatter/** - - crates/biome_formatter_test/** - - crates/biome_js_formatter/** - - crates/biome_json_formatter/** - - crates/biome_css_formatter/** +- changed-files: + - any-glob-to-any-file: + - crates/biome_formatter/** + - crates/biome_formatter_test/** + - crates/biome_js_formatter/** + - crates/biome_json_formatter/** + - crates/biome_css_formatter/** A-Editors: - - crates/editors/** +- changed-files: + - any-glob-to-any-file: + - crates/editors/** A-Diagnostic: - - crates/biome_diagnostics/** - - crates/biome_diagnostics_categories/** - - crates/biome_diagnostics_macros/** +- changed-files: + - any-glob-to-any-file: + - crates/biome_diagnostics/** + - crates/biome_diagnostics_categories/** + - crates/biome_diagnostics_macros/** A-Tooling: - - xtask/** - - crates/biome_ungrammar/** +- changed-files: + - any-glob-to-any-file: + - xtask/** + - crates/biome_ungrammar/** A-Website: - - website/** +- changed-files: + - any-glob-to-any-file: + - website/** A-LSP: - - crates/biome_lsp/** +- changed-files: + - any-glob-to-any-file: + - crates/biome_lsp/** A-Changelog: - - CHANGELOG.md +- changed-files: + - any-glob-to-any-file: + - CHANGELOG.md L-Javascript: - - crates/biome_js_*/** +- changed-files: + - any-glob-to-any-file: + - crates/biome_js_*/** L-Json: - - crates/biome_json_*/** +- changed-files: + - any-glob-to-any-file: + - crates/biome_json_*/** L-CSS: - - crates/biome_css_*/** +- changed-files: + - any-glob-to-any-file: + - crates/biome_css_*/** diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 000000000000..cf6174cd283f --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,58 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "timezone": "Europe/Gibraltar", + "schedule": [ + "before 9am on monday" + ], + "extends": [ + "config:best-practices" + ], + "rangeStrategy": "bump", + "lockFileMaintenance": { + "enabled": false + }, + "assignees": [ + "@biomejs/maintainers", + "@biomejs/core-contributors" + ], + "packageRules": [ + { + "groupName": "github-actions", + "matchManagers": [ + "github-actions" + ] + }, + { + "groupName": "Rust crates", + "matchManagers": [ + "cargo" + ], + "matchFileNames": [ + "crates/**", + "xtask/**" + ], + "ignoreDeps": [ + "syn", + "quote" + ] + }, + { + "groupName": "Website", + "matchFileNames": [ + "website/package.json" + ], + "matchManagers": [ + "npm" + ] + }, + { + "groupName": "@biomejs packages", + "matchFileNames": [ + "packages/**" + ], + "matchManagers": [ + "npm" + ] + } + ] +} diff --git a/.github/workflows/bench_cli.yml b/.github/workflows/bench_cli.yml index 6109e16ffff0..e43c3c4f90c1 100644 --- a/.github/workflows/bench_cli.yml +++ b/.github/workflows/bench_cli.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Get PR SHA id: sha - uses: actions/github-script@v6 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7 with: result-encoding: string script: | @@ -29,12 +29,16 @@ jobs: return response.data.head.sha; - name: Checkout PR Branch - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: ref: ${{ steps.sha.outputs.result }} - name: Install toolchain - uses: moonrepo/setup-rust@v1 + uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + with: + channel: stable + cache-target: release + cache-base: main - name: Install hyperfine run: cargo install hyperfine @@ -46,7 +50,7 @@ jobs: cp target/release/biome benchmark/target/biome_pr - name: Checkout Main Branch - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: clean: false ref: main @@ -57,17 +61,17 @@ jobs: cp target/release/biome benchmark/target/biome_main - name: Checkout webpack - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: repository: webpack/webpack path: benchmark/target/webpack - name: Checkout prettier - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: repository: prettier/prettier path: benchmark/target/prettier - name: Checkout eslint - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: repository: eslint/eslint path: benchmark/target/eslint @@ -92,7 +96,7 @@ jobs: - name: Write a new comment # Check if the event is not triggered by a fork if: github.event.pull_request.head.repo.full_name == github.repository - uses: peter-evans/create-or-update-comment@v3 + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 continue-on-error: true with: issue-number: ${{ github.event.issue.number }} diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 5b407d66f2fc..56acfe412eee 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -33,22 +33,23 @@ jobs: steps: - name: Checkout PR Branch - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: ref: ${{ steps.sha.outputs.result }} - name: Install toolchain - uses: moonrepo/setup-rust@v1 + uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 with: channel: stable cache-target: release bins: cargo-codspeed + cache-base: main - name: Compile run: cargo codspeed build --features codspeed -p xtask_bench - name: Run the benchmarks - uses: CodSpeedHQ/action@v2 + uses: CodSpeedHQ/action@1dbf41f0ae41cebfe61e084e535aebe533409b4d # v2 timeout-minutes: 30 with: run: cargo codspeed run diff --git a/.github/workflows/ja-translation.yaml b/.github/workflows/ja-translation.yaml index 89aaeae18fb5..c21226200802 100644 --- a/.github/workflows/ja-translation.yaml +++ b/.github/workflows/ja-translation.yaml @@ -13,9 +13,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout PR Branch - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Cache pnpm modules - uses: actions/cache@v4 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 with: path: ~/.pnpm-store key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} diff --git a/.github/workflows/label-issue.yaml b/.github/workflows/label-issue.yaml index 433ec74b0b6f..56f0c1f7e7fe 100644 --- a/.github/workflows/label-issue.yaml +++ b/.github/workflows/label-issue.yaml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Label documentation issues - uses: github/issue-labeler@v3.3 + uses: github/issue-labeler@c1b0f9f52a63158c4adc09425e858e87b32e9685 # v3.4 with: repo-token: ${{ secrets.GITHUB_TOKEN }} configuration-path: .github/documentation-issue-labeler.yaml diff --git a/.github/workflows/labels.yml b/.github/workflows/labels.yml index 339ed48ebedd..b9cdc5cc52dd 100644 --- a/.github/workflows/labels.yml +++ b/.github/workflows/labels.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest if: github.repository_owner == 'biomejs' steps: - - uses: actions/labeler@v4 + - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5 with: repo-token: "${{ secrets.GITHUB_TOKEN }}" sync-labels: true diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ef6b882e1135..39001f7b958c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,16 +20,19 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Support longpaths run: git config core.longpaths true - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - name: Free Disk Space + uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@v1 + uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 with: components: rustfmt bins: taplo-cli + cache-base: main - name: Run rustfmt run: | cargo fmt --all --verbose -- --check @@ -40,13 +43,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@v1 + uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 with: components: clippy + cache-base: main - name: Run cargo check run: cargo check --workspace --all-targets --release - name: Run clippy @@ -57,13 +61,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@v1 + uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 with: channel: nightly + cache: false - name: Install udeps run: cargo install cargo-udeps --locked - name: Run udeps @@ -80,13 +85,14 @@ jobs: - os: macos-latest steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@v1 + uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 with: bins: cargo-nextest + cache-base: main - name: Run tests on ${{ matrix.os }} run: cargo nextest run --workspace --verbose - name: Clean cache @@ -105,13 +111,16 @@ jobs: if: matrix.os == 'windows-latest' run: git config --system core.longpaths true - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: submodules: recursive - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@v1 + uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + with: + cache-target: release + cache-base: main - name: Compile run: cargo build --release --locked -p xtask_coverage - name: Run Test262 suite diff --git a/.github/workflows/parser_conformance.yml b/.github/workflows/parser_conformance.yml index 84b82e8ee3a3..144a242262c1 100644 --- a/.github/workflows/parser_conformance.yml +++ b/.github/workflows/parser_conformance.yml @@ -25,18 +25,24 @@ jobs: steps: - name: Checkout PR Branch - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Support longpaths run: git config core.longpaths true - name: Checkout PR Branch - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: submodules: recursive + - name: Free Disk Space + uses: ./.github/actions/free-disk-space + - name: Install toolchain - uses: moonrepo/setup-rust@v1 + uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + with: + cache-target: release + cache-base: main - name: Compile run: cargo build --release --locked -p xtask_coverage @@ -46,7 +52,7 @@ jobs: run: cargo coverage --json > new_results.json - name: Checkout main Branch - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 with: clean: false ref: main @@ -71,11 +77,11 @@ jobs: - name: Get the PR number if: github.event_name == 'pull_request' id: pr-number - uses: kkak10/pr-number-action@v1.3 + uses: kkak10/pr-number-action@8f5358941366822cd0825e04dfe68437f2f5f15b # v1.3 - name: Find Previous Comment if: github.event_name == 'pull_request' - uses: peter-evans/find-comment@v1.3.0 + uses: peter-evans/find-comment@d5fe37641ad8451bdd80312415672ba26c86575e # v3.0.0 id: previous-comment with: issue-number: ${{ steps.pr-number.outputs.pr }} @@ -83,7 +89,7 @@ jobs: - name: Update existing comment if: github.event_name == 'pull_request' && steps.previous-comment.outputs.comment-id - uses: peter-evans/create-or-update-comment@v3 + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 continue-on-error: true with: comment-id: ${{ steps.previous-comment.outputs.comment-id }} @@ -93,7 +99,7 @@ jobs: - name: Write a new comment if: github.event_name == 'pull_request' && !steps.previous-comment.outputs.comment-id - uses: peter-evans/create-or-update-comment@v3 + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 continue-on-error: true with: issue-number: ${{ steps.pr-number.outputs.pr }} diff --git a/.github/workflows/publish_container_ci.yaml b/.github/workflows/publish_container_ci.yaml index c2f6c86ef562..6d29bcd469e3 100644 --- a/.github/workflows/publish_container_ci.yaml +++ b/.github/workflows/publish_container_ci.yaml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Login to GitHub Container Registry - uses: docker/login-action@v2 + uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3 with: registry: ghcr.io username: ${{ github.actor }} diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 3577f9e8a717..c2d20ad52fe6 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -28,14 +28,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout PR branch - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@v1 + uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 with: components: rustfmt bins: taplo-cli + cache-base: main - name: Run format run: | cargo fmt --all --check @@ -46,13 +47,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout PR Branch - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@v1 + uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 with: components: clippy + cache-base: main - name: Run clippy run: cargo lint @@ -61,7 +63,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout PR Branch - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain @@ -81,13 +83,14 @@ jobs: - os: ubuntu-latest steps: - name: Checkout PR branch - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@v1 + uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 with: bins: cargo-nextest + cache-base: main - name: Run tests run: cargo nextest run --workspace --verbose - name: Run doctests @@ -111,19 +114,22 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout PR branch - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@v1 + uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + with: + cache-target: release + cache-base: main - name: Build main binary run: cargo build -p biome_cli --release - name: Install Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: node-version: 20 - name: Cache pnpm modules - uses: actions/cache@v4 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 with: path: ~/.pnpm-store key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} @@ -152,11 +158,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout PR branch - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@v1 + uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + with: + cache-base: main - name: Run doc command run: cargo documentation @@ -165,11 +173,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout PR branch - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Install toolchain - uses: moonrepo/setup-rust@v1 + uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + with: + cache-base: main - name: Run the grammar codegen run: cargo codegen grammar - name: Run the analyzer codegen diff --git a/.github/workflows/pull_request_js.yml b/.github/workflows/pull_request_js.yml index b1849b5ce263..8aa88e0351da 100644 --- a/.github/workflows/pull_request_js.yml +++ b/.github/workflows/pull_request_js.yml @@ -26,11 +26,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Cache pnpm modules - uses: actions/cache@v3 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 with: path: ~/.pnpm-store key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} @@ -47,11 +47,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout PR Branch - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Free Disk Space uses: ./.github/actions/free-disk-space - name: Cache pnpm modules - uses: actions/cache@v4 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 with: path: ~/.pnpm-store key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} @@ -59,7 +59,9 @@ jobs: ${{ runner.os }}- - uses: pnpm/action-setup@v3 - name: Install toolchain - uses: moonrepo/setup-rust@v1 + uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f # v1 + with: + cache-base: main - name: Install wasm-pack run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh - name: Build WASM module for the web diff --git a/.github/workflows/release_cli.yml b/.github/workflows/release_cli.yml index 207e51a7e67b..2e398dcaee2d 100644 --- a/.github/workflows/release_cli.yml +++ b/.github/workflows/release_cli.yml @@ -19,7 +19,7 @@ jobs: nightly: ${{ env.nightly }} version_changed: ${{ steps.version.outputs.changed }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Check nightly status id: nightly @@ -27,7 +27,7 @@ jobs: run: echo "nightly=true" >> $GITHUB_ENV - name: Check version changes - uses: EndBug/version-check@v2 + uses: EndBug/version-check@53c9309fefac91a21f852d5ca69f33878280d2f5 # v2 if: env.nightly != 'true' id: version with: @@ -88,10 +88,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Install Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: node-version: 20 @@ -144,9 +144,9 @@ jobs: # Upload the CLI binary as a build artifact - name: Upload CLI artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4 with: - name: cli + name: cli-${{ matrix.target }} path: ./dist/biome-* if-no-files-found: error @@ -156,7 +156,7 @@ jobs: needs: check steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Install wasm-pack run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh @@ -169,9 +169,9 @@ jobs: run: wasm-pack build --out-dir ../../packages/@biomejs/wasm-web --target web --release --scope biomedev crates/biome_wasm - name: Upload WASM artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4 with: - name: wasm + name: wasm-${{ matrix.target }} path: | ./packages/@biomejs/wasm-bundler ./packages/@biomejs/wasm-nodejs @@ -189,20 +189,22 @@ jobs: contents: write id-token: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Download CLI artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4 with: - name: cli + pattern: cli-* + merge-multiple: true - name: Download WASM artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4 with: - name: wasm + pattern: wasm-* + merge-multiple: true path: packages/@biomejs - name: Install Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: node-version: 20 registry-url: 'https://registry.npmjs.org' @@ -228,7 +230,7 @@ jobs: run: | bash scripts/print-changelog.sh ${{ needs.build.outputs.version }} >| ${{ github.workspace }}/RELEASE_NOTES - name: Create GitHub release and tag - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@9d7c94cfd0a1f3ed45544c887983e9fa900f0564 # v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/.github/workflows/release_crates.yml b/.github/workflows/release_crates.yml index 1f46a08deaec..21096d017c22 100644 --- a/.github/workflows/release_crates.yml +++ b/.github/workflows/release_crates.yml @@ -17,7 +17,7 @@ jobs: environment: crate-publish steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Login to crate.io run: cargo login ${{ secrets.CRATES_IO_TOKEN }} - name: Publish crates to crates.io diff --git a/.github/workflows/release_js_api.yml b/.github/workflows/release_js_api.yml index f6ade9208f2c..e09eb45eeeed 100644 --- a/.github/workflows/release_js_api.yml +++ b/.github/workflows/release_js_api.yml @@ -19,7 +19,7 @@ jobs: nightly: ${{ env.nightly }} version_changed: ${{ steps.version.outputs.changed }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Check nightly status id: nightly @@ -27,7 +27,7 @@ jobs: run: echo "nightly=true" >> $GITHUB_ENV - name: Check version changes - uses: EndBug/version-check@v2 + uses: EndBug/version-check@53c9309fefac91a21f852d5ca69f33878280d2f5 # v2 if: env.nightly != 'true' id: version with: @@ -58,10 +58,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Install Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: node-version: 20 @@ -69,7 +69,7 @@ jobs: run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh - name: Cache pnpm modules - uses: actions/cache@v4 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4 with: path: ~/.pnpm-store key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} @@ -102,7 +102,7 @@ jobs: pnpm --filter @biomejs/js-api run build - name: Upload JS API artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4 with: name: js-api path: | @@ -118,16 +118,16 @@ jobs: contents: write id-token: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Download package artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4 with: name: js-api path: packages/@biomejs/js-api/dist - name: Install Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: node-version: 20 registry-url: 'https://registry.npmjs.org' @@ -151,7 +151,7 @@ jobs: run: | bash scripts/print-changelog.sh ${{ needs.build.outputs.version }} >| ${{ github.workspace }}/RELEASE_NOTES - name: Create GitHub release and tag - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@9d7c94cfd0a1f3ed45544c887983e9fa900f0564 # v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/.github/workflows/runtime.yml b/.github/workflows/runtime.yml deleted file mode 100644 index 598c15b2eab8..000000000000 --- a/.github/workflows/runtime.yml +++ /dev/null @@ -1,54 +0,0 @@ -# We have code that relies on Rust code AND JS code, we want to run this job when the relevant code changes -name: Checks for our runtimes -on: - push: - branches: - - main - paths: - - 'packages/**' - - 'crates/**' - pull_request: - branches: - - main - paths: - - 'packages/**' - - 'crates/**' - -env: - RUST_LOG: info - RUST_BACKTRACE: 1 - -jobs: - apis-check: - name: Checks on APIs project - runs-on: ubuntu-latest - steps: - - name: Checkout PR Branch - uses: actions/checkout@v4 - - name: Free Disk Space - uses: ./.github/actions/free-disk-space - - name: Install wasm-pack - run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh - - - name: Cache pnpm modules - uses: actions/cache@v4 - with: - path: ~/.pnpm-store - key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}- - - uses: pnpm/action-setup@v3 - - name: Install toolchain - uses: moonrepo/setup-rust@v1 - - name: Install libraries - run: pnpm --filter @biomejs/js-api i - - name: Compile backends - run: | - pnpm --filter @biomejs/js-api run build:wasm-bundler - pnpm --filter @biomejs/js-api run build:wasm-node - pnpm --filter @biomejs/js-api run build:wasm-web - pnpm --filter @biomejs/backend-jsonrpc i - pnpm --filter @biomejs/backend-jsonrpc run build - - name: CI checks - working-directory: packages/@biomejs/js-api - run: pnpm run ci diff --git a/CHANGELOG.md b/CHANGELOG.md index 69000114f89e..e22771d00c08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,37 +9,287 @@ New entries must be placed in a section entitled `Unreleased`. Read our [guidelines for writing a good changelog entry](https://github.com/biomejs/biome/blob/main/CONTRIBUTING.md#changelog). -## Ureleased +## Unreleased ### Analyzer ### CLI +#### Bug fixes + +- Biome now tags the diagnostics emitted by `organizeImports` and `formatter` with correct severity levels, so they will be properly filtered by the flag `--diagnositic-level` ([#2288](https://github.com/biomejs/biome/issues/2288)). Contributed by @Sec-ant +- Biome now correctly filters out files that are not present in the current directory when using the `--changed` flag [#1996](https://github.com/biomejs/biome/issues/1996). + +#### New features + +- Add a command to migrate from ESLint + + `@biomejs/biome migrate eslint` allows you to migrate an ESLint configuration to Biome. + The command supports [legacy ESLint configurations](https://eslint.org/docs/latest/use/configure/configuration-files) and [new flat ESLint configurations](https://eslint.org/docs/latest/use/configure/configuration-files-new). + Legacy ESLint configurations using the YAML format are not supported. + + When loading a legacy ESLint configuration, Biome resolves the `extends` field. + It resolves both shared configurations and plugin presets! + To do this, it invokes NodeJS. + + Biome relies on the metadata of its rules to determine the [equivalent rule of an ESLint rule](https://biomejs.dev/linter/rules-sources/). + A Biome rule is either inspired or roughly identical to an ESLint rules. + By default, inspired and nursery rules are excluded from the migration. + You can use the CLI flags `--include-inspired` and `--include-nursery` to migrate them as well. + + Note that this is a best-effort approach. + You are not guaranteed to get the same behavior as ESLint. + + Given the following ESLint configuration: + + ```json + { + "ignore_patterns": ["**/*.test.js"], + "globals": { "var2": "readonly" }, + "rules": { + "eqeqeq": "error" + }, + "overrides": [{ + "files": ["lib/*.js"], + "rules": { + "default-param-last": "off" + } + }] + } + ``` + + `@biomejs/biome migrate eslint --write` changes the Biome configuration as follows: + + ```json + { + "linter": { + "rules": { + "recommended": false, + "suspicious": { + "noDoubleEquals": "error" + } + } + }, + "javascript": { "globals": ["var2"] }, + "overrides": [{ + "include": ["lib/*.js"], + "linter": { + "rules": { + "style": { + "useDefaultParameterLast": "off" + } + } + } + }] + } + ``` + + Also, if the working diretcory contains `.eslintignore`, then Biome migrates the glob patterns. + Nested `.eslintignore` in subdirectories and negated glob patterns are not supported. + + If you find any issue, please don't hesitate to report them. + + Contributed by @Conaclos + +#### Enhancements + +- Improve support of `.prettierignore` when migrating from Prettier + + Now, Biome translates most of the glob patterns in `.prettierignore` to the equivalent Biome ignore pattern. + Only negated glob patterns are not supported. + + Contributed by @Conaclos + ### Configuration -#### Bug fixes +#### Enhancements -- Fix enabled rules calculation. The precendence of individual rules, `all` and `recommend` presets in top-level and group-level configs is now correctly respected. More details can be seen in ([#2072](https://github.com/biomejs/biome/pull/2072)) ([#2028](https://github.com/biomejs/biome/issues/2028)). Contributed by @Sec-ant +- Biome now displays the location of a parsing error for its configuration file ([#1627](https://github.com/biomejs/biome/issues/1627)). + + Previously, when Biome encountered a parsing error in its configuration file, + it didn't indicate the location of the error. + It now displays the name of the configuration file and the range where the error occurred. + + Contributed by @Conaclos ### Editors ### Formatter +### JavaScript APIs + +### Linter + +#### New features + +- Add a new option `ignoreReact` to [noUnusedImports](https://biomejs.dev/linter/rules/no-unused-imports). + + When `ignoreReact` is enabled, Biome ignores imports of `React` from the `react` package. + The option is disabled by default. + + Contributed by @Conaclos + +- Implement [#2043](https://github.com/biomejs/biome/issues/2043): The React rule [`useExhaustiveDependencies`](https://biomejs.dev/linter/rules/use-exhaustive-dependencies/) is now also compatible with Preact hooks imported from `preact/hooks` or `preact/compat`. Contributed by @arendjr + +#### Enhancements + #### Bug fixes -- Fix [#1661](https://github.com/biomejs/biome/issues/1661). Now nested conditionals are aligned with Prettier's logic, and won't contain mixed spaced and tabs. Contributed by @ematipico +- Lint rules `useNodejsImportProtocol`, `useNodeAssertStrict`, `noRestrictedImports`, `noNodejsModules` will no longer check `declare module` statements anymore. Contributed by @Sec-ant +### Parser -### JavaScript APIs + +## 1.6.4 (2022-04-03) + +### Analyzer + +#### Bug fixes + +- An operator with no spaces around in a binary expression no longer breaks the js analyzer ([#2243](https://github.com/biomejs/biome/issues/2243)). Contributed by @Sec-ant + +### CLI + +#### Bug fixes + +- Fix the printed error count ([#2048](https://github.com/biomejs/biome/issues/2048)). Contributed by @Sec-ant + +### Configuration + +#### Bug fixes + +- Correctly calculate enabled rules in lint rule groups. Now a specific rule belonging to a group can be enabled even if its group-level preset option `recommended` or `all` is `false` ([#2191](https://github.com/biomejs/biome/issues/2191)). Contributed by @Sec-ant + +### Editors + +#### Bug fixes + +- Fix the unexpected code deletion and repetition when `quickfix.biome` is enabled and some `import`-related rules are applied ([#2222](https://github.com/biomejs/biome/issues/2222), [#688](https://github.com/biomejs/biome/issues/688), [#1015](https://github.com/biomejs/biome/issues/1015)). Contributed by @Sec-ant + +### Linter + +#### Bug fixes + +- Fix [#2211](https://github.com/biomejs/biome/issues/2211). noChildrenProp should work fine when children pass as a prop in a new line. Contributed by @fireairforce + +- Fix [#2248](https://github.com/biomejs/biome/issues/2248). `lint/a11y/useButtonType` should not trigger when button element with spread attribute. Contributed by @fireairforce + +- Fix [#2216](https://github.com/biomejs/biome/issues/2216). `lint/style/useNamingConvention` should not ignore JSX Component name binding. Contributed by @fireairforce + +#### Enhancements + +- Add support for object property members in the rule `useSortedClasses`. Contributed by @ematipico + +### Parser + +- The parser doesn't throw any error when the frontmatter of `.astro` files contains an illegal return: + + ```astro + --- + const condition = true; + if (condition) { + return "Something"; + } + --- +
+ ``` + Contributed by @ematipico + +## 1.6.3 (2024-03-25) + +### CLI + +#### Bug fixes + +- Fix configuration resolution. Biome is now able to correctly find the `biome.jsonc` configuration file when `--config-path` is explicitly set ([#2164](https://github.com/biomejs/biome/issues/2164)). Contributed by @Sec-ant + +- JavaScript/TypeScript files of different variants (`.ts`, `.js`, `.tsx`, `.jsx`) in a single workspace now have stable formatting behaviors when running the CLI command in paths of different nested levels or in different operating systems ([#2080](https://github.com/biomejs/biome/issues/2080), [#2109](https://github.com/biomejs/biome/issues/2109)). Contributed by @Sec-ant + +### Configuration + +#### Bug fixes + +- Complete the documentation and overrides support for options `formatter.lineEnding`, `[language].formatter.lineEnding`, `formatter.attributePosition` and `javascript.formatter.attributePosition`. Contributed by @Sec-ant + +### Formatter + +#### Bug fixes + +- Fix [#2172](https://github.com/biomejs/biome/issues/2172) by breaking long object destructuring patterns. Contributed by @ah-yu ### Linter #### New features -- Implement [#2043](https://github.com/biomejs/biome/issues/2043): The React rule [`useExhaustiveDependencies`](https://biomejs.dev/linter/rules/use-exhaustive-dependencies/) is now also compatible with Preact hooks imported from `preact/hooks` or `preact/compat`. Contributed by @arendjr +- Add rule [noEvolvingAny](https://biomejs.dev/linter/rules/no-evolving-any) to disallow variables from evolving into `any` type through reassignments. Contributed by @fujiyamaorange + +#### Enhancements + +- Rename `noSemicolonInJsx` to `noSuspiciousSemicolonInJsx`. Contributed by @fujiyamaorange + +### LSP + +#### Bug fixes + +- Quickfix action no longer autofixes lint rule errors on save when `linter` is disabled ([#2161](https://github.com/biomejs/biome/issues/2161)). Contributed by @Sec-ant +- Range formatting for Astro/Svelte/Vue doesn't place code out of place, especially when formatting on paste is enabled. Contributed by @ematipico + +## 1.6.2 (2024-03-22) + +### Analyzer + +#### Bug fixes + +- The `noSuperWithoutExtends` rule now allows for calling `super()` in derived class constructors of class expressions ([#2108](https://github.com/biomejs/biome/issues/2108)). Contributed by @Sec-ant + +- Fix discrepancies on file source detection. Allow module syntax in `.cts` files ([#2114](https://github.com/biomejs/biome/issues/2114)). Contributed by @Sec-ant + +### CLI + +#### Bug fixes + +- Fixes [#2131](https://github.com/biomejs/biome/issues/2131), where folders were incorrectly ignored when running the command `check`. Now folders are correctly ignored based on their command. Contributed by @ematipico + +- Smoother handling of `"endOfLine": "auto"` in prettier migration: falling back to `"lf"` ([#2145](https://github.com/biomejs/biome/pull/2145)). Contributed by @eMerzh + +### Configuration + +#### Bug fixes + +- Fix enabled rules calculation. The precendence of individual rules, `all` and `recommend` presets in top-level and group-level configs is now correctly respected. More details can be seen in ([#2072](https://github.com/biomejs/biome/pull/2072)) ([#2028](https://github.com/biomejs/biome/issues/2028)). Contributed by @Sec-ant + +### Formatter + +#### Bug fixes + +- Fix [#1661](https://github.com/biomejs/biome/issues/1661). Now nested conditionals are aligned with Prettier's logic, and won't contain mixed spaces and tabs. Contributed by @ematipico + +### JavaScript APIs + +#### Enhancements + +- Support applying lint fixes when calling the `lintContent` method of the `Biome` class ([#1956](https://github.com/biomejs/biome/pull/1956)). Contributed by @mnahkies ### Parser +#### Bug fixes + +- Rule `noUndeclaredDependencies` now also validates `peerDependencies` and `optionalDependencies` ([#2122](https://github.com/biomejs/biome/issues/2122)). Contributed by @Sec-ant + +- Rule `noUndeclaredDependencies` won't check `declare module` statements anymore ([#2123](https://github.com/biomejs/biome/issues/2123)). Contributed by @Sec-ant + +- Fix [#1925](https://github.com/biomejs/biome/issues/1925). The fix for `useOptionalChain` would sometimes suggest an incorrect fix that discarded optional chaining operators on the left-hand side of logical expressions. These are now preserved. Contributed by @arendjr + +- Rule `noUndeclaredVariables` now also checks for worker globals ([#2121](https://github.com/biomejs/biome/issues/2121)). Contributed by @Sec-ant + +### LSP + +#### Bug fixes + +- Correctly parse `.jsonc` files. Contributed by @Sec-ant + +- Correctly resolve external `extends` configs. Contributed by @Sec-ant + ## 1.6.1 (2024-03-12) ### CLI @@ -111,10 +361,6 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b #### Bug fixes -- JavaScript lexer is now able to lex regular expression literals with escaped non-ascii chars ([#1941](https://github.com/biomejs/biome/issues/1941)). - - Contributed by @Sec-ant - ## 1.6.0 (2024-03-08) ### Analyzer @@ -543,7 +789,7 @@ Additionally, the following rules are now recommended: ```diff -
- +
+ +
``` Contributed by @DaniGuardiola @@ -765,7 +1011,7 @@ Additionally, the following rules are now recommended: - Fix [#1656](https://github.com/biomejs/biome/issues/1656). [useOptionalChain](https://biomejs.dev/linter/rules/use-optional-chain/) code action now correctly handles logical and chains where methods with the same name are invoked with different arguments: ```diff - - tags·&&·tags.includes('a')·&&·tags.includes('b') + - tags && tags.includes('a') && tags.includes('b') + tags?.includes('a') && tags.includes('b') ``` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 670261afdaee..67dcc1758c30 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -198,7 +198,7 @@ cargo t test_some_function --show-output ## Checks -When you finished your work, and you are ready to **commit and open a PR**, there are few other +When you finished your work, and you are ready to **commit and open a PR**, there are few other things you would need to run and check: - `just f` (alias for `just format`), formats Rust and TOML files. - `just l` (alias for `just lint`), run the linter for the whole project. @@ -225,15 +225,15 @@ to the `knope.toml` file, which we use for changelog generation. ### Analyzers and lint rules -To know the technical details of how our analyzer works, how to create a rule and how to write tests, please check our [internal page](https://docs.rs/biome_analyze/latest/biome_analyze/) +To know the technical details of how our analyzer works, how to create a rule and how to write tests, please check our [internal page](https://github.com/biomejs/biome/blob/main/crates/biome_analyze/CONTRIBUTING.md) ### Parser -To know the technical details of how our parser works and how to write test, please check our [internal page](https://docs.rs/biome_parser/latest/biome_parser/) +To know the technical details of how our parser works and how to write test, please check our [internal page](https://github.com/biomejs/biome/blob/main/crates/biome_parser/CONTRIBUTING.md) ### Formatter -To know the technical details of how our formatter works and how to write test, please check our [internal page](https://docs.rs/biome_js_formatter/latest/biome_js_formatter/) +To know the technical details of how our formatter works and how to write test, please check our [internal page](https://github.com/biomejs/biome/blob/main/crates/biome_formatter/CONTRIBUTING.md) ## Crate dependencies @@ -440,3 +440,5 @@ Members are listed in alphabetical order. Members are free to use the full name, - [Victor Teles @victor-teles](https://github.com/victor-teles) - [Yagiz Nizipli @anonrig](https://github.com/anonrig) - [Yoshiaki Togami @togami2864](https://github.com/togami2864) +- [Ze-Zheng Wu @Sec-ant](https://github.com/Sec-ant) +- [Zheyu Zhang @ah-yu](https://github.com/ah-yu) diff --git a/Cargo.lock b/Cargo.lock index 0e608f29e5fd..88a339cfd40f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -155,6 +155,7 @@ version = "0.0.0" dependencies = [ "anyhow", "biome_analyze", + "biome_configuration", "biome_console", "biome_css_formatter", "biome_deserialize", @@ -162,6 +163,7 @@ dependencies = [ "biome_diagnostics", "biome_formatter", "biome_fs", + "biome_js_analyze", "biome_js_formatter", "biome_json_formatter", "biome_json_parser", @@ -185,6 +187,7 @@ dependencies = [ "rustc-hash", "serde", "serde_json", + "smallvec", "tikv-jemallocator", "tokio", "tracing", @@ -193,6 +196,37 @@ dependencies = [ "tracing-tree", ] +[[package]] +name = "biome_configuration" +version = "0.0.1" +dependencies = [ + "biome_analyze", + "biome_console", + "biome_css_analyze", + "biome_css_syntax", + "biome_deserialize", + "biome_deserialize_macros", + "biome_diagnostics", + "biome_flags", + "biome_formatter", + "biome_js_analyze", + "biome_js_formatter", + "biome_js_syntax", + "biome_json_analyze", + "biome_json_formatter", + "biome_json_parser", + "biome_json_syntax", + "biome_rowan", + "bpaf", + "indexmap 1.9.3", + "insta", + "oxc_resolver", + "rustc-hash", + "schemars", + "serde", + "serde_json", +] + [[package]] name = "biome_console" version = "0.5.7" @@ -221,12 +255,10 @@ version = "0.5.7" dependencies = [ "biome_analyze", "biome_console", - "biome_css_factory", "biome_css_parser", "biome_css_syntax", "biome_diagnostics", "biome_rowan", - "biome_service", "biome_test_utils", "insta", "lazy_static", @@ -245,18 +277,16 @@ dependencies = [ name = "biome_css_formatter" version = "0.5.7" dependencies = [ - "biome_css_factory", "biome_css_parser", "biome_css_syntax", "biome_diagnostics", "biome_formatter", "biome_formatter_test", - "biome_fs", "biome_parser", "biome_rowan", + "biome_service", "biome_suppression", "countme", - "insta", "serde", "serde_json", "tests_macros", @@ -279,7 +309,6 @@ dependencies = [ "quickcheck_macros", "tests_macros", "tracing", - "unicode-bom", ] [[package]] @@ -390,7 +419,9 @@ dependencies = [ name = "biome_formatter_test" version = "0.0.0" dependencies = [ + "biome_configuration", "biome_console", + "biome_deserialize", "biome_diagnostics", "biome_formatter", "biome_fs", @@ -421,6 +452,42 @@ dependencies = [ "tracing", ] +[[package]] +name = "biome_graphql_factory" +version = "0.1.0" +dependencies = [ + "biome_graphql_syntax", + "biome_rowan", +] + +[[package]] +name = "biome_graphql_parser" +version = "0.1.0" +dependencies = [ + "biome_console", + "biome_diagnostics", + "biome_graphql_factory", + "biome_graphql_syntax", + "biome_parser", + "biome_rowan", + "biome_unicode_table", + "insta", + "quickcheck", + "quickcheck_macros", + "tests_macros", + "tracing", + "unicode-bom", +] + +[[package]] +name = "biome_graphql_syntax" +version = "0.1.0" +dependencies = [ + "biome_rowan", + "schemars", + "serde", +] + [[package]] name = "biome_grit_factory" version = "0.5.7" @@ -429,6 +496,29 @@ dependencies = [ "biome_rowan", ] +[[package]] +name = "biome_grit_parser" +version = "0.1.0" +dependencies = [ + "biome_console", + "biome_diagnostics", + "biome_grit_factory", + "biome_grit_syntax", + "biome_parser", + "biome_rowan", + "bitflags 2.3.1", + "insta", + "quickcheck", + "quickcheck_macros", + "schemars", + "serde", + "serde_json", + "smallvec", + "tests_macros", + "tracing", + "unicode-bom", +] + [[package]] name = "biome_grit_syntax" version = "0.5.7" @@ -446,6 +536,25 @@ dependencies = [ "biome_rowan", ] +[[package]] +name = "biome_html_parser" +version = "0.0.0" +dependencies = [ + "biome_console", + "biome_diagnostics", + "biome_html_factory", + "biome_html_syntax", + "biome_parser", + "biome_rowan", + "biome_test_utils", + "biome_unicode_table", + "insta", + "quickcheck", + "quickcheck_macros", + "tests_macros", + "tracing", +] + [[package]] name = "biome_html_syntax" version = "0.5.7" @@ -471,10 +580,9 @@ dependencies = [ "biome_project", "biome_rowan", "biome_string_case", + "biome_suppression", "biome_test_utils", - "biome_text_edit", "biome_unicode_table", - "countme", "insta", "lazy_static", "natord", @@ -500,21 +608,20 @@ version = "0.5.7" dependencies = [ "biome_deserialize", "biome_deserialize_macros", - "biome_diagnostics", "biome_diagnostics_categories", "biome_formatter", "biome_formatter_test", - "biome_fs", "biome_js_factory", "biome_js_parser", "biome_js_syntax", "biome_parser", "biome_rowan", + "biome_service", + "biome_suppression", "biome_text_size", "biome_unicode_table", "countme", "iai", - "insta", "quickcheck", "quickcheck_macros", "schemars", @@ -549,7 +656,6 @@ dependencies = [ "smallvec", "tests_macros", "tracing", - "unicode-bom", ] [[package]] @@ -560,7 +666,6 @@ dependencies = [ "biome_diagnostics", "biome_js_parser", "biome_js_syntax", - "biome_markup", "biome_rowan", "rust-lapper", "rustc-hash", @@ -570,8 +675,6 @@ dependencies = [ name = "biome_js_syntax" version = "0.5.7" dependencies = [ - "biome_console", - "biome_diagnostics", "biome_js_factory", "biome_js_parser", "biome_rowan", @@ -603,11 +706,9 @@ dependencies = [ "biome_analyze", "biome_console", "biome_diagnostics", - "biome_json_factory", "biome_json_parser", "biome_json_syntax", "biome_rowan", - "biome_service", "biome_test_utils", "insta", "lazy_static", @@ -632,15 +733,13 @@ dependencies = [ "biome_diagnostics", "biome_formatter", "biome_formatter_test", - "biome_fs", - "biome_json_factory", "biome_json_parser", "biome_json_syntax", "biome_parser", "biome_rowan", + "biome_service", "biome_suppression", "countme", - "insta", "schemars", "serde", "serde_json", @@ -681,6 +780,7 @@ version = "0.0.0" dependencies = [ "anyhow", "biome_analyze", + "biome_configuration", "biome_console", "biome_diagnostics", "biome_fs", @@ -717,7 +817,6 @@ dependencies = [ "biome_json_parser", "biome_json_syntax", "biome_rowan", - "biome_service", "biome_test_utils", "insta", "lazy_static", @@ -731,8 +830,10 @@ dependencies = [ "biome_console", "biome_diagnostics", "biome_rowan", + "biome_unicode_table", "bitflags 2.3.1", "drop_bomb", + "unicode-bom", ] [[package]] @@ -768,7 +869,6 @@ dependencies = [ "quickcheck", "quickcheck_macros", "rustc-hash", - "schemars", "serde", "serde_json", "tracing", @@ -779,7 +879,9 @@ name = "biome_service" version = "0.0.0" dependencies = [ "biome_analyze", + "biome_configuration", "biome_console", + "biome_css_analyze", "biome_css_formatter", "biome_css_parser", "biome_css_syntax", @@ -837,6 +939,7 @@ name = "biome_test_utils" version = "0.0.0" dependencies = [ "biome_analyze", + "biome_configuration", "biome_console", "biome_deserialize", "biome_diagnostics", @@ -891,10 +994,8 @@ dependencies = [ "console_error_panic_hook", "js-sys", "quote", - "schemars", "serde", "serde-wasm-bindgen", - "serde_json", "wasm-bindgen", ] @@ -3716,6 +3817,9 @@ dependencies = [ "anyhow", "biome_analyze", "biome_cli", + "biome_configuration", + "biome_css_analyze", + "biome_css_syntax", "biome_diagnostics", "biome_js_analyze", "biome_js_factory", @@ -3804,6 +3908,9 @@ version = "0.0.0" dependencies = [ "biome_analyze", "biome_console", + "biome_css_analyze", + "biome_css_parser", + "biome_css_syntax", "biome_diagnostics", "biome_js_analyze", "biome_js_parser", diff --git a/Cargo.toml b/Cargo.toml index a86a50343298..129bcfad343e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,11 +14,11 @@ resolver = "2" [workspace.lints.rust] absolute_paths_not_starting_with_crate = "warn" +dead_code = "warn" trivial_numeric_casts = "warn" unused_import_braces = "warn" unused_lifetimes = "warn" unused_macro_rules = "warn" -unused_tuple_struct_fields = "warn" [workspace.lints.clippy] cargo_common_metadata = "allow" @@ -99,6 +99,7 @@ biome_aria = { version = "0.5.7", path = "./crates/biome_aria" biome_aria_metadata = { version = "0.5.7", path = "./crates/biome_aria_metadata" } biome_console = { version = "0.5.7", path = "./crates/biome_console" } biome_control_flow = { version = "0.5.7", path = "./crates/biome_control_flow" } +biome_css_analyze = { version = "0.5.7", path = "./crates/biome_css_analyze" } biome_css_factory = { version = "0.5.7", path = "./crates/biome_css_factory" } biome_css_formatter = { version = "0.5.7", path = "./crates/biome_css_formatter" } biome_css_parser = { version = "0.5.7", path = "./crates/biome_css_parser" } @@ -110,7 +111,10 @@ biome_diagnostics_categories = { version = "0.5.7", path = "./crates/biome_diagn biome_diagnostics_macros = { version = "0.5.7", path = "./crates/biome_diagnostics_macros" } biome_formatter = { version = "0.5.7", path = "./crates/biome_formatter" } biome_fs = { version = "0.5.7", path = "./crates/biome_fs" } +biome_graphql_factory = { version = "0.1.0", path = "./crates/biome_graphql_factory" } +biome_graphql_syntax = { version = "0.1.0", path = "./crates/biome_graphql_syntax" } biome_grit_factory = { version = "0.5.7", path = "./crates/biome_grit_factory" } +biome_grit_parser = { version = "0.1.0", path = "./crates/biome_grit_parser" } biome_grit_syntax = { version = "0.5.7", path = "./crates/biome_grit_syntax" } biome_html_factory = { version = "0.5.7", path = "./crates/biome_html_factory" } biome_html_syntax = { version = "0.5.7", path = "./crates/biome_html_syntax" } @@ -120,7 +124,6 @@ biome_js_formatter = { version = "0.5.7", path = "./crates/biome_js_fo biome_js_parser = { version = "0.5.7", path = "./crates/biome_js_parser" } biome_js_semantic = { version = "0.5.7", path = "./crates/biome_js_semantic" } biome_js_syntax = { version = "0.5.7", path = "./crates/biome_js_syntax" } -biome_js_transform = { version = "0.5.7", path = "./crates/biome_js_transform" } biome_json_analyze = { version = "0.5.7", path = "./crates/biome_json_analyze" } biome_json_factory = { version = "0.5.7", path = "./crates/biome_json_factory" } biome_json_formatter = { version = "0.5.7", path = "./crates/biome_json_formatter" } @@ -137,6 +140,7 @@ biome_text_size = { version = "0.5.7", path = "./crates/biome_text_ biome_unicode_table = { version = "0.5.7", path = "./crates/biome_unicode_table" } # not publish biome_cli = { path = "./crates/biome_cli" } +biome_configuration = { path = "./crates/biome_configuration" } biome_flags = { path = "./crates/biome_flags" } biome_formatter_test = { path = "./crates/biome_formatter_test" } biome_lsp = { path = "./crates/biome_lsp" } diff --git a/Dockerfile.benchmark b/Dockerfile.benchmark index e46fb6c31023..745e1d7d3605 100644 --- a/Dockerfile.benchmark +++ b/Dockerfile.benchmark @@ -1,4 +1,4 @@ -FROM rust:1.69.0 +FROM rust:1.69.0@sha256:c2dcc19371a976065950915307b03a9c5514e5143bdd833635d5501a0642992e WORKDIR /usr/src/ # https://github.com/nodesource/distributions diff --git a/GOVERNANCE.md b/GOVERNANCE.md index 8936d8f4ebd2..272602e1557c 100644 --- a/GOVERNANCE.md +++ b/GOVERNANCE.md @@ -56,7 +56,7 @@ Only [maintainers](#maintainer) can be nominated to be core contributors. Core contributors may either be nominated by another, [Core contributor](#core-contributor), or [lead](#lead). -When nominating a core contributor, a new thread in the `#core-contributors` channel has to be created, with a case and [their contributions](#contributions) of why the person should join as [core contributor](#core-contributor). +When nominating a core contributor, a new **private** thread in the `#core-contributors` channel has to be created, with a case and [their contributions](#contributions) of why the person should join as [core contributor](#core-contributor). `#core-contributors` is a private channel available only to people who have the `Core contributor` role. @@ -89,13 +89,13 @@ Maintainers are those with a history of consistent contributions, including but Maintainers may either be nominated by another [maintainer](#maintainer), [Core contributor](#core-contributor), [lead](#lead). -When nominating a new maintainer, a new thread in the `#maintainers` channel has to be created, provide a link to the history of the [person's contributions](#contributions) to the project and a brief explanation of why the person should join as [maintainer](#maintainer). +When nominating a new maintainer, a new **private** thread in the `#maintainers` channel has to be created, provide a link to the history of the [person's contributions](#contributions) to the project and a brief explanation of why the person should join as [maintainer](#maintainer). `#maintainers` is a private channel available only to people who have the `maintainer` role. The voting period will follow the [voting rules](#voting-rules). An individual becomes a [maintainer](#maintainer) if: - reaches more than 50% of positive votes among the people who have voting rights; -- if the voting session ends with 50%, the Lead maintainers will take the decision; +- if the voting session ends with 50%, the Leads will take the decision; A maintainer can be self-nominated. They will have to message a [lead maintainer](#lead) privately with links to their contributions to the project. Then, the lead can: - reject the nomination in place, provide reasons why and possibly some suggestions for the future; @@ -103,16 +103,17 @@ A maintainer can be self-nominated. They will have to message a [lead maintainer When the verdict is reached, the thread will be deleted, and a [core contributor](#core-contributor) or [lead](#lead) will reach out to the nominee. -If vote is successful, the lead will ask the nominee if they want to accept the title. +If vote is successful, the person reaching out will ask the nominee if they want to accept the title. In the event of a rejection, the nominated person will be privately given the requirements they have not met. Details of the discussion, such as the names of those who objected the nomination, will not be disclosed. ### Voting Rules +- The voting sessions are run in Discord, so Maintainers and Core Contributors are expected to have an account. - Members are required to vote. - Members may abstain from a vote. -- Members who do not vote within seven days will automatically abstain. -- Leads may reduce the seven days automatic abstain for urgent decisions. +- Members who do not vote within three days will automatically abstain. +- Leads may reduce the three days automatic abstain for urgent decisions. - Leads reserve the right to veto approval with a publicly disclosed reason. - It's highly suggested to pair the vote with a reason of the vote, e.g. "I vote in favour because that person writes good code". These reasons will be collected and brought up to the nominee at the end of the voting phase. @@ -211,11 +212,19 @@ The reviewers will determine responses based on the information gathered and the ## OpenCollective fund allocation -- Funds will be allocated for project-specific services such as domain registration and website hosting. -- Core contributors are allowed to claim expenses related to conferences where they talk about Biome, or Biome workshops that they run. Expenses that can be claimed are but not limited to: trip (plane, train, etc.), meals, transport, parking. +**Funds will be allocated for project-specific services**: + - Domain registrations + - Website hosting + - Password manager to manage secrets and passwords among Lead members + +Core contributors are allowed to claim expenses related to conferences where they talk about Biome, or Biome workshops that they run. Expenses that can be claimed are but not limited to: trip (plane, train, etc.), meals, transport, parking. - The person will have to provide proof of attendance (badge, video, etc.); - Expenses will have to be uploaded via the open collective website. -- Expenses will be approved by the [leads](#lead). + - Only the expenses that are afforded in the days of the workspace/conference are accepted: + - If a conference lasts multiple days and the member decides to attend *both* days, and the member speaks only the first day, only the expenses of the first day should be taken in consideration. In this example, if the member booked three nights in a hotel to attend these two days, the expense should be divided by 3 - three nights - and only expense 2 days: night before the conference, plus the night of the day the member speaks. + - If a conference lasts one day and the member decides to make their performance longer, all the expenses afforded in the other days won't be accepted. Only 2 nights of accommodation are accepted. + +Expenses must be approved by at least one [lead](#lead). In the presence of one single lead, the lead will ask one core contributor to fact-check the honesty of expenses, and leave a comment in the Open Collective expense page. In case of multiple leads, the lead submitting the expense must seek the approval of at least one other lead. > [!NOTE] > Other usage of funds has yet to be decided. diff --git a/benchmark/package-lock.json b/benchmark/package-lock.json index d8ac4ec92779..b64b1b71c647 100644 --- a/benchmark/package-lock.json +++ b/benchmark/package-lock.json @@ -1,3144 +1,3144 @@ { - "name": "benchmark", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "benchmark", - "version": "1.0.0", - "license": "MIT OR Apache-2.0", - "devDependencies": { - "@mixer/parallel-prettier": "^2.0.3", - "dprint": "^0.43.0", - "eslint": "^8.54.0", - "prettier": "^3.1.0" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@dprint/darwin-arm64": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@dprint/darwin-arm64/-/darwin-arm64-0.43.0.tgz", - "integrity": "sha512-0lf4+ihokesOlYmFCyLdB44QYA0+IfHK8pD53i2FJ3i8XJ5yZypokO2zq+lM9MI6lt8foxh5j8at7ChIaGX6HA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@dprint/darwin-x64": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@dprint/darwin-x64/-/darwin-x64-0.43.0.tgz", - "integrity": "sha512-mMVobMZ3QUGSYgyICQSERk6Bdq2EfNL9kYTFqiK+0EBq4WF8XFE/+Itr1Os+QODhtDcn76j2hk3WkvBGruYvog==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@dprint/linux-arm64-glibc": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@dprint/linux-arm64-glibc/-/linux-arm64-glibc-0.43.0.tgz", - "integrity": "sha512-yyRCS1UYylKfRWXdH7XDfRy0xzub2rLhvC/TwCQS1o7Qo95XXxFhlDrTLsGI+vMS5m2abJtBN3Zv+tvNctGWTQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@dprint/linux-arm64-musl": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@dprint/linux-arm64-musl/-/linux-arm64-musl-0.43.0.tgz", - "integrity": "sha512-tDG3h+/IOUC7VXrjF0dNAhstDn+hwuLmQ9Pdp6fOIt9n7nD71VK1M4f8+yi3BdhxYuIKj3+VYPbS9FodWgB6Uw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@dprint/linux-x64-glibc": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@dprint/linux-x64-glibc/-/linux-x64-glibc-0.43.0.tgz", - "integrity": "sha512-pwHW+/CLcGCzBAL0efmrC/KAgOBIkT+Xc2kOo3e/buEJe32CCTuv74jdsLy8WWrAcOJz0S3dLzdPDEQxuzDOnA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@dprint/linux-x64-musl": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@dprint/linux-x64-musl/-/linux-x64-musl-0.43.0.tgz", - "integrity": "sha512-jNOKk0h0oQLzXBkIep03SsgadZ2bnUcI0O0c7IGCPt1S+w66iMDhz78KiGk6FK70Vxb+bNRYeJiL03pbx55PhA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@dprint/win32-x64": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@dprint/win32-x64/-/win32-x64-0.43.0.tgz", - "integrity": "sha512-4KtAyDtSTtJZc3VNO0G5pceAJJxvOPSVHJ1LpTdUqcfMGi1pORaCpEFs0TLhz15d8i7HmYbbtwT+hhiuTDRCXw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", - "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", - "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", - "dev": true - }, - "node_modules/@mixer/parallel-prettier": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@mixer/parallel-prettier/-/parallel-prettier-2.0.3.tgz", - "integrity": "sha512-42ImvDusmxjpQLHEmZrljV/+L9ynfmaTe5ooLMTTLyELulUJtJW8vBXCadQdodfZ5wjr2Sg3YGIzWE0rnBsfDg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "commander": "^7.0.0", - "glob-stream": "^7.0.0", - "ignore": "^5.1.8", - "ora": "^5.3.0", - "prettier": "^2.0.4", - "rxjs": "^6.6.3" - }, - "bin": { - "pprettier": "dist/index.js" - }, - "peerDependencies": { - "prettier": "^2.0.0" - } - }, - "node_modules/@mixer/parallel-prettier/node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "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, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "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, - "engines": { - "node": ">= 8" - } - }, - "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, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "dev": 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, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "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, - "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_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, - "engines": { - "node": ">=8" - } - }, - "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, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "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 - }, - "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 - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "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" - } - ] - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "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" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "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, - "engines": { - "node": ">=6" - } - }, - "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, - "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/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", - "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "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, - "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 - }, - "node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "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 - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "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 - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dprint": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/dprint/-/dprint-0.43.0.tgz", - "integrity": "sha512-+dhMk7HE2B6Us4HkxWrJTcVvaOXd+YvSD+AwRXz7fCVrM1lgxqLPR+xt+ZqNjt2tDmCvU/i00L6yIoPbTqr+yA==", - "dev": true, - "hasInstallScript": true, - "bin": { - "dprint": "bin.js" - }, - "optionalDependencies": { - "@dprint/darwin-arm64": "0.43.0", - "@dprint/darwin-x64": "0.43.0", - "@dprint/linux-arm64-glibc": "0.43.0", - "@dprint/linux-arm64-musl": "0.43.0", - "@dprint/linux-x64-glibc": "0.43.0", - "@dprint/linux-x64-musl": "0.43.0", - "@dprint/win32-x64": "0.43.0" - } - }, - "node_modules/duplexify": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", - "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.4.1", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1", - "stream-shift": "^1.0.0" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "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, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", - "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.3", - "@eslint/js": "8.54.0", - "@humanwhocodes/config-array": "^0.11.13", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.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, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "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, - "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, - "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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "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 - }, - "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 - }, - "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 - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "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, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "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 - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "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/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, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob-stream": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-7.0.0.tgz", - "integrity": "sha512-evR4kvr6s0Yo5t4CD4H171n4T8XcnPFznvsbeN8K9FPzc0Q0wYqcOWyGtck2qcvJSLXKnU6DnDyfmbDDabYvRQ==", - "dev": true, - "dependencies": { - "extend": "^3.0.2", - "glob": "^7.2.0", - "glob-parent": "^6.0.2", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.1", - "pumpify": "^2.0.1", - "readable-stream": "^3.6.0", - "remove-trailing-separator": "^1.1.0", - "to-absolute-glob": "^2.0.2", - "unique-stream": "^2.3.1" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "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, - "engines": { - "node": ">=8" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "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" - } - ] - }, - "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "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==", - "dev": true, - "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 - }, - "node_modules/is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "dependencies": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "dependencies": { - "is-unc-path": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "dependencies": { - "unc-path-regex": "^0.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "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, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "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 - }, - "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 - }, - "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, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "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, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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 - }, - "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, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "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, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "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 - }, - "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==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.1" - } - }, - "node_modules/ordered-read-streams/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "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, - "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", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", - "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", - "dev": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/pumpify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz", - "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==", - "dev": true, - "dependencies": { - "duplexify": "^4.1.1", - "inherits": "^2.0.3", - "pump": "^3.0.0" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "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" - } - ] - }, - "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, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", - "dev": true - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "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" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "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, - "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, - "engines": { - "node": ">=8" - } - }, - "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 - }, - "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "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, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "dependencies": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "node_modules/through2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha512-rtwLUQEwT8ZeKQbyFJyomBRYXyE16U5VKuy0ftxLMK/PZb2fkOsg5r9kHdauuVDbsNdIBoC/HCthpidamQFXYA==", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "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, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "dependencies": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.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 - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "dependencies": { - "defaults": "^1.0.3" - } - }, - "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, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "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 - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true - }, - "@dprint/darwin-arm64": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@dprint/darwin-arm64/-/darwin-arm64-0.43.0.tgz", - "integrity": "sha512-0lf4+ihokesOlYmFCyLdB44QYA0+IfHK8pD53i2FJ3i8XJ5yZypokO2zq+lM9MI6lt8foxh5j8at7ChIaGX6HA==", - "dev": true, - "optional": true - }, - "@dprint/darwin-x64": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@dprint/darwin-x64/-/darwin-x64-0.43.0.tgz", - "integrity": "sha512-mMVobMZ3QUGSYgyICQSERk6Bdq2EfNL9kYTFqiK+0EBq4WF8XFE/+Itr1Os+QODhtDcn76j2hk3WkvBGruYvog==", - "dev": true, - "optional": true - }, - "@dprint/linux-arm64-glibc": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@dprint/linux-arm64-glibc/-/linux-arm64-glibc-0.43.0.tgz", - "integrity": "sha512-yyRCS1UYylKfRWXdH7XDfRy0xzub2rLhvC/TwCQS1o7Qo95XXxFhlDrTLsGI+vMS5m2abJtBN3Zv+tvNctGWTQ==", - "dev": true, - "optional": true - }, - "@dprint/linux-arm64-musl": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@dprint/linux-arm64-musl/-/linux-arm64-musl-0.43.0.tgz", - "integrity": "sha512-tDG3h+/IOUC7VXrjF0dNAhstDn+hwuLmQ9Pdp6fOIt9n7nD71VK1M4f8+yi3BdhxYuIKj3+VYPbS9FodWgB6Uw==", - "dev": true, - "optional": true - }, - "@dprint/linux-x64-glibc": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@dprint/linux-x64-glibc/-/linux-x64-glibc-0.43.0.tgz", - "integrity": "sha512-pwHW+/CLcGCzBAL0efmrC/KAgOBIkT+Xc2kOo3e/buEJe32CCTuv74jdsLy8WWrAcOJz0S3dLzdPDEQxuzDOnA==", - "dev": true, - "optional": true - }, - "@dprint/linux-x64-musl": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@dprint/linux-x64-musl/-/linux-x64-musl-0.43.0.tgz", - "integrity": "sha512-jNOKk0h0oQLzXBkIep03SsgadZ2bnUcI0O0c7IGCPt1S+w66iMDhz78KiGk6FK70Vxb+bNRYeJiL03pbx55PhA==", - "dev": true, - "optional": true - }, - "@dprint/win32-x64": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@dprint/win32-x64/-/win32-x64-0.43.0.tgz", - "integrity": "sha512-4KtAyDtSTtJZc3VNO0G5pceAJJxvOPSVHJ1LpTdUqcfMGi1pORaCpEFs0TLhz15d8i7HmYbbtwT+hhiuTDRCXw==", - "dev": true, - "optional": true - }, - "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - } - }, - "@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", - "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - } - }, - "@eslint/js": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", - "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", - "dev": true - }, - "@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", - "dev": true - }, - "@mixer/parallel-prettier": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@mixer/parallel-prettier/-/parallel-prettier-2.0.3.tgz", - "integrity": "sha512-42ImvDusmxjpQLHEmZrljV/+L9ynfmaTe5ooLMTTLyELulUJtJW8vBXCadQdodfZ5wjr2Sg3YGIzWE0rnBsfDg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "commander": "^7.0.0", - "glob-stream": "^7.0.0", - "ignore": "^5.1.8", - "ora": "^5.3.0", - "prettier": "^2.0.4", - "rxjs": "^6.6.3" - }, - "dependencies": { - "prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true - } - } - }, - "@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, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@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 - }, - "@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, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "dev": true - }, - "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, - "requires": {} - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "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 - }, - "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, - "requires": { - "color-convert": "^2.0.1" - } - }, - "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 - }, - "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 - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-spinners": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", - "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", - "dev": true - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true - }, - "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, - "requires": { - "color-name": "~1.1.4" - } - }, - "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 - }, - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "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 - }, - "defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dprint": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/dprint/-/dprint-0.43.0.tgz", - "integrity": "sha512-+dhMk7HE2B6Us4HkxWrJTcVvaOXd+YvSD+AwRXz7fCVrM1lgxqLPR+xt+ZqNjt2tDmCvU/i00L6yIoPbTqr+yA==", - "dev": true, - "requires": { - "@dprint/darwin-arm64": "0.43.0", - "@dprint/darwin-x64": "0.43.0", - "@dprint/linux-arm64-glibc": "0.43.0", - "@dprint/linux-arm64-musl": "0.43.0", - "@dprint/linux-x64-glibc": "0.43.0", - "@dprint/linux-x64-musl": "0.43.0", - "@dprint/win32-x64": "0.43.0" - } - }, - "duplexify": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", - "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", - "dev": true, - "requires": { - "end-of-stream": "^1.4.1", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1", - "stream-shift": "^1.0.0" - } - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "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 - }, - "eslint": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", - "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.3", - "@eslint/js": "8.54.0", - "@humanwhocodes/config-array": "^0.11.13", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - } - }, - "eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "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 - }, - "espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "requires": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - } - }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "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, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "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 - }, - "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 - }, - "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 - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "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, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "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 - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "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" - } - }, - "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, - "requires": { - "is-glob": "^4.0.3" - } - }, - "glob-stream": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-7.0.0.tgz", - "integrity": "sha512-evR4kvr6s0Yo5t4CD4H171n4T8XcnPFznvsbeN8K9FPzc0Q0wYqcOWyGtck2qcvJSLXKnU6DnDyfmbDDabYvRQ==", - "dev": true, - "requires": { - "extend": "^3.0.2", - "glob": "^7.2.0", - "glob-parent": "^6.0.2", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.1", - "pumpify": "^2.0.1", - "readable-stream": "^3.6.0", - "remove-trailing-separator": "^1.1.0", - "to-absolute-glob": "^2.0.2", - "unique-stream": "^2.3.1" - } - }, - "globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "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 - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true - }, - "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "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, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true - }, - "is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==", - "dev": true - }, - "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 - }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "^1.0.0" - } - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "requires": { - "unc-path-regex": "^0.1.2" - } - }, - "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 - }, - "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 - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "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, - "requires": { - "argparse": "^2.0.1" - } - }, - "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 - }, - "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 - }, - "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, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "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, - "requires": { - "p-locate": "^5.0.0" - } - }, - "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 - }, - "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, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "requires": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - } - }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - } - }, - "ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - } - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "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 - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prettier": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", - "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz", - "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==", - "dev": true, - "requires": { - "duplexify": "^4.1.1", - "inherits": "^2.0.3", - "pump": "^3.0.0" - } - }, - "punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "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, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", - "dev": true - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "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, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "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 - }, - "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 - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "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, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - } - } - }, - "through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha512-rtwLUQEwT8ZeKQbyFJyomBRYXyE16U5VKuy0ftxLMK/PZb2fkOsg5r9kHdauuVDbsNdIBoC/HCthpidamQFXYA==", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "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, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", - "dev": true - }, - "unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "requires": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "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 - }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "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 - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } + "name": "@biomejs/benchmark", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@biomejs/benchmark", + "version": "1.0.0", + "license": "MIT OR Apache-2.0", + "devDependencies": { + "@mixer/parallel-prettier": "2.0.3", + "dprint": "0.43.0", + "eslint": "8.54.0", + "prettier": "3.1.0" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@dprint/darwin-arm64": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@dprint/darwin-arm64/-/darwin-arm64-0.43.0.tgz", + "integrity": "sha512-0lf4+ihokesOlYmFCyLdB44QYA0+IfHK8pD53i2FJ3i8XJ5yZypokO2zq+lM9MI6lt8foxh5j8at7ChIaGX6HA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@dprint/darwin-x64": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@dprint/darwin-x64/-/darwin-x64-0.43.0.tgz", + "integrity": "sha512-mMVobMZ3QUGSYgyICQSERk6Bdq2EfNL9kYTFqiK+0EBq4WF8XFE/+Itr1Os+QODhtDcn76j2hk3WkvBGruYvog==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@dprint/linux-arm64-glibc": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@dprint/linux-arm64-glibc/-/linux-arm64-glibc-0.43.0.tgz", + "integrity": "sha512-yyRCS1UYylKfRWXdH7XDfRy0xzub2rLhvC/TwCQS1o7Qo95XXxFhlDrTLsGI+vMS5m2abJtBN3Zv+tvNctGWTQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@dprint/linux-arm64-musl": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@dprint/linux-arm64-musl/-/linux-arm64-musl-0.43.0.tgz", + "integrity": "sha512-tDG3h+/IOUC7VXrjF0dNAhstDn+hwuLmQ9Pdp6fOIt9n7nD71VK1M4f8+yi3BdhxYuIKj3+VYPbS9FodWgB6Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@dprint/linux-x64-glibc": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@dprint/linux-x64-glibc/-/linux-x64-glibc-0.43.0.tgz", + "integrity": "sha512-pwHW+/CLcGCzBAL0efmrC/KAgOBIkT+Xc2kOo3e/buEJe32CCTuv74jdsLy8WWrAcOJz0S3dLzdPDEQxuzDOnA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@dprint/linux-x64-musl": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@dprint/linux-x64-musl/-/linux-x64-musl-0.43.0.tgz", + "integrity": "sha512-jNOKk0h0oQLzXBkIep03SsgadZ2bnUcI0O0c7IGCPt1S+w66iMDhz78KiGk6FK70Vxb+bNRYeJiL03pbx55PhA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@dprint/win32-x64": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@dprint/win32-x64/-/win32-x64-0.43.0.tgz", + "integrity": "sha512-4KtAyDtSTtJZc3VNO0G5pceAJJxvOPSVHJ1LpTdUqcfMGi1pORaCpEFs0TLhz15d8i7HmYbbtwT+hhiuTDRCXw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "node_modules/@mixer/parallel-prettier": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@mixer/parallel-prettier/-/parallel-prettier-2.0.3.tgz", + "integrity": "sha512-42ImvDusmxjpQLHEmZrljV/+L9ynfmaTe5ooLMTTLyELulUJtJW8vBXCadQdodfZ5wjr2Sg3YGIzWE0rnBsfDg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "commander": "^7.0.0", + "glob-stream": "^7.0.0", + "ignore": "^5.1.8", + "ora": "^5.3.0", + "prettier": "^2.0.4", + "rxjs": "^6.6.3" + }, + "bin": { + "pprettier": "dist/index.js" + }, + "peerDependencies": { + "prettier": "^2.0.0" + } + }, + "node_modules/@mixer/parallel-prettier/node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "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, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "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, + "engines": { + "node": ">= 8" + } + }, + "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, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": 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, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "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, + "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_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, + "engines": { + "node": ">=8" + } + }, + "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, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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 + }, + "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 + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "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" + } + ] + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "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" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "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, + "engines": { + "node": ">=6" + } + }, + "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, + "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/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", + "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "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, + "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 + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "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 + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "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 + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dprint": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/dprint/-/dprint-0.43.0.tgz", + "integrity": "sha512-+dhMk7HE2B6Us4HkxWrJTcVvaOXd+YvSD+AwRXz7fCVrM1lgxqLPR+xt+ZqNjt2tDmCvU/i00L6yIoPbTqr+yA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "dprint": "bin.js" + }, + "optionalDependencies": { + "@dprint/darwin-arm64": "0.43.0", + "@dprint/darwin-x64": "0.43.0", + "@dprint/linux-arm64-glibc": "0.43.0", + "@dprint/linux-arm64-musl": "0.43.0", + "@dprint/linux-x64-glibc": "0.43.0", + "@dprint/linux-x64-musl": "0.43.0", + "@dprint/win32-x64": "0.43.0" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "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, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.54.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.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, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "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, + "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, + "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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "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 + }, + "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 + }, + "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 + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "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, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "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 + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "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/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, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-stream": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-7.0.0.tgz", + "integrity": "sha512-evR4kvr6s0Yo5t4CD4H171n4T8XcnPFznvsbeN8K9FPzc0Q0wYqcOWyGtck2qcvJSLXKnU6DnDyfmbDDabYvRQ==", + "dev": true, + "dependencies": { + "extend": "^3.0.2", + "glob": "^7.2.0", + "glob-parent": "^6.0.2", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.1", + "pumpify": "^2.0.1", + "readable-stream": "^3.6.0", + "remove-trailing-separator": "^1.1.0", + "to-absolute-glob": "^2.0.2", + "unique-stream": "^2.3.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "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, + "engines": { + "node": ">=8" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "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" + } + ] + }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "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==", + "dev": true, + "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 + }, + "node_modules/is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "dependencies": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "dependencies": { + "is-unc-path": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "dependencies": { + "unc-path-regex": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "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, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "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 + }, + "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 + }, + "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, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "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, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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 + }, + "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, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "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 + }, + "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==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.1" + } + }, + "node_modules/ordered-read-streams/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "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, + "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", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", + "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz", + "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==", + "dev": true, + "dependencies": { + "duplexify": "^4.1.1", + "inherits": "^2.0.3", + "pump": "^3.0.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "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" + } + ] + }, + "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, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "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" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "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, + "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, + "engines": { + "node": ">=8" + } + }, + "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 + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "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, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "dev": true, + "dependencies": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha512-rtwLUQEwT8ZeKQbyFJyomBRYXyE16U5VKuy0ftxLMK/PZb2fkOsg5r9kHdauuVDbsNdIBoC/HCthpidamQFXYA==", + "dev": true, + "dependencies": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "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, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dev": true, + "dependencies": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.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 + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "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, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "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 + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, + "@dprint/darwin-arm64": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@dprint/darwin-arm64/-/darwin-arm64-0.43.0.tgz", + "integrity": "sha512-0lf4+ihokesOlYmFCyLdB44QYA0+IfHK8pD53i2FJ3i8XJ5yZypokO2zq+lM9MI6lt8foxh5j8at7ChIaGX6HA==", + "dev": true, + "optional": true + }, + "@dprint/darwin-x64": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@dprint/darwin-x64/-/darwin-x64-0.43.0.tgz", + "integrity": "sha512-mMVobMZ3QUGSYgyICQSERk6Bdq2EfNL9kYTFqiK+0EBq4WF8XFE/+Itr1Os+QODhtDcn76j2hk3WkvBGruYvog==", + "dev": true, + "optional": true + }, + "@dprint/linux-arm64-glibc": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@dprint/linux-arm64-glibc/-/linux-arm64-glibc-0.43.0.tgz", + "integrity": "sha512-yyRCS1UYylKfRWXdH7XDfRy0xzub2rLhvC/TwCQS1o7Qo95XXxFhlDrTLsGI+vMS5m2abJtBN3Zv+tvNctGWTQ==", + "dev": true, + "optional": true + }, + "@dprint/linux-arm64-musl": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@dprint/linux-arm64-musl/-/linux-arm64-musl-0.43.0.tgz", + "integrity": "sha512-tDG3h+/IOUC7VXrjF0dNAhstDn+hwuLmQ9Pdp6fOIt9n7nD71VK1M4f8+yi3BdhxYuIKj3+VYPbS9FodWgB6Uw==", + "dev": true, + "optional": true + }, + "@dprint/linux-x64-glibc": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@dprint/linux-x64-glibc/-/linux-x64-glibc-0.43.0.tgz", + "integrity": "sha512-pwHW+/CLcGCzBAL0efmrC/KAgOBIkT+Xc2kOo3e/buEJe32CCTuv74jdsLy8WWrAcOJz0S3dLzdPDEQxuzDOnA==", + "dev": true, + "optional": true + }, + "@dprint/linux-x64-musl": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@dprint/linux-x64-musl/-/linux-x64-musl-0.43.0.tgz", + "integrity": "sha512-jNOKk0h0oQLzXBkIep03SsgadZ2bnUcI0O0c7IGCPt1S+w66iMDhz78KiGk6FK70Vxb+bNRYeJiL03pbx55PhA==", + "dev": true, + "optional": true + }, + "@dprint/win32-x64": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@dprint/win32-x64/-/win32-x64-0.43.0.tgz", + "integrity": "sha512-4KtAyDtSTtJZc3VNO0G5pceAJJxvOPSVHJ1LpTdUqcfMGi1pORaCpEFs0TLhz15d8i7HmYbbtwT+hhiuTDRCXw==", + "dev": true, + "optional": true + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + } + }, + "@eslint/js": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", + "dev": true + }, + "@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "@mixer/parallel-prettier": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@mixer/parallel-prettier/-/parallel-prettier-2.0.3.tgz", + "integrity": "sha512-42ImvDusmxjpQLHEmZrljV/+L9ynfmaTe5ooLMTTLyELulUJtJW8vBXCadQdodfZ5wjr2Sg3YGIzWE0rnBsfDg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "commander": "^7.0.0", + "glob-stream": "^7.0.0", + "ignore": "^5.1.8", + "ora": "^5.3.0", + "prettier": "^2.0.4", + "rxjs": "^6.6.3" + }, + "dependencies": { + "prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true + } + } + }, + "@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, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@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 + }, + "@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, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true + }, + "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, + "requires": {} + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "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 + }, + "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, + "requires": { + "color-convert": "^2.0.1" + } + }, + "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 + }, + "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 + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-spinners": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", + "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", + "dev": true + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true + }, + "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, + "requires": { + "color-name": "~1.1.4" + } + }, + "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 + }, + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + }, + "defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dprint": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/dprint/-/dprint-0.43.0.tgz", + "integrity": "sha512-+dhMk7HE2B6Us4HkxWrJTcVvaOXd+YvSD+AwRXz7fCVrM1lgxqLPR+xt+ZqNjt2tDmCvU/i00L6yIoPbTqr+yA==", + "dev": true, + "requires": { + "@dprint/darwin-arm64": "0.43.0", + "@dprint/darwin-x64": "0.43.0", + "@dprint/linux-arm64-glibc": "0.43.0", + "@dprint/linux-arm64-musl": "0.43.0", + "@dprint/linux-x64-glibc": "0.43.0", + "@dprint/linux-x64-musl": "0.43.0", + "@dprint/win32-x64": "0.43.0" + } + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dev": true, + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "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 + }, + "eslint": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.54.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + } + }, + "eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "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 + }, + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + } + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "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, + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "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 + }, + "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 + }, + "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 + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "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, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "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 + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "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" + } + }, + "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, + "requires": { + "is-glob": "^4.0.3" + } + }, + "glob-stream": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-7.0.0.tgz", + "integrity": "sha512-evR4kvr6s0Yo5t4CD4H171n4T8XcnPFznvsbeN8K9FPzc0Q0wYqcOWyGtck2qcvJSLXKnU6DnDyfmbDDabYvRQ==", + "dev": true, + "requires": { + "extend": "^3.0.2", + "glob": "^7.2.0", + "glob-parent": "^6.0.2", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.1", + "pumpify": "^2.0.1", + "readable-stream": "^3.6.0", + "remove-trailing-separator": "^1.1.0", + "to-absolute-glob": "^2.0.2", + "unique-stream": "^2.3.1" + } + }, + "globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "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 + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "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, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true + }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==", + "dev": true + }, + "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 + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "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 + }, + "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 + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "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, + "requires": { + "argparse": "^2.0.1" + } + }, + "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 + }, + "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 + }, + "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, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "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, + "requires": { + "p-locate": "^5.0.0" + } + }, + "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 + }, + "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, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, + "ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "requires": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + } + }, + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "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 + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prettier": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", + "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz", + "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==", + "dev": true, + "requires": { + "duplexify": "^4.1.1", + "inherits": "^2.0.3", + "pump": "^3.0.0" + } + }, + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "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, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "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, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "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 + }, + "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 + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "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, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, + "through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "dev": true, + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha512-rtwLUQEwT8ZeKQbyFJyomBRYXyE16U5VKuy0ftxLMK/PZb2fkOsg5r9kHdauuVDbsNdIBoC/HCthpidamQFXYA==", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "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, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", + "dev": true + }, + "unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dev": true, + "requires": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "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 + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "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 + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } } diff --git a/benchmark/package.json b/benchmark/package.json index 56ffb0046017..97d5a837e225 100644 --- a/benchmark/package.json +++ b/benchmark/package.json @@ -7,9 +7,9 @@ "author": "Biome Developers and Contributors", "license": "MIT OR Apache-2.0", "devDependencies": { - "@mixer/parallel-prettier": "^2.0.3", - "dprint": "^0.43.0", - "eslint": "^8.54.0", - "prettier": "^3.1.0" + "@mixer/parallel-prettier": "2.0.3", + "dprint": "0.43.0", + "eslint": "8.54.0", + "prettier": "3.1.0" } } diff --git a/crates/biome_analyze/CONTRIBUTING.md b/crates/biome_analyze/CONTRIBUTING.md index 761591f8f2aa..d0153e2dba9b 100644 --- a/crates/biome_analyze/CONTRIBUTING.md +++ b/crates/biome_analyze/CONTRIBUTING.md @@ -4,41 +4,13 @@ The analyzer is a generic crate aimed to implement a visitor-like infrastructure it's possible to inspect a piece of AST and emit diagnostics or actions based on a static check. -## Folder structure +The analyzer allows implementors to create **four different** types of rules: +- **Syntax**: This rule checks the syntax according to the language specification and emits error diagnostics accordingly. +- **Lint**: This rule performs static analysis of the source code to detect invalid or error-prone patterns, and emits diagnostics along with proposed fixes. +- **Assist**: This rule detects refactoring opportunities and emits code action signals. +- **Transformation**: This rule detects transformations that should be applied to the code. -First, you need to identify the crate where you want to implement the rule. -If the rule is going to be implemented for the JavaScript language (and its super languages), -then the rule will be implemented inside the `biome_js_analyze` crate. - -Rules are divided by capabilities: - -- `analyzers/` folder contains rules that don't require any particular capabilities, via the `Ast<>` query type; - -- `semantic_analyzer/` folder contains rules that require the use of the semantic model, via `Semantic<>` query type; - -- `aria_analyzers/` folder contains rules that require the use of ARIA metadata, via `Aria<>` query type; - -- `assists/` folder contains rules that contribute to refactor code, with not associated diagnostics. - These are rules that are usually meant for editors and IDEs. - -Most of the rules will go under `analyzers/` or `semantic_analyzer/`. - -Inside these four folders, we have a folder for each group that _Biome_ supports. - -When implementing **new rules**, they have to be implemented under the group `nursery`. -New rules should always be considered unstable/not exhaustive. - -In addition to selecting a group, rules may be flagged as `recommended`. -The **recommended rules** are enabled in the default configuration of the _Biome_ linter. -As a general principle, a recommended rule should catch actual programming errors. -For instance, detecting a coding pattern that will throw an exception at runtime. -Pedantic rules that check for specific unwanted patterns but may have high false positive rates, -should be left off from the recommended set. -Rules intended to be recommended should be flagged as such even if they are still part of the `nursery` group, -as unstable rules are only enabled by default on unstable builds. -This gives the project time to test the rule, find edge cases, etc. - -## Lint rules +## Creating a rules When creating or updating a lint rule, you need to be aware that there's a lot of generated code inside our toolchain. Our CI ensures that this code is not out of sync and fails otherwise. @@ -70,14 +42,14 @@ _Biome_ follows a naming convention according to what the rule do: When a rule's sole intention is to **mandate a single concept** - such as forcing the use of camel-casing - the rule should be named using the `use` prefix. For example, the rule to mandating the use of camel-cased variable names is named `useCamelCase`. -### What a rule should say to the user +### Explain a rule to the user A rule should be informative to the user, and give as much explanation as possible. When writing a rule, you must adhere to the following **pillars**: 1. Explain to the user the error. Generally, this is the message of the diagnostic. -2. Explain to the user **why** the error is triggered. Generally, this is implemented with an additional node. -3. Tell the user what they should do. Generally, this is implemented using a code action. If a code action is not applicable a note should tell the user what they should do to fix the error. +1. Explain to the user **why** the error is triggered. Generally, this is implemented with an additional node. +1. Tell the user what they should do. Generally, this is implemented using a code action. If a code action is not applicable a note should tell the user what they should do to fix the error. ### Create and implement the rule @@ -86,33 +58,17 @@ Let's say we want to create a new rule called `myRuleName`, which uses the seman 1. Run the command ```shell - just new-lintrule crates/biome_js_analyze/src/semantic_analyzers/nursery myRuleName + just new-js-lintrule myRuleName ``` + The script will create a new **lint** rule for the _JavaScript_ language, inside the `biome_js_analyze` - Rules go in different folders, and the folder depend on the type of query system your rule - will use: - - - `type Query = Ast<>` -> `analyzers/` folder - - `type Query = Semantic<>` -> `semantic_analyzers/` folder - - `type Query = SemanticServices` -> `semantic_analyzers/` folder - - `type Query = Aria<>` -> `aria_analyzers` folder - - `type Query = ControlFlowGraph` -> `analyzers/` folder - - The core team will help you out if you don't get the folder right. - Using the incorrect folder won't break any code. +1. The `Ast` query type allows you to query the AST of a program. +1. The `State` type doesn't have to be used, so it can be considered optional. However, it has to be defined as `type State = ()`. +1. Implement the `run` function: -2. The `Query` needs to have the `Semantic` type, because we want to have access to the semantic model. - `Query` tells the engine on which AST node we want to trigger the rule. + This function is called every time the analyzer finds a match for the query specified by the rule, and may return zero or more "signals". -3. The `State` type doesn't have to be used, so it can be considered optional. - However, it has to be defined as `type State = ()`. - -4. Implement the `run` function: - - This function is called every time the analyzer finds a match for the query specified by the rule, - and may return zero or more "signals". - -5. Implement the `diagnostic` function, to tell the user where's the error and why: +1. Implement the `diagnostic` function. Follow the [pillars](#explain-a-rule-to-the-user): ```rust,ignore impl Rule for UseAwesomeTricks { @@ -122,10 +78,8 @@ Let's say we want to create a new rule called `myRuleName`, which uses the seman ``` While implementing the diagnostic, please keep [Biome's technical principals](https://biomejs.dev/internals/philosophy/#technical) in mind. - This function is called for every signal emitted by the `run` function, and it may return - zero or one diagnostic. -6. Implement the optional `action` function, if we are able to provide automatic code fix to the rule: +1. Implement the optional `action` function, if we are able to provide a code action: ```rust,ignore impl Rule for UseAwesomeTricks { @@ -134,7 +88,6 @@ Let's say we want to create a new rule called `myRuleName`, which uses the seman } ``` - This function is called for every signal emitted by the `run` function. It may return zero or one code action. Rules can return a code action that can be **safe** or **unsafe**. If a rule returns a code action, you must add `fix_kind` to the macro `declare_rule`. ```rust,ignore @@ -147,21 +100,47 @@ Let's say we want to create a new rule called `myRuleName`, which uses the seman `category` must be `ActionCategory::QuickFix`. `applicability` is either `Applicability:MaybeIncorrect` or `Applicability:Always`. `Applicability:Always` must only be used when the code transformation is safe. - In other words, the code transformation should always result in code that does no change the behavior of the code. + In other words, the code transformation should always result in code that doesn't change the behavior of the logic. In the case of `noVar`, it is not always safe to turn `var` to `const` or `let`. -Don't forget to format your code with `cargo format` and lint with `cargo lint`. +Don't forget to format your code with `just f` and lint with `just l`. That's it! Now, let's test the rule. ### Test the rule +#### Quick test + +A swift way to test your rule is to go inside the `biome_js_analyze/src/lib.rs` file (this will change based on where you're implementing the rule) and modify the `quick_test` function. + +Usually this test is ignored, so remove _comment_ the macro `#[ignore]` macro, change the `let SOURCE` variable to whatever source code you need to test. Then update the rule filter, and add your rule: + +```rust,ignore +let rule_filter = RuleFilter::Rule("nursery", "useAwesomeTrick"); +``` + +Now from your terminal, go inside the `biome_js_analyze` folder and run the test using `cargo`: + +```shell +cargo t quick_test +``` + +Remember that, in case you add `dbg!` macros inside your source code, you'll have to use `--show-output`: + +```shell +cargo t quick_test -- --show-output +``` + +The test is designed to **show** diagnostics and code actions if the rule correctly emits the signal. If nothing is shown, your logic didn't emit any signal. + +#### Snapshots + Inside the `tests/specs/` folder, rules are divided by group and rule name. The test infrastructure is rigid around the association of the pair "group/rule name", which means that _**your test cases are placed inside the wrong group, you won't see any diagnostics**_. Since each new rule will start from `nursery`, that's where we start. -If you used `just new-lintrule`, a folder that use the name of the rule should exist. +If you used `just new-js-lintrule`, a folder that use the name of the rule should exist. Otherwise, create a folder called `myRuleName/`, and then create one or more files where you want to create different cases. A common pattern is to create files prefixed by `invalid` or `valid`. @@ -179,33 +158,15 @@ For instance, for the rule `noVar`, the file `invalidScript.jsonc` contains: Note that code in a file ending with the extension `.jsonc` are in a _script environment_. This means that you cannot use syntax that belongs to _ECMAScript modules_ such as `import` and `export`. -Run the command +Run the command: ```shell just test-lintrule myRuleName ``` -and if you've done everything correctly, -you should see some snapshots emitted with diagnostics and code actions. - -Check our main [contribution document](https://github.com/biomejs/biome/blob/main/CONTRIBUTING.md#testing) -to know how to deal with the snapshot tests. - -### Promote a rule - -Promoting a rule when is stable can be a tedious work. Internally, we have a script -that does that for you: - -```shell -just promote-rule noConsoleLog style -``` - -The first argument is the name of the rule, in camel case. The second argument -is the name of the group where you're promoting the rule to. - -The script will run some checks and some other script for you. +and if you've done everything correctly, you should see some snapshots emitted with diagnostics and code actions. -You're now ready to commit the changes [using `git`](#commit-your-work)! +Check our main [contribution document](https://github.com/biomejs/biome/blob/main/CONTRIBUTING.md#testing) to know how to deal with the snapshot tests. ### Document the rule @@ -269,17 +230,6 @@ For simplicity, use `just` to run all the commands with: just gen-lint ``` -This command runs several sub-commands: - -- `cargo codegen-configuration`, **this command must be run first** and, it will update the configuration; - -- `cargo lintdoc`, it will update the website with the documentation of the rules, check [`declare_rule`](#declare_rule) - for more information about it; - -- `cargo codegen-bindings`, it will update the TypeScript types released inside the JS APIs; - -- `cargo codegen-schema`, it will update the JSON Schema file of the configuration, used by the npm packages. - ### Commit your work Once the rule implemented, tested, and documented, you are ready to open a pull request! @@ -291,12 +241,6 @@ Stage and commit your changes: > git commit -m 'feat(biome_js_analyze): myRuleName' ``` -To test if everything is ready, run the following command: - -```shell -just ready -``` - ### Rule configuration Some rules may allow customization using options. diff --git a/crates/biome_analyze/src/lib.rs b/crates/biome_analyze/src/lib.rs index 6775eccc13a2..fd1cf9d60144 100644 --- a/crates/biome_analyze/src/lib.rs +++ b/crates/biome_analyze/src/lib.rs @@ -272,8 +272,6 @@ where continue; } }; - trace!("Event {:?}", &node_event); - // If this is a node event pass it to the visitors for this phase for visitor in self.visitors.iter_mut() { let ctx = VisitorContext { diff --git a/crates/biome_analyze/src/options.rs b/crates/biome_analyze/src/options.rs index 140ae61ac2bd..fc7905db2f1c 100644 --- a/crates/biome_analyze/src/options.rs +++ b/crates/biome_analyze/src/options.rs @@ -84,7 +84,7 @@ impl AnalyzerOptions { self.configuration .rules .get_rule_options::(&RuleKey::rule::()) - .map(R::Options::clone) + .cloned() } pub fn preferred_quote(&self) -> &PreferredQuote { diff --git a/crates/biome_analyze/src/rule.rs b/crates/biome_analyze/src/rule.rs index 8bd90b40f106..68d4c698b08d 100644 --- a/crates/biome_analyze/src/rule.rs +++ b/crates/biome_analyze/src/rule.rs @@ -158,6 +158,24 @@ impl RuleSource { } } + pub fn to_namespaced_rule_name(&self) -> String { + match self { + Self::Clippy(rule_name) | Self::Eslint(rule_name) => (*rule_name).to_string(), + Self::EslintImport(rule_name) => format!("import/{rule_name}"), + Self::EslintImportAccess(rule_name) => format!("import-access/{rule_name}"), + Self::EslintJest(rule_name) => format!("jest/{rule_name}"), + Self::EslintJsxA11y(rule_name) => format!("jsx-a11y/{rule_name}"), + Self::EslintReact(rule_name) => format!("react/{rule_name}"), + Self::EslintReactHooks(rule_name) => format!("react-hooks/{rule_name}"), + Self::EslintTypeScript(rule_name) => format!("@typescript-eslint/{rule_name}"), + Self::EslintSonarJs(rule_name) => format!("sonarjs/{rule_name}"), + Self::EslintStylistic(rule_name) => format!("@stylistic/{rule_name}"), + Self::EslintUnicorn(rule_name) => format!("unicorn/{rule_name}"), + Self::EslintMysticatea(rule_name) => format!("@mysticatea/{rule_name}"), + Self::EslintBarrelFiles(rule_name) => format!("barrel-files/{rule_name}"), + } + } + pub fn to_rule_url(&self) -> String { match self { Self::Clippy(rule_name) => format!("https://rust-lang.github.io/rust-clippy/master/#/{rule_name}"), @@ -186,29 +204,9 @@ impl RuleSource { matches!(self, Self::Eslint(_)) } - /// TypeScript plugin - pub const fn is_eslint_typescript(&self) -> bool { - matches!(self, Self::EslintTypeScript(_)) - } - /// All ESLint plugins, exception for the TypeScript one pub const fn is_eslint_plugin(&self) -> bool { - matches!( - self, - Self::EslintImport(_) - | Self::EslintImportAccess(_) - | Self::EslintJest(_) - | Self::EslintStylistic(_) - | Self::EslintJsxA11y(_) - | Self::EslintReact(_) - | Self::EslintReactHooks(_) - | Self::EslintSonarJs(_) - | Self::EslintUnicorn(_) - ) - } - - pub const fn is_clippy(&self) -> bool { - matches!(self, Self::Clippy(_)) + !matches!(self, Self::Clippy(_) | Self::Eslint(_)) } } diff --git a/crates/biome_analyze/src/signals.rs b/crates/biome_analyze/src/signals.rs index cf7870db7361..0f4ae01c8b9a 100644 --- a/crates/biome_analyze/src/signals.rs +++ b/crates/biome_analyze/src/signals.rs @@ -134,7 +134,7 @@ impl Default for AnalyzerActionIter { impl From> for CodeSuggestionAdvice { fn from(action: AnalyzerAction) -> Self { - let (_, suggestion) = action.mutation.as_text_edits().unwrap_or_default(); + let (_, suggestion) = action.mutation.as_text_range_and_edit().unwrap_or_default(); CodeSuggestionAdvice { applicability: action.applicability, msg: action.message, @@ -145,7 +145,7 @@ impl From> for CodeSuggestionAdvice { impl From> for CodeSuggestionItem { fn from(action: AnalyzerAction) -> Self { - let (range, suggestion) = action.mutation.as_text_edits().unwrap_or_default(); + let (range, suggestion) = action.mutation.as_text_range_and_edit().unwrap_or_default(); CodeSuggestionItem { rule_name: action.rule_name, diff --git a/crates/biome_aria/src/roles.rs b/crates/biome_aria/src/roles.rs index 847e5bb3a349..1fcb5ccaa906 100644 --- a/crates/biome_aria/src/roles.rs +++ b/crates/biome_aria/src/roles.rs @@ -983,7 +983,7 @@ impl<'a> AriaRoles { pub fn get_implicit_role( &self, element: &str, - // To generate `attributes`, you can use `biome_js_analyze::aria_services::AriaServices::extract_defined_attributes` + // To generate `attributes`, you can use `biome_js_analyze::services::aria::AriaServices::extract_defined_attributes` attributes: &FxHashMap>, ) -> Option<&'static dyn AriaRoleDefinition> { let result = match element { diff --git a/crates/biome_cli/Cargo.toml b/crates/biome_cli/Cargo.toml index 02c690011e93..ddf75e46c369 100644 --- a/crates/biome_cli/Cargo.toml +++ b/crates/biome_cli/Cargo.toml @@ -17,17 +17,17 @@ version = "0.0.0" name = "biome" path = "src/main.rs" - [dependencies] anyhow = "1.0.52" biome_analyze = { workspace = true } +biome_configuration = { workspace = true } biome_console = { workspace = true } -biome_css_formatter = { workspace = true } biome_deserialize = { workspace = true } biome_deserialize_macros = { workspace = true } biome_diagnostics = { workspace = true } biome_formatter = { workspace = true } biome_fs = { workspace = true } +biome_js_analyze = { workspace = true } biome_js_formatter = { workspace = true } biome_json_formatter = { workspace = true } biome_json_parser = { workspace = true } @@ -47,6 +47,7 @@ rayon = { workspace = true } rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } +smallvec = { workspace = true } tokio = { workspace = true, features = ["io-std", "io-util", "net", "time", "rt", "sync", "rt-multi-thread", "macros"] } tracing = { workspace = true } tracing-appender = "0.2" @@ -61,7 +62,7 @@ tokio = { workspace = true, features = ["process"] } mimalloc = "0.1.29" [target.'cfg(all(target_family="unix", not(all(target_arch = "aarch64", target_env = "musl"))))'.dependencies] -tikv-jemallocator = "0.5.0" +tikv-jemallocator = "0.5.1" [dev-dependencies] biome_css_formatter = { workspace = true } diff --git a/crates/biome_cli/src/changed.rs b/crates/biome_cli/src/changed.rs index 5fc30006c541..414eec453508 100644 --- a/crates/biome_cli/src/changed.rs +++ b/crates/biome_cli/src/changed.rs @@ -1,6 +1,7 @@ use crate::CliDiagnostic; +use biome_configuration::PartialConfiguration; use biome_fs::FileSystem; -use biome_service::{DynRef, PartialConfiguration}; +use biome_service::DynRef; use std::ffi::OsString; pub(crate) fn get_changed_files( diff --git a/crates/biome_cli/src/cli_options.rs b/crates/biome_cli/src/cli_options.rs index e9eb69cb892a..36cdff7d2979 100644 --- a/crates/biome_cli/src/cli_options.rs +++ b/crates/biome_cli/src/cli_options.rs @@ -1,7 +1,7 @@ use crate::logging::LoggingKind; use crate::LoggingLevel; +use biome_configuration::ConfigurationBasePath; use biome_diagnostics::Severity; -use biome_service::ConfigurationBasePath; use bpaf::Bpaf; use std::path::PathBuf; use std::str::FromStr; @@ -21,7 +21,7 @@ pub struct CliOptions { #[bpaf(long("verbose"), switch, fallback(false))] pub verbose: bool, - /// Set the directory of the biome.json configuration file and disable default configuration file resolution. + /// Set the directory of the biome.json or biome.jsonc configuration file and disable default configuration file resolution. #[bpaf(long("config-path"), argument("PATH"), optional)] pub config_path: Option, diff --git a/crates/biome_cli/src/commands/check.rs b/crates/biome_cli/src/commands/check.rs index 0794f807d2d3..bf59ee3c9a43 100644 --- a/crates/biome_cli/src/commands/check.rs +++ b/crates/biome_cli/src/commands/check.rs @@ -4,14 +4,16 @@ use crate::commands::{get_stdin, resolve_manifest, validate_configuration_diagno use crate::{ execute_mode, setup_cli_subscriber, CliDiagnostic, CliSession, Execution, TraversalMode, }; -use biome_deserialize::Merge; -use biome_service::configuration::organize_imports::PartialOrganizeImports; -use biome_service::configuration::{ - load_configuration, LoadedConfiguration, PartialFormatterConfiguration, +use biome_configuration::{ + organize_imports::PartialOrganizeImports, PartialConfiguration, PartialFormatterConfiguration, PartialLinterConfiguration, }; -use biome_service::workspace::{FixFileMode, UpdateSettingsParams}; -use biome_service::PartialConfiguration; +use biome_deserialize::Merge; +use biome_service::configuration::PartialConfigurationExt; +use biome_service::{ + configuration::{load_configuration, LoadedConfiguration}, + workspace::{FixFileMode, UpdateSettingsParams}, +}; use std::ffi::OsString; pub(crate) struct CheckCommandPayload { @@ -46,7 +48,7 @@ pub(crate) fn check( since, changed, } = payload; - setup_cli_subscriber(cli_options.log_level.clone(), cli_options.log_kind.clone()); + setup_cli_subscriber(cli_options.log_level, cli_options.log_kind); let fix_file_mode = if apply && apply_unsafe { return Err(CliDiagnostic::incompatible_arguments( diff --git a/crates/biome_cli/src/commands/ci.rs b/crates/biome_cli/src/commands/ci.rs index 5c8a53035b61..97cd5766e20a 100644 --- a/crates/biome_cli/src/commands/ci.rs +++ b/crates/biome_cli/src/commands/ci.rs @@ -2,14 +2,13 @@ use crate::changed::get_changed_files; use crate::cli_options::CliOptions; use crate::commands::validate_configuration_diagnostics; use crate::{execute_mode, setup_cli_subscriber, CliDiagnostic, CliSession, Execution}; +use biome_configuration::{organize_imports::PartialOrganizeImports, PartialConfiguration}; +use biome_configuration::{PartialFormatterConfiguration, PartialLinterConfiguration}; use biome_deserialize::Merge; -use biome_service::configuration::organize_imports::PartialOrganizeImports; use biome_service::configuration::{ - load_configuration, LoadedConfiguration, PartialFormatterConfiguration, - PartialLinterConfiguration, + load_configuration, LoadedConfiguration, PartialConfigurationExt, }; use biome_service::workspace::UpdateSettingsParams; -use biome_service::PartialConfiguration; use std::ffi::OsString; pub(crate) struct CiCommandPayload { @@ -35,7 +34,7 @@ pub(crate) fn ci(session: CliSession, payload: CiCommandPayload) -> Result<(), C since, changed, } = payload; - setup_cli_subscriber(cli_options.log_level.clone(), cli_options.log_kind.clone()); + setup_cli_subscriber(cli_options.log_level, cli_options.log_kind); let loaded_configuration = load_configuration(&session.app.fs, cli_options.as_configuration_base_path())?; diff --git a/crates/biome_cli/src/commands/format.rs b/crates/biome_cli/src/commands/format.rs index a816f138f4da..0c202fa12b00 100644 --- a/crates/biome_cli/src/commands/format.rs +++ b/crates/biome_cli/src/commands/format.rs @@ -6,13 +6,16 @@ use crate::execute::ReportMode; use crate::{ execute_mode, setup_cli_subscriber, CliDiagnostic, CliSession, Execution, TraversalMode, }; +use biome_configuration::vcs::PartialVcsConfiguration; +use biome_configuration::{ + PartialCssFormatter, PartialFilesConfiguration, PartialFormatterConfiguration, + PartialJavascriptFormatter, PartialJsonFormatter, +}; use biome_console::{markup, ConsoleExt}; use biome_deserialize::Merge; use biome_diagnostics::PrintDiagnostic; -use biome_service::configuration::vcs::PartialVcsConfiguration; use biome_service::configuration::{ - load_configuration, LoadedConfiguration, PartialCssFormatter, PartialFilesConfiguration, - PartialFormatterConfiguration, PartialJavascriptFormatter, PartialJsonFormatter, + load_configuration, LoadedConfiguration, PartialConfigurationExt, }; use biome_service::workspace::UpdateSettingsParams; use std::ffi::OsString; @@ -51,7 +54,7 @@ pub(crate) fn format( since, changed, } = payload; - setup_cli_subscriber(cli_options.log_level.clone(), cli_options.log_kind.clone()); + setup_cli_subscriber(cli_options.log_level, cli_options.log_kind); let loaded_configuration = load_configuration(&session.app.fs, cli_options.as_configuration_base_path())?; diff --git a/crates/biome_cli/src/commands/init.rs b/crates/biome_cli/src/commands/init.rs index b81ee72befd2..ce3f7ec40bd1 100644 --- a/crates/biome_cli/src/commands/init.rs +++ b/crates/biome_cli/src/commands/init.rs @@ -1,7 +1,8 @@ use crate::{CliDiagnostic, CliSession}; +use biome_configuration::PartialConfiguration; use biome_console::{markup, ConsoleExt, HorizontalLine}; use biome_fs::ConfigName; -use biome_service::{create_config, PartialConfiguration}; +use biome_service::configuration::create_config; pub(crate) fn init(mut session: CliSession, emit_jsonc: bool) -> Result<(), CliDiagnostic> { let fs = &mut session.app.fs; diff --git a/crates/biome_cli/src/commands/lint.rs b/crates/biome_cli/src/commands/lint.rs index f3386df30324..304ec5f0ccf9 100644 --- a/crates/biome_cli/src/commands/lint.rs +++ b/crates/biome_cli/src/commands/lint.rs @@ -4,13 +4,15 @@ use crate::commands::{get_stdin, resolve_manifest, validate_configuration_diagno use crate::{ execute_mode, setup_cli_subscriber, CliDiagnostic, CliSession, Execution, TraversalMode, }; +use biome_configuration::vcs::PartialVcsConfiguration; +use biome_configuration::{ + PartialConfiguration, PartialFilesConfiguration, PartialLinterConfiguration, +}; use biome_deserialize::Merge; -use biome_service::configuration::vcs::PartialVcsConfiguration; use biome_service::configuration::{ - load_configuration, LoadedConfiguration, PartialFilesConfiguration, PartialLinterConfiguration, + load_configuration, LoadedConfiguration, PartialConfigurationExt, }; use biome_service::workspace::{FixFileMode, UpdateSettingsParams}; -use biome_service::PartialConfiguration; use std::ffi::OsString; pub(crate) struct LintCommandPayload { @@ -40,7 +42,7 @@ pub(crate) fn lint(session: CliSession, payload: LintCommandPayload) -> Result<( changed, since, } = payload; - setup_cli_subscriber(cli_options.log_level.clone(), cli_options.log_kind.clone()); + setup_cli_subscriber(cli_options.log_level, cli_options.log_kind); let fix_file_mode = if apply && apply_unsafe { return Err(CliDiagnostic::incompatible_arguments( diff --git a/crates/biome_cli/src/commands/migrate.rs b/crates/biome_cli/src/commands/migrate.rs index c84e0dfd86d5..a7073203cc4e 100644 --- a/crates/biome_cli/src/commands/migrate.rs +++ b/crates/biome_cli/src/commands/migrate.rs @@ -2,28 +2,26 @@ use crate::cli_options::CliOptions; use crate::diagnostics::MigrationDiagnostic; use crate::execute::{execute_mode, Execution, TraversalMode}; use crate::{setup_cli_subscriber, CliDiagnostic, CliSession}; +use biome_console::{markup, ConsoleExt}; use biome_service::configuration::{load_configuration, LoadedConfiguration}; -use biome_service::ConfigurationBasePath; -use std::path::PathBuf; + +use super::MigrateSubCommand; /// Handler for the "check" command of the Biome CLI pub(crate) fn migrate( session: CliSession, cli_options: CliOptions, write: bool, - prettier: bool, + sub_command: Option, ) -> Result<(), CliDiagnostic> { - let base_path = match cli_options.config_path.as_ref() { - None => ConfigurationBasePath::default(), - Some(path) => ConfigurationBasePath::FromUser(PathBuf::from(path)), - }; + let base_path = cli_options.as_configuration_base_path(); let LoadedConfiguration { configuration: _, diagnostics: _, directory_path, file_path, } = load_configuration(&session.app.fs, base_path)?; - setup_cli_subscriber(cli_options.log_level.clone(), cli_options.log_kind.clone()); + setup_cli_subscriber(cli_options.log_level, cli_options.log_kind); if let (Some(path), Some(directory_path)) = (file_path, directory_path) { execute_mode( @@ -31,15 +29,19 @@ pub(crate) fn migrate( write, configuration_file_path: path, configuration_directory_path: directory_path, - prettier, + sub_command, }), session, &cli_options, vec![], ) } else { + let console = session.app.console; + console.log(markup! { + "If this project has not yet been set up with Biome yet, please follow the ""Getting Started guide"" first." + }); Err(CliDiagnostic::MigrateError(MigrationDiagnostic { - reason: "Biome couldn't find the configuration file".to_string(), + reason: "Biome couldn't find the Biome configuration file.".to_string(), })) } } diff --git a/crates/biome_cli/src/commands/mod.rs b/crates/biome_cli/src/commands/mod.rs index ca8276474d11..2a5001121f49 100644 --- a/crates/biome_cli/src/commands/mod.rs +++ b/crates/biome_cli/src/commands/mod.rs @@ -3,23 +3,22 @@ use crate::diagnostics::DeprecatedConfigurationFile; use crate::execute::Stdin; use crate::logging::LoggingKind; use crate::{CliDiagnostic, CliSession, LoggingLevel, VERSION}; -use biome_console::{markup, Console, ConsoleExt}; -use biome_diagnostics::{Diagnostic, PrintDiagnostic}; -use biome_fs::BiomePath; -use biome_service::configuration::vcs::PartialVcsConfiguration; -use biome_service::configuration::{ +use biome_configuration::{ css::partial_css_formatter, javascript::partial_javascript_formatter, json::partial_json_formatter, partial_configuration, partial_files_configuration, partial_formatter_configuration, partial_linter_configuration, vcs::partial_vcs_configuration, -}; -use biome_service::configuration::{ - LoadedConfiguration, PartialCssFormatter, PartialFilesConfiguration, + vcs::PartialVcsConfiguration, PartialCssFormatter, PartialFilesConfiguration, PartialFormatterConfiguration, PartialJavascriptFormatter, PartialJsonFormatter, PartialLinterConfiguration, }; +use biome_configuration::{ConfigurationDiagnostic, PartialConfiguration}; +use biome_console::{markup, Console, ConsoleExt}; +use biome_diagnostics::{Diagnostic, PrintDiagnostic}; +use biome_fs::BiomePath; +use biome_service::configuration::LoadedConfiguration; use biome_service::documentation::Doc; use biome_service::workspace::{OpenProjectParams, UpdateProjectParams}; -use biome_service::{ConfigurationDiagnostic, PartialConfiguration, WorkspaceError}; +use biome_service::WorkspaceError; use bpaf::Bpaf; use std::ffi::OsString; use std::path::PathBuf; @@ -33,6 +32,7 @@ pub(crate) mod init; pub(crate) mod lint; pub(crate) mod migrate; pub(crate) mod rage; +pub(crate) mod search; pub(crate) mod version; #[derive(Debug, Clone, Bpaf)] @@ -277,6 +277,40 @@ pub enum BiomeCommand { sub_command: Option, }, + /// Searches for Grit patterns across a project. + #[bpaf(command, hide)] // !! Command is hidden until ready for release. + Search { + #[bpaf(external, hide_usage)] + cli_options: CliOptions, + + #[bpaf(external(partial_files_configuration), optional, hide_usage)] + files_configuration: Option, + + #[bpaf(external(partial_vcs_configuration), optional, hide_usage)] + vcs_configuration: Option, + + /// Use this option when you want to search through code piped from + /// `stdin`, and print the output to `stdout`. + /// + /// The file doesn't need to exist on disk, what matters is the + /// extension of the file. Based on the extension, Biome knows how to + /// parse the code. + /// + /// Example: `echo 'let a;' | biome search '`let $var`' --stdin-file-path=file.js` + #[bpaf(long("stdin-file-path"), argument("PATH"), hide_usage)] + stdin_file_path: Option, + + /// The GritQL pattern to search for. + /// + /// Note that the search command (currently) does not support rewrites. + #[bpaf(positional("PATH"))] + pattern: String, + + /// Single file, single path or list of paths. + #[bpaf(positional("PATH"), many)] + paths: Vec, + }, + /// A command to retrieve the documentation of various aspects of the CLI. /// /// ## Examples @@ -312,6 +346,16 @@ pub enum MigrateSubCommand { /// It attempts to find the files `.prettierrc`/`prettier.json` and `.prettierignore`, and map the Prettier's configuration into Biome's configuration file. #[bpaf(command)] Prettier, + /// It attempts to find the ESLint configuration file in the working directory, and update the Biome's configuration file as a result. + #[bpaf(command)] + Eslint { + /// Includes rules inspired from an eslint rule in the migration + #[bpaf(long("include-inspired"))] + include_inspired: bool, + /// Includes nursery rules in the migration + #[bpaf(long("include-nursery"))] + include_nursery: bool, + }, } impl MigrateSubCommand { @@ -321,7 +365,7 @@ impl MigrateSubCommand { } impl BiomeCommand { - pub const fn get_color(&self) -> Option<&ColorsArg> { + const fn cli_options(&self) -> Option<&CliOptions> { match self { BiomeCommand::Version(cli_options) | BiomeCommand::Rage(cli_options, ..) @@ -329,7 +373,8 @@ impl BiomeCommand { | BiomeCommand::Lint { cli_options, .. } | BiomeCommand::Ci { cli_options, .. } | BiomeCommand::Format { cli_options, .. } - | BiomeCommand::Migrate { cli_options, .. } => cli_options.colors.as_ref(), + | BiomeCommand::Migrate { cli_options, .. } + | BiomeCommand::Search { cli_options, .. } => Some(cli_options), BiomeCommand::LspProxy(_, _) | BiomeCommand::Start(_) | BiomeCommand::Stop @@ -340,22 +385,17 @@ impl BiomeCommand { } } + pub const fn get_color(&self) -> Option<&ColorsArg> { + match self.cli_options() { + Some(cli_options) => cli_options.colors.as_ref(), + None => None, + } + } + pub const fn should_use_server(&self) -> bool { - match self { - BiomeCommand::Version(cli_options) - | BiomeCommand::Rage(cli_options, ..) - | BiomeCommand::Check { cli_options, .. } - | BiomeCommand::Lint { cli_options, .. } - | BiomeCommand::Ci { cli_options, .. } - | BiomeCommand::Format { cli_options, .. } - | BiomeCommand::Migrate { cli_options, .. } => cli_options.use_server, - BiomeCommand::Init(_) - | BiomeCommand::Start(_) - | BiomeCommand::Stop - | BiomeCommand::Explain { .. } - | BiomeCommand::LspProxy(_, _) - | BiomeCommand::RunServer { .. } - | BiomeCommand::PrintSocket => false, + match self.cli_options() { + Some(cli_options) => cli_options.use_server, + None => false, } } @@ -364,59 +404,18 @@ impl BiomeCommand { } pub fn is_verbose(&self) -> bool { - match self { - BiomeCommand::Check { cli_options, .. } - | BiomeCommand::Lint { cli_options, .. } - | BiomeCommand::Format { cli_options, .. } - | BiomeCommand::Ci { cli_options, .. } - | BiomeCommand::Migrate { cli_options, .. } => cli_options.verbose, - BiomeCommand::Version(_) - | BiomeCommand::Rage(..) - | BiomeCommand::Start(_) - | BiomeCommand::Stop - | BiomeCommand::Init(_) - | BiomeCommand::Explain { .. } - | BiomeCommand::LspProxy(_, _) - | BiomeCommand::RunServer { .. } - | BiomeCommand::PrintSocket => false, - } + self.cli_options() + .map_or(false, |cli_options| cli_options.verbose) } pub fn log_level(&self) -> LoggingLevel { - match self { - BiomeCommand::Check { cli_options, .. } - | BiomeCommand::Lint { cli_options, .. } - | BiomeCommand::Format { cli_options, .. } - | BiomeCommand::Ci { cli_options, .. } - | BiomeCommand::Migrate { cli_options, .. } => cli_options.log_level.clone(), - BiomeCommand::Version(_) - | BiomeCommand::LspProxy(_, _) - | BiomeCommand::Rage(..) - | BiomeCommand::Start(_) - | BiomeCommand::Stop - | BiomeCommand::Init(_) - | BiomeCommand::Explain { .. } - | BiomeCommand::RunServer { .. } - | BiomeCommand::PrintSocket => LoggingLevel::default(), - } + self.cli_options() + .map_or(LoggingLevel::default(), |cli_options| cli_options.log_level) } + pub fn log_kind(&self) -> LoggingKind { - match self { - BiomeCommand::Check { cli_options, .. } - | BiomeCommand::Lint { cli_options, .. } - | BiomeCommand::Format { cli_options, .. } - | BiomeCommand::Ci { cli_options, .. } - | BiomeCommand::Migrate { cli_options, .. } => cli_options.log_kind.clone(), - BiomeCommand::Version(_) - | BiomeCommand::Rage(..) - | BiomeCommand::LspProxy(_, _) - | BiomeCommand::Start(_) - | BiomeCommand::Stop - | BiomeCommand::Init(_) - | BiomeCommand::Explain { .. } - | BiomeCommand::RunServer { .. } - | BiomeCommand::PrintSocket => LoggingKind::default(), - } + self.cli_options() + .map_or(LoggingKind::default(), |cli_options| cli_options.log_kind) } } @@ -510,3 +509,9 @@ pub(crate) fn get_stdin( Ok(stdin) } + +/// Tests that all CLI options adhere to the invariants expected by `bpaf`. +#[test] +fn check_options() { + biome_command().check_invariants(false); +} diff --git a/crates/biome_cli/src/commands/rage.rs b/crates/biome_cli/src/commands/rage.rs index ccd28d320619..bff193ce6d89 100644 --- a/crates/biome_cli/src/commands/rage.rs +++ b/crates/biome_cli/src/commands/rage.rs @@ -1,3 +1,4 @@ +use biome_configuration::ConfigurationBasePath; use biome_console::fmt::{Display, Formatter}; use biome_console::{fmt, markup, ConsoleExt, HorizontalLine, Markup}; use biome_diagnostics::termcolor::{ColorChoice, WriteColor}; @@ -5,7 +6,7 @@ use biome_diagnostics::{termcolor, PrintDescription}; use biome_fs::FileSystem; use biome_service::configuration::{load_configuration, LoadedConfiguration}; use biome_service::workspace::{client, RageEntry, RageParams}; -use biome_service::{ConfigurationBasePath, DynRef, Workspace}; +use biome_service::{DynRef, Workspace}; use serde_json::Value; use std::collections::HashMap; use std::{env, io, ops::Deref}; diff --git a/crates/biome_cli/src/commands/search.rs b/crates/biome_cli/src/commands/search.rs new file mode 100644 index 000000000000..fd5358f9fbb5 --- /dev/null +++ b/crates/biome_cli/src/commands/search.rs @@ -0,0 +1,82 @@ +use crate::cli_options::CliOptions; +use crate::commands::{get_stdin, resolve_manifest, validate_configuration_diagnostics}; +use crate::execute::ReportMode; +use crate::{ + execute_mode, setup_cli_subscriber, CliDiagnostic, CliSession, Execution, TraversalMode, +}; +use biome_configuration::{vcs::PartialVcsConfiguration, PartialFilesConfiguration}; +use biome_deserialize::Merge; +use biome_service::configuration::{ + load_configuration, LoadedConfiguration, PartialConfigurationExt, +}; +use biome_service::workspace::UpdateSettingsParams; +use std::ffi::OsString; + +pub(crate) struct SearchCommandPayload { + pub(crate) cli_options: CliOptions, + pub(crate) files_configuration: Option, + pub(crate) paths: Vec, + pub(crate) pattern: String, + pub(crate) stdin_file_path: Option, + pub(crate) vcs_configuration: Option, +} + +/// Handler for the "search" command of the Biome CLI +pub(crate) fn search( + session: CliSession, + payload: SearchCommandPayload, +) -> Result<(), CliDiagnostic> { + let SearchCommandPayload { + cli_options, + files_configuration, + paths, + pattern, + stdin_file_path, + vcs_configuration, + } = payload; + setup_cli_subscriber(cli_options.log_level, cli_options.log_kind); + + let loaded_configuration = + load_configuration(&session.app.fs, cli_options.as_configuration_base_path())?; + validate_configuration_diagnostics( + &loaded_configuration, + session.app.console, + cli_options.verbose, + )?; + resolve_manifest(&session)?; + + let LoadedConfiguration { + mut configuration, + directory_path: configuration_path, + .. + } = loaded_configuration; + + configuration.files.merge_with(files_configuration); + configuration.vcs.merge_with(vcs_configuration); + + // check if support for git ignore files is enabled + let vcs_base_path = configuration_path.or(session.app.fs.working_directory()); + let (vcs_base_path, gitignore_matches) = + configuration.retrieve_gitignore_matches(&session.app.fs, vcs_base_path.as_deref())?; + + session + .app + .workspace + .update_settings(UpdateSettingsParams { + working_directory: session.app.fs.working_directory(), + configuration, + vcs_base_path, + gitignore_matches, + })?; + + let console = &mut *session.app.console; + let stdin = get_stdin(stdin_file_path, console, "search")?; + + let execution = if cli_options.json { + Execution::with_report(TraversalMode::Search { pattern, stdin }, ReportMode::Json) + } else { + Execution::new(TraversalMode::Search { pattern, stdin }) + }; + + execute_mode(execution, session, &cli_options, paths) +} diff --git a/crates/biome_cli/src/diagnostics.rs b/crates/biome_cli/src/diagnostics.rs index 799066168cf2..999ecb3f793e 100644 --- a/crates/biome_cli/src/diagnostics.rs +++ b/crates/biome_cli/src/diagnostics.rs @@ -1,9 +1,8 @@ -use biome_console::fmt::{Display, Formatter}; +use biome_console::fmt::Display; use biome_console::markup; use biome_diagnostics::adapters::{BpafError, IoError}; use biome_diagnostics::{ - Advices, Category, Diagnostic, DiagnosticTags, Error, Location, LogCategory, - MessageAndDescription, Severity, Visit, + Advices, Category, Diagnostic, Error, LogCategory, MessageAndDescription, Severity, Visit, }; use biome_service::WorkspaceError; use std::process::{ExitCode, Termination}; @@ -19,7 +18,7 @@ fn command_name() -> String { /// A diagnostic that is emitted when running biome via CLI. /// /// When displaying the diagnostic, -#[derive(Debug)] +#[derive(Debug, Diagnostic)] pub enum CliDiagnostic { /// Returned when it is called with a subcommand it doesn't know UnknownCommand(UnknownCommand), @@ -439,201 +438,6 @@ impl CliDiagnostic { } } -impl Diagnostic for CliDiagnostic { - fn category(&self) -> Option<&'static Category> { - match self { - CliDiagnostic::UnknownCommand(diagnostic) => diagnostic.category(), - CliDiagnostic::UnknownCommandHelp(diagnostic) => diagnostic.category(), - CliDiagnostic::ParseError(diagnostic) => diagnostic.category(), - CliDiagnostic::UnexpectedArgument(diagnostic) => diagnostic.category(), - CliDiagnostic::MissingArgument(diagnostic) => diagnostic.category(), - CliDiagnostic::EmptyArguments(diagnostic) => diagnostic.category(), - CliDiagnostic::IncompatibleArguments(diagnostic) => diagnostic.category(), - CliDiagnostic::CheckError(diagnostic) => diagnostic.category(), - CliDiagnostic::OverflowNumberArgument(diagnostic) => diagnostic.category(), - CliDiagnostic::WorkspaceError(diagnostic) => diagnostic.category(), - CliDiagnostic::IoError(diagnostic) => diagnostic.category(), - CliDiagnostic::ServerNotRunning(diagnostic) => diagnostic.category(), - CliDiagnostic::IncompatibleEndConfiguration(diagnostic) => diagnostic.category(), - CliDiagnostic::NoFilesWereProcessed(diagnostic) => diagnostic.category(), - CliDiagnostic::FileCheck(diagnostic) => diagnostic.category(), - CliDiagnostic::MigrateError(diagnostic) => diagnostic.category(), - } - } - - fn tags(&self) -> DiagnosticTags { - match self { - CliDiagnostic::UnknownCommand(diagnostic) => diagnostic.tags(), - CliDiagnostic::UnknownCommandHelp(diagnostic) => diagnostic.tags(), - CliDiagnostic::ParseError(diagnostic) => diagnostic.tags(), - CliDiagnostic::UnexpectedArgument(diagnostic) => diagnostic.tags(), - CliDiagnostic::MissingArgument(diagnostic) => diagnostic.tags(), - CliDiagnostic::EmptyArguments(diagnostic) => diagnostic.tags(), - CliDiagnostic::IncompatibleArguments(diagnostic) => diagnostic.tags(), - CliDiagnostic::CheckError(diagnostic) => diagnostic.tags(), - CliDiagnostic::OverflowNumberArgument(diagnostic) => diagnostic.tags(), - CliDiagnostic::WorkspaceError(diagnostic) => diagnostic.tags(), - CliDiagnostic::IoError(diagnostic) => diagnostic.tags(), - CliDiagnostic::ServerNotRunning(diagnostic) => diagnostic.tags(), - CliDiagnostic::IncompatibleEndConfiguration(diagnostic) => diagnostic.tags(), - CliDiagnostic::NoFilesWereProcessed(diagnostic) => diagnostic.tags(), - CliDiagnostic::FileCheck(diagnostic) => diagnostic.tags(), - CliDiagnostic::MigrateError(diagnostic) => diagnostic.tags(), - } - } - - fn severity(&self) -> Severity { - match self { - CliDiagnostic::UnknownCommand(diagnostic) => diagnostic.severity(), - CliDiagnostic::UnknownCommandHelp(diagnostic) => diagnostic.severity(), - CliDiagnostic::ParseError(diagnostic) => diagnostic.severity(), - CliDiagnostic::UnexpectedArgument(diagnostic) => diagnostic.severity(), - CliDiagnostic::MissingArgument(diagnostic) => diagnostic.severity(), - CliDiagnostic::EmptyArguments(diagnostic) => diagnostic.severity(), - CliDiagnostic::IncompatibleArguments(diagnostic) => diagnostic.severity(), - CliDiagnostic::CheckError(diagnostic) => diagnostic.severity(), - CliDiagnostic::OverflowNumberArgument(diagnostic) => diagnostic.severity(), - CliDiagnostic::WorkspaceError(diagnostic) => diagnostic.severity(), - CliDiagnostic::IoError(diagnostic) => diagnostic.severity(), - CliDiagnostic::ServerNotRunning(diagnostic) => diagnostic.severity(), - CliDiagnostic::IncompatibleEndConfiguration(diagnostic) => diagnostic.severity(), - CliDiagnostic::NoFilesWereProcessed(diagnostic) => diagnostic.severity(), - CliDiagnostic::FileCheck(diagnostic) => diagnostic.severity(), - CliDiagnostic::MigrateError(diagnostic) => diagnostic.severity(), - } - } - - fn location(&self) -> Location<'_> { - match self { - CliDiagnostic::UnknownCommand(diagnostic) => diagnostic.location(), - CliDiagnostic::UnknownCommandHelp(diagnostic) => diagnostic.location(), - CliDiagnostic::ParseError(diagnostic) => diagnostic.location(), - CliDiagnostic::UnexpectedArgument(diagnostic) => diagnostic.location(), - CliDiagnostic::MissingArgument(diagnostic) => diagnostic.location(), - CliDiagnostic::EmptyArguments(diagnostic) => diagnostic.location(), - CliDiagnostic::IncompatibleArguments(diagnostic) => diagnostic.location(), - CliDiagnostic::CheckError(diagnostic) => diagnostic.location(), - CliDiagnostic::OverflowNumberArgument(diagnostic) => diagnostic.location(), - CliDiagnostic::WorkspaceError(diagnostic) => diagnostic.location(), - CliDiagnostic::IoError(diagnostic) => diagnostic.location(), - CliDiagnostic::ServerNotRunning(diagnostic) => diagnostic.location(), - CliDiagnostic::IncompatibleEndConfiguration(diagnostic) => diagnostic.location(), - CliDiagnostic::NoFilesWereProcessed(diagnostic) => diagnostic.location(), - CliDiagnostic::FileCheck(diagnostic) => diagnostic.location(), - CliDiagnostic::MigrateError(diagnostic) => diagnostic.location(), - } - } - - fn message(&self, fmt: &mut Formatter<'_>) -> std::io::Result<()> { - match self { - CliDiagnostic::UnknownCommand(diagnostic) => diagnostic.message(fmt), - CliDiagnostic::UnknownCommandHelp(diagnostic) => diagnostic.message(fmt), - CliDiagnostic::ParseError(diagnostic) => diagnostic.message(fmt), - CliDiagnostic::UnexpectedArgument(diagnostic) => diagnostic.message(fmt), - CliDiagnostic::MissingArgument(diagnostic) => diagnostic.message(fmt), - CliDiagnostic::EmptyArguments(diagnostic) => diagnostic.message(fmt), - CliDiagnostic::IncompatibleArguments(diagnostic) => diagnostic.message(fmt), - CliDiagnostic::CheckError(diagnostic) => diagnostic.message(fmt), - CliDiagnostic::OverflowNumberArgument(diagnostic) => diagnostic.message(fmt), - CliDiagnostic::WorkspaceError(diagnostic) => diagnostic.message(fmt), - CliDiagnostic::IoError(diagnostic) => diagnostic.message(fmt), - CliDiagnostic::ServerNotRunning(diagnostic) => diagnostic.message(fmt), - CliDiagnostic::IncompatibleEndConfiguration(diagnostic) => diagnostic.message(fmt), - CliDiagnostic::NoFilesWereProcessed(diagnostic) => diagnostic.message(fmt), - CliDiagnostic::FileCheck(diagnostic) => diagnostic.message(fmt), - CliDiagnostic::MigrateError(diagnostic) => diagnostic.message(fmt), - } - } - - fn description(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - CliDiagnostic::UnknownCommand(diagnostic) => diagnostic.description(fmt), - CliDiagnostic::UnknownCommandHelp(diagnostic) => diagnostic.description(fmt), - CliDiagnostic::ParseError(diagnostic) => diagnostic.description(fmt), - CliDiagnostic::UnexpectedArgument(diagnostic) => diagnostic.description(fmt), - CliDiagnostic::MissingArgument(diagnostic) => diagnostic.description(fmt), - CliDiagnostic::EmptyArguments(diagnostic) => diagnostic.description(fmt), - CliDiagnostic::IncompatibleArguments(diagnostic) => diagnostic.description(fmt), - CliDiagnostic::CheckError(diagnostic) => diagnostic.description(fmt), - CliDiagnostic::OverflowNumberArgument(diagnostic) => diagnostic.description(fmt), - CliDiagnostic::WorkspaceError(diagnostic) => diagnostic.description(fmt), - CliDiagnostic::IoError(diagnostic) => diagnostic.description(fmt), - CliDiagnostic::ServerNotRunning(diagnostic) => diagnostic.description(fmt), - CliDiagnostic::IncompatibleEndConfiguration(diagnostic) => diagnostic.description(fmt), - CliDiagnostic::NoFilesWereProcessed(diagnostic) => diagnostic.description(fmt), - CliDiagnostic::FileCheck(diagnostic) => diagnostic.description(fmt), - CliDiagnostic::MigrateError(diagnostic) => diagnostic.description(fmt), - } - } - - fn advices(&self, visitor: &mut dyn Visit) -> std::io::Result<()> { - match self { - CliDiagnostic::UnknownCommand(diagnostic) => diagnostic.advices(visitor), - CliDiagnostic::UnknownCommandHelp(diagnostic) => diagnostic.advices(visitor), - CliDiagnostic::ParseError(diagnostic) => diagnostic.advices(visitor), - CliDiagnostic::UnexpectedArgument(diagnostic) => diagnostic.advices(visitor), - CliDiagnostic::MissingArgument(diagnostic) => diagnostic.advices(visitor), - CliDiagnostic::EmptyArguments(diagnostic) => diagnostic.advices(visitor), - CliDiagnostic::IncompatibleArguments(diagnostic) => diagnostic.advices(visitor), - CliDiagnostic::CheckError(diagnostic) => diagnostic.advices(visitor), - CliDiagnostic::OverflowNumberArgument(diagnostic) => diagnostic.advices(visitor), - CliDiagnostic::WorkspaceError(diagnostic) => diagnostic.advices(visitor), - CliDiagnostic::IoError(diagnostic) => diagnostic.advices(visitor), - CliDiagnostic::ServerNotRunning(diagnostic) => diagnostic.advices(visitor), - CliDiagnostic::IncompatibleEndConfiguration(diagnostic) => diagnostic.advices(visitor), - CliDiagnostic::NoFilesWereProcessed(diagnostic) => diagnostic.advices(visitor), - CliDiagnostic::FileCheck(diagnostic) => diagnostic.advices(visitor), - CliDiagnostic::MigrateError(diagnostic) => diagnostic.advices(visitor), - } - } - - fn verbose_advices(&self, visitor: &mut dyn Visit) -> std::io::Result<()> { - match self { - CliDiagnostic::UnknownCommand(diagnostic) => diagnostic.verbose_advices(visitor), - CliDiagnostic::UnknownCommandHelp(diagnostic) => diagnostic.verbose_advices(visitor), - CliDiagnostic::ParseError(diagnostic) => diagnostic.verbose_advices(visitor), - CliDiagnostic::UnexpectedArgument(diagnostic) => diagnostic.verbose_advices(visitor), - CliDiagnostic::MissingArgument(diagnostic) => diagnostic.verbose_advices(visitor), - CliDiagnostic::EmptyArguments(diagnostic) => diagnostic.verbose_advices(visitor), - CliDiagnostic::IncompatibleArguments(diagnostic) => diagnostic.verbose_advices(visitor), - CliDiagnostic::CheckError(diagnostic) => diagnostic.verbose_advices(visitor), - CliDiagnostic::OverflowNumberArgument(diagnostic) => { - diagnostic.verbose_advices(visitor) - } - CliDiagnostic::WorkspaceError(diagnostic) => diagnostic.verbose_advices(visitor), - CliDiagnostic::IoError(diagnostic) => diagnostic.verbose_advices(visitor), - CliDiagnostic::ServerNotRunning(diagnostic) => diagnostic.verbose_advices(visitor), - CliDiagnostic::IncompatibleEndConfiguration(diagnostic) => { - diagnostic.verbose_advices(visitor) - } - CliDiagnostic::NoFilesWereProcessed(diagnostic) => diagnostic.verbose_advices(visitor), - CliDiagnostic::FileCheck(diagnostic) => diagnostic.verbose_advices(visitor), - CliDiagnostic::MigrateError(diagnostic) => diagnostic.verbose_advices(visitor), - } - } - - fn source(&self) -> Option<&dyn Diagnostic> { - match self { - CliDiagnostic::UnknownCommand(diagnostic) => diagnostic.source(), - CliDiagnostic::UnknownCommandHelp(diagnostic) => diagnostic.source(), - CliDiagnostic::ParseError(diagnostic) => diagnostic.source(), - CliDiagnostic::UnexpectedArgument(diagnostic) => diagnostic.source(), - CliDiagnostic::MissingArgument(diagnostic) => diagnostic.source(), - CliDiagnostic::EmptyArguments(diagnostic) => diagnostic.source(), - CliDiagnostic::IncompatibleArguments(diagnostic) => diagnostic.source(), - CliDiagnostic::CheckError(diagnostic) => diagnostic.source(), - CliDiagnostic::OverflowNumberArgument(diagnostic) => diagnostic.source(), - CliDiagnostic::WorkspaceError(diagnostic) => diagnostic.source(), - CliDiagnostic::IoError(diagnostic) => diagnostic.source(), - CliDiagnostic::ServerNotRunning(diagnostic) => diagnostic.source(), - CliDiagnostic::IncompatibleEndConfiguration(diagnostic) => diagnostic.source(), - CliDiagnostic::NoFilesWereProcessed(diagnostic) => diagnostic.source(), - CliDiagnostic::FileCheck(diagnostic) => diagnostic.source(), - CliDiagnostic::MigrateError(diagnostic) => diagnostic.source(), - } - } -} - impl From for CliDiagnostic { fn from(error: WorkspaceError) -> Self { CliDiagnostic::workspace_error(error) diff --git a/crates/biome_cli/src/execute/migrate.rs b/crates/biome_cli/src/execute/migrate.rs index f2d9917b1842..1af802fd07f7 100644 --- a/crates/biome_cli/src/execute/migrate.rs +++ b/crates/biome_cli/src/execute/migrate.rs @@ -1,11 +1,11 @@ -mod prettier; - +use crate::commands::MigrateSubCommand; use crate::diagnostics::MigrationDiagnostic; use crate::execute::diagnostics::{ContentDiffAdvice, MigrateDiffDiagnostic}; use crate::execute::migrate::prettier::read_prettier_files; use crate::{CliDiagnostic, CliSession}; +use biome_configuration::PartialConfiguration; use biome_console::{markup, ConsoleExt}; -use biome_deserialize::json::deserialize_from_json_str; +use biome_deserialize::json::deserialize_from_json_ast; use biome_deserialize::Merge; use biome_diagnostics::Diagnostic; use biome_diagnostics::{category, PrintDiagnostic}; @@ -15,19 +15,29 @@ use biome_json_syntax::{JsonFileSource, JsonRoot}; use biome_migrate::{migrate_configuration, ControlFlow}; use biome_rowan::{AstNode, NodeCache}; use biome_service::workspace::{ChangeFileParams, FixAction, FormatFileParams, OpenFileParams}; -use biome_service::{PartialConfiguration, VERSION}; +use biome_service::VERSION; use std::borrow::Cow; use std::ffi::OsStr; use std::path::PathBuf; +mod eslint; +mod eslint_any_rule_to_biome; +mod eslint_eslint; +mod eslint_jsxa11y; +mod eslint_to_biome; +mod eslint_typescript; +mod eslint_unicorn; +mod ignorefile; +mod node; +mod prettier; + pub(crate) struct MigratePayload<'a> { pub(crate) session: CliSession<'a>, pub(crate) write: bool, pub(crate) configuration_file_path: PathBuf, pub(crate) configuration_directory_path: PathBuf, pub(crate) verbose: bool, - #[allow(unused)] - pub(crate) prettier: bool, + pub(crate) sub_command: Option, } pub(crate) fn run(migrate_payload: MigratePayload) -> Result<(), CliDiagnostic> { @@ -37,191 +47,288 @@ pub(crate) fn run(migrate_payload: MigratePayload) -> Result<(), CliDiagnostic> configuration_file_path, configuration_directory_path, verbose, - prettier, + sub_command, } = migrate_payload; let mut cache = NodeCache::default(); let fs = &session.app.fs; let console = session.app.console; let workspace = session.app.workspace; - let has_deprecated_configuration = - configuration_file_path.file_name() == Some(OsStr::new("rome.json")); - let open_options = if write { OpenOptions::default().read(true).write(true) } else { OpenOptions::default().read(true) }; - - let mut configuration_file = + let mut biome_config_file = fs.open_with_options(configuration_file_path.as_path(), open_options)?; - let mut configuration_content = String::new(); - configuration_file.read_to_string(&mut configuration_content)?; + let mut biome_config_content = String::new(); + biome_config_file.read_to_string(&mut biome_config_content)?; let biome_path = BiomePath::new(configuration_file_path.as_path()); workspace.open_file(OpenFileParams { path: biome_path.clone(), - content: configuration_content.to_string(), + content: biome_config_content.to_string(), version: 0, document_file_source: Some(JsonFileSource::json().into()), })?; - let parsed = parse_json_with_cache( - &configuration_content, + &biome_config_content, &mut cache, JsonParserOptions::default(), ); - let mut errors = 0; - let mut tree = parsed.tree(); - let mut actions = Vec::new(); - loop { - let (action, _) = migrate_configuration( - &tree, - configuration_file_path.as_path(), - VERSION.to_string(), - |signal| { - let current_diagnostic = signal.diagnostic(); - if current_diagnostic.is_some() { - errors += 1; - } - - if let Some(action) = signal.actions().next() { - return ControlFlow::Break(action); + match sub_command { + Some(MigrateSubCommand::Prettier) => { + let prettier_configuration = read_prettier_files(fs, console)?; + if prettier_configuration.has_configuration() { + let biome_config = + deserialize_from_json_ast::(&parsed.tree(), "") + .into_deserialized(); + let Some(mut biome_config) = biome_config else { + return Ok(()); + }; + let old_biome_config = biome_config.clone(); + biome_config.merge_with(prettier_configuration.as_biome_configuration()); + if let Ok(ignore_patterns) = ignorefile::read_ignore_file(fs, prettier::IGNORE_FILE) + { + if !ignore_patterns.patterns.is_empty() { + biome_config + .formatter + .get_or_insert(Default::default()) + .ignore + .get_or_insert(Default::default()) + .extend(ignore_patterns.patterns); + } + if ignore_patterns.has_negated_patterns { + console.log(markup! { + {prettier::IGNORE_FILE}" contains negated glob patterns that start with ""!"".\nThese patterns cannot be migrated because Biome doesn't support them." + }) + } else if write && biome_config != old_biome_config { + console.log(markup!{ + {prettier::IGNORE_FILE}" has been successfully migrated." + }); + } } - - ControlFlow::Continue(()) - }, - ); - - match action { - Some(action) => { - if let Some((range, _)) = action.mutation.as_text_edits() { - tree = match JsonRoot::cast(action.mutation.commit()) { - Some(tree) => tree, - None => return Err(CliDiagnostic::check_error(category!("migrate"))), - }; - actions.push(FixAction { - rule_name: action - .rule_name - .map(|(group, rule)| (Cow::Borrowed(group), Cow::Borrowed(rule))), - range, + if biome_config == old_biome_config { + console.log(markup! { + "No changes to apply to the Biome configuration file." }); + } else { + let new_content = serde_json::to_string(&biome_config).map_err(|err| { + CliDiagnostic::MigrateError(MigrationDiagnostic { + reason: err.to_string(), + }) + })?; + workspace.change_file(ChangeFileParams { + path: biome_path.clone(), + content: new_content, + version: 1, + })?; + let printed = workspace.format_file(FormatFileParams { path: biome_path })?; + if write { + biome_config_file.set_content(printed.as_code().as_bytes())?; + console.log(markup!{ + ".prettierrc"" has been successfully migrated." + }); + } else { + let file_name = configuration_file_path.display().to_string(); + let diagnostic = MigrateDiffDiagnostic { + file_name, + diff: ContentDiffAdvice { + old: biome_config_content, + new: printed.as_code().to_string(), + }, + }; + console.error(markup! {{PrintDiagnostic::simple(&diagnostic)}}); + console.log(markup! { + "Run the command with the option ""--write"" to apply the changes." + }) + } } } - None => { - break; - } } - } - - let new_configuration_content = tree.to_string(); - - if prettier { - let prettier_configuration = read_prettier_files(fs, console)?; - - if prettier_configuration.has_configuration() { - let configuration = deserialize_from_json_str::( - configuration_content.as_str(), - JsonParserOptions::default(), - "", - ) - .into_deserialized(); - if let Some(mut configuration) = configuration { - configuration.merge_with(prettier_configuration.as_biome_configuration()); - - let new_content = serde_json::to_string(&configuration).map_err(|err| { + Some(MigrateSubCommand::Eslint { + include_inspired, + include_nursery, + }) => { + let eslint::Config { + path: eslint_path, + data: eslint_config, + } = eslint::read_eslint_config(fs, console)?; + let biome_config = + deserialize_from_json_ast::(&parsed.tree(), "") + .into_deserialized(); + let Some(mut biome_config) = biome_config else { + return Ok(()); + }; + let (biome_eslint_config, results) = + eslint_config.into_biome_config(&eslint_to_biome::MigrationOptions { + include_inspired, + include_nursery, + }); + let old_biome_config = biome_config.clone(); + biome_config.merge_with(biome_eslint_config); + if let Ok(ignore_patterns) = ignorefile::read_ignore_file(fs, eslint::IGNORE_FILE) { + if !ignore_patterns.patterns.is_empty() { + biome_config + .linter + .get_or_insert(Default::default()) + .ignore + .get_or_insert(Default::default()) + .extend(ignore_patterns.patterns); + } + if ignore_patterns.has_negated_patterns { + console.log(markup! { + {eslint::IGNORE_FILE}" contains negated glob patterns that start with ""!"".\nThese patterns cannot be migrated because Biome doesn't support them." + }) + } else if write && biome_config != old_biome_config { + console.log(markup!{ + {eslint::IGNORE_FILE}" has been successfully migrated." + }); + } + } + if biome_config == old_biome_config { + console.log(markup! { + "No changes to apply to the Biome configuration file." + }); + } else { + let new_content = serde_json::to_string(&biome_config).map_err(|err| { CliDiagnostic::MigrateError(MigrationDiagnostic { reason: err.to_string(), }) })?; - workspace.change_file(ChangeFileParams { path: biome_path.clone(), content: new_content, version: 1, })?; - - let printed = workspace.format_file(FormatFileParams { - path: biome_path.clone(), - })?; - + let printed = workspace.format_file(FormatFileParams { path: biome_path })?; if write { - configuration_file.set_content(printed.as_code().as_bytes())?; + biome_config_file.set_content(printed.as_code().as_bytes())?; console.log(markup!{ - "The configuration "{{configuration_file_path.display().to_string()}}" has been successfully migrated." + {eslint_path}" has been successfully migrated." }); - if prettier_configuration.has_ignore_file() { - console.log(markup!{ - "Please make sure that the globs of the "".prettierignore"" file still work in Biome. Prettier's globs use git globs, while Biome's globs use uni-style globs. They both seem similar, but their semantics differ." - }) - } } else { let file_name = configuration_file_path.display().to_string(); let diagnostic = MigrateDiffDiagnostic { file_name, diff: ContentDiffAdvice { - old: configuration_content, + old: biome_config_content, new: printed.as_code().to_string(), }, }; console.error(markup! {{PrintDiagnostic::simple(&diagnostic)}}); - console.log(markup! { - "Run the command with the option ""--write"" to apply the changes." + "Run the command with the option ""--write"" to apply the changes." }) } } - } - } else if configuration_content != new_configuration_content || has_deprecated_configuration { - if write { - let mut configuration_file = if has_deprecated_configuration { - let biome_file_path = configuration_directory_path.join(ConfigName::biome_json()); - fs.create_new(biome_file_path.as_path())? - } else { - configuration_file - }; - configuration_file.set_content(tree.to_string().as_bytes())?; - console.log(markup!{ - "The configuration "{{configuration_file_path.display().to_string()}}" has been successfully migrated." + if results.has_inspired_rules { + console.log(markup! { + "Run the command with the option ""--include-inspired"" to also migrate inspired rules." }) - } else { - let file_name = configuration_file_path.display().to_string(); - let diagnostic = if has_deprecated_configuration { - MigrateDiffDiagnostic { - file_name, - diff: ContentDiffAdvice { - old: "rome.json".to_string(), - new: "biome.json".to_string(), - }, - } - } else { - MigrateDiffDiagnostic { - file_name, - diff: ContentDiffAdvice { - old: configuration_content, - new: new_configuration_content, + } + } + None => { + let has_deprecated_configuration = + configuration_file_path.file_name() == Some(OsStr::new("rome.json")); + + let mut errors = 0; + let mut tree = parsed.tree(); + let mut actions = Vec::new(); + loop { + let (action, _) = migrate_configuration( + &tree, + configuration_file_path.as_path(), + VERSION.to_string(), + |signal| { + let current_diagnostic = signal.diagnostic(); + if current_diagnostic.is_some() { + errors += 1; + } + if let Some(action) = signal.actions().next() { + return ControlFlow::Break(action); + } + ControlFlow::Continue(()) }, + ); + match action { + Some(action) => { + if let (root, Some((range, _))) = + action.mutation.commit_with_text_range_and_edit(true) + { + tree = match JsonRoot::cast(root) { + Some(tree) => tree, + None => { + return Err(CliDiagnostic::check_error(category!("migrate"))) + } + }; + actions.push(FixAction { + rule_name: action.rule_name.map(|(group, rule)| { + (Cow::Borrowed(group), Cow::Borrowed(rule)) + }), + range, + }); + } + } + None => { + break; + } } - }; - if diagnostic.tags().is_verbose() { - if verbose { - console.error(markup! {{PrintDiagnostic::verbose(&diagnostic)}}) + } + + let new_configuration_content = tree.to_string(); + if biome_config_content != new_configuration_content || has_deprecated_configuration { + if write { + let mut configuration_file = if has_deprecated_configuration { + let biome_file_path = + configuration_directory_path.join(ConfigName::biome_json()); + fs.create_new(biome_file_path.as_path())? + } else { + biome_config_file + }; + configuration_file.set_content(tree.to_string().as_bytes())?; + console.log(markup!{ + "The configuration "{{configuration_file_path.display().to_string()}}" has been successfully migrated." + }) + } else { + let file_name = configuration_file_path.display().to_string(); + let diagnostic = if has_deprecated_configuration { + MigrateDiffDiagnostic { + file_name, + diff: ContentDiffAdvice { + old: "rome.json".to_string(), + new: "biome.json".to_string(), + }, + } + } else { + MigrateDiffDiagnostic { + file_name, + diff: ContentDiffAdvice { + old: biome_config_content, + new: new_configuration_content, + }, + } + }; + if diagnostic.tags().is_verbose() { + if verbose { + console.error(markup! {{PrintDiagnostic::verbose(&diagnostic)}}) + } + } else { + console.error(markup! {{PrintDiagnostic::simple(&diagnostic)}}) + } + console.log(markup! { + "Run the command with the option ""--write"" to apply the changes." + }) } } else { - console.error(markup! {{PrintDiagnostic::simple(&diagnostic)}}) - } - console.log(markup! { - "Run the command with the option ""--write"" to apply the changes." + console.log(markup! { + + "Your configuration file is up to date." + }) + } } - } else { - console.log(markup! { - - "Your configuration file is up to date." - - }) } - Ok(()) } diff --git a/crates/biome_cli/src/execute/migrate/eslint.rs b/crates/biome_cli/src/execute/migrate/eslint.rs new file mode 100644 index 000000000000..69fac53a4f87 --- /dev/null +++ b/crates/biome_cli/src/execute/migrate/eslint.rs @@ -0,0 +1,395 @@ +use biome_console::{markup, Console, ConsoleExt}; +use biome_deserialize::json::deserialize_from_json_str; +use biome_deserialize::Merge; +use biome_diagnostics::{DiagnosticExt, PrintDiagnostic}; +use biome_fs::{FileSystem, OpenOptions}; +use biome_json_parser::JsonParserOptions; +use biome_service::DynRef; +use std::borrow::Cow; +use std::path::{Path, PathBuf}; +use std::vec; + +use crate::diagnostics::MigrationDiagnostic; +use crate::CliDiagnostic; + +use super::eslint_eslint; +use super::node; + +/// This modules includes implementations for loading and deserializing an eslint configuration. +/// +/// See [super::eslint_eslint] for the data representation of an ESLint configuration. +/// +/// Each ESLint plugin has its own module in which rule options are defined. +/// For example, the ESLint TypeScript plugin is defined in [super::eslint_typescript]. +/// Note that we don't need to deserialise every existing rule option. +/// We only need to deserialise options that have equivalent biome options. +/// This greatly reduces the amount of work involved. + +/// ESLint flat configuration filenames. +/// +/// See https://eslint.org/docs/latest/use/configure/configuration-files-new +const FLAT_CONFIG_FILES: [&str; 3] = [ + // Prefixed with `./` to ensure that it is loadable via NodeJS's `import()` + "./eslint.config.js", + "./eslint.config.mjs", + "./eslint.config.cjs", +]; + +/// List of ESLint **legacy** configuration filenames. +/// +/// See https://eslint.org/docs/latest/use/configure/configuration-files +/// +/// Order is important. +/// It translates the priority of the files. +/// For example, ESLint looks for `./.eslintrc.js` before looking for `./.eslintrc.json`. +const LEGACY_CONFIG_FILES: [&str; 5] = [ + // Prefixed with `./` to ensure that it is loadable via NodeJS's `import()` + "./.eslintrc.js", + // Prefixed with `./` to ensure that it is loadable via NodeJS's `import()` + "./.eslintrc.cjs", + ".eslintrc.yaml", + ".eslintrc.yml", + ".eslintrc.json", +]; + +/// An ESLint config can be embedded in `package.json` +const PACKAGE_JSON: &str = "package.json"; + +/// ESLint Ignore file. Use the same syntax as gitignore. +pub(crate) const IGNORE_FILE: &str = ".eslintignore"; + +/// Returns the ESLint configuration file in the working directory with the highest priority. +/// +/// This function respects the priority between ESLint configuration files. +/// For example, it looks for `./.eslintrc.js` before looking for `./.eslintrc.json`. +/// It first ries to load a flat configuration file. +/// +/// Unlike ESLint, it doesn't look for a configuration file in parent directories +/// when no configuration file is found in the working directory. +/// +/// Deserialization errors are reported using `console`. +/// Other errors (File Not found, unspported config format, ...) are directly returned. +/// +/// We extract the ESLint configuration from a JavaScript file, by invoking `node`. +/// +/// The `extends` field is recusively resolved. +pub(crate) fn read_eslint_config( + fs: &DynRef<'_, dyn FileSystem>, + console: &mut dyn Console, +) -> Result { + for config_path_str in FLAT_CONFIG_FILES { + let path = Path::new(config_path_str); + if fs.path_exists(path) { + return load_flat_config_data(path, console).map(|data| Config { + path: config_path_str, + data: data.into(), + }); + } + } + for config_path_str in LEGACY_CONFIG_FILES { + let path = Path::new(config_path_str); + if fs.path_exists(path) { + return load_legacy_config_data(fs, path, console).map(|data| Config { + path: config_path_str, + data: data.into(), + }); + } + } + let path = Path::new(PACKAGE_JSON); + if fs.path_exists(path) { + // We don't report errors in `PACKAGE_JSON`. + if let Ok(data) = load_legacy_config_data(fs, path, console) { + return Ok(Config { + path: PACKAGE_JSON, + data: data.into(), + }); + } + } + Err(CliDiagnostic::MigrateError(MigrationDiagnostic { reason: "The default ESLint configuration file `.eslintrc.*` was not found in the working directory.".to_string()})) +} + +#[derive(Debug)] +pub(crate) struct Config { + /// Path of the ESlint config file + pub(crate) path: &'static str, + /// Resolved ESlint config + pub(crate) data: eslint_eslint::AnyConfigData, +} + +/// Load an ESlint Flat config +/// See https://eslint.org/docs/latest/use/configure/configuration-files-new +fn load_flat_config_data( + path: &Path, + console: &mut dyn Console, +) -> Result { + let node::Resolution { content, .. } = node::load_config(&path.to_string_lossy())?; + let (deserialized, diagnostics) = deserialize_from_json_str::( + &content, + JsonParserOptions::default(), + "", + ) + .consume(); + let path_str = path.to_string_lossy(); + for diagnostic in diagnostics.into_iter().filter(|diag| { + matches!( + diag.severity(), + biome_diagnostics::Severity::Fatal + | biome_diagnostics::Severity::Error + | biome_diagnostics::Severity::Warning + ) + }) { + let diagnostic = diagnostic.with_file_path(path_str.to_string()); + console.error(markup! {{PrintDiagnostic::simple(&diagnostic)}}); + } + if let Some(result) = deserialized { + Ok(result) + } else { + Err(CliDiagnostic::MigrateError(MigrationDiagnostic { + reason: "Could not deserialize the Eslint configuration file".to_string(), + })) + } +} + +/// Load an ESlint legacy config +/// See https://eslint.org/docs/latest/use/configure/configuration-files +fn load_legacy_config_data( + fs: &DynRef<'_, dyn FileSystem>, + path: &Path, + console: &mut dyn Console, +) -> Result { + let (deserialized, diagnostics) = match path.extension().and_then(|file_ext| file_ext.to_str()) { + Some("json") => { + let mut file = fs.open_with_options(path, OpenOptions::default().read(true))?; + let mut content = String::new(); + file.read_to_string(&mut content)?; + if path.file_name().is_some_and(|name| name == PACKAGE_JSON) { + let (deserialized, _) = deserialize_from_json_str::( + &content, + JsonParserOptions::default() + .with_allow_trailing_commas() + .with_allow_comments(), + "", + ).consume(); + (deserialized.and_then(|packagejson| packagejson.eslint_config), vec![]) + } else { + deserialize_from_json_str::( + &content, + JsonParserOptions::default() + .with_allow_trailing_commas() + .with_allow_comments(), + "", + ).consume() + } + }, + Some("js" | "cjs") => { + let node::Resolution { content, ..} = node::load_config(&path.to_string_lossy())?; + deserialize_from_json_str::( + &content, + JsonParserOptions::default(), + "", + ).consume() + }, + Some(ext) => return Err(CliDiagnostic::MigrateError(MigrationDiagnostic{ reason: format!("ESLint configuration ending with the extension `{ext}` are not supported.") })), + None => return Err(CliDiagnostic::MigrateError(MigrationDiagnostic{ reason: "The ESLint configuration format cannot be determined because the file has no extension.".to_string() })), + }; + let path_str = path.to_string_lossy(); + for diagnostic in diagnostics.into_iter().filter(|diag| { + matches!( + diag.severity(), + biome_diagnostics::Severity::Fatal + | biome_diagnostics::Severity::Error + | biome_diagnostics::Severity::Warning + ) + }) { + let diagnostic = diagnostic.with_file_path(path_str.to_string()); + console.error(markup! {{PrintDiagnostic::simple(&diagnostic)}}); + } + if let Some(mut result) = deserialized { + // recursively resolve the `extends` field. + while !result.extends.is_empty() { + resolve_extends(&mut result, console); + } + Ok(result) + } else { + Err(CliDiagnostic::MigrateError(MigrationDiagnostic { + reason: "Could not deserialize the Eslint configuration file".to_string(), + })) + } +} + +/// Returns the configuration from a preset or an error if the resolution failed. +/// +/// This handles: +/// - native ESLint presets such as `eslint:recommended`; +/// - plugin presets such as `plugin:@typescript-eslint/recommended`; +/// - and shared configurations such as `standard`. +fn load_eslint_extends_config( + name: &str, +) -> Result { + let (specifier, resolved_path, deserialized) = if let Some((protocol, rest)) = + name.split_once(':') + { + let (module_name, config_name) = match protocol { + // e.g. `eslint:recommended` + // - module_name: `@eslint/js` + // - config_name: `recommended` + "eslint" => (Cow::Borrowed("@eslint/js"), rest), + // e.g. `plugin:@typescript-eslint/recommended` + // - module_name: `@typescript-eslint/eslint-plugin` + // - config_name: `recommended` + // e.g. `plugin:unicorn/recommended` + // - module_name: `eslint-plugin-unicorn` + // - config_name: `recommended` + "plugin" => { + let Some(config_name) = rest.split('/').last() else { + return Err(CliDiagnostic::MigrateError(MigrationDiagnostic { + reason: format!( + "The configuration {rest} cannot be resolved. Make sure that your ESLint configuration file is valid." + ), + })); + }; + let rest = rest.trim_end_matches(config_name); + let module_name = rest.trim_end_matches('/'); + let module_name = EslintPackage::Plugin.resolve_name(module_name); + (module_name, config_name) + } + name => { + return Err(CliDiagnostic::MigrateError(MigrationDiagnostic { + reason: format!( + "The module {name} cannot be resolved. This is likely an internal error." + ), + })); + } + }; + // load ESLint preset + let Ok(node::Resolution { + content, + resolved_path, + }) = node::load_config(&module_name) + else { + return Err(CliDiagnostic::MigrateError(MigrationDiagnostic { + reason: format!( + "The module '{rest}' cannot be loaded. Make sure that the module exists." + ), + })); + }; + let deserialized = deserialize_from_json_str::( + &content, + JsonParserOptions::default(), + "", + ) + .into_deserialized(); + if let Some(mut deserialized) = deserialized { + let deserialized = deserialized.configs.remove(config_name); + if deserialized.is_none() { + return Err(CliDiagnostic::MigrateError(MigrationDiagnostic { + reason: format!("The ESLint configuration '{config_name}' cannot be extracted from the module '{module_name}'. Make sure that '{config_name}' is a valid configuration name.") + })); + } + (module_name, resolved_path, deserialized) + } else { + (module_name, resolved_path, None) + } + } else { + // load ESLint shared config + let module_name = if matches!(name.as_bytes().first(), Some(b'.' | b'/' | b'#')) { + // local path + Cow::Borrowed(name) + } else { + EslintPackage::Config.resolve_name(name) + }; + let Ok(node::Resolution { + content, + resolved_path, + }) = node::load_config(&module_name) + else { + return Err(CliDiagnostic::MigrateError(MigrationDiagnostic { + reason: format!( + "The module '{module_name}' cannot be loaded. Make sure that the module exists." + ), + })); + }; + let deserialized = deserialize_from_json_str::( + &content, + JsonParserOptions::default(), + "", + ) + .into_deserialized(); + (module_name, resolved_path, deserialized) + }; + let Some(mut deserialized) = deserialized else { + return Err(CliDiagnostic::MigrateError(MigrationDiagnostic { + reason: format!("The ESLint configuration of the module '{specifier}' cannot be extracted. This is likely an internal error.") + })); + }; + // Resolve relative path in `extends`. + deserialized.extends.iter_mut().for_each(|extends_item| { + if extends_item.starts_with('.') { + let Some(resolved_path) = Path::new(&resolved_path).parent() else { + return; + }; + let mut path = PathBuf::new(); + path.push(resolved_path); + path.push(Path::new(&extends_item)); + *extends_item = path.to_string_lossy().to_string(); + } + }); + Ok(deserialized) +} + +/// Load and merge included configuration via `self.extends`. +/// +/// Unknown presets are ignored. +/// `self.extends` is replaced by an empty array. +fn resolve_extends(config: &mut eslint_eslint::LegacyConfigData, console: &mut dyn Console) { + let extensions: Vec<_> = config + .extends + .iter() + .filter_map(|preset| match load_eslint_extends_config(preset) { + Ok(config) => Some(config), + Err(diag) => { + console.error(markup! {{PrintDiagnostic::simple(&diag)}}); + None + } + }) + .collect(); + config.extends.clear(); + for ext in extensions { + config.merge_with(ext); + } +} + +/// ESLint to specific rules to resolve a module name. +/// See https://eslint.org/docs/latest/extend/shareable-configs#using-a-shareable-config +/// See also https://eslint.org/docs/latest/extend/plugins +#[derive(Debug)] +enum EslintPackage { + Config, + Plugin, +} +impl EslintPackage { + fn resolve_name<'a>(&self, name: &'a str) -> Cow<'a, str> { + let artifact = match self { + EslintPackage::Config => "eslint-config-", + EslintPackage::Plugin => "eslint-plugin-", + }; + debug_assert!(matches!(artifact, "eslint-plugin-" | "eslint-config-")); + if name.starts_with('@') { + // handle scoped module + if let Some((scope, scoped)) = name.split_once('/') { + if scoped.starts_with(artifact) { + Cow::Borrowed(name) + } else { + Cow::Owned(format!("{scope}/{artifact}{scoped}")) + } + } else { + let artifact = artifact.trim_end_matches('-'); + Cow::Owned(format!("{name}/{artifact}")) + } + } else if name.starts_with(artifact) { + Cow::Borrowed(name) + } else { + Cow::Owned(format!("{artifact}{name}")) + } + } +} diff --git a/crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs b/crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs new file mode 100644 index 000000000000..60fc40d6e242 --- /dev/null +++ b/crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs @@ -0,0 +1,1199 @@ +//! Generated file, do not edit by hand, see `xtask/codegen` + +use super::{eslint_eslint, eslint_to_biome}; +pub(crate) fn migrate_eslint_any_rule( + rules: &mut biome_configuration::Rules, + eslint_name: &str, + rule_severity: eslint_eslint::Severity, + options: &eslint_to_biome::MigrationOptions, + results: &mut eslint_to_biome::MigrationResults, +) -> bool { + match eslint_name { + "@mysticatea/no-this-in-static" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group.no_this_in_static.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@stylistic/jsx-self-closing-comp" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group + .use_self_closing_elements + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/array-type" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group + .use_consistent_array_type + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/ban-types" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group.no_banned_types.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/consistent-type-exports" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.use_export_type.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/consistent-type-imports" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.use_import_type.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/naming-convention" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + let group = rules.style.get_or_insert_with(Default::default); + let rule = group + .use_naming_convention + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/no-empty-interface" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_empty_interface.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/no-explicit-any" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_explicit_any.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/no-extra-non-null-assertion" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group + .no_extra_non_null_assertion + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/no-extraneous-class" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group.no_static_only_class.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/no-inferrable-types" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.no_inferrable_types.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/no-invalid-void-type" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group + .no_confusing_void_type + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/no-misused-new" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group + .no_misleading_instantiator + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/no-namespace" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.no_namespace.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/no-non-null-assertion" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group + .no_non_null_assertion + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/no-redeclare" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_redeclare.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/no-this-alias" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group + .no_useless_this_alias + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/no-unnecessary-type-constraint" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group + .no_useless_type_constraint + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/no-unsafe-declaration-merging" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group + .no_unsafe_declaration_merging + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/no-use-before-define" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group + .no_invalid_use_before_declaration + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/no-useless-constructor" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group + .no_useless_constructor + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/no-useless-empty-export" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group + .no_useless_empty_export + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/no-useless-template-literals" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group + .no_unused_template_literal + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/parameter-properties" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + let group = rules.style.get_or_insert_with(Default::default); + let rule = group + .no_parameter_properties + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/prefer-as-const" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group + .use_as_const_assertion + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/prefer-enum-initializers" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group + .use_enum_initializers + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/prefer-for-of" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.use_for_of.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/prefer-function-type" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group + .use_shorthand_function_type + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/prefer-literal-enum-member" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group + .use_literal_enum_members + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/prefer-namespace-keyword" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group + .use_namespace_keyword + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "@typescript-eslint/prefer-optional-chain" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group.use_optional_chain.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "barrel-files/avoid-namespace-import" => { + if !options.include_nursery { + return false; + } + let group = rules.nursery.get_or_insert_with(Default::default); + let rule = group.no_namespace_import.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "barrel-files/avoid-re-export-all" => { + if !options.include_nursery { + return false; + } + let group = rules.nursery.get_or_insert_with(Default::default); + let rule = group.no_re_export_all.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "constructor-super" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group + .no_invalid_constructor_super + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "curly" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.use_block_statements.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "default-case-last" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group + .use_default_switch_clause_last + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "default-param-last" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group + .use_default_parameter_last + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "dot-notation" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group.use_literal_keys.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "eqeqeq" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_double_equals.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "for-direction" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group + .use_valid_for_direction + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "getter-return" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.use_getter_return.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "import-access/eslint-plugin-import-access" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + if !options.include_nursery { + return false; + } + let group = rules.nursery.get_or_insert_with(Default::default); + let rule = group + .use_import_restrictions + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "import/no-default-export" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.no_default_export.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "import/no-nodejs-modules" => { + if !options.include_nursery { + return false; + } + let group = rules.nursery.get_or_insert_with(Default::default); + let rule = group.no_nodejs_modules.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jest/max-nested-describe" => { + if !options.include_nursery { + return false; + } + let group = rules.nursery.get_or_insert_with(Default::default); + let rule = group + .no_excessive_nested_test_suites + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jest/no-disabled-tests" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + if !options.include_nursery { + return false; + } + let group = rules.nursery.get_or_insert_with(Default::default); + let rule = group.no_skipped_tests.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jest/no-done-callback" => { + if !options.include_nursery { + return false; + } + let group = rules.nursery.get_or_insert_with(Default::default); + let rule = group.no_done_callback.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jest/no-duplicate-hooks" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + if !options.include_nursery { + return false; + } + let group = rules.nursery.get_or_insert_with(Default::default); + let rule = group + .no_duplicate_test_hooks + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jest/no-export" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + if !options.include_nursery { + return false; + } + let group = rules.nursery.get_or_insert_with(Default::default); + let rule = group.no_exports_in_test.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jest/no-focused-tests" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + if !options.include_nursery { + return false; + } + let group = rules.nursery.get_or_insert_with(Default::default); + let rule = group.no_focused_tests.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jest/no-standalone-expect" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + if !options.include_nursery { + return false; + } + let group = rules.nursery.get_or_insert_with(Default::default); + let rule = group + .no_misplaced_assertion + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/alt-text" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group.use_alt_text.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/anchor-has-content" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group.use_anchor_content.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/anchor-is-valid" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group.use_valid_anchor.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/aria-activedescendant-has-tabindex" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group + .use_aria_activedescendant_with_tabindex + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/aria-props" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group.use_valid_aria_props.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/aria-proptypes" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group + .use_valid_aria_values + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/aria-role" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group.use_valid_aria_role.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/aria-unsupported-elements" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group + .no_aria_unsupported_elements + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/click-events-have-key-events" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group + .use_key_with_click_events + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/heading-has-content" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group.use_heading_content.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/html-has-lang" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group.use_html_lang.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/iframe-has-title" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group.use_iframe_title.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/lang" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group.use_valid_lang.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/media-has-caption" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group.use_media_caption.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/mouse-events-have-key-events" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group + .use_key_with_mouse_events + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/no-access-key" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group.no_access_key.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/no-aria-hidden-on-focusable" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group + .no_aria_hidden_on_focusable + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/no-autofocus" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group.no_autofocus.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/no-distracting-elements" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group + .no_distracting_elements + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/no-interactive-element-to-noninteractive-role" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group + .no_interactive_element_to_noninteractive_role + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/no-noninteractive-element-to-interactive-role" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group + .no_noninteractive_element_to_interactive_role + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/no-noninteractive-tabindex" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group + .no_noninteractive_tabindex + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/no-redundant-roles" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group.no_redundant_roles.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/role-has-required-aria-props" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group + .use_aria_props_for_role + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/scope" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group.no_header_scope.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "jsx-a11y/tabindex-no-positive" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group.no_positive_tabindex.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-async-promise-executor" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group + .no_async_promise_executor + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-case-declarations" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group + .no_switch_declarations + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-class-assign" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_class_assign.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-compare-neg-zero" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_compare_neg_zero.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-cond-assign" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group + .no_assign_in_expressions + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-console" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_console_log.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-const-assign" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group.no_const_assign.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-constant-condition" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group + .no_constant_condition + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-constructor-return" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group + .no_constructor_return + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-control-regex" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group + .no_control_characters_in_regex + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-debugger" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_debugger.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-dupe-args" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group + .no_duplicate_parameters + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-dupe-class-members" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group + .no_duplicate_class_members + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-dupe-else-if" => { + if !options.include_nursery { + return false; + } + let group = rules.nursery.get_or_insert_with(Default::default); + let rule = group.no_duplicate_else_if.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-dupe-keys" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group + .no_duplicate_object_keys + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-duplicate-case" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_duplicate_case.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-else-return" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.no_useless_else.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-empty" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group + .no_empty_block_statements + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-empty-character-class" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group + .no_empty_character_class_in_regex + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-empty-pattern" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group.no_empty_pattern.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-eval" => { + let group = rules.security.get_or_insert_with(Default::default); + let rule = group.no_global_eval.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-ex-assign" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_catch_assign.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-extra-boolean-cast" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group + .no_extra_boolean_cast + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-extra-label" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group.no_useless_label.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-fallthrough" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group + .no_fallthrough_switch_clause + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-func-assign" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_function_assign.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-global-assign" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_global_assign.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-import-assign" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_import_assign.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-inner-declarations" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group + .no_inner_declarations + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-label-var" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_label_var.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-labels" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_confusing_labels.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-lone-blocks" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group + .no_useless_lone_block_statements + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-lonely-if" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group + .use_collapsed_else_if + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-loss-of-precision" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group.no_precision_loss.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-misleading-character-class" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group + .no_misleading_character_class + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-negated-condition" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.no_negation_else.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-new-native-nonconstructor" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group + .no_invalid_new_builtin + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-new-symbol" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group.no_new_symbol.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-nonoctal-decimal-escape" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group + .no_nonoctal_decimal_escape + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-obj-calls" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group + .no_global_object_calls + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-param-reassign" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.no_parameter_assign.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-prototype-builtins" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group + .no_prototype_builtins + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-regex-spaces" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group + .no_multiple_spaces_in_regular_expression_literals + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-restricted-globals" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group + .no_restricted_globals + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-restricted-imports" => { + if !options.include_nursery { + return false; + } + let group = rules.nursery.get_or_insert_with(Default::default); + let rule = group + .no_restricted_imports + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-self-assign" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group.no_self_assign.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-self-compare" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_self_compare.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-sequences" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.no_comma_operator.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-setter-return" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group.no_setter_return.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-shadow-restricted-names" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group + .no_shadow_restricted_names + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-sparse-array" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_sparse_array.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-this-before-super" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group.no_unreachable_super.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-undef" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group + .no_undeclared_variables + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-unneeded-ternary" => { + if !options.include_nursery { + return false; + } + let group = rules.nursery.get_or_insert_with(Default::default); + let rule = group.no_useless_ternary.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-unreachable" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group.no_unreachable.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-unsafe-finally" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group.no_unsafe_finally.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-unsafe-negation" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_unsafe_negation.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-unsafe-optional-chaining" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group + .no_unsafe_optional_chaining + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-unused-labels" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group.no_unused_labels.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-unused-private-class-members" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group + .no_unused_private_class_members + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-unused-vars" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group.no_unused_variables.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-useless-catch" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group.no_useless_catch.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-useless-rename" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group.no_useless_rename.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-var" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.no_var.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-void" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group.no_void.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "no-with" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group.no_with.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "one-var" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group + .use_single_var_declarator + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "operator-assignment" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.use_shorthand_assign.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "prefer-arrow-callback" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group.use_arrow_function.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "prefer-const" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.use_const.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "prefer-exponentiation-operator" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group + .use_exponentiation_operator + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "prefer-numeric-literals" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.use_numeric_literals.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "prefer-regex-literals" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group.use_regex_literals.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "prefer-rest-params" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.no_arguments.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "prefer-template" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.use_template.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "react-hooks/exhaustive-deps" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group + .use_exhaustive_dependencies + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "react-hooks/rules-of-hooks" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group + .use_hook_at_top_level + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "react/button-has-type" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group.use_button_type.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "react/jsx-boolean-value" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.no_implicit_boolean.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "react/jsx-fragments" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.use_fragment_syntax.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "react/jsx-key" => { + if !options.include_nursery { + return false; + } + let group = rules.nursery.get_or_insert_with(Default::default); + let rule = group + .use_jsx_key_in_iterable + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "react/jsx-no-comment-textnodes" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_comment_text.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "react/jsx-no-duplicate-props" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group + .no_duplicate_jsx_props + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "react/jsx-no-target-blank" => { + let group = rules.a11y.get_or_insert_with(Default::default); + let rule = group.no_blank_target.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "react/jsx-no-useless-fragment" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group.no_useless_fragments.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "react/no-array-index-key" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_array_index_key.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "react/no-children-prop" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group.no_children_prop.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "react/no-danger" => { + let group = rules.security.get_or_insert_with(Default::default); + let rule = group + .no_dangerously_set_inner_html_with_children + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "react/no-danger-with-children" => { + let group = rules.security.get_or_insert_with(Default::default); + let rule = group + .no_dangerously_set_inner_html + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "react/void-dom-elements-no-children" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group + .no_void_elements_with_children + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "require-await" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.use_await.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "require-yield" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group.use_yield.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "sonarjs/cognitive-complexity" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group + .no_excessive_cognitive_complexity + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "unicorn/filename-case" => { + if !options.include_inspired { + results.has_inspired_rules = true; + return false; + } + let group = rules.style.get_or_insert_with(Default::default); + let rule = group + .use_filenaming_convention + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "unicorn/no-array-for-each" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group.no_for_each.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "unicorn/no-instanceof-array" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.use_is_array.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "unicorn/no-thenable" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.no_then_property.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "unicorn/no-useless-switch-case" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group + .no_useless_switch_case + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "unicorn/prefer-array-flat-map" => { + let group = rules.complexity.get_or_insert_with(Default::default); + let rule = group.use_flat_map.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "unicorn/prefer-node-protocol" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group + .use_nodejs_import_protocol + .get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "unicorn/prefer-number-properties" => { + let group = rules.style.get_or_insert_with(Default::default); + let rule = group.use_number_namespace.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "use-isnan" => { + let group = rules.correctness.get_or_insert_with(Default::default); + let rule = group.use_is_nan.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + "valid-typeof" => { + let group = rules.suspicious.get_or_insert_with(Default::default); + let rule = group.use_valid_typeof.get_or_insert(Default::default()); + rule.set_level(rule_severity.into()); + } + _ => { + return false; + } + } + true +} diff --git a/crates/biome_cli/src/execute/migrate/eslint_eslint.rs b/crates/biome_cli/src/execute/migrate/eslint_eslint.rs new file mode 100644 index 000000000000..68e7a4109107 --- /dev/null +++ b/crates/biome_cli/src/execute/migrate/eslint_eslint.rs @@ -0,0 +1,575 @@ +use biome_deserialize::Merge; +use biome_deserialize::{ + Deserializable, DeserializableValue, DeserializationDiagnostic, DeserializationVisitor, + VisitableType, +}; +use biome_deserialize_macros::Deserializable; +use biome_rowan::TextRange; +use rustc_hash::FxHashMap; +use rustc_hash::FxHashSet; +use std::borrow::Cow; +use std::collections::hash_set; +use std::hash::{Hash, Hasher}; +use std::ops::DerefMut; +use std::vec; +use std::{any::TypeId, marker::PhantomData, ops::Deref}; + +use super::{eslint_jsxa11y, eslint_typescript, eslint_unicorn}; + +/// This modules includes implementations for deserializing an eslint configuration. +/// +/// The defined types follow the ESLint configuration schema described at +/// . +/// +/// See [super::eslint_to_biome] for converting an ESLint config to a Biome config. + +#[derive(Debug)] +pub(crate) enum AnyConfigData { + Flat(FlatConfigData), + Legacy(LegacyConfigData), +} +impl From for AnyConfigData { + fn from(value: FlatConfigData) -> Self { + AnyConfigData::Flat(value) + } +} +impl From for AnyConfigData { + fn from(value: LegacyConfigData) -> Self { + AnyConfigData::Legacy(value) + } +} + +#[derive(Debug, Default, Deserializable)] +pub(crate) struct FlatConfigData(pub(crate) Vec); + +#[derive(Debug, Default, Deserializable)] +#[deserializable(unknown_fields = "allow")] +pub(crate) struct FlatConfigObject { + pub(crate) files: Vec, + /// The glob patterns that ignore to lint. + pub(crate) ignores: Vec, + // using `Option` is important to distinguish a global ignores from a config objerct + pub(crate) language_options: Option, + // using `Option` is important to distinguish a global ignores from a config objerct + pub(crate) rules: Option, +} +impl FlatConfigObject { + /// Rteurns `true` if this config contains only `ignores`. + /// + /// See https://eslint.org/docs/latest/use/configure/configuration-files-new#globally-ignoring-files-with-ignores + pub(crate) fn is_global_ignores(&self) -> bool { + !self.ignores.is_empty() + && self.files.is_empty() + && self.language_options.is_none() + && self.rules.is_none() + } + + /// Rteurns `true` if this config doesn't specify `files` or `ignores`. + pub(crate) fn is_global_config(&self) -> bool { + self.ignores.is_empty() && self.files.is_empty() + } +} +impl Merge for FlatConfigObject { + fn merge_with(&mut self, other: Self) { + self.files.extend(other.files); + self.ignores.extend(other.ignores); + self.language_options.merge_with(other.language_options); + self.rules.merge_with(other.rules); + } +} + +#[derive(Debug, Default, Deserializable)] +#[deserializable(unknown_fields = "allow")] +pub(crate) struct FlatLanguageOptions { + pub(crate) globals: Globals, +} +impl Merge for FlatLanguageOptions { + fn merge_with(&mut self, other: Self) { + self.globals.merge_with(other.globals); + } +} + +#[derive(Debug, Default, Deserializable)] +#[deserializable(unknown_fields = "allow")] +pub(crate) struct EslintPackageJson { + pub(crate) eslint_config: Option, +} + +#[derive(Debug, Default, Deserializable)] +#[deserializable(unknown_fields = "allow")] +pub(crate) struct LegacyConfigData { + pub(crate) extends: Shorthand, + pub(crate) globals: Globals, + /// The glob patterns that ignore to lint. + pub(crate) ignore_patterns: Shorthand, + /// The parser options. + pub(crate) rules: Rules, + pub(crate) overrides: Vec, +} +impl Merge for LegacyConfigData { + fn merge_with(&mut self, mut other: Self) { + self.extends.merge_with(other.extends); + self.globals.merge_with(other.globals); + self.ignore_patterns.merge_with(other.ignore_patterns); + self.rules.merge_with(other.rules); + self.overrides.append(&mut other.overrides); + } +} + +//? ESLint plugins export metadata in their main export. +/// This includes presets in the `configs` field. +#[derive(Debug, Default, Deserializable)] +#[deserializable(unknown_fields = "allow")] +pub(crate) struct PluginExport { + pub(crate) configs: FxHashMap, +} + +#[derive(Debug, Default, Deserializable)] +pub(crate) struct Globals(pub(crate) FxHashMap); +impl Globals { + pub(crate) fn enabled(self) -> impl Iterator { + self.0.into_iter().filter_map(|(global_name, global_conf)| { + global_conf.is_enabled().then_some(global_name) + }) + } +} +impl Deref for Globals { + type Target = FxHashMap; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Merge for Globals { + fn merge_with(&mut self, other: Self) { + self.0.extend(other.0); + } +} + +#[derive(Debug)] +pub(crate) enum GlobalConf { + Flag(bool), + Qualifier(GlobalConfQualifier), +} +impl GlobalConf { + pub(crate) fn is_enabled(&self) -> bool { + match self { + GlobalConf::Flag(result) => *result, + GlobalConf::Qualifier(qualifier) => !matches!(qualifier, GlobalConfQualifier::Off), + } + } +} +impl Deserializable for GlobalConf { + fn deserialize( + value: &impl biome_deserialize::DeserializableValue, + name: &str, + diagnostics: &mut Vec, + ) -> Option { + if value.visitable_type()? == VisitableType::STR { + Deserializable::deserialize(value, name, diagnostics).map(Self::Qualifier) + } else { + Deserializable::deserialize(value, name, diagnostics).map(Self::Flag) + } + } +} + +#[derive(Debug, Deserializable)] +pub(crate) enum GlobalConfQualifier { + Off, + Readable, + Readonly, + Writable, + Writeable, +} + +#[derive(Debug, Default, Deserializable)] +#[deserializable(unknown_fields = "allow")] +pub(crate) struct OverrideConfigData { + pub(crate) extends: Shorthand, + pub(crate) globals: Globals, + /// The glob patterns for excluded files. + pub(crate) excluded_files: Shorthand, + /// The glob patterns for target files. + pub(crate) files: Shorthand, + pub(crate) rules: Rules, +} + +#[derive(Debug, Default)] +pub(crate) struct Shorthand(Vec); +impl Merge for Shorthand { + fn merge_with(&mut self, mut other: Self) { + self.0.append(&mut other.0); + } +} +impl From for Shorthand { + fn from(value: T) -> Self { + Self(vec![value]) + } +} +impl Deref for Shorthand { + type Target = Vec; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl DerefMut for Shorthand { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl IntoIterator for Shorthand { + type Item = T; + type IntoIter = vec::IntoIter; + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} +impl Deserializable for Shorthand { + fn deserialize( + value: &impl DeserializableValue, + name: &str, + diagnostics: &mut Vec, + ) -> Option { + Some(Shorthand( + if value.visitable_type()? == VisitableType::ARRAY { + Deserializable::deserialize(value, name, diagnostics)? + } else { + Vec::from_iter([Deserializable::deserialize(value, name, diagnostics)?]) + }, + )) + } +} + +/// Model the possible shapes of an ESLint's rule configuration +#[derive(Debug, Clone)] +pub(crate) enum RuleConf { + // `{ rule: }` and `{ rule: [] }` + Severity(Severity), + // `{ rule: }` and `{ rule: [, ] }` + Option(Severity, T), + // `{ rule: }` and `{ rule: [, , ] }` + Options(Severity, T, U), + // `{ rule: }` and `{ rule: [, , , ...] }` + Spread(Severity, Vec), +} +impl RuleConf { + pub(crate) fn severity(&self) -> Severity { + match self { + Self::Severity(severity) => *severity, + Self::Option(severity, _) => *severity, + Self::Options(severity, _, _) => *severity, + Self::Spread(severity, _) => *severity, + } + } +} +impl RuleConf { + pub(crate) fn into_vec(self) -> Vec { + match self { + RuleConf::Severity(_) => vec![], + RuleConf::Option(_, value) | RuleConf::Options(_, value, _) => vec![value], + RuleConf::Spread(_, result) => result, + } + } +} +impl RuleConf { + pub(crate) fn option_or_default(self) -> T { + match self { + RuleConf::Severity(_) | RuleConf::Options(_, _, _) | RuleConf::Spread(_, _) => { + T::default() + } + RuleConf::Option(_, option) => option, + } + } +} +impl Deserializable for RuleConf { + fn deserialize( + value: &impl biome_deserialize::DeserializableValue, + name: &str, + diagnostics: &mut Vec, + ) -> Option { + struct Visitor(PhantomData<(T, U)>); + impl DeserializationVisitor + for Visitor + { + type Output = RuleConf; + const EXPECTED_TYPE: VisitableType = VisitableType::ARRAY; + fn visit_array( + self, + values: impl Iterator>, + range: TextRange, + _name: &str, + diagnostics: &mut Vec, + ) -> Option { + let mut values = values.flatten(); + let Some(first_value) = values.next() else { + diagnostics.push( + DeserializationDiagnostic::new("A severity is expected.").with_range(range), + ); + return None; + }; + let severity = Deserializable::deserialize(&first_value, "", diagnostics)?; + if TypeId::of::() == TypeId::of::<()>() { + return Some(RuleConf::Severity(severity)); + } + let Some(second_value) = values.next() else { + return Some(RuleConf::Severity(severity)); + }; + let Some(option) = T::deserialize(&second_value, "", diagnostics) else { + // Recover by ignoring the failed deserialization + return Some(RuleConf::Severity(severity)); + }; + let Some(third_value) = values.next() else { + return Some(RuleConf::Option(severity, option)); + }; + if TypeId::of::() != TypeId::of::<()>() { + if let Some(option2) = U::deserialize(&third_value, "", diagnostics) { + return Some(RuleConf::Options(severity, option, option2)); + } else { + // Recover by ignoring the failed deserialization + return Some(RuleConf::Option(severity, option)); + } + } + let Some(option2) = T::deserialize(&third_value, "", diagnostics) else { + // Recover by ignoring the failed deserialization + return Some(RuleConf::Option(severity, option)); + }; + let mut spread = Vec::new(); + spread.push(option); + spread.push(option2); + spread.extend(values.filter_map(|val| T::deserialize(&val, "", diagnostics))); + Some(RuleConf::Spread(severity, spread)) + } + } + if matches!( + value.visitable_type()?, + VisitableType::NUMBER | VisitableType::STR + ) { + Deserializable::deserialize(value, name, diagnostics).map(RuleConf::Severity) + } else { + value.deserialize(Visitor(PhantomData), name, diagnostics) + } + } +} + +#[derive(Clone, Copy, Debug, Deserializable)] +#[deserializable(try_from = "NumberOrString")] +pub(crate) enum Severity { + Off, + Warn, + Error, +} +impl TryFrom for Severity { + type Error = &'static str; + + fn try_from(value: NumberOrString) -> Result { + match value { + NumberOrString::Number(n) => match n { + 0 => Ok(Severity::Off), + 1 => Ok(Severity::Warn), + 2 => Ok(Severity::Error), + _ => Err("Severity should be 0, 1 or 2."), + }, + NumberOrString::String(s) => match s.as_ref() { + "off" => Ok(Severity::Off), + "warn" => Ok(Severity::Warn), + "error" => Ok(Severity::Error), + _ => Err("Severity should be 'off', 'warn' or 'error'."), + }, + } + } +} +impl From for biome_configuration::RulePlainConfiguration { + fn from(value: Severity) -> biome_configuration::RulePlainConfiguration { + match value { + Severity::Off => biome_configuration::RulePlainConfiguration::Off, + Severity::Warn => biome_configuration::RulePlainConfiguration::Warn, + Severity::Error => biome_configuration::RulePlainConfiguration::Error, + } + } +} +#[derive(Debug, Clone)] +enum NumberOrString { + Number(u64), + String(String), +} +impl Deserializable for NumberOrString { + fn deserialize( + value: &impl biome_deserialize::DeserializableValue, + name: &str, + diagnostics: &mut Vec, + ) -> Option { + Some(if value.visitable_type()? == VisitableType::STR { + Self::String(Deserializable::deserialize(value, name, diagnostics)?) + } else { + Self::Number(Deserializable::deserialize(value, name, diagnostics)?) + }) + } +} + +#[derive(Debug, Default)] +pub(crate) struct Rules(pub(crate) FxHashSet); +impl Merge for Rules { + fn merge_with(&mut self, other: Self) { + self.0.extend(other.0); + } +} +impl IntoIterator for Rules { + type Item = Rule; + type IntoIter = hash_set::IntoIter; + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} +impl Deref for Rules { + type Target = FxHashSet; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deserializable for Rules { + fn deserialize( + value: &impl biome_deserialize::DeserializableValue, + name: &str, + diagnostics: &mut Vec, + ) -> Option { + struct Visitor; + impl DeserializationVisitor for Visitor { + type Output = Rules; + const EXPECTED_TYPE: VisitableType = VisitableType::MAP; + fn visit_map( + self, + members: impl Iterator< + Item = Option<( + impl biome_deserialize::DeserializableValue, + impl biome_deserialize::DeserializableValue, + )>, + >, + _range: biome_rowan::TextRange, + name: &str, + diagnostics: &mut Vec, + ) -> Option { + use biome_deserialize::Text; + let mut result = FxHashSet::default(); + for (key, value) in members.flatten() { + let Some(rule_name) = Text::deserialize(&key, "", diagnostics) else { + continue; + }; + match rule_name.text() { + // Eslint rules with options that we handle + "no-restricted-globals" => { + if let Some(conf) = RuleConf::deserialize(&value, name, diagnostics) { + result.insert(Rule::NoRestrictedGlobals(conf)); + } + } + // Eslint plugin rules with options that we handle + "jsx-a11y/aria-role" => { + if let Some(conf) = RuleConf::deserialize(&value, name, diagnostics) { + result.insert(Rule::Jsxa11yArioaRoles(conf)); + } + } + "@typescript-eslint/array-type" => { + if let Some(conf) = RuleConf::deserialize(&value, name, diagnostics) { + result.insert(Rule::TypeScriptArrayType(conf)); + } + } + "@typescript-eslint/naming-convention" => { + if let Some(conf) = RuleConf::deserialize(&value, name, diagnostics) { + result.insert(Rule::TypeScriptNamingConvention(conf)); + } + } + "unicorn/filename-case" => { + if let Some(conf) = RuleConf::deserialize(&value, name, diagnostics) { + result.insert(Rule::UnicornFilenameCase(conf)); + } + } + // Other rules + rule_name => { + if let Some(conf) = + RuleConf::<()>::deserialize(&value, name, diagnostics) + { + result.insert(Rule::Any( + Cow::Owned(rule_name.to_string()), + conf.severity(), + )); + } + } + } + } + Some(Rules(result)) + } + } + value.deserialize(Visitor, name, diagnostics) + } +} + +#[derive(Debug)] +pub(crate) enum NoRestrictedGlobal { + Plain(String), + WithMessage(GlobalWithMessage), +} +impl NoRestrictedGlobal { + pub(crate) fn into_name(self) -> String { + match self { + NoRestrictedGlobal::Plain(name) => name, + NoRestrictedGlobal::WithMessage(named) => named.name, + } + } +} +impl Deserializable for NoRestrictedGlobal { + fn deserialize( + value: &impl DeserializableValue, + name: &str, + diagnostics: &mut Vec, + ) -> Option { + if value.visitable_type()? == VisitableType::STR { + Deserializable::deserialize(value, name, diagnostics).map(NoRestrictedGlobal::Plain) + } else { + Deserializable::deserialize(value, name, diagnostics) + .map(NoRestrictedGlobal::WithMessage) + } + } +} +#[derive(Debug, Default, Deserializable)] +pub(crate) struct GlobalWithMessage { + name: String, + message: String, +} + +#[derive(Debug)] +pub(crate) enum Rule { + /// Any rule without its options. + Any(Cow<'static, str>, Severity), + // Eslint rules with its options + // We use this to configure equivalent Bione's rules. + NoRestrictedGlobals(RuleConf>), + // Eslint plugins + Jsxa11yArioaRoles(RuleConf>), + TypeScriptArrayType(RuleConf), + TypeScriptNamingConvention(RuleConf>), + UnicornFilenameCase(RuleConf), + // If ypu add new variants, dont forget to update [Rules::deserialize]. +} +impl Rule { + pub(crate) fn name(&self) -> Cow<'static, str> { + match self { + Rule::Any(name, _) => name.clone(), + Rule::NoRestrictedGlobals(_) => Cow::Borrowed("no-restricted-globals"), + Rule::Jsxa11yArioaRoles(_) => Cow::Borrowed("jsx-a11y/aria-role"), + Rule::TypeScriptArrayType(_) => Cow::Borrowed("@typescript-eslint/array-type"), + Rule::TypeScriptNamingConvention(_) => { + Cow::Borrowed("@typescript-eslint/naming-convention") + } + Rule::UnicornFilenameCase(_) => Cow::Borrowed("unicorn/filename-case"), + } + } +} +impl Eq for Rule {} +impl PartialEq for Rule { + fn eq(&self, other: &Self) -> bool { + self.name() == other.name() + } +} +impl Hash for Rule { + fn hash(&self, state: &mut H) { + self.name().hash(state); + } +} diff --git a/crates/biome_cli/src/execute/migrate/eslint_jsxa11y.rs b/crates/biome_cli/src/execute/migrate/eslint_jsxa11y.rs new file mode 100644 index 000000000000..c8b415c394e0 --- /dev/null +++ b/crates/biome_cli/src/execute/migrate/eslint_jsxa11y.rs @@ -0,0 +1,21 @@ +/// Configuration related to the +/// [JSX A11y Eslint plugin](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y). +/// +/// Also, the module includes implementation to convert rule options to Biome's rule options. +use biome_deserialize_macros::Deserializable; +use biome_js_analyze::lint::a11y::use_valid_aria_role; + +#[derive(Debug, Default, Deserializable)] +pub(crate) struct AriaRoleOptions { + allowed_invalid_roles: Vec, + #[deserializable(rename = "ignoreNonDOM")] + ignore_non_dom: bool, +} +impl From for use_valid_aria_role::ValidAriaRoleOptions { + fn from(val: AriaRoleOptions) -> Self { + use_valid_aria_role::ValidAriaRoleOptions { + allow_invalid_roles: val.allowed_invalid_roles, + ignore_non_dom: val.ignore_non_dom, + } + } +} diff --git a/crates/biome_cli/src/execute/migrate/eslint_to_biome.rs b/crates/biome_cli/src/execute/migrate/eslint_to_biome.rs new file mode 100644 index 000000000000..c6fca32e2429 --- /dev/null +++ b/crates/biome_cli/src/execute/migrate/eslint_to_biome.rs @@ -0,0 +1,267 @@ +use biome_configuration::{self as biome_config}; +use biome_deserialize::{Merge, StringSet}; +use biome_js_analyze::lint::style::no_restricted_globals; + +use super::{eslint_any_rule_to_biome::migrate_eslint_any_rule, eslint_eslint, eslint_typescript}; + +/// This modules includes implementations for converting an ESLint config to a Biome config. +/// +/// The conversion relies on: +/// - the generated [super::eslint_any_rule_to_biome::migrate_eslint_any_rule] +/// module that relies on Biome's rule metadata to determine +/// the equivalent Biome's rule of an Eslint rule +/// - hand-written handling of Biome rules that have options in the current module. + +#[derive(Debug, Clone)] +pub(crate) struct MigrationOptions { + /// Migrate inspired rules from eslint and its plugins? + pub(crate) include_inspired: bool, + /// Migrate nursery rules from eslint and its plugins? + pub(crate) include_nursery: bool, +} + +#[derive(Debug, Default)] +pub(crate) struct MigrationResults { + // Contains inspired rules that were not migrated because `include_inspired` is disabled + pub(crate) has_inspired_rules: bool, +} + +impl eslint_eslint::AnyConfigData { + pub(crate) fn into_biome_config( + self, + options: &MigrationOptions, + ) -> (biome_config::PartialConfiguration, MigrationResults) { + match self { + Self::Flat(config) => config.into_biome_config(options), + Self::Legacy(config) => config.into_biome_config(options), + } + } +} + +impl eslint_eslint::FlatConfigData { + pub(crate) fn into_biome_config( + self, + options: &MigrationOptions, + ) -> (biome_config::PartialConfiguration, MigrationResults) { + let mut results = MigrationResults::default(); + let mut biome_config = biome_config::PartialConfiguration::default(); + let mut linter = biome_config::PartialLinterConfiguration::default(); + let mut overrides = biome_config::Overrides::default(); + let mut global_ignores = StringSet::default(); + let mut global_config_object = eslint_eslint::FlatConfigObject::default(); + // First determine the base configuration + for flat_config_object in self.0 { + if flat_config_object.is_global_ignores() { + global_ignores.extend(flat_config_object.ignores); + } else if flat_config_object.is_global_config() { + global_config_object.merge_with(flat_config_object); + } else { + let mut override_pattern = biome_config::OverridePattern::default(); + if let Some(language_options) = flat_config_object.language_options { + let globals = language_options.globals.enabled().collect::(); + let js_config = biome_config::PartialJavascriptConfiguration { + globals: Some(globals), + ..Default::default() + }; + override_pattern.javascript = Some(js_config) + } + if !flat_config_object.ignores.is_empty() { + override_pattern.ignore = + Some(flat_config_object.ignores.into_iter().collect()); + } + if !flat_config_object.files.is_empty() { + override_pattern.include = Some(flat_config_object.files.into_iter().collect()); + } + if let Some(rules) = flat_config_object.rules { + if !rules.is_empty() { + override_pattern.linter = Some(biome_config::OverrideLinterConfiguration { + rules: Some(rules.into_biome_rules(options, &mut results)), + ..Default::default() + }); + } + } + overrides.0.push(override_pattern); + } + } + if !overrides.0.is_empty() { + biome_config.overrides = Some(overrides); + } + debug_assert!(global_config_object.is_global_config()); + let mut rules = if let Some(rules) = global_config_object.rules { + rules.into_biome_rules(options, &mut results) + } else { + biome_config::Rules::default() + }; + if let Some(language_options) = global_config_object.language_options { + let globals = language_options.globals.enabled().collect::(); + let js_config = biome_config::PartialJavascriptConfiguration { + globals: Some(globals), + ..Default::default() + }; + biome_config.javascript = Some(js_config) + } + rules.recommended = Some(false); + linter.rules = Some(rules); + if !global_ignores.is_empty() { + linter.ignore = Some(global_ignores); + } + biome_config.linter = Some(linter); + (biome_config, results) + } +} + +impl eslint_eslint::LegacyConfigData { + pub(crate) fn into_biome_config( + self, + options: &MigrationOptions, + ) -> (biome_config::PartialConfiguration, MigrationResults) { + let mut results = MigrationResults::default(); + let mut biome_config = biome_config::PartialConfiguration::default(); + if !self.globals.is_empty() { + let globals = self.globals.enabled().collect::(); + let js_config = biome_config::PartialJavascriptConfiguration { + globals: Some(globals), + ..Default::default() + }; + biome_config.javascript = Some(js_config) + } + let mut linter = biome_config::PartialLinterConfiguration::default(); + let mut rules = self.rules.into_biome_rules(options, &mut results); + rules.recommended = Some(false); + linter.rules = Some(rules); + if !self.ignore_patterns.is_empty() { + let ignore = self.ignore_patterns.into_iter().collect::(); + linter.ignore = Some(ignore); + } + if !self.overrides.is_empty() { + let mut overrides = biome_config::Overrides::default(); + for override_elt in self.overrides { + let mut override_pattern = biome_config::OverridePattern::default(); + if !override_elt.globals.is_empty() { + let globals = override_elt.globals.enabled().collect::(); + let js_config = biome_config::PartialJavascriptConfiguration { + globals: Some(globals), + ..Default::default() + }; + override_pattern.javascript = Some(js_config) + } + if !override_elt.excluded_files.is_empty() { + override_pattern.ignore = + Some(override_elt.excluded_files.into_iter().collect()); + } + if !override_elt.files.is_empty() { + override_pattern.include = Some(override_elt.files.into_iter().collect()); + } + if !override_elt.rules.is_empty() { + override_pattern.linter = Some(biome_config::OverrideLinterConfiguration { + rules: Some(override_elt.rules.into_biome_rules(options, &mut results)), + ..Default::default() + }); + } + overrides.0.push(override_pattern); + } + biome_config.overrides = Some(overrides); + } + biome_config.linter = Some(linter); + (biome_config, results) + } +} + +impl eslint_eslint::Rules { + pub(crate) fn into_biome_rules( + self, + options: &MigrationOptions, + results: &mut MigrationResults, + ) -> biome_config::Rules { + let mut rules = biome_config::Rules::default(); + for eslint_rule in self { + migrate_eslint_rule(&mut rules, eslint_rule, options, results); + } + rules + } +} + +/// Look for an equivalent Biome rule for ESLint `rule`, +/// and then mutate `rules` if a equivalent rule is found. +/// Also, takes care of Biome's rules with options. +fn migrate_eslint_rule( + rules: &mut biome_config::Rules, + rule: eslint_eslint::Rule, + opts: &MigrationOptions, + results: &mut MigrationResults, +) { + let name = rule.name(); + match rule { + eslint_eslint::Rule::Any(name, severity) => { + let _ = migrate_eslint_any_rule(rules, &name, severity, opts, results); + } + eslint_eslint::Rule::NoRestrictedGlobals(conf) => { + if migrate_eslint_any_rule(rules, &name, conf.severity(), opts, results) { + let severity = conf.severity(); + let globals = conf.into_vec().into_iter().map(|g| g.into_name()); + let group = rules.style.get_or_insert_with(Default::default); + group.no_restricted_globals = Some(biome_config::RuleConfiguration::WithOptions( + biome_config::RuleWithOptions { + level: severity.into(), + options: Box::new(no_restricted_globals::RestrictedGlobalsOptions { + denied_globals: globals.collect(), + }), + }, + )); + } + } + eslint_eslint::Rule::Jsxa11yArioaRoles(conf) => { + if migrate_eslint_any_rule(rules, &name, conf.severity(), opts, results) { + if let eslint_eslint::RuleConf::Option(severity, rule_options) = conf { + let group = rules.a11y.get_or_insert_with(Default::default); + group.use_valid_aria_role = Some(biome_config::RuleConfiguration::WithOptions( + biome_config::RuleWithOptions { + level: severity.into(), + options: Box::new((*rule_options).into()), + }, + )); + } + } + } + eslint_eslint::Rule::TypeScriptArrayType(conf) => { + if migrate_eslint_any_rule(rules, &name, conf.severity(), opts, results) { + if let eslint_eslint::RuleConf::Option(severity, rule_options) = conf { + let group = rules.style.get_or_insert_with(Default::default); + group.use_consistent_array_type = + Some(biome_config::RuleConfiguration::WithOptions( + biome_config::RuleWithOptions { + level: severity.into(), + options: rule_options.into(), + }, + )); + } + } + } + eslint_eslint::Rule::TypeScriptNamingConvention(conf) => { + if migrate_eslint_any_rule(rules, &name, conf.severity(), opts, results) { + let severity = conf.severity(); + let options = eslint_typescript::NamingConventionOptions::override_default( + conf.into_vec().into_iter().map(|v| *v), + ); + let group = rules.style.get_or_insert_with(Default::default); + group.use_naming_convention = Some(biome_config::RuleConfiguration::WithOptions( + biome_config::RuleWithOptions { + level: severity.into(), + options: options.into(), + }, + )); + } + } + eslint_eslint::Rule::UnicornFilenameCase(conf) => { + if migrate_eslint_any_rule(rules, &name, conf.severity(), opts, results) { + let group = rules.style.get_or_insert_with(Default::default); + group.use_filenaming_convention = Some( + biome_config::RuleConfiguration::WithOptions(biome_config::RuleWithOptions { + level: conf.severity().into(), + options: Box::new(conf.option_or_default().into()), + }), + ); + } + } + } +} diff --git a/crates/biome_cli/src/execute/migrate/eslint_typescript.rs b/crates/biome_cli/src/execute/migrate/eslint_typescript.rs new file mode 100644 index 000000000000..6ffefbe4190e --- /dev/null +++ b/crates/biome_cli/src/execute/migrate/eslint_typescript.rs @@ -0,0 +1,247 @@ +/// Configuration related to [TypeScript Eslint](https://typescript-eslint.io/). +/// +/// ALso, the module includes implementation to convert rule options to Biome's rule options. +use biome_deserialize_macros::Deserializable; +use biome_js_analyze::lint::style::{use_consistent_array_type, use_naming_convention}; + +use super::eslint_eslint; + +#[derive(Debug, Default, Deserializable)] +pub(crate) struct ArrayTypeOptions { + default: ArrayType, + readonly: Option, +} +impl From for use_consistent_array_type::ConsistentArrayTypeOptions { + fn from(val: ArrayTypeOptions) -> Self { + use_consistent_array_type::ConsistentArrayTypeOptions { + syntax: val.default.into(), + } + } +} +#[derive(Debug, Default, Deserializable)] +pub(crate) enum ArrayType { + #[default] + Array, + #[deserializable(rename = "array-simple")] + ArraySimple, + Generic, +} +impl From for use_consistent_array_type::ConsistentArrayType { + fn from(val: ArrayType) -> Self { + match val { + // NOTE: we translate `array-simple` to `array`. + ArrayType::Array | ArrayType::ArraySimple => { + use_consistent_array_type::ConsistentArrayType::Shorthand + } + ArrayType::Generic => use_consistent_array_type::ConsistentArrayType::Generic, + } + } +} + +#[derive(Debug)] +pub(crate) struct NamingConventionOptions(Vec); +impl NamingConventionOptions { + pub(crate) fn override_default( + overrides: impl IntoIterator, + ) -> Self { + let mut result = Self::default(); + result.0.extend(overrides); + result + } +} +impl Default for NamingConventionOptions { + fn default() -> Self { + Self(vec![ + NamingConventionSelection { + selector: Selector::Default.into(), + format: Some(vec![NamingConventionCase::Camel]), + leading_underscore: Some(Underscore::Allow), + trailing_underscore: Some(Underscore::Allow), + ..Default::default() + }, + NamingConventionSelection { + selector: Selector::Import.into(), + format: Some(vec![ + NamingConventionCase::Camel, + NamingConventionCase::Pascal, + ]), + ..Default::default() + }, + NamingConventionSelection { + selector: Selector::Variable.into(), + format: Some(vec![ + NamingConventionCase::Camel, + NamingConventionCase::Upper, + ]), + leading_underscore: Some(Underscore::Allow), + trailing_underscore: Some(Underscore::Allow), + ..Default::default() + }, + NamingConventionSelection { + selector: Selector::TypeLike.into(), + format: Some(vec![NamingConventionCase::Pascal]), + leading_underscore: Some(Underscore::Allow), + trailing_underscore: Some(Underscore::Allow), + ..Default::default() + }, + ]) + } +} +impl From for use_naming_convention::NamingConventionOptions { + fn from(val: NamingConventionOptions) -> Self { + let mut enum_member_format = None; + for selection in val.0 { + if selection.selector.contains(&Selector::EnumMember) { + // We only extract the first format because Biome doesn't allow for now multiple cases. + enum_member_format = selection + .format + .and_then(|format| format.into_iter().next()); + } + } + use_naming_convention::NamingConventionOptions { + strict_case: matches!( + enum_member_format, + Some(NamingConventionCase::StrictCamel | NamingConventionCase::StrictPascal) + ), + require_ascii: false, + enum_member_case: enum_member_format + .and_then(|format| { + match format { + NamingConventionCase::Camel | NamingConventionCase::StrictCamel => { + Some(use_naming_convention::EnumMemberCase::Camel) + } + NamingConventionCase::Pascal | NamingConventionCase::StrictPascal => { + Some(use_naming_convention::EnumMemberCase::Pascal) + } + NamingConventionCase::Upper => { + Some(use_naming_convention::EnumMemberCase::Constant) + } + // Biome doesn't support `snake_case` for enum member + NamingConventionCase::Snake => None, + } + }) + .unwrap_or_default(), + } + } +} +#[derive(Debug, Default, Deserializable)] +#[deserializable(unknown_fields = "allow")] +pub(crate) struct NamingConventionSelection { + pub(crate) selector: eslint_eslint::Shorthand, + pub(crate) modifiers: Option>, + pub(crate) types: Option>, + //pub(crate) custom: Option, + pub(crate) format: Option>, + pub(crate) leading_underscore: Option, + pub(crate) trailing_underscore: Option, + //pub(crate) prefix: Option>, + //pub(crate) suffix: Option>, + //pub(crate) filter: Option, +} +//#[derive(Debug, Default, Deserializable)] +//pub(crate) struct Custom { +// regex: String, +// #[deserializable(rename = "match")] +// matches: bool, +//} +//#[derive(Debug, Clone)] +//pub(crate) enum Filter { +// Regex(String), +// Custom(Custom), +//} +//impl Deserializable for Filter { +// fn deserialize( +// value: &impl biome_deserialize::DeserializableValue, +// name: &str, +// diagnostics: &mut Vec, +// ) -> Option { +// if value.visitable()? == VisitableType::STR { +// Deserializable::deserialize(value, name, diagnostics).map(Filter::Regex) +// } else { +// Deserializable::deserialize(value, name, diagnostics).map(Filter::Custom) +// } +// } +//} +#[derive(Debug, Deserializable)] +pub(crate) enum NamingConventionCase { + #[deserializable(rename = "camelCase")] + Camel, + #[deserializable(rename = "strictCamelCase")] + StrictCamel, + #[deserializable(rename = "PascalCase")] + Pascal, + #[deserializable(rename = "StrictPascalCase")] + StrictPascal, + #[deserializable(rename = "snake_case")] + Snake, + #[deserializable(rename = "UPPER_CASE")] + Upper, +} +#[derive(Debug, Default, Eq, PartialEq, Deserializable)] +pub(crate) enum Selector { + // Individual selectors + ClassicAccessor, + AutoAccessor, + Class, + ClassMethod, + ClassProperty, + Enum, + EnumMember, + Function, + Import, + Interface, + ObjectLiteralMethod, + ObjectLiteralProperty, + Parameter, + ParameterProperty, + TypeAlias, + TypeMethod, + TypeParameter, + TypeProperty, + Variable, + // group selector + #[default] + Default, + Accessor, + MemberLike, + Method, + Property, + TypeLike, + VariableLike, +} +#[derive(Debug, Deserializable)] +pub(crate) enum Modifier { + Abstract, + Async, + Const, + Destructured, + Exported, + Global, + Override, + Private, + Protected, + Public, + Readonly, + RequiresQuotes, + #[deserializable(rename = "#private")] + SharpPrivate, + Static, + Unused, +} +#[derive(Debug, Deserializable)] +pub(crate) enum Type { + Array, + Boolean, + Function, + Number, + String, +} +#[derive(Debug, Deserializable)] +pub(crate) enum Underscore { + Forbid, + Require, + RequireDouble, + Allow, + AllowDouble, + AllowSingleOrDouble, +} diff --git a/crates/biome_cli/src/execute/migrate/eslint_unicorn.rs b/crates/biome_cli/src/execute/migrate/eslint_unicorn.rs new file mode 100644 index 000000000000..d04a0424f693 --- /dev/null +++ b/crates/biome_cli/src/execute/migrate/eslint_unicorn.rs @@ -0,0 +1,78 @@ +/// Configuration related to the +/// [Unicorn Eslint plugin](https://github.com/sindresorhus/eslint-plugin-unicorn). +/// +/// ALso, the module includes implementation to convert rule options to Biome's rule options. +use biome_deserialize_macros::Deserializable; +use biome_js_analyze::lint::style::use_filenaming_convention; +use smallvec::SmallVec; + +#[derive(Clone, Debug, Default, Deserializable)] +pub(crate) struct FilenameCaseOptions { + case: FilenameCase, + cases: FilenameCases, + ignore: Vec, + multiple_file_extensions: bool, +} +impl From for use_filenaming_convention::FilenamingConventionOptions { + fn from(val: FilenameCaseOptions) -> Self { + let filename_cases: Option = val.cases.into(); + use_filenaming_convention::FilenamingConventionOptions { + strict_case: true, + require_ascii: true, + filename_cases: filename_cases.unwrap_or_else(|| { + use_filenaming_convention::FilenameCases::from_iter([val.case.into()]) + }), + } + } +} +#[derive(Clone, Debug, Default, Deserializable)] +pub(crate) enum FilenameCase { + #[default] + #[deserializable(rename = "kebabCase")] + Kebab, + #[deserializable(rename = "camelCase")] + Camel, + #[deserializable(rename = "snakeCase")] + Snake, + #[deserializable(rename = "pascalCase")] + Pascal, +} +impl From for use_filenaming_convention::FilenameCase { + fn from(val: FilenameCase) -> Self { + match val { + FilenameCase::Kebab => use_filenaming_convention::FilenameCase::Kebab, + FilenameCase::Camel => use_filenaming_convention::FilenameCase::Camel, + FilenameCase::Snake => use_filenaming_convention::FilenameCase::Snake, + FilenameCase::Pascal => use_filenaming_convention::FilenameCase::Pascal, + } + } +} +#[derive(Clone, Debug, Default, Deserializable)] +pub(crate) struct FilenameCases { + kebab_case: bool, + camel_case: bool, + snake_case: bool, + pascal_case: bool, +} +impl From for Option { + fn from(val: FilenameCases) -> Self { + let mut cases: SmallVec<[use_filenaming_convention::FilenameCase; 4]> = SmallVec::new(); + if val.kebab_case { + cases.push(use_filenaming_convention::FilenameCase::Kebab); + } + if val.camel_case { + cases.push(use_filenaming_convention::FilenameCase::Camel); + } + if val.snake_case { + cases.push(use_filenaming_convention::FilenameCase::Snake); + } + if val.pascal_case { + cases.push(use_filenaming_convention::FilenameCase::Pascal); + } + if cases.is_empty() { + None + } else { + Some(use_filenaming_convention::FilenameCases::from_iter(cases)) + } + } +} diff --git a/crates/biome_cli/src/execute/migrate/ignorefile.rs b/crates/biome_cli/src/execute/migrate/ignorefile.rs new file mode 100644 index 000000000000..2defb56e35cd --- /dev/null +++ b/crates/biome_cli/src/execute/migrate/ignorefile.rs @@ -0,0 +1,195 @@ +use std::{io, path::Path}; + +use biome_fs::{FileSystem, OpenOptions}; +use biome_service::DynRef; +use indexmap::IndexSet; + +pub(crate) fn read_ignore_file( + fs: &DynRef<'_, dyn FileSystem>, + ignore_filename: &str, +) -> io::Result { + let mut file = fs.open_with_options( + Path::new(ignore_filename), + OpenOptions::default().read(true), + )?; + let mut content = String::new(); + file.read_to_string(&mut content)?; + Ok(IgnorePatterns::from(&content)) +} + +#[derive(Debug)] +pub(crate) struct IgnorePatterns { + pub(crate) patterns: IndexSet, + pub(crate) has_negated_patterns: bool, +} +impl IgnorePatterns { + pub(crate) fn from(content: &str) -> Self { + let mut has_negated_patterns = false; + let mut patterns = IndexSet::new(); + for line in content.lines() { + // Trailing spaces are ignored + let line = line.trim_end(); + // empty lines and comments are ignored + if line.is_empty() || line.starts_with('#') { + continue; + } + if line.starts_with('!') { + has_negated_patterns = true; + // Skip negated patterns because we don't support them. + continue; + } + let pattern = if let Some(stripped_line) = line.strip_prefix('/') { + // Patterns tha tstarts with `/` are relative to the ignore file + format!("./{}", stripped_line) + } else if line.find('/').is_some_and(|index| index < (line.len() - 1)) + || line == "**" + || line == "**/" + { + // Patterns that includes at least one `/` in the middle are relatives paths + line.to_string() + } else { + format!("**/{line}") + }; + patterns.insert(pattern); + } + IgnorePatterns { + patterns, + has_negated_patterns, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn empty() { + const IGNORE_FILE_CONTENT: &str = r#""#; + let result = IgnorePatterns::from(IGNORE_FILE_CONTENT); + + assert!(!result.has_negated_patterns); + assert!(result.patterns.is_empty()); + } + + #[test] + fn comments_and_empty_lines() { + const IGNORE_FILE_CONTENT: &str = r#" +# Comment 1 +# folloed by a blank line + +# Comment 2 +# folloed by a blank line (trailing space are ignored) + + "#; + let result = IgnorePatterns::from(IGNORE_FILE_CONTENT); + + assert!(!result.has_negated_patterns); + assert!(result.patterns.is_empty()); + } + + #[test] + fn non_relative_patterns() { + const IGNORE_FILE_CONTENT: &str = r#" +file-or-dir +dir/ +** +**/ +* +*/ +"#; + let result = IgnorePatterns::from(IGNORE_FILE_CONTENT); + + assert!(!result.has_negated_patterns); + assert_eq!( + result.patterns, + [ + "**/file-or-dir".to_string(), + "**/dir/".to_string(), + "**".to_string(), + "**/".to_string(), + "**/*".to_string(), + "**/*/".to_string(), + ] + .into() + ); + } + + #[test] + fn relative_patterns() { + const IGNORE_FILE_CONTENT: &str = r#" +dir/dubfile-or-subdir +dir/subdir/ +**/* +**/*/ +**/a/b +**/a/b/ +"#; + let result = IgnorePatterns::from(IGNORE_FILE_CONTENT); + + assert!(!result.has_negated_patterns); + assert_eq!( + result.patterns, + [ + "dir/dubfile-or-subdir".to_string(), + "dir/subdir/".to_string(), + "**/*".to_string(), + "**/*/".to_string(), + "**/a/b".to_string(), + "**/a/b/".to_string(), + ] + .into() + ); + } + + #[test] + fn relative_patterns_starting_with_root_slash() { + const IGNORE_FILE_CONTENT: &str = r#" +/dir/dubfile-or-subdir +/dir/subdir/ +/**/* +/**/*/ +/**/a/b +/**/a/b/ +"#; + let result = IgnorePatterns::from(IGNORE_FILE_CONTENT); + + assert!(!result.has_negated_patterns); + assert_eq!( + result.patterns, + [ + "./dir/dubfile-or-subdir".to_string(), + "./dir/subdir/".to_string(), + "./**/*".to_string(), + "./**/*/".to_string(), + "./**/a/b".to_string(), + "./**/a/b/".to_string(), + ] + .into() + ); + } + + #[test] + fn negated_pattern() { + const IGNORE_FILE_CONTENT: &str = r#"!a"#; + let result = IgnorePatterns::from(IGNORE_FILE_CONTENT); + + assert!(result.has_negated_patterns); + assert!(result.patterns.is_empty()); + } + + #[test] + fn take_leading_spaces_into_account() { + const IGNORE_FILE_CONTENT: &str = r#" + # This is not a comment because there is some leading spaces + "#; + let result = IgnorePatterns::from(IGNORE_FILE_CONTENT); + + assert!(!result.has_negated_patterns); + assert_eq!( + result.patterns, + ["**/ # This is not a comment because there is some leading spaces".to_string()] + .into() + ); + } +} diff --git a/crates/biome_cli/src/execute/migrate/node.rs b/crates/biome_cli/src/execute/migrate/node.rs new file mode 100644 index 000000000000..7f265f413f15 --- /dev/null +++ b/crates/biome_cli/src/execute/migrate/node.rs @@ -0,0 +1,64 @@ +use std::process::Command; + +use crate::{diagnostics::MigrationDiagnostic, CliDiagnostic}; + +/// Imports `specifier` using Node's `import()` or node's `require()` and +/// returns the JSONified content of its default export. +pub(crate) fn load_config(specifier: &str) -> Result { + let content_output = Command::new("node") + .arg("--eval") + .arg(format!( + "import('{specifier}').then((c) => console.log(JSON.stringify(c.default)))" + )) + .output(); + match content_output { + Err(_) => { + Err(CliDiagnostic::MigrateError(MigrationDiagnostic { + reason: "The `node` program doesn't exist or cannot be invoked by Biome.\n`node` is invoked to resolve ESLint configurations written in JavaScript.\nThis includes shared configurations and plugin configurations imported with ESLint's `extends`.".to_string() + })) + }, + Ok(output) => { + let path_output = Command::new("node") + .arg("--print") + .arg(format!( + "require.resolve('{specifier}')" + )) + .output(); + let resolved_path = path_output.ok().map_or(String::new(), |path_output| String::from_utf8_lossy(&path_output.stdout).trim().to_string()); + if !output.stderr.is_empty() { + // Try with `require` before giving up. + let output2 = Command::new("node") + .arg("--print") + .arg(format!( + "JSON.stringify(require('{specifier}'))" + )) + .output(); + if let Ok(output2) = output2 { + if output2.stderr.is_empty() { + return Ok(Resolution { + content: String::from_utf8_lossy(&output2.stdout).to_string(), + resolved_path, + }); + } + } + let stderr = String::from_utf8_lossy(&output.stderr); + return Err(CliDiagnostic::MigrateError(MigrationDiagnostic { + reason: format!("`node` was invoked to resolve '{specifier}'. This invocation failed with the following error:\n{stderr}") + })); + } + Ok(Resolution { + content: String::from_utf8_lossy(&output.stdout).to_string(), + resolved_path, + }) + } + } +} + +#[derive(Debug)] +pub(crate) struct Resolution { + /// Resolved path of the file. + /// May be empty if the resolution failed. + pub(crate) resolved_path: String, + /// File content in JSON + pub(crate) content: String, +} diff --git a/crates/biome_cli/src/execute/migrate/prettier.rs b/crates/biome_cli/src/execute/migrate/prettier.rs index cec88ef490e7..2cf08367956f 100644 --- a/crates/biome_cli/src/execute/migrate/prettier.rs +++ b/crates/biome_cli/src/execute/migrate/prettier.rs @@ -1,20 +1,18 @@ use crate::diagnostics::MigrationDiagnostic; use crate::CliDiagnostic; +use biome_configuration::{ + PartialConfiguration, PartialFormatterConfiguration, PartialJavascriptConfiguration, + PartialJavascriptFormatter, PlainIndentStyle, +}; use biome_console::{markup, Console, ConsoleExt}; use biome_deserialize::json::deserialize_from_json_str; -use biome_deserialize::StringSet; use biome_deserialize_macros::Deserializable; use biome_diagnostics::{DiagnosticExt, PrintDiagnostic}; use biome_formatter::{AttributePosition, LineEnding, LineWidth, QuoteStyle}; use biome_fs::{FileSystem, OpenOptions}; use biome_js_formatter::context::{ArrowParentheses, QuoteProperties, Semicolons, TrailingComma}; use biome_json_parser::JsonParserOptions; -use biome_service::configuration::{ - PartialFormatterConfiguration, PartialJavascriptConfiguration, PartialJavascriptFormatter, - PlainIndentStyle, -}; -use biome_service::{DynRef, PartialConfiguration}; -use indexmap::IndexSet; +use biome_service::DynRef; use std::path::{Path, PathBuf}; #[derive(Clone, Debug, Deserializable, Eq, PartialEq)] @@ -72,6 +70,7 @@ enum EndOfLine { Lf, Crlf, Cr, + Auto, } #[derive(Clone, Debug, Default, Deserializable, Eq, PartialEq)] @@ -134,6 +133,7 @@ impl From for LineEnding { EndOfLine::Lf => LineEnding::Lf, EndOfLine::Crlf => LineEnding::Crlf, EndOfLine::Cr => LineEnding::Cr, + EndOfLine::Auto => LineEnding::default(), } } } @@ -216,9 +216,6 @@ impl From for PartialJavascriptFormatter { pub(crate) struct FromPrettierConfiguration { /// Path of the Prettier configuration file configuration_path: Option, - /// Path of the `.prettierignore` file - #[allow(unused)] - ignore_path: Option, /// The translated Biome configuration, from the Prettier configuration formatter_configuration: Option, @@ -239,22 +236,10 @@ impl FromPrettierConfiguration { self.javascript_formatter_configuration = Some(javascript_formatter); } - pub(crate) fn store_ignored_globs(&mut self, value: StringSet) { - let formatter_configuration = self - .formatter_configuration - .get_or_insert(PartialFormatterConfiguration::default()); - - formatter_configuration.ignore = Some(value); - } - pub(crate) fn store_configuration_path(&mut self, path: impl Into) { self.configuration_path = Some(path.into()); } - pub(crate) fn store_ignore_path(&mut self, path: impl Into) { - self.ignore_path = Some(path.into()) - } - pub(crate) fn as_biome_configuration(&self) -> PartialConfiguration { let mut configuration = PartialConfiguration { formatter: self.formatter_configuration.clone(), @@ -274,17 +259,13 @@ impl FromPrettierConfiguration { self.formatter_configuration.is_some() || self.javascript_formatter_configuration.is_some() } - pub(crate) fn has_ignore_file(&self) -> bool { - self.ignore_path.is_some() - } - pub(crate) fn get_configuration_path(&self) -> Option<&Path> { self.configuration_path.as_deref() } } -const PRETTIER_CONFIG_FILES: [&str; 2] = [".prettierrc", ".prettierrc.json"]; -const PRETTIER_IGNORE_FILE: &str = ".prettierignore"; +const CONFIG_FILES: [&str; 2] = [".prettierrc", ".prettierrc.json"]; +pub(crate) const IGNORE_FILE: &str = ".prettierignore"; /// This function is in charge of reading prettier files, deserialize its contents and convert them in a Biome configuration type pub(crate) fn read_prettier_files( fs: &DynRef<'_, dyn FileSystem>, @@ -292,7 +273,7 @@ pub(crate) fn read_prettier_files( ) -> Result { let mut from_prettier_configuration = FromPrettierConfiguration::default(); let mut prettier_config_content = String::new(); - for config_name in PRETTIER_CONFIG_FILES { + for config_name in CONFIG_FILES { let open_options = OpenOptions::default().read(true); let path = Path::new(config_name); let file = fs.open_with_options(path, open_options); @@ -342,8 +323,12 @@ pub(crate) fn read_prettier_files( })); } else { let prettier_configuration = deserialized.into_deserialized(); - if let Some(prettier_configuration) = prettier_configuration { + if prettier_configuration.end_of_line == EndOfLine::Auto { + console.log(markup! { + "Prettier's `\"endOfLine\": \"auto\"` option is not supported in Biome. The default `\"lf\"` option is used instead." + }); + } let formatter_configuration = prettier_configuration .clone() .try_into() @@ -353,36 +338,11 @@ pub(crate) fn read_prettier_files( .store_configuration((formatter_configuration, javascript_configuration)); } } - - let mut ignore_file_content = String::new(); - let open_options = OpenOptions::default().read(true); - let path = Path::new(PRETTIER_IGNORE_FILE); - let file = fs.open_with_options(path, open_options); - if let Ok(mut file) = file { - let result = file.read_to_string(&mut ignore_file_content); - if let Err(err) = result { - return Err(CliDiagnostic::io_error(err)); - } - from_prettier_configuration.store_ignore_path(path) - } - - if !ignore_file_content.is_empty() { - let lines = StringSet::new( - ignore_file_content - .lines() - .filter(|line| !line.is_empty()) - .filter(|line| !line.starts_with('#')) - .map(String::from) - .collect::>(), - ); - from_prettier_configuration.store_ignored_globs(lines); - } - Ok(from_prettier_configuration) } #[cfg(test)] -mod test { +mod tests { use crate::execute::migrate::prettier::{PrettierConfiguration, PrettierTrailingComma}; use biome_deserialize::json::deserialize_from_json_str; use biome_json_parser::JsonParserOptions; diff --git a/crates/biome_cli/src/execute/mod.rs b/crates/biome_cli/src/execute/mod.rs index 16cccdeb67a0..acd298a18e52 100644 --- a/crates/biome_cli/src/execute/mod.rs +++ b/crates/biome_cli/src/execute/mod.rs @@ -5,12 +5,13 @@ mod std_in; mod traverse; use crate::cli_options::CliOptions; +use crate::commands::MigrateSubCommand; use crate::execute::migrate::MigratePayload; use crate::execute::traverse::traverse; use crate::{CliDiagnostic, CliSession}; use biome_diagnostics::{category, Category}; use biome_fs::BiomePath; -use biome_service::workspace::{FeatureName, FixFileMode}; +use biome_service::workspace::{FeatureName, FeaturesBuilder, FixFileMode}; use std::ffi::OsString; use std::fmt::{Display, Formatter}; use std::path::{Path, PathBuf}; @@ -28,10 +29,17 @@ pub(crate) struct Execution { } impl Execution { - pub(crate) fn as_feature_name(&self) -> FeatureName { + pub(crate) fn to_features(&self) -> Vec { match self.traversal_mode { - TraversalMode::Format { .. } => FeatureName::Format, - _ => FeatureName::Lint, + TraversalMode::Format { .. } => FeaturesBuilder::new().with_formatter().build(), + TraversalMode::Lint { .. } => FeaturesBuilder::new().with_linter().build(), + TraversalMode::Check { .. } | TraversalMode::CI { .. } => FeaturesBuilder::new() + .with_organize_imports() + .with_formatter() + .with_linter() + .build(), + TraversalMode::Migrate { .. } => vec![], + TraversalMode::Search { .. } => FeaturesBuilder::new().with_search().build(), } } } @@ -112,12 +120,23 @@ pub(crate) enum TraversalMode { Migrate { /// Write result to disk write: bool, - /// The path directory where `biome.json` is placed - configuration_file_path: PathBuf, /// The path to `biome.json` + configuration_file_path: PathBuf, + /// The path directory where `biome.json` is placed configuration_directory_path: PathBuf, - /// Migrate from prettier - prettier: bool, + sub_command: Option, + }, + /// This mode is enabled when running the command `biome search` + Search { + /// The GritQL pattern to search for. + /// + /// Note that the search command (currently) does not support rewrites. + pattern: String, + + /// An optional tuple. + /// 1. The virtual path to the file + /// 2. The content of the file + stdin: Option, }, } @@ -129,6 +148,7 @@ impl Display for TraversalMode { TraversalMode::Format { .. } => write!(f, "format"), TraversalMode::Migrate { .. } => write!(f, "migrate"), TraversalMode::Lint { .. } => write!(f, "lint"), + TraversalMode::Search { .. } => write!(f, "search"), } } } @@ -200,7 +220,8 @@ impl Execution { | TraversalMode::Lint { fix_file_mode, .. } => fix_file_mode.as_ref(), TraversalMode::Format { .. } | TraversalMode::CI { .. } - | TraversalMode::Migrate { .. } => None, + | TraversalMode::Migrate { .. } + | TraversalMode::Search { .. } => None, } } @@ -211,6 +232,7 @@ impl Execution { TraversalMode::CI { .. } => category!("ci"), TraversalMode::Format { .. } => category!("format"), TraversalMode::Migrate { .. } => category!("migrate"), + TraversalMode::Search { .. } => category!("search"), } } @@ -263,9 +285,8 @@ impl Execution { match self.traversal_mode { TraversalMode::Check { fix_file_mode, .. } | TraversalMode::Lint { fix_file_mode, .. } => fix_file_mode.is_some(), - TraversalMode::CI { .. } => false, - TraversalMode::Format { write, .. } => write, - TraversalMode::Migrate { write: dry_run, .. } => dry_run, + TraversalMode::CI { .. } | TraversalMode::Search { .. } => false, + TraversalMode::Format { write, .. } | TraversalMode::Migrate { write, .. } => write, } } @@ -273,7 +294,8 @@ impl Execution { match &self.traversal_mode { TraversalMode::Format { stdin, .. } | TraversalMode::Lint { stdin, .. } - | TraversalMode::Check { stdin, .. } => stdin.as_ref(), + | TraversalMode::Check { stdin, .. } + | TraversalMode::Search { stdin, .. } => stdin.as_ref(), TraversalMode::CI { .. } | TraversalMode::Migrate { .. } => None, } } @@ -303,7 +325,7 @@ pub(crate) fn execute_mode( write, configuration_file_path, configuration_directory_path, - prettier, + sub_command, } = mode.traversal_mode { let payload = MigratePayload { @@ -312,7 +334,7 @@ pub(crate) fn execute_mode( configuration_file_path, configuration_directory_path, verbose: cli_options.verbose, - prettier, + sub_command, }; migrate::run(payload) } else { diff --git a/crates/biome_cli/src/execute/process_file.rs b/crates/biome_cli/src/execute/process_file.rs index 3ca932c126fc..2f86270836e1 100644 --- a/crates/biome_cli/src/execute/process_file.rs +++ b/crates/biome_cli/src/execute/process_file.rs @@ -2,17 +2,19 @@ mod check; mod format; mod lint; mod organize_imports; +mod search; pub(crate) mod workspace_file; use crate::execute::diagnostics::{ResultExt, UnhandledDiagnostic}; -use crate::execute::process_file::check::check_file; -use crate::execute::process_file::format::format; -use crate::execute::process_file::lint::lint; use crate::execute::traverse::TraversalOptions; use crate::execute::TraversalMode; use biome_diagnostics::{category, DiagnosticExt, DiagnosticTags, Error}; use biome_fs::BiomePath; -use biome_service::workspace::{FeatureName, FeaturesBuilder, SupportKind, SupportsFeatureParams}; +use biome_service::workspace::{FeatureName, SupportKind, SupportsFeatureParams}; +use check::check_file; +use format::format; +use lint::lint; +use search::search; use std::marker::PhantomData; use std::ops::Deref; use std::path::Path; @@ -61,11 +63,8 @@ pub(crate) enum Message { } impl Message { - pub(crate) const fn is_error(&self) -> bool { - matches!( - self, - Message::Diff { .. } | Message::Diagnostics { .. } | Message::Failure - ) + pub(crate) const fn is_failure(&self) -> bool { + matches!(self, Message::Failure) } } @@ -132,11 +131,7 @@ pub(crate) fn process_file(ctx: &TraversalOptions, path: &Path) -> FileResult { .workspace .file_features(SupportsFeatureParams { path: biome_path, - feature: FeaturesBuilder::new() - .with_formatter() - .with_linter() - .with_organize_imports() - .build(), + features: ctx.execution.to_features(), }) .with_file_path_and_code_and_tags( path.display().to_string(), @@ -220,6 +215,7 @@ pub(crate) fn process_file(ctx: &TraversalOptions, path: &Path) -> FileResult { TraversalMode::Format { .. } => file_features.support_kind_for(&FeatureName::Format), TraversalMode::Lint { .. } => file_features.support_kind_for(&FeatureName::Lint), TraversalMode::Migrate { .. } => None, + TraversalMode::Search { .. } => file_features.support_kind_for(&FeatureName::Search), }; if let Some(reason) = unsupported_reason { @@ -256,6 +252,10 @@ pub(crate) fn process_file(ctx: &TraversalOptions, path: &Path) -> FileResult { TraversalMode::Migrate { .. } => { unreachable!("The migration should not be called for this file") } + TraversalMode::Search { ref pattern, .. } => { + // the unsupported case should be handled already at this point + search(shared_context, path, pattern) + } } }) } diff --git a/crates/biome_cli/src/execute/process_file/check.rs b/crates/biome_cli/src/execute/process_file/check.rs index 02567da8bff7..7978d987ccfb 100644 --- a/crates/biome_cli/src/execute/process_file/check.rs +++ b/crates/biome_cli/src/execute/process_file/check.rs @@ -11,7 +11,7 @@ pub(crate) fn check_file<'ctx>( path: &Path, file_features: &'ctx FileFeaturesResult, ) -> FileResult { - let mut has_errors = false; + let mut has_failures = false; let mut workspace_file = WorkspaceFile::new(ctx, path)?; let mut changed = false; tracing::info_span!("Process check", path =? workspace_file.path.display()).in_scope( @@ -24,15 +24,15 @@ pub(crate) fn check_file<'ctx>( changed = true } if let FileStatus::Message(msg) = status { - if msg.is_error() { - has_errors = true + if msg.is_failure() { + has_failures = true; } ctx.push_message(msg); } } Err(err) => { ctx.push_message(err); - has_errors = true; + has_failures = true; } } } @@ -44,15 +44,15 @@ pub(crate) fn check_file<'ctx>( changed = true } if let FileStatus::Message(msg) = status { - if msg.is_error() { - has_errors = true + if msg.is_failure() { + has_failures = true; } ctx.push_message(msg); } } Err(err) => { ctx.push_message(err); - has_errors = true; + has_failures = true; } } } @@ -65,20 +65,20 @@ pub(crate) fn check_file<'ctx>( changed = true } if let FileStatus::Message(msg) = status { - if msg.is_error() { - has_errors = true + if msg.is_failure() { + has_failures = true; } ctx.push_message(msg); } } Err(err) => { ctx.push_message(err); - has_errors = true; + has_failures = true; } } } - if has_errors { + if has_failures { Ok(FileStatus::Message(Message::Failure)) } else if changed { Ok(FileStatus::Changed) diff --git a/crates/biome_cli/src/execute/process_file/lint.rs b/crates/biome_cli/src/execute/process_file/lint.rs index a9aeed54b69f..7e6cd42b669e 100644 --- a/crates/biome_cli/src/execute/process_file/lint.rs +++ b/crates/biome_cli/src/execute/process_file/lint.rs @@ -19,7 +19,6 @@ pub(crate) fn lint_with_guard<'ctx>( ) -> FileResult { tracing::info_span!("Processes linting", path =? workspace_file.path.display()).in_scope( move || { - let mut errors = 0; let mut input = workspace_file.input()?; let mut changed = false; if let Some(fix_mode) = ctx.execution.as_fix_file_mode() { @@ -54,7 +53,6 @@ pub(crate) fn lint_with_guard<'ctx>( workspace_file.update_file(output)?; input = workspace_file.input()?; } - errors = fix_result.errors; } let max_diagnostics = ctx.remaining_diagnostics.load(Ordering::Relaxed); @@ -71,7 +69,6 @@ pub(crate) fn lint_with_guard<'ctx>( let no_diagnostics = pull_diagnostics_result.diagnostics.is_empty() && pull_diagnostics_result.skipped_diagnostics == 0; - errors += pull_diagnostics_result.errors; if !no_diagnostics { let input = match workspace_file.as_extension() { @@ -93,9 +90,7 @@ pub(crate) fn lint_with_guard<'ctx>( }); } - if errors > 0 { - Ok(FileStatus::Message(Message::Failure)) - } else if changed { + if changed { Ok(FileStatus::Changed) } else { Ok(FileStatus::Unchanged) diff --git a/crates/biome_cli/src/execute/process_file/search.rs b/crates/biome_cli/src/execute/process_file/search.rs new file mode 100644 index 000000000000..8969bf31adb2 --- /dev/null +++ b/crates/biome_cli/src/execute/process_file/search.rs @@ -0,0 +1,35 @@ +use crate::execute::diagnostics::ResultExt; +use crate::execute::process_file::workspace_file::WorkspaceFile; +use crate::execute::process_file::{FileResult, FileStatus, SharedTraversalOptions}; +use biome_diagnostics::category; +use std::path::Path; + +pub(crate) fn search<'ctx>( + ctx: &'ctx SharedTraversalOptions<'ctx, '_>, + path: &Path, + pattern: &str, +) -> FileResult { + let mut workspace_file = WorkspaceFile::new(ctx, path)?; + search_with_guard(ctx, &mut workspace_file, pattern) +} + +pub(crate) fn search_with_guard<'ctx>( + _ctx: &'ctx SharedTraversalOptions<'ctx, '_>, + workspace_file: &mut WorkspaceFile, + pattern: &str, +) -> FileResult { + tracing::info_span!("Processes searching", path =? workspace_file.path.display()).in_scope( + move || { + let _result = workspace_file + .guard() + .search_pattern(pattern) + .with_file_path_and_code( + workspace_file.path.display().to_string(), + category!("search"), + )?; + + // FIXME: We need to report some real results here... + Ok(FileStatus::Unchanged) + }, + ) +} diff --git a/crates/biome_cli/src/execute/std_in.rs b/crates/biome_cli/src/execute/std_in.rs index 84635a263d10..cde99cf3f624 100644 --- a/crates/biome_cli/src/execute/std_in.rs +++ b/crates/biome_cli/src/execute/std_in.rs @@ -28,7 +28,7 @@ pub(crate) fn run<'a>( if mode.is_format() { let file_features = workspace.file_features(SupportsFeatureParams { path: biome_path.clone(), - feature: FeaturesBuilder::new().with_formatter().build(), + features: FeaturesBuilder::new().with_formatter().build(), })?; if file_features.is_protected() { let protected_diagnostic = @@ -76,7 +76,7 @@ pub(crate) fn run<'a>( // apply fix file of the linter let file_features = workspace.file_features(SupportsFeatureParams { path: biome_path.clone(), - feature: FeaturesBuilder::new() + features: FeaturesBuilder::new() .with_linter() .with_organize_imports() .with_formatter() diff --git a/crates/biome_cli/src/execute/traverse.rs b/crates/biome_cli/src/execute/traverse.rs index 002207d08641..507f77351661 100644 --- a/crates/biome_cli/src/execute/traverse.rs +++ b/crates/biome_cli/src/execute/traverse.rs @@ -13,7 +13,7 @@ use biome_diagnostics::PrintGitHubDiagnostic; use biome_diagnostics::{category, DiagnosticExt, Error, PrintDiagnostic, Resource, Severity}; use biome_fs::{BiomePath, FileSystem, PathInterner}; use biome_fs::{TraversalContext, TraversalScope}; -use biome_service::workspace::{FeaturesBuilder, IsPathIgnoredParams}; +use biome_service::workspace::IsPathIgnoredParams; use biome_service::{extension_error, workspace::SupportsFeatureParams, Workspace, WorkspaceError}; use crossbeam::channel::{unbounded, Receiver, Sender}; use rustc_hash::FxHashSet; @@ -103,6 +103,10 @@ impl<'a> fmt::Display for SummaryTotal<'a> { }) } } + + TraversalMode::Search { .. } => fmt.write_markup(markup! { + "Searched "{files}" in "{self.2} + }), } } } @@ -518,9 +522,9 @@ impl<'ctx> DiagnosticsPrinter<'ctx> { new, diff_kind, } => { - let is_error = self.execution.is_ci() || !self.execution.is_format_write(); // A diff is an error in CI mode and in format check mode - if self.execution.is_ci() || !self.execution.is_format_write() { + let is_error = self.execution.is_ci() || !self.execution.is_format_write(); + if is_error { self.errors.fetch_add(1, Ordering::Relaxed); } @@ -548,7 +552,7 @@ impl<'ctx> DiagnosticsPrinter<'ctx> { new: new.clone(), }, }; - diagnostics_to_print.push(Error::from(diag)) + diagnostics_to_print.push(diag.with_severity(severity)); } DiffKind::OrganizeImports => { let diag = CIOrganizeImportsDiffDiagnostic { @@ -558,7 +562,7 @@ impl<'ctx> DiagnosticsPrinter<'ctx> { new: new.clone(), }, }; - diagnostics_to_print.push(Error::from(diag)) + diagnostics_to_print.push(diag.with_severity(severity)) } }; } else { @@ -571,7 +575,7 @@ impl<'ctx> DiagnosticsPrinter<'ctx> { new: new.clone(), }, }; - diagnostics_to_print.push(Error::from(diag)) + diagnostics_to_print.push(diag.with_severity(severity)) } DiffKind::OrganizeImports => { let diag = OrganizeImportsDiffDiagnostic { @@ -581,7 +585,7 @@ impl<'ctx> DiagnosticsPrinter<'ctx> { new: new.clone(), }, }; - diagnostics_to_print.push(Error::from(diag)) + diagnostics_to_print.push(diag.with_severity(severity)) } }; } @@ -702,7 +706,7 @@ impl<'ctx, 'app> TraversalContext for TraversalOptions<'ctx, 'app> { .workspace .is_path_ignored(IsPathIgnoredParams { biome_path: biome_path.clone(), - feature: self.execution.as_feature_name(), + features: self.execution.to_features(), }) .unwrap_or_else(|err| { self.push_diagnostic(err.into()); @@ -713,11 +717,7 @@ impl<'ctx, 'app> TraversalContext for TraversalOptions<'ctx, 'app> { let file_features = self.workspace.file_features(SupportsFeatureParams { path: biome_path.clone(), - feature: FeaturesBuilder::new() - .with_linter() - .with_formatter() - .with_organize_imports() - .build(), + features: self.execution.to_features(), }); let file_features = match file_features { @@ -750,6 +750,7 @@ impl<'ctx, 'app> TraversalContext for TraversalOptions<'ctx, 'app> { TraversalMode::Lint { .. } => file_features.supports_lint(), // Imagine if Biome can't handle its own configuration file... TraversalMode::Migrate { .. } => true, + TraversalMode::Search { .. } => false, } } diff --git a/crates/biome_cli/src/lib.rs b/crates/biome_cli/src/lib.rs index f73e4c0aa2dc..6b3645919010 100644 --- a/crates/biome_cli/src/lib.rs +++ b/crates/biome_cli/src/lib.rs @@ -9,6 +9,7 @@ use biome_console::{ColorMode, Console}; use biome_fs::OsFileSystem; use biome_service::{App, DynRef, Workspace, WorkspaceRef}; +use commands::search::SearchCommandPayload; use std::env; mod changed; @@ -193,13 +194,24 @@ impl<'app> CliSession<'app> { cli_options, write, sub_command, - } => commands::migrate::migrate( - self, + } => commands::migrate::migrate(self, cli_options, write, sub_command), + BiomeCommand::Search { cli_options, - write, - sub_command - .map(|sub_command| sub_command.is_prettier()) - .unwrap_or_default(), + files_configuration, + paths, + pattern, + stdin_file_path, + vcs_configuration, + } => commands::search::search( + self, + SearchCommandPayload { + cli_options, + files_configuration, + paths, + pattern, + stdin_file_path, + vcs_configuration, + }, ), BiomeCommand::RunServer { stop_on_disconnect, diff --git a/crates/biome_cli/src/logging.rs b/crates/biome_cli/src/logging.rs index c75a859e686d..2a9d2faeadc9 100644 --- a/crates/biome_cli/src/logging.rs +++ b/crates/biome_cli/src/logging.rs @@ -40,7 +40,7 @@ pub fn setup_cli_subscriber(level: LoggingLevel, kind: LoggingKind) { }; } -#[derive(Debug, Default, Clone, Ord, PartialOrd, Eq, PartialEq)] +#[derive(Copy, Debug, Default, Clone, Ord, PartialOrd, Eq, PartialEq)] pub enum LoggingLevel { /// No logs should be shown #[default] @@ -52,7 +52,7 @@ pub enum LoggingLevel { } impl LoggingLevel { - fn to_filter_level(&self) -> Option { + fn to_filter_level(self) -> Option { match self { LoggingLevel::None => None, LoggingLevel::Info => Some(LevelFilter::INFO), @@ -138,7 +138,7 @@ impl Filter for LoggingFilter { } /// The kind of logging -#[derive(Debug, Default, Clone, Eq, PartialEq)] +#[derive(Copy, Debug, Default, Clone, Eq, PartialEq)] pub enum LoggingKind { /// A pretty log on multiple lines with nice colours #[default] diff --git a/crates/biome_cli/tests/cases/config_path.rs b/crates/biome_cli/tests/cases/config_path.rs new file mode 100644 index 000000000000..f1dacea075fc --- /dev/null +++ b/crates/biome_cli/tests/cases/config_path.rs @@ -0,0 +1,55 @@ +use crate::run_cli; +use crate::snap_test::{assert_cli_snapshot, SnapshotPayload}; +use biome_console::BufferConsole; +use biome_fs::MemoryFileSystem; +use biome_service::DynRef; +use bpaf::Args; +use std::path::Path; + +#[test] +fn set_config_path() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let file_path = Path::new("src/index.js"); + fs.insert(file_path.into(), "a['b'] = 42;".as_bytes()); + + let config_path = Path::new("config/biome.jsonc"); + fs.insert( + config_path.into(), + r#" + { + "organizeImports": { + "enabled": true + }, + "linter": { + "enabled": false + }, + "formatter": { + "enabled": true, + }, + "javascript": { + "formatter": { + "quoteStyle": "single" + } + } + }"# + .as_bytes(), + ); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("check"), ("--config-path=config"), ("src")].as_slice()), + ); + + assert!(result.is_err(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "set_config_path", + fs, + console, + result, + )); +} diff --git a/crates/biome_cli/tests/cases/cts_files.rs b/crates/biome_cli/tests/cases/cts_files.rs new file mode 100644 index 000000000000..0dd3a86318b4 --- /dev/null +++ b/crates/biome_cli/tests/cases/cts_files.rs @@ -0,0 +1,35 @@ +use crate::run_cli; +use crate::snap_test::{assert_cli_snapshot, SnapshotPayload}; +use biome_console::BufferConsole; +use biome_fs::MemoryFileSystem; +use biome_service::DynRef; +use bpaf::Args; +use std::path::Path; + +#[test] +fn should_allow_using_export_statements() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let file_path = Path::new("a.cts"); + fs.insert( + file_path.into(), + r#"export default { cjs: true };"#.as_bytes(), + ); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("lint"), file_path.as_os_str().to_str().unwrap()].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "should_allow_using_export_statements", + fs, + console, + result, + )); +} diff --git a/crates/biome_cli/tests/cases/diagnostics.rs b/crates/biome_cli/tests/cases/diagnostics.rs index 785916bb5cf2..5ce129a887ec 100644 --- a/crates/biome_cli/tests/cases/diagnostics.rs +++ b/crates/biome_cli/tests/cases/diagnostics.rs @@ -137,3 +137,60 @@ fn max_diagnostics_verbose() { result, )); } + +#[test] +fn diagnostic_level() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let file_path = Path::new("biome.json"); + fs.insert( + file_path.into(), + r#"{ + "formatter": { + "enabled": true + }, + "organizeImports": { + "enabled": true + }, + "linter": { + "enabled": false + } +} +"#, + ); + + let file_path = PathBuf::from("src/index.js".to_string()); + fs.insert( + file_path, + r#"import { graphql, useFragment, useMutation } from "react-relay"; +import { FC, memo, useCallback } from "react"; +"#, + ); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("check"), ("--diagnostic-level=error"), ("src")].as_slice()), + ); + + assert!(result.is_err(), "run_cli returned {result:?}"); + + let messages = &console.out_buffer; + + assert!(messages + .iter() + .filter(|m| m.level == LogLevel::Error) + .any(|m| { + let content = format!("{:?}", m.content); + content.contains("organizeImports") + })); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "diagnostic_level", + fs, + console, + result, + )); +} diff --git a/crates/biome_cli/tests/cases/handle_astro_files.rs b/crates/biome_cli/tests/cases/handle_astro_files.rs index ba0e3d0f3700..dc88e47ad0fb 100644 --- a/crates/biome_cli/tests/cases/handle_astro_files.rs +++ b/crates/biome_cli/tests/cases/handle_astro_files.rs @@ -36,6 +36,15 @@ import { Code } from "astro:components"; ---
"#; +const ASTRO_RETURN: &str = r#"--- +const foo = true; +if (foo) { + return "Something"; +} + +--- +
"#; + const ASTRO_FILE_IMPORTS_AFTER: &str = r#"--- import { Code } from "astro:components"; import { getLocale } from "astro:i18n"; @@ -272,3 +281,28 @@ fn sorts_imports_write() { result, )); } + +#[test] +fn does_not_throw_parse_error_for_return() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let astro_file_path = Path::new("file.astro"); + fs.insert(astro_file_path.into(), ASTRO_RETURN.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("lint"), astro_file_path.as_os_str().to_str().unwrap()].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "does_not_throw_parse_error_for_return", + fs, + console, + result, + )); +} diff --git a/crates/biome_cli/tests/cases/mod.rs b/crates/biome_cli/tests/cases/mod.rs index f886c354ac51..0c086ce1cc3f 100644 --- a/crates/biome_cli/tests/cases/mod.rs +++ b/crates/biome_cli/tests/cases/mod.rs @@ -3,6 +3,8 @@ mod biome_json_support; mod config_extends; +mod config_path; +mod cts_files; mod diagnostics; mod handle_astro_files; mod handle_svelte_files; diff --git a/crates/biome_cli/tests/commands/check.rs b/crates/biome_cli/tests/commands/check.rs index 9c0a2cd0911c..bad4a4d101fc 100644 --- a/crates/biome_cli/tests/commands/check.rs +++ b/crates/biome_cli/tests/commands/check.rs @@ -191,7 +191,6 @@ fn maximum_diagnostics() { .filter(|m| m.level == LogLevel::Log) .any(|m| { let content = format!("{:?}", m.content); - dbg!(&content); content.contains("The number of diagnostics exceeds the number allowed by Biome") && content.contains("Diagnostics not shown") && content.contains("77") @@ -2797,3 +2796,52 @@ fn use_literal_keys_should_emit_correct_ast_issue_266() { result, )); } + +#[test] +fn should_show_formatter_diagnostics_for_files_ignored_by_linter() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let file_path = Path::new("build/file.js"); + fs.insert( + file_path.into(), + r#" + value['optimizelyService'] = optimizelyService; + "#, + ); + + let biome_json = Path::new("biome.json"); + fs.insert( + biome_json.into(), + r#"{ + "$schema": "https://biomejs.dev/schemas/1.6.1/schema.json", + "organizeImports": { + "enabled": true + }, + "linter": { + "ignore": ["build/**"], + "enabled": true, + "rules": { + "recommended": true + } + } +} + "#, + ); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("check"), file_path.as_os_str().to_str().unwrap()].as_slice()), + ); + + assert!(result.is_err(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "should_show_formatter_diagnostics_for_files_ignored_by_linter", + fs, + console, + result, + )); +} diff --git a/crates/biome_cli/tests/commands/format.rs b/crates/biome_cli/tests/commands/format.rs index 62a7720ce412..abdc79ba6ed0 100644 --- a/crates/biome_cli/tests/commands/format.rs +++ b/crates/biome_cli/tests/commands/format.rs @@ -3461,3 +3461,59 @@ fn format_empty_svelte_ts_files_write() { result, )); } + +#[test] +fn should_format_files_in_folders_ignored_by_linter() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let file_path = Path::new("build/file.js"); + fs.insert( + file_path.into(), + r#" + value['optimizelyService'] = optimizelyService; + "#, + ); + + let biome_json = Path::new("biome.json"); + fs.insert( + biome_json.into(), + r#"{ + "$schema": "https://biomejs.dev/schemas/1.6.1/schema.json", + "organizeImports": { + "enabled": true + }, + "linter": { + "ignore": ["**/build"], + "enabled": true, + "rules": { + "recommended": true + } + } +} + "#, + ); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from( + [ + ("format"), + "--write", + file_path.as_os_str().to_str().unwrap(), + ] + .as_slice(), + ), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "should_format_files_in_folders_ignored_by_linter", + fs, + console, + result, + )); +} diff --git a/crates/biome_cli/tests/commands/lint.rs b/crates/biome_cli/tests/commands/lint.rs index 4a4be8009a6a..24de22f186c2 100644 --- a/crates/biome_cli/tests/commands/lint.rs +++ b/crates/biome_cli/tests/commands/lint.rs @@ -1918,6 +1918,52 @@ fn top_level_all_down_level_empty() { )); } +#[test] +fn group_level_disable_recommended_enable_specific() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + // useButtonType should be enabled. + let biome_json = r#"{ + "linter": { + "rules": { + "a11y": { + "recommended": false, + "useButtonType": "error" + } + } + } + }"#; + + let code = r#" + function SubmitButton() { + return ; + } + "#; + + let file_path = Path::new("fix.jsx"); + fs.insert(file_path.into(), code.as_bytes()); + + let config_path = Path::new("biome.json"); + fs.insert(config_path.into(), biome_json.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("lint"), file_path.as_os_str().to_str().unwrap()].as_slice()), + ); + + assert!(result.is_err(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "group_level_disable_recommended_enable_specific", + fs, + console, + result, + )); +} + #[test] fn ignore_configured_globals() { let mut fs = MemoryFileSystem::default(); diff --git a/crates/biome_cli/tests/commands/migrate.rs b/crates/biome_cli/tests/commands/migrate.rs index 8565d2e9c28e..46e0bd75bcc9 100644 --- a/crates/biome_cli/tests/commands/migrate.rs +++ b/crates/biome_cli/tests/commands/migrate.rs @@ -132,269 +132,3 @@ fn should_create_biome_json_file() { result, )); } - -#[test] -fn prettier_migrate() { - let mut fs = MemoryFileSystem::default(); - let mut console = BufferConsole::default(); - - let configuration = r#"{ "linter": { "enabled": true } }"#; - let prettier = r#"{ "useTabs": false, "semi": true, "singleQuote": true }"#; - - let configuration_path = Path::new("biome.json"); - fs.insert(configuration_path.into(), configuration.as_bytes()); - - let prettier_path = Path::new(".prettierrc"); - fs.insert(prettier_path.into(), prettier.as_bytes()); - - let result = run_cli( - DynRef::Borrowed(&mut fs), - &mut console, - Args::from([("migrate"), "prettier"].as_slice()), - ); - - assert!(result.is_ok(), "run_cli returned {result:?}"); - - assert_cli_snapshot(SnapshotPayload::new( - module_path!(), - "prettier_migrate", - fs, - console, - result, - )); -} - -#[test] -fn prettier_migrate_with_ignore() { - let mut fs = MemoryFileSystem::default(); - let mut console = BufferConsole::default(); - - let configuration = r#"{ "linter": { "enabled": true } }"#; - let prettier = r#"{ "useTabs": false, "semi": true, "singleQuote": true }"#; - let prettier_ignore = r#" -dist/** - -node_modules/** - -# I am a comment -generated/*.spec.js -"#; - - let configuration_path = Path::new("biome.json"); - fs.insert(configuration_path.into(), configuration.as_bytes()); - - let prettier_path = Path::new(".prettierrc"); - fs.insert(prettier_path.into(), prettier.as_bytes()); - - let prettier_ignore_path = Path::new(".prettierignore"); - fs.insert(prettier_ignore_path.into(), prettier_ignore.as_bytes()); - - let result = run_cli( - DynRef::Borrowed(&mut fs), - &mut console, - Args::from([("migrate"), "prettier"].as_slice()), - ); - - assert!(result.is_ok(), "run_cli returned {result:?}"); - - assert_cli_snapshot(SnapshotPayload::new( - module_path!(), - "prettier_migrate_with_ignore", - fs, - console, - result, - )); -} - -#[test] -fn prettier_migrate_jsonc() { - let mut fs = MemoryFileSystem::default(); - let mut console = BufferConsole::default(); - - let configuration = r#"{ "linter": { "enabled": true } }"#; - let prettier = r#"{ "useTabs": false, "semi": true, "singleQuote": true }"#; - - let configuration_path = Path::new("biome.jsonc"); - fs.insert(configuration_path.into(), configuration.as_bytes()); - - let prettier_path = Path::new(".prettierrc"); - fs.insert(prettier_path.into(), prettier.as_bytes()); - - let result = run_cli( - DynRef::Borrowed(&mut fs), - &mut console, - Args::from([("migrate"), "prettier"].as_slice()), - ); - - assert!(result.is_ok(), "run_cli returned {result:?}"); - - assert_cli_snapshot(SnapshotPayload::new( - module_path!(), - "prettier_migrate_jsonc", - fs, - console, - result, - )); -} - -#[test] -fn prettier_migrate_no_file() { - let mut fs = MemoryFileSystem::default(); - let mut console = BufferConsole::default(); - - let configuration = r#"{ "linter": { "enabled": true } }"#; - - let configuration_path = Path::new("biome.json"); - fs.insert(configuration_path.into(), configuration.as_bytes()); - - let result = run_cli( - DynRef::Borrowed(&mut fs), - &mut console, - Args::from([("migrate"), "prettier"].as_slice()), - ); - - assert!(result.is_err(), "run_cli returned {result:?}"); - - assert_cli_snapshot(SnapshotPayload::new( - module_path!(), - "prettier_migrate_no_file", - fs, - console, - result, - )); -} - -#[test] -fn prettier_migrate_yml_file() { - let mut fs = MemoryFileSystem::default(); - let mut console = BufferConsole::default(); - - let configuration = r#"{ "linter": { "enabled": true } }"#; - let prettier = r#"useTabs: true"#; - - let configuration_path = Path::new("biome.json"); - fs.insert(configuration_path.into(), configuration.as_bytes()); - - let prettier_path = Path::new(".prettierrc"); - fs.insert(prettier_path.into(), prettier.as_bytes()); - - let result = run_cli( - DynRef::Borrowed(&mut fs), - &mut console, - Args::from([("migrate"), "prettier"].as_slice()), - ); - - assert!(result.is_err(), "run_cli returned {result:?}"); - - assert_cli_snapshot(SnapshotPayload::new( - module_path!(), - "prettier_migrate_yml_file", - fs, - console, - result, - )); -} - -#[test] -fn prettier_migrate_write() { - let mut fs = MemoryFileSystem::default(); - let mut console = BufferConsole::default(); - - let configuration = r#"{ "linter": { "enabled": true } }"#; - let prettier = r#"{ "useTabs": false, "semi": true, "singleQuote": true }"#; - - let configuration_path = Path::new("biome.json"); - fs.insert(configuration_path.into(), configuration.as_bytes()); - - let prettier_path = Path::new(".prettierrc"); - fs.insert(prettier_path.into(), prettier.as_bytes()); - - let result = run_cli( - DynRef::Borrowed(&mut fs), - &mut console, - Args::from([("migrate"), "prettier", "--write"].as_slice()), - ); - - assert!(result.is_ok(), "run_cli returned {result:?}"); - - assert_cli_snapshot(SnapshotPayload::new( - module_path!(), - "prettier_migrate_write", - fs, - console, - result, - )); -} - -#[test] -fn prettier_migrate_write_with_ignore_file() { - let mut fs = MemoryFileSystem::default(); - let mut console = BufferConsole::default(); - - let configuration = r#"{ "linter": { "enabled": true } }"#; - let prettier = r#"{ "useTabs": false, "semi": true, "singleQuote": true }"#; - let prettier_ignore = r#" -dist/** - -node_modules/** - -# I am a comment -generated/*.spec.js -"#; - - let configuration_path = Path::new("biome.json"); - fs.insert(configuration_path.into(), configuration.as_bytes()); - - let prettier_path = Path::new(".prettierrc"); - fs.insert(prettier_path.into(), prettier.as_bytes()); - - let prettier_ignore_path = Path::new(".prettierignore"); - fs.insert(prettier_ignore_path.into(), prettier_ignore.as_bytes()); - - let result = run_cli( - DynRef::Borrowed(&mut fs), - &mut console, - Args::from([("migrate"), "prettier", "--write"].as_slice()), - ); - - assert!(result.is_ok(), "run_cli returned {result:?}"); - - assert_cli_snapshot(SnapshotPayload::new( - module_path!(), - "prettier_migrate_write_with_ignore_file", - fs, - console, - result, - )); -} - -#[test] -fn prettier_migrate_write_biome_jsonc() { - let mut fs = MemoryFileSystem::default(); - let mut console = BufferConsole::default(); - - let configuration = r#"{ "linter": { "enabled": true } }"#; - let prettier = r#"{ "useTabs": false, "semi": true, "singleQuote": true }"#; - - let configuration_path = Path::new("biome.jsonc"); - fs.insert(configuration_path.into(), configuration.as_bytes()); - - let prettier_path = Path::new(".prettierrc"); - fs.insert(prettier_path.into(), prettier.as_bytes()); - - let result = run_cli( - DynRef::Borrowed(&mut fs), - &mut console, - Args::from([("migrate"), "prettier", "--write"].as_slice()), - ); - - assert!(result.is_ok(), "run_cli returned {result:?}"); - - assert_cli_snapshot(SnapshotPayload::new( - module_path!(), - "prettier_migrate_write_biome_jsonc", - fs, - console, - result, - )); -} diff --git a/crates/biome_cli/tests/commands/migrate_eslint.rs b/crates/biome_cli/tests/commands/migrate_eslint.rs new file mode 100644 index 000000000000..bd3da6c9171f --- /dev/null +++ b/crates/biome_cli/tests/commands/migrate_eslint.rs @@ -0,0 +1,509 @@ +use crate::run_cli; +use crate::snap_test::{assert_cli_snapshot, SnapshotPayload}; +use biome_console::BufferConsole; +use biome_fs::MemoryFileSystem; +use biome_service::DynRef; +use bpaf::Args; +use std::path::Path; + +#[test] +fn migrate_eslintrcjson() { + let biomejson = r#"{ "linter": { "enabled": true } }"#; + let eslintrc = r#"{ + "ignorePatterns": [ + "**/*.test.js", // trailing comma amd comment + ], + "globals": { + "var1": "writable", + "var2": "readonly" + }, + "rules": { + "dot-notation": 0, + "default-param-last": "off", + "eqeqeq": "warn", + "getter-return": [2, + // support unknown options + { "allowImplicit": true } + ], + "no-eval": 1, + "no-extra-label": ["error"] + }, + "overrides": [{ + "files": ["bin/*.js", "lib/*.js"], + "excludedFiles": "*.test.js", + "rules": { + "eqeqeq": ["off"] + } + }], + "unknownField": "ignored" + }"#; + + let mut fs = MemoryFileSystem::default(); + fs.insert(Path::new("biome.json").into(), biomejson.as_bytes()); + fs.insert(Path::new(".eslintrc.json").into(), eslintrc.as_bytes()); + + let mut console = BufferConsole::default(); + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from(["migrate", "eslint"].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "migrate_eslintrcjson", + fs, + console, + result, + )); +} + +#[test] +fn migrate_eslintrcjson_write() { + let biomejson = r#"{ "linter": { "enabled": true } }"#; + let eslintrc = r#"{ + "ignorePatterns": [ + "**/*.test.js", // trailing comma amd comment + ], + "globals": { + "var1": "writable", + "var2": "readonly" + }, + "rules": { + "dot-notation": 0, + "default-param-last": "off", + "eqeqeq": "warn", + "getter-return": [2, + // support unknown options + { "allowImplicit": true } + ], + "no-eval": 1, + "no-extra-label": ["error"] + }, + "overrides": [{ + "files": ["bin/*.js", "lib/*.js"], + "excludedFiles": "*.test.js", + "rules": { + "eqeqeq": ["off"] + } + }], + "unknownField": "ignored" + }"#; + + let mut fs = MemoryFileSystem::default(); + fs.insert(Path::new("biome.json").into(), biomejson.as_bytes()); + fs.insert(Path::new(".eslintrc.json").into(), eslintrc.as_bytes()); + + let mut console = BufferConsole::default(); + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from(["migrate", "eslint", "--write"].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "migrate_eslintrcjson_write", + fs, + console, + result, + )); +} + +#[test] +fn migrate_eslintrcjson_override_existing_config() { + let biomejson = r#"{ "linter": { "rules": { "recommended": true, "suspicious": { "noDoubleEquals": "error" } } } }"#; + let eslintrc = r#"{ "rules": { "eqeqeq": "off" } }"#; + + let mut fs = MemoryFileSystem::default(); + fs.insert(Path::new("biome.json").into(), biomejson.as_bytes()); + fs.insert(Path::new(".eslintrc.json").into(), eslintrc.as_bytes()); + + let mut console = BufferConsole::default(); + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from(["migrate", "eslint"].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "migrate_eslintrcjson_override_existing_config", + fs, + console, + result, + )); +} + +#[test] +fn migrate_eslintrcjson_exclude_inspired() { + let biomejson = r#"{}"#; + let eslintrc = r#"{ "rules": { "no-else-return": "error" } }"#; + + let mut fs = MemoryFileSystem::default(); + fs.insert(Path::new("biome.json").into(), biomejson.as_bytes()); + fs.insert(Path::new(".eslintrc.json").into(), eslintrc.as_bytes()); + + let mut console = BufferConsole::default(); + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from(["migrate", "eslint"].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "migrate_eslintrcjson_exclude_inspired", + fs, + console, + result, + )); +} + +#[test] +fn migrate_eslintrcjson_include_inspired() { + let biomejson = r#"{}"#; + let eslintrc = r#"{ "rules": { "no-else-return": "error" } }"#; + + let mut fs = MemoryFileSystem::default(); + fs.insert(Path::new("biome.json").into(), biomejson.as_bytes()); + fs.insert(Path::new(".eslintrc.json").into(), eslintrc.as_bytes()); + + let mut console = BufferConsole::default(); + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from(["migrate", "eslint", "--include-inspired"].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "migrate_eslintrcjson_include_inspired", + fs, + console, + result, + )); +} + +#[test] +fn migrate_eslintrcjson_rule_options() { + let biomejson = r#"{ "linter": { "enabled": true } }"#; + let eslintrc = r#"{ + "rules": { + "no-restricted-globals": ["error", "event", "fdescribe"], + "jsx-a11y/aria-role": ["error", { + "allowedInvalidRoles": ["text"], + "ignoreNonDOM": true + }], + "@typescript-eslint/array-type": ["error", { "default": "generic" }], + "@typescript-eslint/naming-convention": ["error", + { + "selector": "enumMember", + "format": ["UPPER_CASE"] + } + ], + "unicorn/filename-case": ["error", { + "cases": { + "camelCase": true, + "pascalCase": true + } + }] + }, + "overrides": [{ + "files": ["default.js"], + "rules": { + "no-restricted-globals": "error", + "jsx-a11y/aria-role": "error", + "@typescript-eslint/array-type": "error", + "@typescript-eslint/naming-convention": "error", + "unicorn/filename-case": "error" + } + }, { + "files": ["alternative.js"], + "rules": { + "no-restricted-globals": ["error", + { + "name": "event", + "message": "Use local parameter instead." + }, + { + "name": "fdescribe", + "message": "Do not commit fdescribe. Use describe instead." + } + ], + "@typescript-eslint/array-type": ["error", { "default": "array" }], + "@typescript-eslint/naming-convention": ["error", + { + "selector": "default", + "format": ["UPPER_CASE"] + } + ], + "unicorn/filename-case": ["error", { + "case": "kebabCase", + "multipleFileExtensions": true + }] + } + }], + }"#; + + let mut fs = MemoryFileSystem::default(); + fs.insert(Path::new("biome.json").into(), biomejson.as_bytes()); + fs.insert(Path::new(".eslintrc.json").into(), eslintrc.as_bytes()); + + let mut console = BufferConsole::default(); + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from(["migrate", "eslint", "--include-inspired"].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "migrate_eslintrcjson_rule_options", + fs, + console, + result, + )); +} + +#[test] +fn migrate_eslintrcjson_empty() { + let biomejson = r#"{ "linter": { "enabled": true } } +"#; + let eslintrc = r#"{}"#; + + let mut fs = MemoryFileSystem::default(); + fs.insert(Path::new("biome.json").into(), biomejson.as_bytes()); + fs.insert(Path::new(".eslintrc.json").into(), eslintrc.as_bytes()); + + let mut console = BufferConsole::default(); + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from(["migrate", "eslint"].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "migrate_eslintrcjson_empty", + fs, + console, + result, + )); +} + +#[test] +fn migrate_eslintrcjson_missing_biomejson() { + let eslintrc = r#"{}"#; + + let mut fs = MemoryFileSystem::default(); + fs.insert(Path::new(".eslintrc.json").into(), eslintrc.as_bytes()); + + let mut console = BufferConsole::default(); + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from(["migrate", "eslint"].as_slice()), + ); + + assert!(result.is_err(), "run_cli returned {result:?}"); + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "migrate_eslintrcjson_missing_biomejson", + fs, + console, + result, + )); +} + +#[test] +fn migrate_eslintrcyaml_unsupported() { + let biomejson = r#"{}"#; + let eslintrc = ""; + + let mut fs = MemoryFileSystem::default(); + fs.insert(Path::new("biome.json").into(), biomejson.as_bytes()); + fs.insert(Path::new(".eslintrc.yaml").into(), eslintrc.as_bytes()); + + let mut console = BufferConsole::default(); + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from(["migrate", "eslint"].as_slice()), + ); + + assert!(result.is_err(), "run_cli returned {result:?}"); + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "migrate_eslintrcyaml_unsupported", + fs, + console, + result, + )); +} + +#[test] +fn migrate_eslint_config_packagejson() { + let biomejson = r#"{ "linter": { "enabled": true } }"#; + let packagejson = r#"{ + "name": "foo", + "version": "0.0.0", + "eslintConfig": { + "rules": { + "eqeqeq": "warn" + } + } + }"#; + + let mut fs = MemoryFileSystem::default(); + fs.insert(Path::new("biome.json").into(), biomejson.as_bytes()); + fs.insert(Path::new("package.json").into(), packagejson.as_bytes()); + + let mut console = BufferConsole::default(); + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from(["migrate", "eslint"].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "migrate_eslint_config_packagejson", + fs, + console, + result, + )); +} + +#[test] +fn migrate_no_eslint_config_packagejson() { + let biomejson = r#"{ "linter": { "enabled": true } }"#; + let packagejson = r#"{ + "name": "foo", + "version": "0.0.0" + }"#; + + let mut fs = MemoryFileSystem::default(); + fs.insert(Path::new("biome.json").into(), biomejson.as_bytes()); + fs.insert(Path::new("package.json").into(), packagejson.as_bytes()); + + let mut console = BufferConsole::default(); + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from(["migrate", "eslint"].as_slice()), + ); + + assert!(result.is_err(), "run_cli returned {result:?}"); + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "migrate_no_eslint_config_packagejson", + fs, + console, + result, + )); +} + +#[test] +fn migrate_eslintignore() { + let biomejson = r#"{ "linter": { "enabled": true } }"#; + let eslintrc = r#"{ "rules": { "eqeqeq": "off" } }"#; + let eslintignore = r#" +# Comment +/src +*.test.js +**/*.spec.js +test/main.js +"#; + + let mut fs = MemoryFileSystem::default(); + fs.insert(Path::new("biome.json").into(), biomejson.as_bytes()); + fs.insert(Path::new(".eslintrc.json").into(), eslintrc.as_bytes()); + fs.insert(Path::new(".eslintignore").into(), eslintignore.as_bytes()); + + let mut console = BufferConsole::default(); + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from(["migrate", "eslint"].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "migrate_eslintignore", + fs, + console, + result, + )); +} + +#[test] +fn migrate_eslintignore_and_ignore_patterns() { + let biomejson = r#"{ "linter": { "enabled": true } }"#; + let eslintrc = r#"{ + "ignorePatterns": ["**/*.spec.js"], + "rules": { "eqeqeq": "off" } + }"#; + let eslintignore = r#"*.test.js"#; + + let mut fs = MemoryFileSystem::default(); + fs.insert(Path::new("biome.json").into(), biomejson.as_bytes()); + fs.insert(Path::new(".eslintrc.json").into(), eslintrc.as_bytes()); + fs.insert(Path::new(".eslintignore").into(), eslintignore.as_bytes()); + + let mut console = BufferConsole::default(); + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from(["migrate", "eslint"].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "migrate_eslintignore_and_ignore_patterns", + fs, + console, + result, + )); +} + +#[test] +fn migrate_eslintignore_negated_patterns() { + let biomejson = r#"{ "linter": { "enabled": true } }"#; + let eslintrc = r#"{ "rules": { "eqeqeq": "off" } }"#; + let eslintignore = r#" +a/** +!a/b +"#; + + let mut fs = MemoryFileSystem::default(); + fs.insert(Path::new("biome.json").into(), biomejson.as_bytes()); + fs.insert(Path::new(".eslintrc.json").into(), eslintrc.as_bytes()); + fs.insert(Path::new(".eslintignore").into(), eslintignore.as_bytes()); + + let mut console = BufferConsole::default(); + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from(["migrate", "eslint"].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "migrate_eslintignore_negated_patterns", + fs, + console, + result, + )); +} diff --git a/crates/biome_cli/tests/commands/migrate_prettier.rs b/crates/biome_cli/tests/commands/migrate_prettier.rs new file mode 100644 index 000000000000..b686269409f1 --- /dev/null +++ b/crates/biome_cli/tests/commands/migrate_prettier.rs @@ -0,0 +1,304 @@ +use crate::run_cli; +use crate::snap_test::{assert_cli_snapshot, SnapshotPayload}; +use biome_console::BufferConsole; +use biome_fs::MemoryFileSystem; +use biome_service::DynRef; +use bpaf::Args; +use std::path::Path; + +#[test] +fn prettier_migrate() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let configuration = r#"{ "linter": { "enabled": true } }"#; + let prettier = r#"{ "useTabs": false, "semi": true, "singleQuote": true }"#; + + let configuration_path = Path::new("biome.json"); + fs.insert(configuration_path.into(), configuration.as_bytes()); + + let prettier_path = Path::new(".prettierrc"); + fs.insert(prettier_path.into(), prettier.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("migrate"), "prettier"].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "prettier_migrate", + fs, + console, + result, + )); +} + +#[test] +fn prettier_migrate_end_of_line() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let configuration = r#"{}"#; + let prettier = r#"{ "endOfLine": "auto" }"#; + + let configuration_path = Path::new("biome.json"); + fs.insert(configuration_path.into(), configuration.as_bytes()); + + let prettier_path = Path::new(".prettierrc"); + fs.insert(prettier_path.into(), prettier.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("migrate"), "prettier"].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "prettier_migrate_end_of_line", + fs, + console, + result, + )); +} + +#[test] +fn prettier_migrate_with_ignore() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let configuration = r#"{ "linter": { "enabled": true } }"#; + let prettier = r#"{ "useTabs": false, "semi": true, "singleQuote": true }"#; + let prettier_ignore = r#" +dist/** + +node_modules/** + +# I am a comment +generated/*.spec.js +"#; + + let configuration_path = Path::new("biome.json"); + fs.insert(configuration_path.into(), configuration.as_bytes()); + + let prettier_path = Path::new(".prettierrc"); + fs.insert(prettier_path.into(), prettier.as_bytes()); + + let prettier_ignore_path = Path::new(".prettierignore"); + fs.insert(prettier_ignore_path.into(), prettier_ignore.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("migrate"), "prettier"].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "prettier_migrate_with_ignore", + fs, + console, + result, + )); +} + +#[test] +fn prettier_migrate_jsonc() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let configuration = r#"{ "linter": { "enabled": true } }"#; + let prettier = r#"{ "useTabs": false, "semi": true, "singleQuote": true }"#; + + let configuration_path = Path::new("biome.jsonc"); + fs.insert(configuration_path.into(), configuration.as_bytes()); + + let prettier_path = Path::new(".prettierrc"); + fs.insert(prettier_path.into(), prettier.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("migrate"), "prettier"].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "prettier_migrate_jsonc", + fs, + console, + result, + )); +} + +#[test] +fn prettier_migrate_no_file() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let configuration = r#"{ "linter": { "enabled": true } }"#; + + let configuration_path = Path::new("biome.json"); + fs.insert(configuration_path.into(), configuration.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("migrate"), "prettier"].as_slice()), + ); + + assert!(result.is_err(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "prettier_migrate_no_file", + fs, + console, + result, + )); +} + +#[test] +fn prettier_migrate_yml_file() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let configuration = r#"{ "linter": { "enabled": true } }"#; + let prettier = r#"useTabs: true"#; + + let configuration_path = Path::new("biome.json"); + fs.insert(configuration_path.into(), configuration.as_bytes()); + + let prettier_path = Path::new(".prettierrc"); + fs.insert(prettier_path.into(), prettier.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("migrate"), "prettier"].as_slice()), + ); + + assert!(result.is_err(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "prettier_migrate_yml_file", + fs, + console, + result, + )); +} + +#[test] +fn prettier_migrate_write() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let configuration = r#"{ "linter": { "enabled": true } }"#; + let prettier = r#"{ "useTabs": false, "semi": true, "singleQuote": true }"#; + + let configuration_path = Path::new("biome.json"); + fs.insert(configuration_path.into(), configuration.as_bytes()); + + let prettier_path = Path::new(".prettierrc"); + fs.insert(prettier_path.into(), prettier.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("migrate"), "prettier", "--write"].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "prettier_migrate_write", + fs, + console, + result, + )); +} + +#[test] +fn prettier_migrate_write_with_ignore_file() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let configuration = r#"{ "linter": { "enabled": true } }"#; + let prettier = r#"{ "useTabs": false, "semi": true, "singleQuote": true }"#; + let prettier_ignore = r#" +dist/** + +node_modules/** + +# I am a comment +generated/*.spec.js +"#; + + let configuration_path = Path::new("biome.json"); + fs.insert(configuration_path.into(), configuration.as_bytes()); + + let prettier_path = Path::new(".prettierrc"); + fs.insert(prettier_path.into(), prettier.as_bytes()); + + let prettier_ignore_path = Path::new(".prettierignore"); + fs.insert(prettier_ignore_path.into(), prettier_ignore.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("migrate"), "prettier", "--write"].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "prettier_migrate_write_with_ignore_file", + fs, + console, + result, + )); +} + +#[test] +fn prettier_migrate_write_biome_jsonc() { + let mut fs = MemoryFileSystem::default(); + let mut console = BufferConsole::default(); + + let configuration = r#"{ "linter": { "enabled": true } }"#; + let prettier = r#"{ "useTabs": false, "semi": true, "singleQuote": true }"#; + + let configuration_path = Path::new("biome.jsonc"); + fs.insert(configuration_path.into(), configuration.as_bytes()); + + let prettier_path = Path::new(".prettierrc"); + fs.insert(prettier_path.into(), prettier.as_bytes()); + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("migrate"), "prettier", "--write"].as_slice()), + ); + + assert!(result.is_ok(), "run_cli returned {result:?}"); + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "prettier_migrate_write_biome_jsonc", + fs, + console, + result, + )); +} diff --git a/crates/biome_cli/tests/commands/mod.rs b/crates/biome_cli/tests/commands/mod.rs index 37ccc00b3031..cd3b4e596508 100644 --- a/crates/biome_cli/tests/commands/mod.rs +++ b/crates/biome_cli/tests/commands/mod.rs @@ -6,5 +6,7 @@ mod init; mod lint; mod lsp_proxy; mod migrate; +mod migrate_eslint; +mod migrate_prettier; mod rage; mod version; diff --git a/crates/biome_cli/tests/snapshots/main_cases_config_extends/extends_config_ok_formatter_no_linter.snap b/crates/biome_cli/tests/snapshots/main_cases_config_extends/extends_config_ok_formatter_no_linter.snap index 91030867f644..5e66e404464a 100644 --- a/crates/biome_cli/tests/snapshots/main_cases_config_extends/extends_config_ok_formatter_no_linter.snap +++ b/crates/biome_cli/tests/snapshots/main_cases_config_extends/extends_config_ok_formatter_no_linter.snap @@ -42,7 +42,7 @@ check ━━━━━━━━━━━━━━━━━━━━━━━━ ```block test.js format ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - i Formatter would have printed the following content: + × Formatter would have printed the following content: 1 │ - debugger;·console.log("string");· 1 │ + debugger; @@ -54,7 +54,5 @@ test.js format ━━━━━━━━━━━━━━━━━━━━━ ```block Checked 1 file in