From 53d04dd1dcaf973a192aade110e033684fc09de2 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Wed, 17 Sep 2025 09:20:20 +0000 Subject: [PATCH] feat(linter): convert `oxlint` to NAPI app (#13723) Convert `oxlint` to a NAPI package. This PR: 1. Moves files from `napi/oxlint` into `apps/oxlint`. 2. Converts `oxlint` into a NAPI package. 3. Alters the [release workflow](https://github.com/oxc-project/oxc/pull/13723/files#diff-80cb497c859bbaf7756da6ced2bca3d31933affc96102983eee1ad7d4bcc60fd) and [script](https://github.com/oxc-project/oxc/pull/13723/files#diff-4c4b7045c68805aeeae7c0af94cf7cf7487cb0403496da974a6a23accdc457d0) for building `oxlint` packages. Most of necessary code modifications and refactoring was done in previous PRs (#13701, #13712, #13722, #13745), so this PR only includes changes necessary for packaging as NAPI. I've done my best to update release workflow, but am mostly "flying blind" without ability to test it, so very likely there are mistakes. A few notes and oddities: * I've kept the `oxlint` NPM package as CommonJS. We could probably switch to ESM, but I thought it better to minimize the changes in this PR. * NAPI-RS creates `.node` files named with a `-msvc` postfix for Windows. The scripts here remove that postfix so that filename of `.node` files and NPM package names match for all platforms, for simplicity. * `tasks/website` has a dependency on `oxlint` as a normal library. This resulted in linker errors, so have had to put all the NAPI stuff behind `napi` cargo feature. Tests for `tasks/website` are run separately in CI, to avoid feature unification turning on the `napi` feature for `website`. I've made a few comments below for the parts which aren't fairly self-explanatory. --- .github/generated/ast_changes_watch_list.yml | 4 +- .github/workflows/ci.yml | 20 ++- .github/workflows/release_oxlint.yml | 48 ++++-- Cargo.lock | 16 +- apps/oxlint/.gitignore | 3 + apps/oxlint/Cargo.toml | 18 +- {napi => apps}/oxlint/build.rs | 0 {napi => apps}/oxlint/package.json | 7 +- {napi => apps}/oxlint/scripts/build.js | 25 ++- {napi => apps}/oxlint/src-js/bindings.d.ts | 0 {napi => apps}/oxlint/src-js/bindings.js | 102 +++++------ .../index.ts => apps/oxlint/src-js/cli.ts | 0 .../oxlint/src-js/generated/constants.mjs | 0 .../oxlint/src-js/plugins/context.ts | 0 {napi => apps}/oxlint/src-js/plugins/index.ts | 0 {napi => apps}/oxlint/src-js/plugins/lint.ts | 0 {napi => apps}/oxlint/src-js/plugins/load.ts | 0 {napi => apps}/oxlint/src-js/plugins/types.ts | 0 {napi => apps}/oxlint/src-js/plugins/utils.ts | 0 .../oxlint/src-js/plugins/visitor.ts | 0 .../src/generated/raw_transfer_constants.rs | 0 .../oxlint/src/js_plugins}/external_linter.rs | 4 +- apps/oxlint/src/js_plugins/mod.rs | 2 + apps/oxlint/src/lib.rs | 28 ++- apps/oxlint/src/lint.rs | 17 +- apps/oxlint/src/main.rs | 5 - apps/oxlint/src/run.rs | 84 +++++++-- .../test/__snapshots__/e2e.test.ts.snap | 0 .../oxlint/test/compile-visitor.test.ts | 0 {napi => apps}/oxlint/test/e2e.test.ts | 4 +- .../basic_custom_plugin/.oxlintrc.json | 0 .../fixtures/basic_custom_plugin/index.js | 0 .../basic_custom_plugin/test_plugin/index.js | 0 .../.oxlintrc.json | 0 .../files/01.js | 0 .../files/02.js | 0 .../files/03.js | 0 .../files/04.js | 0 .../files/05.js | 0 .../files/06.js | 0 .../files/07.js | 0 .../files/08.js | 0 .../files/09.js | 0 .../files/10.js | 0 .../files/11.js | 0 .../files/12.js | 0 .../files/13.js | 0 .../files/14.js | 0 .../files/15.js | 0 .../files/16.js | 0 .../files/17.js | 0 .../files/18.js | 0 .../files/19.js | 0 .../files/20.js | 0 .../test_plugin/index.js | 0 .../.oxlintrc.json | 0 .../index.js | 0 .../test_plugin/index.js | 0 .../.oxlintrc.json | 0 .../index.js | 0 .../test_plugin/index.js | 0 .../fixtures/built_in_errors/.oxlintrc.json | 0 .../test/fixtures/built_in_errors/index.js | 0 .../built_in_no_errors/.oxlintrc.json | 0 .../test/fixtures/built_in_no_errors/index.js | 0 .../context_properties/.oxlintrc.json | 0 .../fixtures/context_properties/files/1.js | 0 .../fixtures/context_properties/files/2.js | 0 .../context_properties/test_plugin/index.js | 0 .../.oxlintrc.json | 0 .../custom_plugin_disable_directives/index.js | 0 .../test_plugin/index.js | 0 .../custom_plugin_missing_rule/.oxlintrc.json | 0 .../test_plugin/index.js | 0 .../.oxlintrc.json | 0 .../custom_plugin_via_overrides/index.js | 0 .../test_plugin/index.js | 0 .../.oxlintrc.json | 0 .../index.js | 0 .../test_plugin/index.js | 0 .../missing_custom_plugin/.oxlintrc.json | 0 .../fixtures/utf16_offsets/.oxlintrc.json | 0 .../test/fixtures/utf16_offsets/index.js | 0 .../utf16_offsets/test_plugin/index.js | 0 {napi => apps}/oxlint/tsconfig.json | 6 +- {napi => apps}/oxlint/tsdown.config.ts | 2 +- {napi => apps}/oxlint/vitest.config.mts | 0 dprint.json | 4 +- napi/oxlint/.gitignore | 1 - napi/oxlint/Cargo.toml | 38 ----- napi/oxlint/README.md | 1 - napi/oxlint/src/lib.rs | 76 --------- npm/oxlint/bin/oxlint | 160 ++---------------- npm/oxlint/package.json | 1 + npm/oxlint/scripts/generate-packages.mjs | 35 ++-- oxlintrc.json | 3 +- package.json | 8 +- pnpm-lock.yaml | 30 ++-- pnpm-workspace.yaml | 1 + .../ast_tools/src/generators/raw_transfer.rs | 6 +- tasks/ast_tools/src/main.rs | 2 +- tasks/website/Cargo.toml | 3 +- 102 files changed, 328 insertions(+), 436 deletions(-) create mode 100644 apps/oxlint/.gitignore rename {napi => apps}/oxlint/build.rs (100%) rename {napi => apps}/oxlint/package.json (89%) rename {napi => apps}/oxlint/scripts/build.js (59%) rename {napi => apps}/oxlint/src-js/bindings.d.ts (100%) rename {napi => apps}/oxlint/src-js/bindings.js (83%) rename napi/oxlint/src-js/index.ts => apps/oxlint/src-js/cli.ts (100%) rename {napi => apps}/oxlint/src-js/generated/constants.mjs (100%) rename {napi => apps}/oxlint/src-js/plugins/context.ts (100%) rename {napi => apps}/oxlint/src-js/plugins/index.ts (100%) rename {napi => apps}/oxlint/src-js/plugins/lint.ts (100%) rename {napi => apps}/oxlint/src-js/plugins/load.ts (100%) rename {napi => apps}/oxlint/src-js/plugins/types.ts (100%) rename {napi => apps}/oxlint/src-js/plugins/utils.ts (100%) rename {napi => apps}/oxlint/src-js/plugins/visitor.ts (100%) rename {napi => apps}/oxlint/src/generated/raw_transfer_constants.rs (100%) rename {napi/oxlint/src => apps/oxlint/src/js_plugins}/external_linter.rs (99%) delete mode 100644 apps/oxlint/src/main.rs rename {napi => apps}/oxlint/test/__snapshots__/e2e.test.ts.snap (100%) rename {napi => apps}/oxlint/test/compile-visitor.test.ts (100%) rename {napi => apps}/oxlint/test/e2e.test.ts (97%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin/.oxlintrc.json (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin/index.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin/test_plugin/index.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/.oxlintrc.json (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/01.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/02.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/03.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/04.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/05.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/06.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/07.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/08.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/09.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/10.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/11.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/12.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/13.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/14.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/15.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/16.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/17.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/18.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/19.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/files/20.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_many_files/test_plugin/index.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_multiple_rules/.oxlintrc.json (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_multiple_rules/index.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_multiple_rules/test_plugin/index.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_warn_severity/.oxlintrc.json (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_warn_severity/index.js (100%) rename {napi => apps}/oxlint/test/fixtures/basic_custom_plugin_warn_severity/test_plugin/index.js (100%) rename {napi => apps}/oxlint/test/fixtures/built_in_errors/.oxlintrc.json (100%) rename {napi => apps}/oxlint/test/fixtures/built_in_errors/index.js (100%) rename {napi => apps}/oxlint/test/fixtures/built_in_no_errors/.oxlintrc.json (100%) rename {napi => apps}/oxlint/test/fixtures/built_in_no_errors/index.js (100%) rename {napi => apps}/oxlint/test/fixtures/context_properties/.oxlintrc.json (100%) rename {napi => apps}/oxlint/test/fixtures/context_properties/files/1.js (100%) rename {napi => apps}/oxlint/test/fixtures/context_properties/files/2.js (100%) rename {napi => apps}/oxlint/test/fixtures/context_properties/test_plugin/index.js (100%) rename {napi => apps}/oxlint/test/fixtures/custom_plugin_disable_directives/.oxlintrc.json (100%) rename {napi => apps}/oxlint/test/fixtures/custom_plugin_disable_directives/index.js (100%) rename {napi => apps}/oxlint/test/fixtures/custom_plugin_disable_directives/test_plugin/index.js (100%) rename {napi => apps}/oxlint/test/fixtures/custom_plugin_missing_rule/.oxlintrc.json (100%) rename {napi => apps}/oxlint/test/fixtures/custom_plugin_missing_rule/test_plugin/index.js (100%) rename {napi => apps}/oxlint/test/fixtures/custom_plugin_via_overrides/.oxlintrc.json (100%) rename {napi => apps}/oxlint/test/fixtures/custom_plugin_via_overrides/index.js (100%) rename {napi => apps}/oxlint/test/fixtures/custom_plugin_via_overrides/test_plugin/index.js (100%) rename {napi => apps}/oxlint/test/fixtures/custom_plugin_via_overrides_missing_rule/.oxlintrc.json (100%) rename {napi => apps}/oxlint/test/fixtures/custom_plugin_via_overrides_missing_rule/index.js (100%) rename {napi => apps}/oxlint/test/fixtures/custom_plugin_via_overrides_missing_rule/test_plugin/index.js (100%) rename {napi => apps}/oxlint/test/fixtures/missing_custom_plugin/.oxlintrc.json (100%) rename {napi => apps}/oxlint/test/fixtures/utf16_offsets/.oxlintrc.json (100%) rename {napi => apps}/oxlint/test/fixtures/utf16_offsets/index.js (100%) rename {napi => apps}/oxlint/test/fixtures/utf16_offsets/test_plugin/index.js (100%) rename {napi => apps}/oxlint/tsconfig.json (75%) rename {napi => apps}/oxlint/tsdown.config.ts (91%) rename {napi => apps}/oxlint/vitest.config.mts (100%) delete mode 100644 napi/oxlint/.gitignore delete mode 100644 napi/oxlint/Cargo.toml delete mode 100644 napi/oxlint/README.md delete mode 100644 napi/oxlint/src/lib.rs diff --git a/.github/generated/ast_changes_watch_list.yml b/.github/generated/ast_changes_watch_list.yml index d3ad4b28bb23b..42604240c1c21 100644 --- a/.github/generated/ast_changes_watch_list.yml +++ b/.github/generated/ast_changes_watch_list.yml @@ -3,6 +3,8 @@ src: - '.github/generated/ast_changes_watch_list.yml' + - 'apps/oxlint/src-js/generated/constants.mjs' + - 'apps/oxlint/src/generated/raw_transfer_constants.rs' - 'crates/oxc_allocator/src/generated/assert_layouts.rs' - 'crates/oxc_allocator/src/generated/fixed_size_constants.rs' - 'crates/oxc_allocator/src/pool/fixed_size.rs' @@ -64,8 +66,6 @@ src: - 'crates/oxc_syntax/src/serialize.rs' - 'crates/oxc_syntax/src/symbol.rs' - 'crates/oxc_traverse/src/generated/scopes_collector.rs' - - 'napi/oxlint/src-js/generated/constants.mjs' - - 'napi/oxlint/src/generated/raw_transfer_constants.rs' - 'napi/parser/generated/constants.mjs' - 'napi/parser/generated/deserialize/js.mjs' - 'napi/parser/generated/deserialize/ts.mjs' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 680cd8732b7fe..4c8e49962c89f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,8 @@ jobs: save-cache: ${{ github.ref_name == 'main' }} cache-key: warm - run: cargo ck - - run: cargo test --all-features + - run: cargo test --workspace --all-features --exclude website + - run: cargo test -p website # Run separately to avoid feature unification problems with `oxlint` - run: git diff --exit-code # Must commit everything test-ubuntu-aarch64: @@ -41,7 +42,8 @@ jobs: save-cache: ${{ github.ref_name == 'main' }} cache-key: warm-aarch64 - run: cargo ck - - run: cargo test --all-features + - run: cargo test --workspace --all-features --exclude website + - run: cargo test -p website # Run separately to avoid feature unification problems with `oxlint` - run: git diff --exit-code # Must commit everything test-mac: # Separate job to save a job on PRs @@ -56,7 +58,8 @@ jobs: save-cache: ${{ github.ref_name == 'main' }} cache-key: warm - run: cargo ck - - run: cargo test --all-features + - run: cargo test --workspace --all-features --exclude website + - run: cargo test -p website # Run separately to avoid feature unification problems with `oxlint` - run: git diff --exit-code # Must commit everything test-windows: @@ -98,7 +101,12 @@ jobs: save-if: ${{ github.ref_name == 'main' }} shared-key: windows-latest - - run: cargo test --all-features # cargo ck # no need to `cargo ck` because it's already checked in linux + - name: Run tests + # No need for `cargo ck` because it's already checked in linux + # Run `website` tests separately to avoid feature unification problems with `oxlint` + run: | + cargo test --workspace --all-features --exclude website + cargo test -p website working-directory: ${{ env.DEV_DRIVE_WORKSPACE }} shell: bash @@ -114,7 +122,9 @@ jobs: save-cache: ${{ github.ref_name == 'main' }} cache-key: s390x-unknown-linux-gnu tools: cross - - run: cross test --all-features --target s390x-unknown-linux-gnu + - run: cross test --workspace --all-features --exclude website --target s390x-unknown-linux-gnu + # Run separately to avoid feature unification problems with `oxlint` + - run: cross test -p website --target s390x-unknown-linux-gnu test-wasm32-wasip1-threads: name: Test wasm32-wasip1-threads diff --git a/.github/workflows/release_oxlint.yml b/.github/workflows/release_oxlint.yml index 238a59ba25352..796a287fdd73f 100644 --- a/.github/workflows/release_oxlint.yml +++ b/.github/workflows/release_oxlint.yml @@ -48,34 +48,42 @@ jobs: - os: windows-latest target: x86_64-pc-windows-msvc code-target: win32-x64 + build-oxlint: pnpm run build-napi-release --target x86_64-pc-windows-msvc - os: windows-latest target: aarch64-pc-windows-msvc code-target: win32-arm64 + build-oxlint: pnpm run build-napi-release --target aarch64-pc-windows-msvc - os: ubuntu-latest target: x86_64-unknown-linux-gnu code-target: linux-x64-gnu + build-oxlint: pnpm run build-napi-release --target x86_64-unknown-linux-gnu --use-napi-cross - os: ubuntu-latest target: aarch64-unknown-linux-gnu code-target: linux-arm64-gnu + build-oxlint: pnpm run build-napi-release --target aarch64-unknown-linux-gnu --use-napi-cross - os: ubuntu-latest target: x86_64-unknown-linux-musl code-target: linux-x64-musl + build-oxlint: pnpm run build-napi-release --target x86_64-unknown-linux-musl -x - os: ubuntu-latest target: aarch64-unknown-linux-musl code-target: linux-arm64-musl + build-oxlint: pnpm run build-napi-release --target aarch64-unknown-linux-musl -x - os: macos-latest target: x86_64-apple-darwin code-target: darwin-x64 + build-oxlint: pnpm run build-napi-release --target x86_64-apple-darwin - os: macos-latest target: aarch64-apple-darwin code-target: darwin-arm64 + build-oxlint: pnpm run build-napi-release --target aarch64-apple-darwin name: Package ${{ matrix.code-target }} runs-on: ${{ matrix.os }} @@ -100,21 +108,35 @@ jobs: - name: Add Rust Target run: rustup target add ${{ matrix.target }} - - name: Build + - uses: oxc-project/setup-node@f42e3bda950c7454575e78ee4eaac880a077700c # v1.0.0 + + - uses: goto-bus-stop/setup-zig@abea47f85e598557f500fa1fd2ab7464fcb39406 # v2.2.1 + if: ${{ contains(matrix.target, 'musl') }} + with: + version: 0.13.0 + + - name: Build oxlint + working-directory: apps/oxlint + run: ${{ matrix.build-oxlint }} --features allocator shell: bash env: TARGET_CC: clang # for mimalloc - run: | - cross build --release -p oxlint --bin oxlint --features allocator --target=${{ matrix.target }} - cross build --release -p oxc_language_server --bin oxc_language_server --target=${{ matrix.target }} + + - name: Build language server + shell: bash + env: + TARGET_CC: clang # for mimalloc + run: cross build --release -p oxc_language_server --bin oxc_language_server --target=${{ matrix.target }} # The binaries are zipped to fix permission loss https://github.com/actions/upload-artifact#permission-loss - name: Archive Binaries if: runner.os == 'Windows' + # Windows `.node` files have `-msvc` postfix e.g. `oxlint.win32-x64-msvc.node`. Remove the postfix. run: | - OXLINT_BIN_NAME=oxlint-${{ matrix.code-target }} - mv target/${{ matrix.target }}/release/oxlint.exe $OXLINT_BIN_NAME.exe - 7z a $OXLINT_BIN_NAME.zip $OXLINT_BIN_NAME.exe + OXLINT_BIN_SRC_NAME=oxlint.${{ matrix.code-target }}-msvc.node + OXLINT_BIN_NAME=oxlint.${{ matrix.code-target }}.node + mv apps/oxlint/src-js/$OXLINT_BIN_SRC_NAME $OXLINT_BIN_NAME + 7z a oxlint-${{ matrix.code-target }}.zip $OXLINT_BIN_NAME OXLS_BIN_NAME=oxc_language_server-${{ matrix.code-target }} mv target/${{ matrix.target }}/release/oxc_language_server.exe $OXLS_BIN_NAME.exe @@ -124,9 +146,9 @@ jobs: - name: Archive Binaries if: runner.os != 'Windows' run: | - OXLINT_BIN_NAME=oxlint-${{ matrix.code-target }} - mv target/${{ matrix.target }}/release/oxlint $OXLINT_BIN_NAME - tar czf $OXLINT_BIN_NAME.tar.gz $OXLINT_BIN_NAME + OXLINT_BIN_NAME=oxlint.${{ matrix.code-target }}.node + mv apps/oxlint/src-js/$OXLINT_BIN_NAME . + tar czf oxlint-${{ matrix.code-target }}.tar.gz $OXLINT_BIN_NAME OXLS_BIN_NAME=oxc_language_server-${{ matrix.code-target }} mv target/${{ matrix.target }}/release/oxc_language_server $OXLS_BIN_NAME @@ -184,6 +206,10 @@ jobs: - uses: oxc-project/setup-node@fdbf0dfd334c4e6d56ceeb77d91c76339c2a0885 # v1.0.4 + - name: Generate oxlint JS build + working-directory: apps/oxlint + run: pnpm run build-js + - name: Generate npm packages run: | node npm/oxlint/scripts/generate-packages.mjs @@ -253,7 +279,7 @@ jobs: ref: main inputs: '{ "version": "${{ needs.check.outputs.version }}" }' - - name: Bump oxc-project/eslint-plugin-oxlint + - name: Bump oxc-project/oxlint-migrate uses: benc-uk/workflow-dispatch@e2e5e9a103e331dad343f381a29e654aea3cf8fc # v1.2.4 with: repo: oxc-project/oxlint-migrate diff --git a/Cargo.lock b/Cargo.lock index 6514c3ac0ed54..796bbf0ebc7fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2064,19 +2064,6 @@ dependencies = [ "syn", ] -[[package]] -name = "oxc_linter_napi" -version = "0.1.0" -dependencies = [ - "napi", - "napi-build", - "napi-derive", - "oxc_allocator", - "oxlint", - "serde_json", - "tokio", -] - [[package]] name = "oxc_macros" version = "0.0.0" @@ -2546,6 +2533,8 @@ dependencies = [ "lazy-regex", "mimalloc-safe", "napi", + "napi-build", + "napi-derive", "oxc-miette", "oxc_allocator", "oxc_diagnostics", @@ -2557,6 +2546,7 @@ dependencies = [ "serde_json", "simdutf8", "tempfile", + "tokio", "tracing-subscriber", ] diff --git a/apps/oxlint/.gitignore b/apps/oxlint/.gitignore new file mode 100644 index 0000000000000..f3c3e09737cb9 --- /dev/null +++ b/apps/oxlint/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +*.node +dist/ diff --git a/apps/oxlint/Cargo.toml b/apps/oxlint/Cargo.toml index def7e1b13f522..7105e8c69c8de 100644 --- a/apps/oxlint/Cargo.toml +++ b/apps/oxlint/Cargo.toml @@ -16,16 +16,10 @@ description.workspace = true workspace = true [lib] -crate-type = ["lib"] +crate-type = ["cdylib", "lib"] path = "src/lib.rs" doctest = false -[[bin]] -name = "oxlint" -path = "src/main.rs" -test = false -doctest = false - [dependencies] oxc_allocator = { workspace = true, features = ["fixed_size"] } oxc_diagnostics = { workspace = true } @@ -36,13 +30,15 @@ bpaf = { workspace = true, features = ["autocomplete", "bright-color", "derive"] cow-utils = { workspace = true } ignore = { workspace = true, features = ["simd-accel"] } miette = { workspace = true } -napi = { workspace = true } +napi = { workspace = true, features = ["async"], optional = true } +napi-derive = { workspace = true, optional = true } rayon = { workspace = true } rustc-hash = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } simdutf8 = { workspace = true } tempfile = { workspace = true } +tokio = { workspace = true, features = ["rt-multi-thread"] } tracing-subscriber = { workspace = true, features = [] } # Omit the `regex` feature [target.'cfg(not(any(target_os = "linux", target_os = "freebsd", target_arch = "arm", target_family = "wasm")))'.dependencies] @@ -54,11 +50,15 @@ mimalloc-safe = { workspace = true, optional = true, features = ["skip_collect_o [target.'cfg(all(target_os = "linux", target_arch = "aarch64"))'.dependencies] mimalloc-safe = { workspace = true, optional = true, features = ["skip_collect_on_exit", "local_dynamic_tls", "no_opt_arch"] } +[build-dependencies] +napi-build = { workspace = true } + [dev-dependencies] insta = { workspace = true } lazy-regex = { workspace = true } [features] -default = [] +default = ["napi"] +napi = ["dep:napi", "dep:napi-derive"] allocator = ["dep:mimalloc-safe"] force_test_reporter = ["oxc_linter/force_test_reporter"] diff --git a/napi/oxlint/build.rs b/apps/oxlint/build.rs similarity index 100% rename from napi/oxlint/build.rs rename to apps/oxlint/build.rs diff --git a/napi/oxlint/package.json b/apps/oxlint/package.json similarity index 89% rename from napi/oxlint/package.json rename to apps/oxlint/package.json index 8f8c612d8952c..a632dbc6e9bcd 100644 --- a/napi/oxlint/package.json +++ b/apps/oxlint/package.json @@ -1,7 +1,7 @@ { "name": "oxlint", "version": "0.1.0", - "bin": "dist/index.js", + "bin": "dist/cli.js", "type": "module", "scripts": { "build": "pnpm run build-napi-release && pnpm run build-js", @@ -16,7 +16,7 @@ "engines": { "node": ">=20.0.0" }, - "description": "Staging package for oxlint while we integrate custom JS plugins into oxlint", + "description": "Linter for the JavaScript Oxidation Compiler", "author": "Boshen and oxc contributors", "license": "MIT", "homepage": "https://oxc.rs", @@ -24,7 +24,7 @@ "repository": { "type": "git", "url": "https://github.com/oxc-project/oxc.git", - "directory": "napi/oxlint" + "directory": "apps/oxlint" }, "publishConfig": { "registry": "https://registry.npmjs.org/", @@ -41,6 +41,7 @@ }, "napi": { "binaryName": "oxlint", + "packageName": "@oxlint/binding", "targets": [ "win32-x64", "win32-arm64", diff --git a/napi/oxlint/scripts/build.js b/apps/oxlint/scripts/build.js similarity index 59% rename from napi/oxlint/scripts/build.js rename to apps/oxlint/scripts/build.js index a32452224de35..e61150a33923f 100755 --- a/napi/oxlint/scripts/build.js +++ b/apps/oxlint/scripts/build.js @@ -1,16 +1,35 @@ import { execSync } from 'node:child_process'; -import { copyFileSync, mkdirSync, readdirSync } from 'node:fs'; +import { copyFileSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs'; import { join } from 'node:path'; const oxlintDirPath = join(import.meta.dirname, '..'), distDirPath = join(oxlintDirPath, 'dist'), - parserDirPath = join(oxlintDirPath, '../parser'); + parserDirPath = join(oxlintDirPath, '../../napi/parser'); + +// Modify `bindings.js` to use correct package names +console.log('Modifying bindings.js...'); +const bindingsPath = join(oxlintDirPath, 'src-js/bindings.js'); +let bindingsJs = readFileSync(bindingsPath, 'utf8'); +bindingsJs = bindingsJs.replace(/require\('@oxlint\/binding-(.+?)'\)/g, (_, name) => { + name = name.replace(/-msvc(\/|$)/g, '$1'); + return `require('@oxlint/${name}')`; +}); +writeFileSync(bindingsPath, bindingsJs); // Build with tsdown console.log('Building with tsdown...'); execSync('pnpm tsdown', { stdio: 'inherit', cwd: oxlintDirPath }); -// Copy files from `napi/parser` to `napi/oxlint/dist` +// Add `package.json` to `dist` dir. +// `npm/oxlint` package is CommonJS, so we need this file to tell Node.js that `dist` is ESM. +console.log('Adding package.json to dist...'); +writeFileSync( + join(distDirPath, 'package.json'), + JSON.stringify({ type: 'module' }, null, 2) + '\n', +); +console.log('- Created package.json'); + +// Copy files from `napi/parser` to `apps/oxlint/dist` console.log('Copying files from parser...'); const parserFilePaths = [ diff --git a/napi/oxlint/src-js/bindings.d.ts b/apps/oxlint/src-js/bindings.d.ts similarity index 100% rename from napi/oxlint/src-js/bindings.d.ts rename to apps/oxlint/src-js/bindings.d.ts diff --git a/napi/oxlint/src-js/bindings.js b/apps/oxlint/src-js/bindings.js similarity index 83% rename from napi/oxlint/src-js/bindings.js rename to apps/oxlint/src-js/bindings.js index 8d6c68c838fbe..45d42a941a1a5 100644 --- a/napi/oxlint/src-js/bindings.js +++ b/apps/oxlint/src-js/bindings.js @@ -79,8 +79,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-android-arm64') - const bindingPackageVersion = require('oxlint-android-arm64/package.json').version + const binding = require('@oxlint/android-arm64') + const bindingPackageVersion = require('@oxlint/android-arm64/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -95,8 +95,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-android-arm-eabi') - const bindingPackageVersion = require('oxlint-android-arm-eabi/package.json').version + const binding = require('@oxlint/android-arm-eabi') + const bindingPackageVersion = require('@oxlint/android-arm-eabi/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -115,8 +115,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-win32-x64-msvc') - const bindingPackageVersion = require('oxlint-win32-x64-msvc/package.json').version + const binding = require('@oxlint/win32-x64') + const bindingPackageVersion = require('@oxlint/win32-x64/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -131,8 +131,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-win32-ia32-msvc') - const bindingPackageVersion = require('oxlint-win32-ia32-msvc/package.json').version + const binding = require('@oxlint/win32-ia32') + const bindingPackageVersion = require('@oxlint/win32-ia32/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -147,8 +147,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-win32-arm64-msvc') - const bindingPackageVersion = require('oxlint-win32-arm64-msvc/package.json').version + const binding = require('@oxlint/win32-arm64') + const bindingPackageVersion = require('@oxlint/win32-arm64/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -166,8 +166,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-darwin-universal') - const bindingPackageVersion = require('oxlint-darwin-universal/package.json').version + const binding = require('@oxlint/darwin-universal') + const bindingPackageVersion = require('@oxlint/darwin-universal/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -182,8 +182,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-darwin-x64') - const bindingPackageVersion = require('oxlint-darwin-x64/package.json').version + const binding = require('@oxlint/darwin-x64') + const bindingPackageVersion = require('@oxlint/darwin-x64/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -198,8 +198,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-darwin-arm64') - const bindingPackageVersion = require('oxlint-darwin-arm64/package.json').version + const binding = require('@oxlint/darwin-arm64') + const bindingPackageVersion = require('@oxlint/darwin-arm64/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -218,8 +218,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-freebsd-x64') - const bindingPackageVersion = require('oxlint-freebsd-x64/package.json').version + const binding = require('@oxlint/freebsd-x64') + const bindingPackageVersion = require('@oxlint/freebsd-x64/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -234,8 +234,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-freebsd-arm64') - const bindingPackageVersion = require('oxlint-freebsd-arm64/package.json').version + const binding = require('@oxlint/freebsd-arm64') + const bindingPackageVersion = require('@oxlint/freebsd-arm64/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -255,8 +255,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-linux-x64-musl') - const bindingPackageVersion = require('oxlint-linux-x64-musl/package.json').version + const binding = require('@oxlint/linux-x64-musl') + const bindingPackageVersion = require('@oxlint/linux-x64-musl/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -271,8 +271,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-linux-x64-gnu') - const bindingPackageVersion = require('oxlint-linux-x64-gnu/package.json').version + const binding = require('@oxlint/linux-x64-gnu') + const bindingPackageVersion = require('@oxlint/linux-x64-gnu/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -289,8 +289,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-linux-arm64-musl') - const bindingPackageVersion = require('oxlint-linux-arm64-musl/package.json').version + const binding = require('@oxlint/linux-arm64-musl') + const bindingPackageVersion = require('@oxlint/linux-arm64-musl/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -305,8 +305,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-linux-arm64-gnu') - const bindingPackageVersion = require('oxlint-linux-arm64-gnu/package.json').version + const binding = require('@oxlint/linux-arm64-gnu') + const bindingPackageVersion = require('@oxlint/linux-arm64-gnu/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -323,8 +323,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-linux-arm-musleabihf') - const bindingPackageVersion = require('oxlint-linux-arm-musleabihf/package.json').version + const binding = require('@oxlint/linux-arm-musleabihf') + const bindingPackageVersion = require('@oxlint/linux-arm-musleabihf/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -339,8 +339,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-linux-arm-gnueabihf') - const bindingPackageVersion = require('oxlint-linux-arm-gnueabihf/package.json').version + const binding = require('@oxlint/linux-arm-gnueabihf') + const bindingPackageVersion = require('@oxlint/linux-arm-gnueabihf/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -357,8 +357,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-linux-loong64-musl') - const bindingPackageVersion = require('oxlint-linux-loong64-musl/package.json').version + const binding = require('@oxlint/linux-loong64-musl') + const bindingPackageVersion = require('@oxlint/linux-loong64-musl/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -373,8 +373,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-linux-loong64-gnu') - const bindingPackageVersion = require('oxlint-linux-loong64-gnu/package.json').version + const binding = require('@oxlint/linux-loong64-gnu') + const bindingPackageVersion = require('@oxlint/linux-loong64-gnu/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -391,8 +391,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-linux-riscv64-musl') - const bindingPackageVersion = require('oxlint-linux-riscv64-musl/package.json').version + const binding = require('@oxlint/linux-riscv64-musl') + const bindingPackageVersion = require('@oxlint/linux-riscv64-musl/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -407,8 +407,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-linux-riscv64-gnu') - const bindingPackageVersion = require('oxlint-linux-riscv64-gnu/package.json').version + const binding = require('@oxlint/linux-riscv64-gnu') + const bindingPackageVersion = require('@oxlint/linux-riscv64-gnu/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -424,8 +424,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-linux-ppc64-gnu') - const bindingPackageVersion = require('oxlint-linux-ppc64-gnu/package.json').version + const binding = require('@oxlint/linux-ppc64-gnu') + const bindingPackageVersion = require('@oxlint/linux-ppc64-gnu/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -440,8 +440,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-linux-s390x-gnu') - const bindingPackageVersion = require('oxlint-linux-s390x-gnu/package.json').version + const binding = require('@oxlint/linux-s390x-gnu') + const bindingPackageVersion = require('@oxlint/linux-s390x-gnu/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -460,8 +460,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-openharmony-arm64') - const bindingPackageVersion = require('oxlint-openharmony-arm64/package.json').version + const binding = require('@oxlint/openharmony-arm64') + const bindingPackageVersion = require('@oxlint/openharmony-arm64/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -476,8 +476,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-openharmony-x64') - const bindingPackageVersion = require('oxlint-openharmony-x64/package.json').version + const binding = require('@oxlint/openharmony-x64') + const bindingPackageVersion = require('@oxlint/openharmony-x64/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -492,8 +492,8 @@ function requireNative() { loadErrors.push(e) } try { - const binding = require('oxlint-openharmony-arm') - const bindingPackageVersion = require('oxlint-openharmony-arm/package.json').version + const binding = require('@oxlint/openharmony-arm') + const bindingPackageVersion = require('@oxlint/openharmony-arm/package.json').version if (bindingPackageVersion !== '0.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 0.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } @@ -524,7 +524,7 @@ if (!nativeBinding || process.env.NAPI_RS_FORCE_WASI) { } if (!nativeBinding) { try { - wasiBinding = require('oxlint-wasm32-wasi') + wasiBinding = require('@oxlint/wasm32-wasi') nativeBinding = wasiBinding } catch (err) { if (process.env.NAPI_RS_FORCE_WASI) { diff --git a/napi/oxlint/src-js/index.ts b/apps/oxlint/src-js/cli.ts similarity index 100% rename from napi/oxlint/src-js/index.ts rename to apps/oxlint/src-js/cli.ts diff --git a/napi/oxlint/src-js/generated/constants.mjs b/apps/oxlint/src-js/generated/constants.mjs similarity index 100% rename from napi/oxlint/src-js/generated/constants.mjs rename to apps/oxlint/src-js/generated/constants.mjs diff --git a/napi/oxlint/src-js/plugins/context.ts b/apps/oxlint/src-js/plugins/context.ts similarity index 100% rename from napi/oxlint/src-js/plugins/context.ts rename to apps/oxlint/src-js/plugins/context.ts diff --git a/napi/oxlint/src-js/plugins/index.ts b/apps/oxlint/src-js/plugins/index.ts similarity index 100% rename from napi/oxlint/src-js/plugins/index.ts rename to apps/oxlint/src-js/plugins/index.ts diff --git a/napi/oxlint/src-js/plugins/lint.ts b/apps/oxlint/src-js/plugins/lint.ts similarity index 100% rename from napi/oxlint/src-js/plugins/lint.ts rename to apps/oxlint/src-js/plugins/lint.ts diff --git a/napi/oxlint/src-js/plugins/load.ts b/apps/oxlint/src-js/plugins/load.ts similarity index 100% rename from napi/oxlint/src-js/plugins/load.ts rename to apps/oxlint/src-js/plugins/load.ts diff --git a/napi/oxlint/src-js/plugins/types.ts b/apps/oxlint/src-js/plugins/types.ts similarity index 100% rename from napi/oxlint/src-js/plugins/types.ts rename to apps/oxlint/src-js/plugins/types.ts diff --git a/napi/oxlint/src-js/plugins/utils.ts b/apps/oxlint/src-js/plugins/utils.ts similarity index 100% rename from napi/oxlint/src-js/plugins/utils.ts rename to apps/oxlint/src-js/plugins/utils.ts diff --git a/napi/oxlint/src-js/plugins/visitor.ts b/apps/oxlint/src-js/plugins/visitor.ts similarity index 100% rename from napi/oxlint/src-js/plugins/visitor.ts rename to apps/oxlint/src-js/plugins/visitor.ts diff --git a/napi/oxlint/src/generated/raw_transfer_constants.rs b/apps/oxlint/src/generated/raw_transfer_constants.rs similarity index 100% rename from napi/oxlint/src/generated/raw_transfer_constants.rs rename to apps/oxlint/src/generated/raw_transfer_constants.rs diff --git a/napi/oxlint/src/external_linter.rs b/apps/oxlint/src/js_plugins/external_linter.rs similarity index 99% rename from napi/oxlint/src/external_linter.rs rename to apps/oxlint/src/js_plugins/external_linter.rs index 4b9f22ae2b838..d5087a49ba102 100644 --- a/napi/oxlint/src/external_linter.rs +++ b/apps/oxlint/src/js_plugins/external_linter.rs @@ -7,14 +7,14 @@ use napi::{ }; use oxc_allocator::{Allocator, free_fixed_size_allocator}; -use oxlint::{ +use oxc_linter::{ ExternalLinter, ExternalLinterLintFileCb, ExternalLinterLoadPluginCb, LintFileResult, PluginLoadResult, }; use crate::{ - JsLintFileCb, JsLoadPluginCb, generated::raw_transfer_constants::{BLOCK_ALIGN, BUFFER_SIZE}, + run::{JsLintFileCb, JsLoadPluginCb}, }; /// Wrap JS callbacks as normal Rust functions, and create [`ExternalLinter`]. diff --git a/apps/oxlint/src/js_plugins/mod.rs b/apps/oxlint/src/js_plugins/mod.rs index 191a7601bc587..819fe152c10ef 100644 --- a/apps/oxlint/src/js_plugins/mod.rs +++ b/apps/oxlint/src/js_plugins/mod.rs @@ -1,3 +1,5 @@ +mod external_linter; mod raw_fs; +pub use external_linter::create_external_linter; pub use raw_fs::RawTransferFileSystem; diff --git a/apps/oxlint/src/lib.rs b/apps/oxlint/src/lib.rs index b764aed31738b..fa71ce05c4e34 100644 --- a/apps/oxlint/src/lib.rs +++ b/apps/oxlint/src/lib.rs @@ -1,15 +1,10 @@ -/// Re-exported external linter types for use in `napi/oxlint`. -pub use oxc_linter::{ - ExternalLinter, ExternalLinterLintFileCb, ExternalLinterLoadPluginCb, LintFileResult, - PluginLoadResult, -}; +// Ignore dead code warnings when building `tasks/website`, which disables `napi` Cargo feature +#![cfg_attr(not(feature = "napi"), allow(dead_code))] mod command; -mod js_plugins; mod lint; mod output_formatter; mod result; -mod run; mod walk; #[cfg(test)] @@ -20,8 +15,23 @@ pub mod cli { pub use super::{command::*, lint::LintRunner, result::CliRunResult}; } -/// Main export for binary -pub use run::lint; +// Only include code to run linter when the `napi` feature is enabled. +// Without this, `tasks/website` will not compile on Linux or Windows. +// `tasks/website` depends on `oxlint` as a normal library, which causes linker errors if NAPI is enabled. +#[cfg(feature = "napi")] +mod run; +#[cfg(feature = "napi")] +pub use run::*; + +// JS plugins are only supported on 64-bit little-endian platforms at present. +// Note: `raw_transfer_constants` module will not compile on 32-bit systems. +#[cfg(all(feature = "napi", target_pointer_width = "64", target_endian = "little"))] +mod generated { + pub mod raw_transfer_constants; +} + +#[cfg(all(feature = "napi", target_pointer_width = "64", target_endian = "little"))] +mod js_plugins; #[cfg(all(feature = "allocator", not(miri), not(target_family = "wasm")))] #[global_allocator] diff --git a/apps/oxlint/src/lint.rs b/apps/oxlint/src/lint.rs index e267634fa3a37..94614c222354a 100644 --- a/apps/oxlint/src/lint.rs +++ b/apps/oxlint/src/lint.rs @@ -22,7 +22,6 @@ use oxc_linter::{ use crate::{ cli::{CliRunResult, LintCommand, MiscOptions, ReportUnusedDirectives, WarningOptions}, - js_plugins::RawTransferFileSystem, output_formatter::{LintCommandInfo, OutputFormatter}, walk::Walk, }; @@ -368,7 +367,21 @@ impl LintRunner { // Use `RawTransferFileSystem` if `ExternalLinter` exists. // This reads the source text into start of allocator, instead of the end. if has_external_linter { - lint_service.with_file_system(Box::new(RawTransferFileSystem)); + #[cfg(all( + feature = "napi", + target_pointer_width = "64", + target_endian = "little" + ))] + lint_service.with_file_system(Box::new(crate::js_plugins::RawTransferFileSystem)); + + #[cfg(not(all( + feature = "napi", + target_pointer_width = "64", + target_endian = "little" + )))] + unreachable!( + "On unsupported platforms, or with `napi` Cargo feature disabled, `ExternalLinter` should not exist" + ); } lint_service.run(&tx_error); diff --git a/apps/oxlint/src/main.rs b/apps/oxlint/src/main.rs deleted file mode 100644 index a1da54bc4cb60..0000000000000 --- a/apps/oxlint/src/main.rs +++ /dev/null @@ -1,5 +0,0 @@ -use oxlint::{cli::CliRunResult, lint}; - -fn main() -> CliRunResult { - lint(None) -} diff --git a/apps/oxlint/src/run.rs b/apps/oxlint/src/run.rs index 65cc1592907a6..7b2f2d17dcd05 100644 --- a/apps/oxlint/src/run.rs +++ b/apps/oxlint/src/run.rs @@ -1,11 +1,68 @@ -use std::io::BufWriter; +use std::{ + io::BufWriter, + process::{ExitCode, Termination}, +}; -use oxc_linter::ExternalLinter; +use napi::{ + Status, + bindgen_prelude::{FnArgs, Promise, Uint8Array}, + threadsafe_function::ThreadsafeFunction, +}; +use napi_derive::napi; use crate::{lint::LintRunner, result::CliRunResult}; +/// JS callback to load a JS plugin. +#[napi] +pub type JsLoadPluginCb = ThreadsafeFunction< + // Arguments + String, // Absolute path of plugin file + // Return value + Promise, // `PluginLoadResult`, serialized to JSON + // Arguments (repeated) + String, + // Error status + Status, + // CalleeHandled + false, +>; + +/// JS callback to lint a file. +#[napi] +pub type JsLintFileCb = ThreadsafeFunction< + // Arguments + FnArgs<( + String, // Absolute path of file to lint + u32, // Buffer ID + Option, // Buffer (optional) + Vec, // Array of rule IDs + )>, + // Return value + String, // `Vec`, serialized to JSON + // Arguments (repeated) + FnArgs<(String, u32, Option, Vec)>, + // Error status + Status, + // CalleeHandled + false, +>; + +/// NAPI entry point. +/// +/// JS side passes in two callbacks: +/// 1. `load_plugin`: Load a JS plugin from a file path. +/// 2. `lint_file`: Lint a file. +/// +/// Returns `true` if linting succeeded without errors, `false` otherwise. +#[expect(clippy::allow_attributes)] +#[allow(clippy::trailing_empty_array, clippy::unused_async)] // https://github.com/napi-rs/napi-rs/issues/2758 +#[napi] +pub async fn lint(load_plugin: JsLoadPluginCb, lint_file: JsLintFileCb) -> bool { + lint_impl(load_plugin, lint_file).report() == ExitCode::SUCCESS +} + /// Run the linter. -pub fn lint(mut external_linter: Option) -> CliRunResult { +fn lint_impl(load_plugin: JsLoadPluginCb, lint_file: JsLintFileCb) -> CliRunResult { init_tracing(); init_miette(); @@ -32,25 +89,24 @@ pub fn lint(mut external_linter: Option) -> CliRunResult { command.handle_threads(); - #[expect(clippy::print_stderr)] - if command.experimental_js_plugins { - // If no `ExternalLinter`, this function was not called by `napi/oxlint` - if external_linter.is_none() { - eprintln!("ERROR: JS plugins are not supported at present"); - return CliRunResult::InvalidOptionConfig; + let external_linter = if command.experimental_js_plugins { + // JS plugins are only supported on 64-bit little-endian platforms at present + #[cfg(all(target_pointer_width = "64", target_endian = "little"))] + { + Some(super::js_plugins::create_external_linter(load_plugin, lint_file)) } - // Exit early if not 64-bit little-endian, to avoid a panic later on when trying to create - // a fixed-size allocator for raw transfer - if cfg!(not(all(target_pointer_width = "64", target_endian = "little"))) { + #[cfg(not(all(target_pointer_width = "64", target_endian = "little")))] + #[expect(clippy::print_stderr)] + { eprintln!( "ERROR: JS plugins are only supported on 64-bit little-endian platforms at present" ); return CliRunResult::InvalidOptionConfig; } } else { - external_linter = None; - } + None + }; // stdio is blocked by LineWriter, use a BufWriter to reduce syscalls. // See `https://github.com/rust-lang/rust/issues/60673`. diff --git a/napi/oxlint/test/__snapshots__/e2e.test.ts.snap b/apps/oxlint/test/__snapshots__/e2e.test.ts.snap similarity index 100% rename from napi/oxlint/test/__snapshots__/e2e.test.ts.snap rename to apps/oxlint/test/__snapshots__/e2e.test.ts.snap diff --git a/napi/oxlint/test/compile-visitor.test.ts b/apps/oxlint/test/compile-visitor.test.ts similarity index 100% rename from napi/oxlint/test/compile-visitor.test.ts rename to apps/oxlint/test/compile-visitor.test.ts diff --git a/napi/oxlint/test/e2e.test.ts b/apps/oxlint/test/e2e.test.ts similarity index 97% rename from napi/oxlint/test/e2e.test.ts rename to apps/oxlint/test/e2e.test.ts index 9817faf98bf64..a12b9b07bb39a 100644 --- a/napi/oxlint/test/e2e.test.ts +++ b/apps/oxlint/test/e2e.test.ts @@ -5,10 +5,10 @@ import { describe, expect, it } from 'vitest'; import { execa } from 'execa'; const PACKAGE_ROOT_PATH = path.dirname(import.meta.dirname); -const ENTRY_POINT_PATH = path.join(PACKAGE_ROOT_PATH, 'dist/index.js'); +const CLI_PATH = path.join(PACKAGE_ROOT_PATH, 'dist/cli.js'); async function runOxlintWithoutPlugins(cwd: string, args: string[] = []) { - return await execa('node', [ENTRY_POINT_PATH, ...args], { + return await execa('node', [CLI_PATH, ...args], { cwd: path.join(PACKAGE_ROOT_PATH, cwd), reject: false, }); diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin/.oxlintrc.json b/apps/oxlint/test/fixtures/basic_custom_plugin/.oxlintrc.json similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin/.oxlintrc.json rename to apps/oxlint/test/fixtures/basic_custom_plugin/.oxlintrc.json diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin/index.js b/apps/oxlint/test/fixtures/basic_custom_plugin/index.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin/index.js rename to apps/oxlint/test/fixtures/basic_custom_plugin/index.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin/test_plugin/index.js b/apps/oxlint/test/fixtures/basic_custom_plugin/test_plugin/index.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin/test_plugin/index.js rename to apps/oxlint/test/fixtures/basic_custom_plugin/test_plugin/index.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/.oxlintrc.json b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/.oxlintrc.json similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/.oxlintrc.json rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/.oxlintrc.json diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/01.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/01.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/01.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/01.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/02.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/02.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/02.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/02.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/03.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/03.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/03.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/03.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/04.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/04.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/04.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/04.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/05.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/05.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/05.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/05.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/06.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/06.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/06.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/06.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/07.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/07.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/07.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/07.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/08.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/08.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/08.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/08.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/09.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/09.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/09.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/09.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/10.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/10.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/10.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/10.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/11.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/11.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/11.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/11.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/12.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/12.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/12.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/12.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/13.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/13.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/13.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/13.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/14.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/14.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/14.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/14.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/15.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/15.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/15.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/15.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/16.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/16.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/16.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/16.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/17.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/17.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/17.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/17.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/18.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/18.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/18.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/18.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/19.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/19.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/19.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/19.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/20.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/20.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/files/20.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/files/20.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_many_files/test_plugin/index.js b/apps/oxlint/test/fixtures/basic_custom_plugin_many_files/test_plugin/index.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_many_files/test_plugin/index.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_many_files/test_plugin/index.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_multiple_rules/.oxlintrc.json b/apps/oxlint/test/fixtures/basic_custom_plugin_multiple_rules/.oxlintrc.json similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_multiple_rules/.oxlintrc.json rename to apps/oxlint/test/fixtures/basic_custom_plugin_multiple_rules/.oxlintrc.json diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_multiple_rules/index.js b/apps/oxlint/test/fixtures/basic_custom_plugin_multiple_rules/index.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_multiple_rules/index.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_multiple_rules/index.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_multiple_rules/test_plugin/index.js b/apps/oxlint/test/fixtures/basic_custom_plugin_multiple_rules/test_plugin/index.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_multiple_rules/test_plugin/index.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_multiple_rules/test_plugin/index.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_warn_severity/.oxlintrc.json b/apps/oxlint/test/fixtures/basic_custom_plugin_warn_severity/.oxlintrc.json similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_warn_severity/.oxlintrc.json rename to apps/oxlint/test/fixtures/basic_custom_plugin_warn_severity/.oxlintrc.json diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_warn_severity/index.js b/apps/oxlint/test/fixtures/basic_custom_plugin_warn_severity/index.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_warn_severity/index.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_warn_severity/index.js diff --git a/napi/oxlint/test/fixtures/basic_custom_plugin_warn_severity/test_plugin/index.js b/apps/oxlint/test/fixtures/basic_custom_plugin_warn_severity/test_plugin/index.js similarity index 100% rename from napi/oxlint/test/fixtures/basic_custom_plugin_warn_severity/test_plugin/index.js rename to apps/oxlint/test/fixtures/basic_custom_plugin_warn_severity/test_plugin/index.js diff --git a/napi/oxlint/test/fixtures/built_in_errors/.oxlintrc.json b/apps/oxlint/test/fixtures/built_in_errors/.oxlintrc.json similarity index 100% rename from napi/oxlint/test/fixtures/built_in_errors/.oxlintrc.json rename to apps/oxlint/test/fixtures/built_in_errors/.oxlintrc.json diff --git a/napi/oxlint/test/fixtures/built_in_errors/index.js b/apps/oxlint/test/fixtures/built_in_errors/index.js similarity index 100% rename from napi/oxlint/test/fixtures/built_in_errors/index.js rename to apps/oxlint/test/fixtures/built_in_errors/index.js diff --git a/napi/oxlint/test/fixtures/built_in_no_errors/.oxlintrc.json b/apps/oxlint/test/fixtures/built_in_no_errors/.oxlintrc.json similarity index 100% rename from napi/oxlint/test/fixtures/built_in_no_errors/.oxlintrc.json rename to apps/oxlint/test/fixtures/built_in_no_errors/.oxlintrc.json diff --git a/napi/oxlint/test/fixtures/built_in_no_errors/index.js b/apps/oxlint/test/fixtures/built_in_no_errors/index.js similarity index 100% rename from napi/oxlint/test/fixtures/built_in_no_errors/index.js rename to apps/oxlint/test/fixtures/built_in_no_errors/index.js diff --git a/napi/oxlint/test/fixtures/context_properties/.oxlintrc.json b/apps/oxlint/test/fixtures/context_properties/.oxlintrc.json similarity index 100% rename from napi/oxlint/test/fixtures/context_properties/.oxlintrc.json rename to apps/oxlint/test/fixtures/context_properties/.oxlintrc.json diff --git a/napi/oxlint/test/fixtures/context_properties/files/1.js b/apps/oxlint/test/fixtures/context_properties/files/1.js similarity index 100% rename from napi/oxlint/test/fixtures/context_properties/files/1.js rename to apps/oxlint/test/fixtures/context_properties/files/1.js diff --git a/napi/oxlint/test/fixtures/context_properties/files/2.js b/apps/oxlint/test/fixtures/context_properties/files/2.js similarity index 100% rename from napi/oxlint/test/fixtures/context_properties/files/2.js rename to apps/oxlint/test/fixtures/context_properties/files/2.js diff --git a/napi/oxlint/test/fixtures/context_properties/test_plugin/index.js b/apps/oxlint/test/fixtures/context_properties/test_plugin/index.js similarity index 100% rename from napi/oxlint/test/fixtures/context_properties/test_plugin/index.js rename to apps/oxlint/test/fixtures/context_properties/test_plugin/index.js diff --git a/napi/oxlint/test/fixtures/custom_plugin_disable_directives/.oxlintrc.json b/apps/oxlint/test/fixtures/custom_plugin_disable_directives/.oxlintrc.json similarity index 100% rename from napi/oxlint/test/fixtures/custom_plugin_disable_directives/.oxlintrc.json rename to apps/oxlint/test/fixtures/custom_plugin_disable_directives/.oxlintrc.json diff --git a/napi/oxlint/test/fixtures/custom_plugin_disable_directives/index.js b/apps/oxlint/test/fixtures/custom_plugin_disable_directives/index.js similarity index 100% rename from napi/oxlint/test/fixtures/custom_plugin_disable_directives/index.js rename to apps/oxlint/test/fixtures/custom_plugin_disable_directives/index.js diff --git a/napi/oxlint/test/fixtures/custom_plugin_disable_directives/test_plugin/index.js b/apps/oxlint/test/fixtures/custom_plugin_disable_directives/test_plugin/index.js similarity index 100% rename from napi/oxlint/test/fixtures/custom_plugin_disable_directives/test_plugin/index.js rename to apps/oxlint/test/fixtures/custom_plugin_disable_directives/test_plugin/index.js diff --git a/napi/oxlint/test/fixtures/custom_plugin_missing_rule/.oxlintrc.json b/apps/oxlint/test/fixtures/custom_plugin_missing_rule/.oxlintrc.json similarity index 100% rename from napi/oxlint/test/fixtures/custom_plugin_missing_rule/.oxlintrc.json rename to apps/oxlint/test/fixtures/custom_plugin_missing_rule/.oxlintrc.json diff --git a/napi/oxlint/test/fixtures/custom_plugin_missing_rule/test_plugin/index.js b/apps/oxlint/test/fixtures/custom_plugin_missing_rule/test_plugin/index.js similarity index 100% rename from napi/oxlint/test/fixtures/custom_plugin_missing_rule/test_plugin/index.js rename to apps/oxlint/test/fixtures/custom_plugin_missing_rule/test_plugin/index.js diff --git a/napi/oxlint/test/fixtures/custom_plugin_via_overrides/.oxlintrc.json b/apps/oxlint/test/fixtures/custom_plugin_via_overrides/.oxlintrc.json similarity index 100% rename from napi/oxlint/test/fixtures/custom_plugin_via_overrides/.oxlintrc.json rename to apps/oxlint/test/fixtures/custom_plugin_via_overrides/.oxlintrc.json diff --git a/napi/oxlint/test/fixtures/custom_plugin_via_overrides/index.js b/apps/oxlint/test/fixtures/custom_plugin_via_overrides/index.js similarity index 100% rename from napi/oxlint/test/fixtures/custom_plugin_via_overrides/index.js rename to apps/oxlint/test/fixtures/custom_plugin_via_overrides/index.js diff --git a/napi/oxlint/test/fixtures/custom_plugin_via_overrides/test_plugin/index.js b/apps/oxlint/test/fixtures/custom_plugin_via_overrides/test_plugin/index.js similarity index 100% rename from napi/oxlint/test/fixtures/custom_plugin_via_overrides/test_plugin/index.js rename to apps/oxlint/test/fixtures/custom_plugin_via_overrides/test_plugin/index.js diff --git a/napi/oxlint/test/fixtures/custom_plugin_via_overrides_missing_rule/.oxlintrc.json b/apps/oxlint/test/fixtures/custom_plugin_via_overrides_missing_rule/.oxlintrc.json similarity index 100% rename from napi/oxlint/test/fixtures/custom_plugin_via_overrides_missing_rule/.oxlintrc.json rename to apps/oxlint/test/fixtures/custom_plugin_via_overrides_missing_rule/.oxlintrc.json diff --git a/napi/oxlint/test/fixtures/custom_plugin_via_overrides_missing_rule/index.js b/apps/oxlint/test/fixtures/custom_plugin_via_overrides_missing_rule/index.js similarity index 100% rename from napi/oxlint/test/fixtures/custom_plugin_via_overrides_missing_rule/index.js rename to apps/oxlint/test/fixtures/custom_plugin_via_overrides_missing_rule/index.js diff --git a/napi/oxlint/test/fixtures/custom_plugin_via_overrides_missing_rule/test_plugin/index.js b/apps/oxlint/test/fixtures/custom_plugin_via_overrides_missing_rule/test_plugin/index.js similarity index 100% rename from napi/oxlint/test/fixtures/custom_plugin_via_overrides_missing_rule/test_plugin/index.js rename to apps/oxlint/test/fixtures/custom_plugin_via_overrides_missing_rule/test_plugin/index.js diff --git a/napi/oxlint/test/fixtures/missing_custom_plugin/.oxlintrc.json b/apps/oxlint/test/fixtures/missing_custom_plugin/.oxlintrc.json similarity index 100% rename from napi/oxlint/test/fixtures/missing_custom_plugin/.oxlintrc.json rename to apps/oxlint/test/fixtures/missing_custom_plugin/.oxlintrc.json diff --git a/napi/oxlint/test/fixtures/utf16_offsets/.oxlintrc.json b/apps/oxlint/test/fixtures/utf16_offsets/.oxlintrc.json similarity index 100% rename from napi/oxlint/test/fixtures/utf16_offsets/.oxlintrc.json rename to apps/oxlint/test/fixtures/utf16_offsets/.oxlintrc.json diff --git a/napi/oxlint/test/fixtures/utf16_offsets/index.js b/apps/oxlint/test/fixtures/utf16_offsets/index.js similarity index 100% rename from napi/oxlint/test/fixtures/utf16_offsets/index.js rename to apps/oxlint/test/fixtures/utf16_offsets/index.js diff --git a/napi/oxlint/test/fixtures/utf16_offsets/test_plugin/index.js b/apps/oxlint/test/fixtures/utf16_offsets/test_plugin/index.js similarity index 100% rename from napi/oxlint/test/fixtures/utf16_offsets/test_plugin/index.js rename to apps/oxlint/test/fixtures/utf16_offsets/test_plugin/index.js diff --git a/napi/oxlint/tsconfig.json b/apps/oxlint/tsconfig.json similarity index 75% rename from napi/oxlint/tsconfig.json rename to apps/oxlint/tsconfig.json index 00460b3a6cc15..f1a7450d93b5b 100644 --- a/napi/oxlint/tsconfig.json +++ b/apps/oxlint/tsconfig.json @@ -6,5 +6,9 @@ "target": "ESNext", "noImplicitAny": true, "skipLibCheck": true - } + }, + "exclude": [ + "node_modules", + "fixtures" + ] } diff --git a/napi/oxlint/tsdown.config.ts b/apps/oxlint/tsdown.config.ts similarity index 91% rename from napi/oxlint/tsdown.config.ts rename to apps/oxlint/tsdown.config.ts index f887d9b1f4670..80df92f41058f 100644 --- a/napi/oxlint/tsdown.config.ts +++ b/apps/oxlint/tsdown.config.ts @@ -1,7 +1,7 @@ import { defineConfig } from 'tsdown'; export default defineConfig({ - entry: ['src-js/index.ts', 'src-js/plugins/index.ts'], + entry: ['src-js/cli.ts', 'src-js/plugins/index.ts'], format: ['esm'], platform: 'node', target: 'node20', diff --git a/napi/oxlint/vitest.config.mts b/apps/oxlint/vitest.config.mts similarity index 100% rename from napi/oxlint/vitest.config.mts rename to apps/oxlint/vitest.config.mts diff --git a/dprint.json b/dprint.json index ba0517d96ab97..1e0f16c09e8dd 100644 --- a/dprint.json +++ b/dprint.json @@ -17,8 +17,8 @@ "**/CHANGELOG.md", "pnpm-workspace.yaml", "pnpm-lock.yaml", - "napi/oxlint/src-js/bindings.js", - "napi/oxlint/src-js/bindings.d.ts", + "apps/oxlint/src-js/bindings.js", + "apps/oxlint/src-js/bindings.d.ts", "napi/{transform,minify,playground}/index.js", "napi/{parser,transform,minify,playground}/index.d.ts", "napi/{parser,transform,minify,playground}/*.wasi-browser.js", diff --git a/napi/oxlint/.gitignore b/napi/oxlint/.gitignore deleted file mode 100644 index 849ddff3b7ec9..0000000000000 --- a/napi/oxlint/.gitignore +++ /dev/null @@ -1 +0,0 @@ -dist/ diff --git a/napi/oxlint/Cargo.toml b/napi/oxlint/Cargo.toml deleted file mode 100644 index 3caa0d3cc5477..0000000000000 --- a/napi/oxlint/Cargo.toml +++ /dev/null @@ -1,38 +0,0 @@ -[package] -name = "oxc_linter_napi" -version = "0.1.0" -authors.workspace = true -categories.workspace = true -edition.workspace = true -homepage.workspace = true -include = ["/src", "build.rs"] -keywords.workspace = true -license.workspace = true -publish = false -repository.workspace = true -rust-version.workspace = true -description.workspace = true - -[lints] -workspace = true - -[lib] -crate-type = ["cdylib", "lib"] -test = false -doctest = false - -[dependencies] -oxc_allocator = { workspace = true, features = ["fixed_size"] } -oxlint = { workspace = true, features = ["allocator"] } - -napi = { workspace = true, features = ["async"] } -napi-derive = { workspace = true } -serde_json = { workspace = true } -tokio = { workspace = true, features = ["rt-multi-thread"] } - -[build-dependencies] -napi-build = { workspace = true } - -[features] -default = [] -force_test_reporter = ["oxlint/force_test_reporter"] diff --git a/napi/oxlint/README.md b/napi/oxlint/README.md deleted file mode 100644 index 6c1e88e453bfd..0000000000000 --- a/napi/oxlint/README.md +++ /dev/null @@ -1 +0,0 @@ -# Oxlint 2 diff --git a/napi/oxlint/src/lib.rs b/napi/oxlint/src/lib.rs deleted file mode 100644 index c0a763e3db19c..0000000000000 --- a/napi/oxlint/src/lib.rs +++ /dev/null @@ -1,76 +0,0 @@ -use std::process::{ExitCode, Termination}; - -use napi::{ - Status, - bindgen_prelude::{FnArgs, Promise, Uint8Array}, - threadsafe_function::ThreadsafeFunction, -}; -use napi_derive::napi; - -use oxlint::lint as oxlint_lint; - -// JS plugins are only supported on 64-bit little-endian platforms at present. -// Note: `raw_transfer_constants` module will not compile on 32-bit systems. -#[cfg(all(target_pointer_width = "64", target_endian = "little"))] -mod generated { - pub mod raw_transfer_constants; -} - -#[cfg(all(target_pointer_width = "64", target_endian = "little"))] -mod external_linter; - -/// JS callback to load a JS plugin. -#[napi] -pub type JsLoadPluginCb = ThreadsafeFunction< - // Arguments - String, // Absolute path of plugin file - // Return value - Promise, // `PluginLoadResult`, serialized to JSON - // Arguments (repeated) - String, - // Error status - Status, - // CalleeHandled - false, ->; - -/// JS callback to lint a file. -#[napi] -pub type JsLintFileCb = ThreadsafeFunction< - // Arguments - FnArgs<( - String, // Absolute path of file to lint - u32, // Buffer ID - Option, // Buffer (optional) - Vec, // Array of rule IDs - )>, - // Return value - String, // `Vec`, serialized to JSON - // Arguments (repeated) - FnArgs<(String, u32, Option, Vec)>, - // Error status - Status, - // CalleeHandled - false, ->; - -/// NAPI entry point. -/// -/// JS side passes in two callbacks: -/// 1. `load_plugin`: Load a JS plugin from a file path. -/// 2. `lint_file`: Lint a file. -/// -/// Returns `true` if linting succeeded without errors, `false` otherwise. -#[expect(clippy::allow_attributes)] -#[allow(clippy::trailing_empty_array, clippy::unused_async)] // https://github.com/napi-rs/napi-rs/issues/2758 -#[napi] -pub async fn lint(load_plugin: JsLoadPluginCb, lint_file: JsLintFileCb) -> bool { - // JS plugins are only supported on 64-bit little-endian platforms at present - #[cfg(all(target_pointer_width = "64", target_endian = "little"))] - let external_linter = Some(external_linter::create_external_linter(load_plugin, lint_file)); - - #[cfg(not(all(target_pointer_width = "64", target_endian = "little")))] - let external_linter = None; - - oxlint_lint(external_linter).report() == ExitCode::SUCCESS -} diff --git a/npm/oxlint/bin/oxlint b/npm/oxlint/bin/oxlint index 40a5c240103a4..1d64f2662785b 100755 --- a/npm/oxlint/bin/oxlint +++ b/npm/oxlint/bin/oxlint @@ -1,149 +1,19 @@ #!/usr/bin/env node -const isMusl = () => { - let musl = false; - if (process.platform === "linux") { - musl = isMuslFromFilesystem(); - if (musl === null) { - musl = isMuslFromReport(); - } - if (musl === null) { - musl = isMuslFromChildProcess(); - } - } - return musl; -}; - -const isFileMusl = (f) => f.includes("libc.musl-") || f.includes("ld-musl-"); - -const isMuslFromFilesystem = () => { - const { readFileSync } = require("fs"); - try { - return readFileSync("/usr/bin/ldd", "utf-8").includes("musl"); - } catch(_error) { - return null; - } -}; - -const isMuslFromReport = () => { - const report = - typeof process.report.getReport === "function" - ? process.report.getReport() - : null; - if (!report) { - return null; - } - if (report.header && report.header.glibcVersionRuntime) { - return false; - } - if (Array.isArray(report.sharedObjects)) { - if (report.sharedObjects.some(isFileMusl)) { - return true; - } - } - return false; -}; - -const isMuslFromChildProcess = () => { - try { - return require("child_process") - .execSync("ldd --version", { encoding: "utf8" }) - .includes("musl"); - } catch (e) { - // If we reach this case, we don't know if the system is musl or not, so is better to just fallback to false - return false; - } -}; - -const { platform, arch, env, version, release } = process; - -const PLATFORMS = { - win32: { - x64: { - musl: "@oxlint/win32-x64/oxlint.exe", - gnu: "@oxlint/win32-x64/oxlint.exe", - }, - arm64: { - musl: "@oxlint/win32-arm64/oxlint.exe", - gnu: "@oxlint/win32-arm64/oxlint.exe", - }, - }, - darwin: { - x64: { - musl: "@oxlint/darwin-x64/oxlint", - gnu: "@oxlint/darwin-x64/oxlint", - }, - arm64: { - musl: "@oxlint/darwin-arm64/oxlint", - gnu: "@oxlint/darwin-arm64/oxlint", - }, - }, - linux: { - x64: { - musl: "@oxlint/linux-x64-musl/oxlint", - gnu: "@oxlint/linux-x64-gnu/oxlint", - }, - arm64: { - musl: "@oxlint/linux-arm64-musl/oxlint", - gnu: "@oxlint/linux-arm64-gnu/oxlint", - }, - }, -}; - -let binPath = ( - PLATFORMS && - PLATFORMS[platform] && - PLATFORMS[platform][arch] && - PLATFORMS[platform][arch][isMusl() ? "musl" : "gnu"] -) || null; - -if (binPath) { - const result = require("child_process").spawnSync( - require.resolve(binPath), - process.argv.slice(2), - { - shell: false, - stdio: "inherit", - env: Object.assign({}, env, { - JS_RUNTIME_VERSION: version, - JS_RUNTIME_NAME: release.name, - NODE_PACKAGE_MANAGER: detectPackageManager(), - }), - } - ); - - if (result.error) { - throw result.error; - } - - process.exitCode = result.status; -} else { - let target = `${platform}-${arch}`; - if (isMusl()) { - target = `${target}-musl`; - } - console.error( - `The oxlint CLI package doesn't ship with prebuilt binaries for your platform (${target}) yet. ` + - "You can create an issue at https://github.com/oxc-project/oxc/issues for support." - ); +// This script is run as CommonJS, so use dynamic import to load ESM module `dist/cli.js`. +// Even if runtime supports require(ESM), can't use `require` here, because `dist/cli.js` +// uses top-level `await`. +// +// `dist/cli.js` uses require(ESM) internally, but only on path where `--experimental-js-plugins` +// CLI option is used. So we still support runtimes without require(ESM) for users who aren't +// using experimental options. +import("../dist/cli.js").catch(onError); + +function onError(err) { + console.error(err); + // Note: NodeJS recommends setting `process.exitCode` instead of calling `process.exit()`. + // `process.exit()` kills the process immediately and `stdout` may not be flushed before process dies. + // https://nodejs.org/api/process.html#processexitcode + // Process should exit immediately after this anyway, because event loop is empty. process.exitCode = 1; } - -/** - * NPM, Yarn, and other package manager set the `npm_config_user_agent`. It has the following format: - * - * ``` - * "npm/8.3.0 node/v16.13.2 win32 x64 workspaces/false - * ``` - * - * @returns The package manager string (`npm/8.3.0`) or null if the user agent string isn't set. - */ -function detectPackageManager() { - const userAgent = env.npm_config_user_agent; - - if (userAgent == null) { - return null; - } - - return userAgent.split(" ")[0]; -} diff --git a/npm/oxlint/package.json b/npm/oxlint/package.json index d616e3c12bdab..5c463687e40dc 100644 --- a/npm/oxlint/package.json +++ b/npm/oxlint/package.json @@ -27,6 +27,7 @@ "bin/oxlint", "bin/oxc_language_server", "configuration_schema.json", + "dist", "README.md" ] } diff --git a/npm/oxlint/scripts/generate-packages.mjs b/npm/oxlint/scripts/generate-packages.mjs index 1ccfc6e735954..bd62879f33b54 100644 --- a/npm/oxlint/scripts/generate-packages.mjs +++ b/npm/oxlint/scripts/generate-packages.mjs @@ -6,10 +6,12 @@ import { fileURLToPath } from 'node:url'; const OXLINT_BIN_NAME = 'oxlint'; const OXLS_BIN_NAME = 'oxc_language_server'; -const OXLINT_ROOT = resolve(fileURLToPath(import.meta.url), '../..'); -const PACKAGES_ROOT = resolve(OXLINT_ROOT, '..'); +const OXLINT_ROOT = resolve(fileURLToPath(import.meta.url), '../..'); // /npm/oxlint +const PACKAGES_ROOT = resolve(OXLINT_ROOT, '..'); // /npm const REPO_ROOT = resolve(PACKAGES_ROOT, '..'); -const MANIFEST_PATH = resolve(OXLINT_ROOT, 'package.json'); +const MANIFEST_PATH = resolve(OXLINT_ROOT, 'package.json'); // /npm/oxlint/package.json +const OXLINT_DIST_SRC = resolve(REPO_ROOT, 'apps/oxlint/dist'); // /apps/oxlint/dist +const OXLINT_DIST_DEST = resolve(OXLINT_ROOT, 'dist'); // /npm/oxlint/dist const rootManifest = JSON.parse( fs.readFileSync(MANIFEST_PATH).toString('utf-8'), @@ -42,6 +44,8 @@ function generateNativePackage(target) { const manifest = { name: packageName, version, + type: 'commonjs', + main: `${OXLINT_BIN_NAME}.${target}.node`, author, license, homepage, @@ -51,7 +55,7 @@ function generateNativePackage(target) { cpu: [arch], ...libc, publishConfig: { - executableFiles: ['oxlint', 'oxc_language_server'], + executableFiles: ['oxc_language_server'], }, }; @@ -59,21 +63,16 @@ function generateNativePackage(target) { console.log(`Create manifest ${manifestPath}`); fs.writeFileSync(manifestPath, JSON.stringify(manifest)); - // Copy the binary - const ext = platform === 'win32' ? '.exe' : ''; - - const oxlintBinSource = resolve( - REPO_ROOT, - `${OXLINT_BIN_NAME}-${target}${ext}`, - ); - const oxlintBinTarget = resolve(packageRoot, `${OXLINT_BIN_NAME}${ext}`); + // Copy the binaries + const oxlintBinSource = resolve(REPO_ROOT, `${OXLINT_BIN_NAME}.${target}.node`); + const oxlintBinTarget = resolve(packageRoot, `${OXLINT_BIN_NAME}.${target}.node`); + const ext = platform === 'win32' ? '.exe' : ''; const oxlsBinSource = resolve(REPO_ROOT, `${OXLS_BIN_NAME}-${target}${ext}`); const oxlsBinTarget = resolve(packageRoot, `${OXLS_BIN_NAME}${ext}`); console.log(`Copy linter binary ${oxlintBinSource}`); fs.copyFileSync(oxlintBinSource, oxlintBinTarget); - fs.chmodSync(oxlintBinTarget, 0o755); console.log(`Copy language server binary ${oxlsBinSource}`); fs.copyFileSync(oxlsBinSource, oxlsBinTarget); @@ -111,8 +110,13 @@ function writeManifest() { fs.writeFileSync(manifestPath, content); } -// NOTE: Must update npm/oxlint/bin/oxlint -// and npm/oxlint/bin/oxc_language_server +// Copy `dist` directory from `apps/oxlint/dist` to `npm/oxlint/dist`. +// `apps/oxlint/scripts/build.js` must be run before this script to create the `dist` directory. +function copyDistFiles() { + fs.cpSync(OXLINT_DIST_SRC, OXLINT_DIST_DEST, { recursive: true }); +} + +// NOTE: Must update npm/oxlint/bin/oxc_language_server const TARGETS = [ 'win32-x64', 'win32-arm64', @@ -129,3 +133,4 @@ for (const target of TARGETS) { } writeManifest(); +copyDistFiles(); diff --git a/oxlintrc.json b/oxlintrc.json index 9a0b0eb1a32cc..5651c90c35758 100644 --- a/oxlintrc.json +++ b/oxlintrc.json @@ -42,6 +42,7 @@ "npm/runtime/**", "tasks/coverage/**", "crates/oxc_semantic/tests/**", - "napi/**" // TODO + "napi/**", // TODO + "apps/oxlint" // TODO ] } diff --git a/package.json b/package.json index 426cdef05e943..dd6bc56d0c4b7 100644 --- a/package.json +++ b/package.json @@ -3,10 +3,10 @@ "private": true, "packageManager": "pnpm@10.16.1", "scripts": { - "build": "pnpm --workspace-concurrency=1 --filter './napi/*' build", - "build-dev": "pnpm --workspace-concurrency=1 --filter './napi/*' build-dev", - "build-test": "pnpm --workspace-concurrency=1 --filter './napi/*' build-test", - "test": "pnpm --workspace-concurrency=1 --filter './napi/*' test", + "build": "pnpm --workspace-concurrency=1 --filter './napi/*' --filter './apps/*' build", + "build-dev": "pnpm --workspace-concurrency=1 --filter './napi/*' --filter './apps/*' build-dev", + "build-test": "pnpm --workspace-concurrency=1 --filter './napi/*' --filter './apps/*' build-test", + "test": "pnpm --workspace-concurrency=1 --filter './napi/*' --filter './apps/*' test", "lint": "oxlint -c oxlintrc.json --type-aware --deny-warnings" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8255b700106dc..299342aa16158 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -42,6 +42,21 @@ importers: specifier: 'catalog:' version: 3.2.4(@types/node@24.3.1)(@vitest/browser@3.2.4)(jiti@2.5.1) + apps/oxlint: + devDependencies: + execa: + specifier: ^9.6.0 + version: 9.6.0 + tsdown: + specifier: ^0.15.0 + version: 0.15.1(typescript@5.9.2) + typescript: + specifier: 'catalog:' + version: 5.9.2 + vitest: + specifier: 'catalog:' + version: 3.2.4(@types/node@24.3.1)(@vitest/browser@3.2.4)(jiti@2.5.1) + editors/vscode: dependencies: vscode-languageclient: @@ -91,21 +106,6 @@ importers: specifier: 'catalog:' version: 3.2.4(@types/node@24.3.1)(@vitest/browser@3.2.4)(jiti@2.5.1) - napi/oxlint: - devDependencies: - execa: - specifier: ^9.6.0 - version: 9.6.0 - tsdown: - specifier: ^0.15.0 - version: 0.15.1(typescript@5.9.2) - typescript: - specifier: 'catalog:' - version: 5.9.2 - vitest: - specifier: 'catalog:' - version: 3.2.4(@types/node@24.3.1)(@vitest/browser@3.2.4)(jiti@2.5.1) - napi/parser: dependencies: '@oxc-project/types': diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index b953b78d9fb35..c022c5a711f02 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,4 +1,5 @@ packages: + - apps/* - napi/* - wasm/* - npm/* diff --git a/tasks/ast_tools/src/generators/raw_transfer.rs b/tasks/ast_tools/src/generators/raw_transfer.rs index 902677ad58618..0e40ba47cacc5 100644 --- a/tasks/ast_tools/src/generators/raw_transfer.rs +++ b/tasks/ast_tools/src/generators/raw_transfer.rs @@ -9,7 +9,7 @@ use quote::quote; use rustc_hash::FxHashSet; use crate::{ - ALLOCATOR_CRATE_PATH, Generator, NAPI_OXLINT_PACKAGE_PATH, NAPI_PARSER_PACKAGE_PATH, + ALLOCATOR_CRATE_PATH, Generator, NAPI_PARSER_PACKAGE_PATH, OXLINT_APP_PATH, codegen::{Codegen, DeriveId}, derives::estree::{ get_fieldless_variant_value, get_struct_field_name, should_flatten_field, @@ -77,7 +77,7 @@ impl Generator for RawTransferGenerator { code: constants_js.clone(), }, Output::Javascript { - path: format!("{NAPI_OXLINT_PACKAGE_PATH}/src-js/generated/constants.mjs"), + path: format!("{OXLINT_APP_PATH}/src-js/generated/constants.mjs"), code: constants_js, }, Output::Rust { @@ -85,7 +85,7 @@ impl Generator for RawTransferGenerator { tokens: constants_rust.clone(), }, Output::Rust { - path: format!("{NAPI_OXLINT_PACKAGE_PATH}/src/generated/raw_transfer_constants.rs"), + path: format!("{OXLINT_APP_PATH}/src/generated/raw_transfer_constants.rs"), tokens: constants_rust.clone(), }, Output::Rust { diff --git a/tasks/ast_tools/src/main.rs b/tasks/ast_tools/src/main.rs index 499f5395b83a0..9c3914ac8762c 100644 --- a/tasks/ast_tools/src/main.rs +++ b/tasks/ast_tools/src/main.rs @@ -257,7 +257,7 @@ const TYPESCRIPT_DEFINITIONS_PATH: &str = "npm/oxc-types/types.d.ts"; const NAPI_PARSER_PACKAGE_PATH: &str = "napi/parser"; /// Path to NAPI oxlint package -const NAPI_OXLINT_PACKAGE_PATH: &str = "napi/oxlint"; +const OXLINT_APP_PATH: &str = "apps/oxlint"; /// Path to write AST changes filter list to const AST_CHANGES_WATCH_LIST_PATH: &str = ".github/generated/ast_changes_watch_list.yml"; diff --git a/tasks/website/Cargo.toml b/tasks/website/Cargo.toml index 2b67eb62610d3..53cf23097b075 100644 --- a/tasks/website/Cargo.toml +++ b/tasks/website/Cargo.toml @@ -21,7 +21,8 @@ bpaf = { workspace = true, features = ["docgen"] } handlebars = { workspace = true } itertools = { workspace = true } oxc_linter = { workspace = true, features = ["ruledocs"] } -oxlint = { path = "../../apps/oxlint" } +# Disable default features to avoid `napi-rs` dependency, which causes linker errors +oxlint = { path = "../../apps/oxlint", default-features = false } pico-args = { workspace = true } project-root = { workspace = true } schemars = { workspace = true }