mirror of
https://github.com/hanzoai/unrs-resolver.git
synced 2026-09-24 17:03:52 +00:00
Merge remote-tracking branch 'upstream/main' into chore/merge_upstream
This commit is contained in:
@@ -3,3 +3,6 @@
|
||||
# See https://x.com/Brooooook_lyn/status/1895848334692401270
|
||||
[target.'cfg(target_env = "gnu")']
|
||||
rustflags = ["-C", "link-args=-Wl,-z,nodelete"]
|
||||
|
||||
[target.wasm32-wasip1-threads]
|
||||
rustflags = ["-Clink-args=-zstack-size=64000000 --max-memory=4294967296"]
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you find any potential vulnerability, join our [discord channel](https://discord.gg/9uXCAwqQZW) and contact Boshen.
|
||||
@@ -1,46 +1,33 @@
|
||||
name: Pnpm
|
||||
name: Setup Node and pnpm
|
||||
|
||||
description: Install pnpm
|
||||
description: Setup Node.js and pnpm with caching, and install yarn fixtures
|
||||
|
||||
inputs:
|
||||
architecture:
|
||||
description: The architecture to use
|
||||
required: false
|
||||
description: "Optional architecture for Node.js (e.g., x64, arm64). If not specified, defaults to the runner architecture."
|
||||
|
||||
cpu:
|
||||
description: The cpu architecture to use
|
||||
required: false
|
||||
description: "Optional CPU architecture for pnpm supportedArchitectures configuration (e.g., x64, arm64)."
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
|
||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
- uses: oxc-project/setup-node@ab97f03642370d79a7e96dd286bd02a1be40e0ba # v1.3.0
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
architecture: ${{ inputs.architecture }}
|
||||
cache: pnpm
|
||||
cpu: ${{ inputs.cpu }}
|
||||
|
||||
- if: ${{ inputs.cpu }}
|
||||
shell: bash
|
||||
run: pnpm config set supportedArchitectures.cpu "${CPU_ARCH}"
|
||||
env:
|
||||
CPU_ARCH: ${{ inputs.cpu }}
|
||||
|
||||
- name: pnpm
|
||||
- name: Install yarn fixtures
|
||||
shell: bash
|
||||
run: |
|
||||
corepack enable
|
||||
pnpm install
|
||||
|
||||
- name: yarn pnp
|
||||
shell: bash
|
||||
run: |
|
||||
cd fixtures/pnp
|
||||
yarn install
|
||||
|
||||
cd ../global-pnp
|
||||
cd global-pnp
|
||||
yarn install
|
||||
|
||||
cd ../yarn
|
||||
cd ../../yarn
|
||||
yarn install
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": ["github>Boshen/renovate"],
|
||||
"ignorePaths": ["**/node_modules/**", "**/fixtures/**"],
|
||||
"packageRules": [
|
||||
{
|
||||
"groupName": "pnp",
|
||||
"matchManagers": ["cargo"],
|
||||
"matchPackageNames": ["pnp"],
|
||||
"rangeStrategy": "auto",
|
||||
"schedule": ["at any time"],
|
||||
"automergeSchedule": ["at any time"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -16,31 +16,18 @@ jobs:
|
||||
autofix:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1
|
||||
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
|
||||
|
||||
- uses: oxc-project/setup-rust@cd82e1efec7fef815e2c23d296756f31c7cdc03d # v1.0.0
|
||||
- uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
|
||||
with:
|
||||
restore-cache: false
|
||||
tools: just,cargo-shear@1,dprint
|
||||
tools: just,cargo-shear@1
|
||||
components: rustfmt
|
||||
|
||||
- name: Restore dprint plugin cache
|
||||
id: cache-restore
|
||||
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
with:
|
||||
key: dprint-autofix-ci-${{ runner.os }}-${{ hashFiles('dprint.json') }}
|
||||
path: ~/.cache/dprint
|
||||
- uses: ./.github/actions/pnpm
|
||||
|
||||
- run: just fmt
|
||||
|
||||
- uses: autofix-ci/action@635ffb0c9798bd160680f18fd73371e355b85f27 # v1.3.2
|
||||
- uses: autofix-ci/action@c5b2d67aa2274e7b5a18224e8171550871fc7e4a # v1.3.4
|
||||
with:
|
||||
fail-fast: false
|
||||
|
||||
- name: Save dprint plugin cache
|
||||
if: ${{ github.ref_name == 'main' }}
|
||||
id: cache-save
|
||||
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
with:
|
||||
key: ${{ steps.cache-restore.outputs.cache-primary-key }}
|
||||
path: ~/.cache/dprint
|
||||
|
||||
@@ -8,28 +8,24 @@ on:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
paths:
|
||||
- "src/*.rs"
|
||||
- "Cargo.lock"
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "src/*.rs"
|
||||
- "Cargo.lock"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
|
||||
cancel-in-progress: ${{ github.ref_name != 'main' }}
|
||||
|
||||
jobs:
|
||||
benchmark:
|
||||
name: Benchmark
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write # required for OIDC authentication with CodSpeed
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1
|
||||
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
|
||||
|
||||
- uses: oxc-project/setup-rust@cd82e1efec7fef815e2c23d296756f31c7cdc03d # v1.0.0
|
||||
- uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
|
||||
with:
|
||||
cache-key: benchmark
|
||||
save-cache: ${{ github.ref_name == 'main' }}
|
||||
@@ -41,8 +37,8 @@ jobs:
|
||||
env:
|
||||
RUSTFLAGS: "-C debuginfo=1 -C strip=none"
|
||||
|
||||
- uses: CodSpeedHQ/action@c28fe9fbe7d57a3da1b7834ae3761c1d8217612d # v3.7.0
|
||||
- uses: CodSpeedHQ/action@3194d9a39c4d46684cb44bf7207fc56626aad8fd # v4.15.1
|
||||
timeout-minutes: 30
|
||||
with:
|
||||
run: cargo codspeed run
|
||||
token: ${{ secrets.CODSPEED_TOKEN }}
|
||||
mode: instrumentation
|
||||
|
||||
+68
-20
@@ -8,15 +8,13 @@ on:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
paths-ignore:
|
||||
paths-ignore: &paths-ignore
|
||||
- "**/*.md"
|
||||
- "!.github/workflows/ci.yml"
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths-ignore:
|
||||
- "**/*.md"
|
||||
- "!.github/workflows/ci.yml"
|
||||
paths-ignore: *paths-ignore
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -35,11 +33,12 @@ jobs:
|
||||
include:
|
||||
- os: windows-latest
|
||||
- os: ubuntu-latest
|
||||
- os: macos-14
|
||||
- os: macos-latest
|
||||
- os: ubuntu-24.04-arm
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1
|
||||
- uses: oxc-project/setup-rust@cd82e1efec7fef815e2c23d296756f31c7cdc03d # v1.0.0
|
||||
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
|
||||
- uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
|
||||
with:
|
||||
save-cache: ${{ github.ref_name == 'main' }}
|
||||
cache-key: warm
|
||||
@@ -47,48 +46,90 @@ jobs:
|
||||
- uses: ./.github/actions/pnpm
|
||||
- run: cargo check --all-features --locked
|
||||
- run: just test
|
||||
if: ${{ matrix.os != 'windows-latest' }}
|
||||
timeout-minutes: 3
|
||||
|
||||
test-big-endian:
|
||||
name: Test big-endian # s390x-unknown-linux-gnu is a big-endian
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
|
||||
- uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
|
||||
with:
|
||||
save-cache: ${{ github.ref_name == 'main' }}
|
||||
cache-key: s390x-unknown-linux-gnu
|
||||
tools: cross
|
||||
- uses: ./.github/actions/pnpm
|
||||
- run: cross check --all-features --locked --target s390x-unknown-linux-gnu
|
||||
- run: cross test --target s390x-unknown-linux-gnu
|
||||
timeout-minutes: 3
|
||||
- run: cross test --all-features --target s390x-unknown-linux-gnu
|
||||
timeout-minutes: 3
|
||||
- run: git diff --exit-code # Must commit everything
|
||||
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1
|
||||
- uses: oxc-project/setup-rust@cd82e1efec7fef815e2c23d296756f31c7cdc03d # v1.0.0
|
||||
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
|
||||
- uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
|
||||
with:
|
||||
components: clippy rust-docs
|
||||
- run: cargo clippy --all-features --all-targets -- -D warnings
|
||||
- run: RUSTDOCFLAGS='-D warnings' cargo doc --no-deps --all-features
|
||||
- uses: crate-ci/typos@392b78fe18a52790c53f42456e46124f77346842 # v1.34.0
|
||||
- uses: crate-ci/typos@5374cbf686e897b15713110e233094e2874de7ef # v1.46.1
|
||||
with:
|
||||
files: .
|
||||
|
||||
wasm:
|
||||
name: Check Wasm
|
||||
wasm32-wasip1:
|
||||
name: Test wasm32-wasip1
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1
|
||||
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
|
||||
|
||||
- uses: oxc-project/setup-rust@cd82e1efec7fef815e2c23d296756f31c7cdc03d # v1.0.0
|
||||
- uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
|
||||
with:
|
||||
cache-key: wasm
|
||||
cache-key: wasm32-wasip1
|
||||
save-cache: ${{ github.ref_name == 'main' }}
|
||||
tools: wasmtime
|
||||
|
||||
- uses: ./.github/actions/pnpm
|
||||
|
||||
- name: Install target
|
||||
run: rustup target add wasm32-wasip1
|
||||
|
||||
- name: Test
|
||||
run: cargo test --target wasm32-wasip1 --profile wasm-test -- --nocapture
|
||||
timeout-minutes: 3
|
||||
env:
|
||||
CARGO_TARGET_WASM32_WASIP1_RUNNER: "wasmtime run -W bulk-memory=y --dir ${{ github.workspace }}::/ --"
|
||||
|
||||
wasm32-unknown-unknown:
|
||||
name: Check wasm32-unknown-unknown
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
|
||||
|
||||
- uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
|
||||
with:
|
||||
cache-key: wasm32-unknown-unknown
|
||||
save-cache: ${{ github.ref_name == 'main' }}
|
||||
|
||||
- name: Check
|
||||
run: |
|
||||
rustup target add wasm32-wasip1
|
||||
cargo check --all-features --target wasm32-wasip1
|
||||
rustup target add wasm32-unknown-unknown
|
||||
cargo check --all-features --target wasm32-unknown-unknown
|
||||
|
||||
wasi:
|
||||
name: Test wasi target
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1
|
||||
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
|
||||
|
||||
- uses: oxc-project/setup-rust@cd82e1efec7fef815e2c23d296756f31c7cdc03d # v1.0.0
|
||||
- uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
|
||||
with:
|
||||
cache-key: wasi
|
||||
save-cache: ${{ github.ref_name == 'main' }}
|
||||
tools: wasmtime
|
||||
|
||||
- uses: ./.github/actions/pnpm
|
||||
|
||||
@@ -99,7 +140,14 @@ jobs:
|
||||
|
||||
- name: Test
|
||||
run: pnpm run test
|
||||
timeout-minutes: 3
|
||||
env:
|
||||
WASI_TEST: 1
|
||||
|
||||
- name: Cargo Test
|
||||
run: cargo test --target wasm32-wasip1-threads --profile wasm-test -- --nocapture
|
||||
timeout-minutes: 3
|
||||
env:
|
||||
CARGO_TARGET_WASM32_WASIP1_THREADS_RUNNER: "wasmtime run -W bulk-memory=y -W threads=y -W shared-memory=y -S threads=y --dir ${{ github.workspace }}::/ --"
|
||||
|
||||
- run: git diff --exit-code # Must commit index.d.ts
|
||||
|
||||
@@ -28,11 +28,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1
|
||||
uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
|
||||
|
||||
- uses: ./.github/actions/pnpm
|
||||
|
||||
- uses: oxc-project/setup-rust@cd82e1efec7fef815e2c23d296756f31c7cdc03d # v1.0.0
|
||||
- uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
|
||||
with:
|
||||
cache-key: codecov
|
||||
save-cache: ${{ github.ref_name == 'main' }}
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
- run: cargo llvm-cov --lcov --output-path lcov.info
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: codecov
|
||||
path: lcov.info
|
||||
@@ -58,17 +58,17 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
if: env.CODECOV_TOKEN
|
||||
uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1
|
||||
uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
|
||||
|
||||
- name: Download coverage file
|
||||
if: env.CODECOV_TOKEN
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: codecov
|
||||
|
||||
- name: Upload to codecov.io
|
||||
if: env.CODECOV_TOKEN
|
||||
uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
|
||||
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
fail_ci_if_error: true
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
name: Copilot Setup Steps
|
||||
|
||||
# This workflow defines the setup steps that GitHub Copilot agents will use
|
||||
# to prepare the development environment for the oxc project.
|
||||
# It preinstalls tools and dependencies needed for Rust and Node.js development.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
paths:
|
||||
- .github/workflows/copilot-setup-steps.yml
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- .github/workflows/copilot-setup-steps.yml
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
copilot-setup-steps:
|
||||
name: Setup Development Environment for Copilot
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Checkout full repo for git history.
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
|
||||
with:
|
||||
cache-key: warm
|
||||
save-cache: false
|
||||
tools: just,watchexec-cli,cargo-insta,typos-cli,cargo-shear
|
||||
components: clippy rust-docs rustfmt
|
||||
|
||||
- uses: ./.github/actions/pnpm
|
||||
@@ -29,9 +29,9 @@ jobs:
|
||||
name: Cargo Deny
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1
|
||||
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
|
||||
|
||||
- uses: oxc-project/setup-rust@cd82e1efec7fef815e2c23d296756f31c7cdc03d # v1.0.0
|
||||
- uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
|
||||
with:
|
||||
restore-cache: false
|
||||
tools: cargo-deny
|
||||
|
||||
@@ -24,14 +24,14 @@ jobs:
|
||||
outputs:
|
||||
version_changed: ${{ steps.version.outputs.changed }}
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1
|
||||
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
|
||||
|
||||
- name: Check version changes
|
||||
uses: EndBug/version-check@36ff30f37c7deabe56a30caa043d127be658c425 # v2.1.5
|
||||
uses: EndBug/version-check@095362f3cd50f690c8fa0e6afeea81834bd8d320 # v3.0.0
|
||||
id: version
|
||||
with:
|
||||
static-checking: localIsNew
|
||||
file-url: https://unpkg.com/unrs-resolver@latest/package.json
|
||||
file-url: https://unpkg.com/oxc-resolver@latest/package.json
|
||||
file-name: package.json
|
||||
|
||||
- name: Set version name
|
||||
@@ -108,12 +108,15 @@ jobs:
|
||||
build: pnpm build
|
||||
- os: ubuntu-latest
|
||||
target: wasm32-wasip1-threads
|
||||
build: pnpm build
|
||||
build: pnpm run build:debug --release # omit --features allocator
|
||||
- os: ubuntu-latest
|
||||
target: aarch64-unknown-linux-ohos
|
||||
build: pnpm build --target aarch64-unknown-linux-ohos
|
||||
|
||||
name: Build ${{ matrix.target }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1
|
||||
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
|
||||
|
||||
- uses: ./.github/actions/pnpm
|
||||
with:
|
||||
@@ -122,6 +125,10 @@ jobs:
|
||||
|
||||
- run: rustup target add ${{ matrix.target }}
|
||||
|
||||
- name: Setup OpenHarmony SDK
|
||||
if: ${{ contains(matrix.target, 'ohos') }}
|
||||
uses: Boshen/setup-ohos-sdk@edb865a89a712f1f15dbad932dfa9cfce849d95c # v1.0.0
|
||||
|
||||
- uses: goto-bus-stop/setup-zig@abea47f85e598557f500fa1fd2ab7464fcb39406 # v2.2.1
|
||||
if: ${{ contains(matrix.target, 'musl') }}
|
||||
with:
|
||||
@@ -134,7 +141,7 @@ jobs:
|
||||
TARGET_CC: clang # for mimalloc
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: bindings-${{ matrix.target }}
|
||||
@@ -148,10 +155,10 @@ jobs:
|
||||
name: Build FreeBSD
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1
|
||||
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
|
||||
- name: Build
|
||||
id: build
|
||||
uses: cross-platform-actions/action@97419d18f6470332677e345e9df97cdc71244ead # v0.28.0
|
||||
uses: cross-platform-actions/action@233156312992f3f169d8d0c633c21d12a5d30455 # v1.0.0
|
||||
env:
|
||||
DEBUG: napi:*
|
||||
RUSTUP_IO_THREADS: 1
|
||||
@@ -182,7 +189,7 @@ jobs:
|
||||
rm -rf node_modules
|
||||
rm -rf target
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: bindings-freebsd
|
||||
path: napi/*.node
|
||||
@@ -197,12 +204,12 @@ jobs:
|
||||
- build
|
||||
- build-freebsd
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1
|
||||
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
|
||||
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
- uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: pnpm
|
||||
@@ -211,10 +218,12 @@ jobs:
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- run: npm install -g npm@latest # For trusted publishing support
|
||||
|
||||
- name: Prepare dirs and artifacts
|
||||
run: |
|
||||
cp package.json napi/package.json
|
||||
@@ -222,11 +231,8 @@ jobs:
|
||||
pnpm napi artifacts --npm-dir npm --build-output-dir napi
|
||||
|
||||
- name: Publish npm packages as latest
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: |
|
||||
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
|
||||
# Using trusted publishing, no token is required.
|
||||
pnpm napi pre-publish --no-gh-release --tagstyle npm --npm-dir npm
|
||||
|
||||
# Publish root package
|
||||
|
||||
@@ -19,24 +19,29 @@ jobs:
|
||||
permissions:
|
||||
pull-requests: write
|
||||
contents: write
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
|
||||
id: app-token
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.RELEASE_PLZ_TOKEN }}
|
||||
persist-credentials: true # required by release-plz
|
||||
client-id: ${{ secrets.APP_ID }}
|
||||
private-key: ${{ secrets.APP_PRIVATE_KEY }}
|
||||
|
||||
- name: Run release-plz
|
||||
- uses: oxc-project/release-plz@e2b12f55ad64a22af8e93634b94439c42913afca # v1.0.6
|
||||
id: release-plz
|
||||
uses: release-plz/action@8724d33cd97b8295051102e2e19ca592962238f5 # v0.5.108
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.RELEASE_PLZ_TOKEN }}
|
||||
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||
with:
|
||||
PAT: ${{ steps.app-token.outputs.token }}
|
||||
|
||||
- uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
|
||||
with:
|
||||
cache-key: warm
|
||||
|
||||
- uses: ./.github/actions/pnpm
|
||||
|
||||
- name: Bump package.json
|
||||
if: ${{ steps.release-plz.outputs.prs_created }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.RELEASE_PLZ_TOKEN }}
|
||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
PR_NUMBER: ${{ fromJSON(steps.release-plz.outputs.pr).number }}
|
||||
VERSION: ${{ fromJSON(steps.release-plz.outputs.pr).releases[0].version }}
|
||||
run: |
|
||||
@@ -47,8 +52,9 @@ jobs:
|
||||
if [[ -n "$pr_number" ]]; then
|
||||
version="${VERSION}"
|
||||
|
||||
jq --arg version "${version}" '.version = ($version) | .scripts.postinstall = "napi-postinstall unrs-resolver \($version) check"' package.json > tmp
|
||||
jq --arg version "${version}" '.version = ($version)' package.json > tmp
|
||||
mv tmp package.json
|
||||
pnpm build
|
||||
|
||||
gh pr checkout $pr_number
|
||||
git add .
|
||||
@@ -0,0 +1,24 @@
|
||||
name: Security Analysis
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- ".github/workflows/**"
|
||||
|
||||
permissions: {}
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
|
||||
cancel-in-progress: ${{ github.ref_name != 'main' }}
|
||||
|
||||
jobs:
|
||||
security:
|
||||
name: Security Analysis
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: oxc-project/security-action@77e230508eccbb400b23746dab6c573a8ea7483e # v1.0.5
|
||||
@@ -1,45 +0,0 @@
|
||||
name: Zizmor
|
||||
|
||||
permissions: {}
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
paths:
|
||||
- ".github/workflows/**"
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- .github/workflows/**
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
zizmor:
|
||||
name: zizmor
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1
|
||||
|
||||
- uses: taiki-e/install-action@2383334cf567d78771fc7d89b6b3802ef1412cf6 # v2.56.8
|
||||
with:
|
||||
tool: zizmor
|
||||
|
||||
- name: Run zizmor
|
||||
run: zizmor --format sarif . > results.sarif
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload SARIF file
|
||||
uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
category: zizmor
|
||||
@@ -3,4 +3,6 @@ target/
|
||||
/node_modules
|
||||
/napi/node_modules
|
||||
/fixtures/pnpm/node_modules
|
||||
/fixtures/yarn/node_modules
|
||||
/fixtures/tsconfck/node_modules
|
||||
fuzz/Cargo.lock
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
22.17.0
|
||||
24.14.0
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"printWidth": 120,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"plugins": ["prettier-plugin-pkg"]
|
||||
}
|
||||
+4
-4
@@ -3,7 +3,7 @@
|
||||
# typos
|
||||
|
||||
[files]
|
||||
extend-exclude = [
|
||||
"CHANGELOG.md",
|
||||
"CHANGELOG_OLD.md",
|
||||
]
|
||||
extend-exclude = ["CHANGELOG.md", "CHANGELOG_OLD.md"]
|
||||
|
||||
[default.extend-identifiers]
|
||||
PnP = "PnP"
|
||||
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
vp staged
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["oxc.oxc-vscode"]
|
||||
}
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnSaveMode": "file",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.oxc": "explicit"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,289 @@
|
||||
# AI Agent Guidelines for unrs-resolver
|
||||
|
||||
This document provides guidance for AI coding assistants (like GitHub Copilot, Cursor, Claude, etc.) when working with the unrs-resolver codebase.
|
||||
|
||||
## Project Overview
|
||||
|
||||
unrs-resolver is a Rust port of webpack's enhanced-resolve, providing ESM and CommonJS module resolution. It offers both a Rust crate and Node.js bindings via NAPI.
|
||||
|
||||
### Key Technologies
|
||||
|
||||
- **Rust**: Core implementation using Rust 2024 edition (MSRV: 1.85.0)
|
||||
- **NAPI**: Node.js bindings for JavaScript/TypeScript usage
|
||||
- **WebAssembly**: Browser support
|
||||
- **GitHub Actions**: CI/CD workflows
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
unrs-resolver/
|
||||
├── src/ # Core Rust implementation
|
||||
│ └── tests/ # Unit tests (one file per feature area)
|
||||
├── tests/ # Integration tests
|
||||
├── fixtures/ # Test fixtures (real files on disk, not generated)
|
||||
├── napi/ # Node.js NAPI bindings
|
||||
├── examples/ # Usage examples
|
||||
├── benches/ # Performance benchmarks
|
||||
└── .github/ # GitHub workflows and configs
|
||||
```
|
||||
|
||||
## Development Workflow
|
||||
|
||||
`just init` has already been run, all tools (`typos-cli`, `cargo-shear`) are already installed, do not run `just init`.
|
||||
|
||||
Rust and `cargo` components `clippy`, `rust-docs` and `rustfmt` have already been installed, do not install them.
|
||||
|
||||
Always run `just ready` as the last step after code has been committed to the repository.
|
||||
|
||||
### Common Tasks
|
||||
|
||||
```bash
|
||||
just ready # Run all checks (format, lint, test, build)
|
||||
just test # Run all tests (Rust + Node.js)
|
||||
just check # Cargo check with all features
|
||||
just lint # Run clippy with strict settings
|
||||
just fmt # Format code (cargo fmt + vp fmt)
|
||||
```
|
||||
|
||||
## Code Conventions
|
||||
|
||||
### Rust
|
||||
|
||||
- Use Rust 2024 edition features
|
||||
- Follow standard Rust formatting (`cargo fmt`)
|
||||
- All clippy warnings must be addressed (`cargo clippy -- --deny warnings`)
|
||||
- Use `tracing` for logging/instrumentation
|
||||
- Implement `FileSystem` trait for custom file systems
|
||||
|
||||
### Node.js/TypeScript
|
||||
|
||||
- Use TypeScript for type definitions (`index.d.ts`)
|
||||
- Follow existing API patterns in NAPI bindings
|
||||
- Use vitest for testing
|
||||
- Support both ESM and CommonJS usage
|
||||
|
||||
### Documentation
|
||||
|
||||
- Use rustdoc for Rust APIs
|
||||
- Maintain TypeScript definitions for Node.js API
|
||||
- Update README.md for significant changes
|
||||
- Add examples for new features
|
||||
|
||||
## Key APIs
|
||||
|
||||
### Rust
|
||||
|
||||
```rust
|
||||
use unrs_resolver::{ResolveOptions, Resolver};
|
||||
|
||||
let options = ResolveOptions::default();
|
||||
let resolver = Resolver::new(options);
|
||||
let resolution = resolver.resolve("/path/to/project", "./module");
|
||||
```
|
||||
|
||||
### Node.js
|
||||
|
||||
```javascript
|
||||
import resolve, { ResolverFactory } from "unrs-resolver";
|
||||
|
||||
// Simple resolve
|
||||
const result = resolve.sync(process.cwd(), "./module");
|
||||
|
||||
// Advanced usage
|
||||
const resolver = new ResolverFactory({
|
||||
conditionNames: ["node", "import"],
|
||||
extensions: [".js", ".ts", ".json"],
|
||||
});
|
||||
```
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Test Categories
|
||||
|
||||
1. **Enhanced-resolve compatibility**: Tests ported from webpack/enhanced-resolve
|
||||
2. **TypeScript support**: tsconfig-paths functionality
|
||||
3. **Yarn Plug'n'Play** resolution
|
||||
4. **Node.js compatibility**: ESM/CJS resolution behavior
|
||||
5. **Performance**: Benchmarks against enhanced-resolve
|
||||
|
||||
### Adding Tests
|
||||
|
||||
Tests must use **fixture directories** with real files on disk. Do not dynamically create files, directories, or temp folders in tests — always add fixture files and commit them to the repository.
|
||||
|
||||
#### Where to put test code
|
||||
|
||||
- **Unit tests** (`src/tests/`): Test individual resolution features (aliases, extensions, exports, etc.). Each file maps to a feature area. Use `super::fixture_root()` to access `fixtures/`.
|
||||
- **Integration tests** (`tests/`): Test end-to-end resolution behavior. Use `env::current_dir().unwrap().join("fixtures/integration")` to access fixtures.
|
||||
- **Node.js tests** (`napi/`): Test the NAPI bindings with vitest.
|
||||
|
||||
#### Where to put fixtures
|
||||
|
||||
```
|
||||
fixtures/
|
||||
├── enhanced-resolve/ # Ported from webpack/enhanced-resolve (shared by many unit tests)
|
||||
├── integration/ # Integration test fixtures (tests/ directory)
|
||||
│ ├── misc/ # Unicode paths, BOM handling, package.json edge cases
|
||||
│ ├── dot/ # Dot-path resolution
|
||||
│ └── ...
|
||||
├── dts_resolver/ # .d.ts resolution fixtures
|
||||
├── invalid/ # Invalid configuration scenarios
|
||||
├── pnp/ # Yarn Plug'n'Play fixtures
|
||||
├── pnpm/ # pnpm node_modules structure
|
||||
├── tsconfck/ # tsconfck compatibility
|
||||
├── tsconfig/ # TypeScript config resolution
|
||||
└── yarn/ # Yarn monorepo fixtures
|
||||
```
|
||||
|
||||
- Add new fixtures under the directory that matches the test file or feature area.
|
||||
- For integration tests, add fixtures under `fixtures/integration/`.
|
||||
- Ensure tests work on Windows, macOS, and Linux.
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Error Handling
|
||||
|
||||
```rust
|
||||
// Use proper error types
|
||||
use unrs_resolver::{ResolveError, ResolveErrorKind};
|
||||
|
||||
match resolver.resolve(path, specifier) {
|
||||
Ok(resolution) => { /* handle success */ },
|
||||
Err(ResolveError { kind: ResolveErrorKind::NotFound, .. }) => { /* handle not found */ },
|
||||
Err(err) => { /* handle other errors */ }
|
||||
}
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
```rust
|
||||
// Build options incrementally
|
||||
let options = ResolveOptions {
|
||||
condition_names: vec!["node".to_string(), "import".to_string()],
|
||||
extensions: vec![".js".to_string(), ".ts".to_string()],
|
||||
main_fields: vec!["module".to_string(), "main".to_string()],
|
||||
..Default::default()
|
||||
};
|
||||
```
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- Use `FileSystem` trait for custom file systems (including in-memory)
|
||||
- Cache `Resolver` instances when possible
|
||||
- Consider `fullySpecified: true` for better performance when extensions are known
|
||||
- Profile with `cargo bench` for performance-critical changes
|
||||
|
||||
## Debugging
|
||||
|
||||
### Rust
|
||||
|
||||
```bash
|
||||
# Enable tracing
|
||||
UNRS_LOG=unrs_resolver=debug cargo test
|
||||
```
|
||||
|
||||
### Node.js
|
||||
|
||||
```bash
|
||||
# Enable tracing
|
||||
UNRS_LOG=DEBUG node your_program.js
|
||||
```
|
||||
|
||||
## Contributing Guidelines
|
||||
|
||||
1. **Small, focused changes**: Make minimal modifications
|
||||
2. **Test coverage**: Add tests for new functionality
|
||||
3. **Documentation**: Update docs for API changes
|
||||
4. **Performance**: Run benchmarks for core changes
|
||||
5. **Compatibility**: Maintain enhanced-resolve compatibility where possible
|
||||
|
||||
## AI Assistant Tips
|
||||
|
||||
- **Context awareness**: This is a low-level resolver, performance matters
|
||||
- **Test compatibility**: Changes should not break existing enhanced-resolve compatibility
|
||||
- **Cross-platform**: Consider Windows path handling differences
|
||||
- **Memory usage**: Be mindful of allocations in hot paths
|
||||
- **Error messages**: Provide helpful error messages that match Node.js behavior
|
||||
|
||||
## References
|
||||
|
||||
- [Enhanced Resolve](https://github.com/webpack/enhanced-resolve) - Original implementation
|
||||
- [Node.js Module Resolution](https://nodejs.org/api/modules.html) - CommonJS algorithm
|
||||
- [Node.js ESM Resolution](https://nodejs.org/api/esm.html#resolution-algorithm) - ESM algorithm
|
||||
- [TypeScript Module Resolution](https://www.typescriptlang.org/docs/handbook/module-resolution.html)
|
||||
|
||||
<!--VITE PLUS START-->
|
||||
|
||||
# Using Vite+, the Unified Toolchain for the Web
|
||||
|
||||
This project is using Vite+, a unified toolchain built on top of Vite, Rolldown, Vitest, tsdown, Oxlint, Oxfmt, and Vite Task. Vite+ wraps runtime management, package management, and frontend tooling in a single global CLI called `vp`. Vite+ is distinct from Vite, but it invokes Vite through `vp dev` and `vp build`.
|
||||
|
||||
## Vite+ Workflow
|
||||
|
||||
`vp` is a global binary that handles the full development lifecycle. Run `vp help` to print a list of commands and `vp <command> --help` for information about a specific command.
|
||||
|
||||
### Start
|
||||
|
||||
- create - Create a new project from a template
|
||||
- migrate - Migrate an existing project to Vite+
|
||||
- config - Configure hooks and agent integration
|
||||
- staged - Run linters on staged files
|
||||
- install (`i`) - Install dependencies
|
||||
- env - Manage Node.js versions
|
||||
|
||||
### Develop
|
||||
|
||||
- dev - Run the development server
|
||||
- check - Run format, lint, and TypeScript type checks
|
||||
- lint - Lint code
|
||||
- fmt - Format code
|
||||
- test - Run tests
|
||||
|
||||
### Execute
|
||||
|
||||
- run - Run monorepo tasks
|
||||
- exec - Execute a command from local `node_modules/.bin`
|
||||
- dlx - Execute a package binary without installing it as a dependency
|
||||
- cache - Manage the task cache
|
||||
|
||||
### Build
|
||||
|
||||
- build - Build for production
|
||||
- pack - Build libraries
|
||||
- preview - Preview production build
|
||||
|
||||
### Manage Dependencies
|
||||
|
||||
Vite+ automatically detects and wraps the underlying package manager such as pnpm, npm, or Yarn through the `packageManager` field in `package.json` or package manager-specific lockfiles.
|
||||
|
||||
- add - Add packages to dependencies
|
||||
- remove (`rm`, `un`, `uninstall`) - Remove packages from dependencies
|
||||
- update (`up`) - Update packages to latest versions
|
||||
- dedupe - Deduplicate dependencies
|
||||
- outdated - Check for outdated packages
|
||||
- list (`ls`) - List installed packages
|
||||
- why (`explain`) - Show why a package is installed
|
||||
- info (`view`, `show`) - View package information from the registry
|
||||
- link (`ln`) / unlink - Manage local package links
|
||||
- pm - Forward a command to the package manager
|
||||
|
||||
### Maintain
|
||||
|
||||
- upgrade - Update `vp` itself to the latest version
|
||||
|
||||
These commands map to their corresponding tools. For example, `vp dev --port 3000` runs Vite's dev server and works the same as Vite. `vp test` runs JavaScript tests through the bundled Vitest. The version of all tools can be checked using `vp --version`. This is useful when researching documentation, features, and bugs.
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
- **Using the package manager directly:** Do not use pnpm, npm, or Yarn directly. Vite+ can handle all package manager operations.
|
||||
- **Always use Vite commands to run tools:** Don't attempt to run `vp vitest` or `vp oxlint`. They do not exist. Use `vp test` and `vp lint` instead.
|
||||
- **Running scripts:** Vite+ commands take precedence over `package.json` scripts. If there is a `test` script defined in `scripts` that conflicts with the built-in `vp test` command, run it using `vp run test`.
|
||||
- **Do not install Vitest, Oxlint, Oxfmt, or tsdown directly:** Vite+ wraps these tools. They must not be installed directly. You cannot upgrade these tools by installing their latest versions. Always use Vite+ commands.
|
||||
- **Use Vite+ wrappers for one-off binaries:** Use `vp dlx` instead of package-manager-specific `dlx`/`npx` commands.
|
||||
- **Import JavaScript modules from `vite-plus`:** Instead of importing from `vite` or `vitest`, all modules should be imported from the project's `vite-plus` dependency. For example, `import { defineConfig } from 'vite-plus';` or `import { expect, test, vi } from 'vite-plus/test';`. You must not install `vitest` to import test utilities.
|
||||
- **Type-Aware Linting:** There is no need to install `oxlint-tsgolint`, `vp lint --type-aware` works out of the box.
|
||||
|
||||
## Review Checklist for Agents
|
||||
|
||||
- [ ] Run `vp install` after pulling remote changes and before getting started.
|
||||
- [ ] Run `vp check` and `vp test` to validate changes.
|
||||
<!--VITE PLUS END-->
|
||||
+724
-43
@@ -1,4 +1,4 @@
|
||||
# Changelog for `oxc-resolver`
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
@@ -7,6 +7,729 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [11.19.1](https://github.com/oxc-project/oxc-resolver/compare/v11.19.0...v11.19.1) - 2026-02-28
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- resolve normalized path on Windows even for `symlinks: false` ([#1036](https://github.com/oxc-project/oxc-resolver/pull/1036)) (by @sapphi-red)
|
||||
- skip unreadable tsconfig files during auto-discovery ([#1033](https://github.com/oxc-project/oxc-resolver/pull/1033)) (by @longlho)
|
||||
|
||||
### <!-- 2 -->🚜 Refactor
|
||||
|
||||
- clean up commented-out code in parse_package_specifier ([#1035](https://github.com/oxc-project/oxc-resolver/pull/1035)) (by @Boshen)
|
||||
|
||||
### <!-- 4 -->⚡ Performance
|
||||
|
||||
- remove unnecessary String clone in PnP resolution ([#1039](https://github.com/oxc-project/oxc-resolver/pull/1039)) (by @Boshen)
|
||||
- use byte operations instead of char iteration in specifier parser ([#1038](https://github.com/oxc-project/oxc-resolver/pull/1038)) (by @Boshen)
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
* @sapphi-red
|
||||
* @longlho
|
||||
|
||||
## [11.19.0](https://github.com/oxc-project/oxc-resolver/compare/v11.18.0...v11.19.0) - 2026-02-25
|
||||
|
||||
### <!-- 0 -->🚀 Features
|
||||
|
||||
- add `node_path` option to disable `NODE_PATH` env var behavior ([#1031](https://github.com/oxc-project/oxc-resolver/pull/1031)) (by @Boshen)
|
||||
- add DTS resolver matching TypeScript's bundler mode ([#997](https://github.com/oxc-project/oxc-resolver/pull/997)) (by @Boshen)
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- remove invalid debug_assert for symlink + package.json ([#1032](https://github.com/oxc-project/oxc-resolver/pull/1032)) (by @Boshen)
|
||||
|
||||
### <!-- 3 -->📚 Documentation
|
||||
|
||||
- map npm package links to npmx.dev ([#1028](https://github.com/oxc-project/oxc-resolver/pull/1028)) (by @Boshen)
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
|
||||
## [11.18.0](https://github.com/oxc-project/oxc-resolver/compare/v11.17.1...v11.18.0) - 2026-02-20
|
||||
|
||||
### <!-- 0 -->🚀 Features
|
||||
|
||||
- support NODE_PATH module lookup ([#1020](https://github.com/oxc-project/oxc-resolver/pull/1020)) (by @Boshen)
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
* @renovate[bot]
|
||||
|
||||
## [11.17.1](https://github.com/oxc-project/oxc-resolver/compare/v11.17.0...v11.17.1) - 2026-02-08
|
||||
|
||||
### <!-- 4 -->⚡ Performance
|
||||
|
||||
- *(resolve)* reuse dot-prefixed subpath in exports/imports ([#1004](https://github.com/oxc-project/oxc-resolver/pull/1004)) (by @Boshen)
|
||||
- *(cache)* remove package.json index arena indirection ([#1003](https://github.com/oxc-project/oxc-resolver/pull/1003)) (by @Boshen)
|
||||
- *(tsconfig)* precompile wildcard path alias matcher ([#1001](https://github.com/oxc-project/oxc-resolver/pull/1001)) (by @Boshen)
|
||||
- precompile alias match metadata in resolver hot path ([#999](https://github.com/oxc-project/oxc-resolver/pull/999)) (by @Boshen)
|
||||
|
||||
### <!-- 9 -->💼 Other
|
||||
|
||||
- add tsconfig paths alias scalability benchmark ([#1002](https://github.com/oxc-project/oxc-resolver/pull/1002)) (by @Boshen)
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
|
||||
## [11.17.0](https://github.com/oxc-project/oxc-resolver/compare/v11.16.4...v11.17.0) - 2026-01-29
|
||||
|
||||
### <!-- 0 -->🚀 Features
|
||||
|
||||
- allow access to inner data in error related types ([#990](https://github.com/oxc-project/oxc-resolver/pull/990)) (by @sapphi-red)
|
||||
|
||||
### Contributors
|
||||
|
||||
* @sapphi-red
|
||||
|
||||
## [11.16.4](https://github.com/oxc-project/oxc-resolver/compare/v11.16.3...v11.16.4) - 2026-01-23
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- resolve clippy unnecessary_unwrap warning ([#980](https://github.com/oxc-project/oxc-resolver/pull/980)) (by @Boshen)
|
||||
|
||||
### Contributors
|
||||
|
||||
* @leegeunhyeok
|
||||
* @Boshen
|
||||
|
||||
## [11.16.3](https://github.com/oxc-project/oxc-resolver/compare/v11.16.2...v11.16.3) - 2026-01-14
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- prevent tsconfig cache pollution with separate raw and built caches ([#970](https://github.com/oxc-project/oxc-resolver/pull/970)) (by @Boshen)
|
||||
- use `/fixtures` path for WASI target (by @Boshen)
|
||||
|
||||
### <!-- 3 -->📚 Documentation
|
||||
|
||||
- *(README.md)* update logo ([#968](https://github.com/oxc-project/oxc-resolver/pull/968)) (by @sapphi-red)
|
||||
|
||||
### <!-- 6 -->🧪 Testing
|
||||
|
||||
- use CARGO_MANIFEST_DIR instead `env::current_dir` (by @Boshen)
|
||||
- fix skipped tests in options.test.mjs (by @Boshen)
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
* @renovate[bot]
|
||||
* @sapphi-red
|
||||
|
||||
## [11.16.1](https://github.com/oxc-project/oxc-resolver/compare/v11.16.0...v11.16.1) - 2025-12-24
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- only recreate the cache when `yarn_pnp` is toggled ([#943](https://github.com/oxc-project/oxc-resolver/pull/943)) (by @Boshen)
|
||||
- resolve absolute path to package with trailing slash ([#942](https://github.com/oxc-project/oxc-resolver/pull/942)) (by @Boshen)
|
||||
- show yarn pnp errors as-is instead of NotFound error ([#939](https://github.com/oxc-project/oxc-resolver/pull/939)) (by @sapphi-red)
|
||||
|
||||
### <!-- 2 -->🚜 Refactor
|
||||
|
||||
- replace builtins.rs with nodejs-built-in-modules crate ([#940](https://github.com/oxc-project/oxc-resolver/pull/940)) (by @Boshen)
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
* @renovate[bot]
|
||||
* @sapphi-red
|
||||
|
||||
## [11.16.0](https://github.com/oxc-project/oxc-resolver/compare/v11.15.0...v11.16.0) - 2025-12-18
|
||||
|
||||
### <!-- 0 -->🚀 Features
|
||||
|
||||
- allow subpath imports that start with #/ ([#907](https://github.com/oxc-project/oxc-resolver/pull/907)) (by @Boshen)
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- resolve solution tsconfig for auto discovered tsconfig ([#927](https://github.com/oxc-project/oxc-resolver/pull/927)) (by @Boshen)
|
||||
- fix `clone_with_options` + `yarn_pnp: true` not working ([#916](https://github.com/oxc-project/oxc-resolver/pull/916)) (by @sapphi-red)
|
||||
|
||||
### <!-- 2 -->🚜 Refactor
|
||||
|
||||
- s/self.cache.as_ref()/&self.cache ([#910](https://github.com/oxc-project/oxc-resolver/pull/910)) (by @Boshen)
|
||||
|
||||
### <!-- 6 -->🧪 Testing
|
||||
|
||||
- Add a test to ensure NODEJS_BUILTINS is alphabetized. ([#926](https://github.com/oxc-project/oxc-resolver/pull/926)) (by @connorshea)
|
||||
- add test cases for package imports starting with `#` or `#/` ([#905](https://github.com/oxc-project/oxc-resolver/pull/905)) (by @Boshen)
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
* @connorshea
|
||||
* @renovate[bot]
|
||||
* @sapphi-red
|
||||
|
||||
## [11.15.0](https://github.com/oxc-project/oxc-resolver/compare/v11.14.2...v11.15.0) - 2025-12-04
|
||||
|
||||
### <!-- 0 -->🚀 Features
|
||||
|
||||
- [**breaking**] disallow manually passing a list of references to `TsconfigOptions::references` ([#902](https://github.com/oxc-project/oxc-resolver/pull/902)) (by @Boshen)
|
||||
- support tsconfig `rootDirs` ([#885](https://github.com/oxc-project/oxc-resolver/pull/885)) (by @Boshen)
|
||||
- *(napi)* expose resolve_file API as resolveFileSync and resolveFileAsync ([#900](https://github.com/oxc-project/oxc-resolver/pull/900)) (by @Boshen)
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- fix resolution when resolving non-relative specifier on tsconfig baseUrl ([#903](https://github.com/oxc-project/oxc-resolver/pull/903)) (by @Boshen)
|
||||
- add fallback for statx NOSYS error on old kernels ([#901](https://github.com/oxc-project/oxc-resolver/pull/901)) (by @Boshen)
|
||||
- correct grammatical errors in documentation and comments ([#897](https://github.com/oxc-project/oxc-resolver/pull/897)) (by @Boshen)
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
* @renovate[bot]
|
||||
|
||||
## [11.14.2](https://github.com/oxc-project/oxc-resolver/compare/v11.14.1...v11.14.2) - 2025-12-02
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- resolve `node_modules/package/dir/foo.js` if `node_modules/package/dir/foo/` exists ([#896](https://github.com/oxc-project/oxc-resolver/pull/896)) (by @Boshen)
|
||||
|
||||
### <!-- 2 -->🚜 Refactor
|
||||
|
||||
- remove redundant PathBuf storage in CachedPath ([#891](https://github.com/oxc-project/oxc-resolver/pull/891)) (by @Boshen)
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
|
||||
## [11.14.1](https://github.com/oxc-project/oxc-resolver/compare/v11.14.0...v11.14.1) - 2025-11-28
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- incorrect resolution when project reference extends a tsconfig without baseUrl ([#882](https://github.com/oxc-project/oxc-resolver/pull/882)) (by @Boshen) - #882
|
||||
- store PathBuf with weak pointers to handle cache clearing ([#879](https://github.com/oxc-project/oxc-resolver/pull/879)) (by @Boshen) - #879
|
||||
|
||||
### <!-- 4 -->⚡ Performance
|
||||
|
||||
- remove an allocation from `CachedPath::module_directory` ([#880](https://github.com/oxc-project/oxc-resolver/pull/880)) (by @Boshen) - #880
|
||||
- skip searching for node_modules/@scope/package.json ([#876](https://github.com/oxc-project/oxc-resolver/pull/876)) (by @Boshen) - #876
|
||||
- remove the redundant `node_modules/package/index` cache value ([#875](https://github.com/oxc-project/oxc-resolver/pull/875)) (by @Boshen) - #875
|
||||
|
||||
### <!-- 6 -->🧪 Testing
|
||||
|
||||
- change all fixture directory names to dashed case ([#884](https://github.com/oxc-project/oxc-resolver/pull/884)) (by @Boshen) - #884
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
* @sapphi-red
|
||||
|
||||
## [11.14.0](https://github.com/oxc-project/oxc-resolver/compare/v11.13.2...v11.14.0) - 2025-11-24
|
||||
|
||||
### <!-- 0 -->🚀 Features
|
||||
|
||||
- add `resolve_file` API for tsconfig auto discovery to work ([#860](https://github.com/oxc-project/oxc-resolver/pull/860)) (by @Boshen) - #860
|
||||
- port tsconfck (find tsconfig files) ([#854](https://github.com/oxc-project/oxc-resolver/pull/854)) (by @Boshen) - #854
|
||||
- add many.rs example for profiling resolver with many packages ([#836](https://github.com/oxc-project/oxc-resolver/pull/836)) (by @Boshen) - #836
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- apply `conditionNames: ['node', 'import']` when resolving tsconfig extends ([#869](https://github.com/oxc-project/oxc-resolver/pull/869)) (by @Boshen) - #869
|
||||
- do not resolve to `node_modules/pacakge/index` ([#849](https://github.com/oxc-project/oxc-resolver/pull/849)) (by @Boshen) - #849
|
||||
- use std::fs::canonicalize as a fallback when canonicalize fails ([#835](https://github.com/oxc-project/oxc-resolver/pull/835)) (by @Boshen) - #835
|
||||
|
||||
### <!-- 2 -->🚜 Refactor
|
||||
|
||||
- remove the redundant `inner_resolver` from `load_pnp` ([#862](https://github.com/oxc-project/oxc-resolver/pull/862)) (by @Boshen) - #862
|
||||
- improve `Debug` and `Display` for `CachedPath` ([#861](https://github.com/oxc-project/oxc-resolver/pull/861)) (by @Boshen) - #861
|
||||
- too_many_arguments = "allow" ([#863](https://github.com/oxc-project/oxc-resolver/pull/863)) (by @Boshen) - #863
|
||||
- change Tsconfig::parse to accept owned string; add replace_bom_with_whitespace ([#859](https://github.com/oxc-project/oxc-resolver/pull/859)) (by @Boshen) - #859
|
||||
- remove the useless getters and setters from `CompilerOptions` ([#858](https://github.com/oxc-project/oxc-resolver/pull/858)) (by @Boshen) - #858
|
||||
- add `Tsconfig:references_resolved` ([#856](https://github.com/oxc-project/oxc-resolver/pull/856)) (by @Boshen) - #856
|
||||
- move tsconfig resolution related code to its own file ([#855](https://github.com/oxc-project/oxc-resolver/pull/855)) (by @Boshen) - #855
|
||||
- use RwLock<Vec<Arc<PackageJson>> for package.json storage ([#838](https://github.com/oxc-project/oxc-resolver/pull/838)) (by @Boshen) - #838
|
||||
- do not store is_symlink in CachedPathImpl ([#850](https://github.com/oxc-project/oxc-resolver/pull/850)) (by @Boshen) - #850
|
||||
- remove CachedPathImpl::canonicaling ([#834](https://github.com/oxc-project/oxc-resolver/pull/834)) (by @Boshen) - #834
|
||||
|
||||
### <!-- 4 -->⚡ Performance
|
||||
|
||||
- cache all package.json resolutions for faster package.json lookup ([#853](https://github.com/oxc-project/oxc-resolver/pull/853)) (by @Boshen) - #853
|
||||
- do not canonicalize the entry path ([#848](https://github.com/oxc-project/oxc-resolver/pull/848)) (by @Boshen) - #848
|
||||
- remove Result from `CachedPathImpl::canonicalized` ([#847](https://github.com/oxc-project/oxc-resolver/pull/847)) (by @Boshen) - #847
|
||||
- fast path for node_modules/package ([#839](https://github.com/oxc-project/oxc-resolver/pull/839)) (by @Boshen) - #839
|
||||
- cache canonicalization results at every recursion level ([#843](https://github.com/oxc-project/oxc-resolver/pull/843)) (by @Boshen) - #843
|
||||
- use IdentityHasher for visited set to avoid double hashing ([#837](https://github.com/oxc-project/oxc-resolver/pull/837)) (by @Boshen) - #837
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
* @renovate[bot]
|
||||
|
||||
## [11.13.2](https://github.com/oxc-project/oxc-resolver/compare/v11.13.1...v11.13.2) - 2025-11-12
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- remove AT_STATX_DONT_SYNC from statx calls ([#828](https://github.com/oxc-project/oxc-resolver/pull/828)) (by @Boshen) - #828
|
||||
|
||||
### <!-- 2 -->🚜 Refactor
|
||||
|
||||
- *(file_system)* deduplicate read methods and use Vec<u8> ([#816](https://github.com/oxc-project/oxc-resolver/pull/816)) (by @Boshen)
|
||||
|
||||
### Contributors
|
||||
|
||||
* @renovate[bot]
|
||||
* @Boshen
|
||||
|
||||
## [11.13.1](https://github.com/oxc-project/oxc-resolver/compare/v11.13.0...v11.13.1) - 2025-11-04
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- *(package_json)* re-read file for serde_json fallback in simd implementation ([#808](https://github.com/oxc-project/oxc-resolver/pull/808)) (by @Boshen)
|
||||
- revert system file cache optimization on Linux ([#810](https://github.com/oxc-project/oxc-resolver/pull/810)) (by @Brooooooklyn) - #810
|
||||
- skip loading tsconfig.json from virtual module paths ([#809](https://github.com/oxc-project/oxc-resolver/pull/809)) (by @sapphi-red) - #809
|
||||
|
||||
### <!-- 2 -->🚜 Refactor
|
||||
|
||||
- use cfg_if and rustix in read_to_string_bypass_system_cache ([#802](https://github.com/oxc-project/oxc-resolver/pull/802)) (by @Boshen) - #802
|
||||
|
||||
### <!-- 4 -->⚡ Performance
|
||||
|
||||
- optimize FileSystem metadata operations with rustix ([#800](https://github.com/oxc-project/oxc-resolver/pull/800)) (by @Boshen) - #800
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
* @Brooooooklyn
|
||||
* @sapphi-red
|
||||
* @renovate[bot]
|
||||
|
||||
## [11.13.0](https://github.com/oxc-project/oxc-resolver/compare/v11.12.0...v11.13.0) - 2025-11-02
|
||||
|
||||
### <!-- 0 -->🚀 Features
|
||||
|
||||
- improve error message for empty package.json files ([#793](https://github.com/oxc-project/oxc-resolver/pull/793)) (by @Boshen) - #793
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- don't drop canonicalized path by cache clear ([#791](https://github.com/oxc-project/oxc-resolver/pull/791)) (by @sapphi-red) - #791
|
||||
|
||||
### Contributors
|
||||
|
||||
* @sapphi-red
|
||||
* @Boshen
|
||||
|
||||
## [11.12.0](https://github.com/oxc-project/oxc-resolver/compare/v11.11.1...v11.12.0) - 2025-10-27
|
||||
|
||||
### <!-- 0 -->🚀 Features
|
||||
|
||||
- improve PackagePathNotExported error message with condition names (by @Boshen)
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
|
||||
## [11.11.1](https://github.com/oxc-project/oxc-resolver/compare/v11.11.0...v11.11.1) - 2025-10-21
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- derive Error for JSONError ([#779](https://github.com/oxc-project/oxc-resolver/pull/779)) (by @Boshen) - #779
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
|
||||
## [11.11.0](https://github.com/oxc-project/oxc-resolver/compare/v11.10.0...v11.11.0) - 2025-10-20
|
||||
|
||||
### <!-- 0 -->🚀 Features
|
||||
|
||||
- add big-endian support for package.json parsing ([#768](https://github.com/oxc-project/oxc-resolver/pull/768)) (by @Boshen) - #768
|
||||
- add tsconfig discovery ([#758](https://github.com/oxc-project/oxc-resolver/pull/758)) (by @Boshen) - #758
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- tsconfig paths should not be applied to paths inside node_modules ([#760](https://github.com/oxc-project/oxc-resolver/pull/760)) (by @Boshen) - #760
|
||||
|
||||
### <!-- 6 -->🧪 Testing
|
||||
|
||||
- add a tsconfig extend not found case ([#763](https://github.com/oxc-project/oxc-resolver/pull/763)) (by @Boshen) - #763
|
||||
|
||||
### Contributors
|
||||
|
||||
* @renovate[bot]
|
||||
* @Boshen
|
||||
|
||||
## [11.10.0](https://github.com/oxc-project/oxc-resolver/compare/v11.9.0...v11.10.0) - 2025-10-17
|
||||
|
||||
### <!-- 0 -->🚀 Features
|
||||
|
||||
- add ESM file:// protocol support with comprehensive tests ([#746](https://github.com/oxc-project/oxc-resolver/pull/746)) (by @Boshen) - #746
|
||||
|
||||
### <!-- 2 -->🚜 Refactor
|
||||
|
||||
- remove normalize-path dependency, use internal PathUtil ([#742](https://github.com/oxc-project/oxc-resolver/pull/742)) (by @Boshen) - #742
|
||||
|
||||
### <!-- 4 -->⚡ Performance
|
||||
|
||||
- use simd-json for package.json parsing ([#761](https://github.com/oxc-project/oxc-resolver/pull/761)) (by @Boshen) - #761
|
||||
- make url crate optional for wasm32 targets (by @Boshen)
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
* @renovate[bot]
|
||||
|
||||
## [11.9.0](https://github.com/oxc-project/oxc-resolver/compare/v11.8.4...v11.9.0) - 2025-10-01
|
||||
|
||||
### <!-- 0 -->🚀 Features
|
||||
|
||||
- only resolve file:// protocol on windows ([#737](https://github.com/oxc-project/oxc-resolver/pull/737)) (by @Boshen) - #737
|
||||
|
||||
### <!-- 6 -->🧪 Testing
|
||||
|
||||
- improve test coverage for edge cases ([#740](https://github.com/oxc-project/oxc-resolver/pull/740)) (by @Boshen) - #740
|
||||
- improve coverage for check_restrictions ([#739](https://github.com/oxc-project/oxc-resolver/pull/739)) (by @Boshen) - #739
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
|
||||
## [11.8.4](https://github.com/oxc-project/oxc-resolver/compare/v11.8.3...v11.8.4) - 2025-09-28
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- ensure canonicalized paths remain accessible via strong references ([#733](https://github.com/oxc-project/oxc-resolver/pull/733)) (by @Boshen) - #733
|
||||
|
||||
### <!-- 4 -->⚡ Performance
|
||||
|
||||
- mark error path functions as #[cold] for better optimization ([#729](https://github.com/oxc-project/oxc-resolver/pull/729)) (by @Boshen) - #729
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
|
||||
## [11.8.3](https://github.com/oxc-project/oxc-resolver/compare/v11.8.2...v11.8.3) - 2025-09-23
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- use `Weak` references for `CachedPath` to enable proper drop ([#727](https://github.com/oxc-project/oxc-resolver/pull/727)) (by @Boshen) - #727
|
||||
|
||||
### <!-- 2 -->🚜 Refactor
|
||||
|
||||
- remove a redundant path clone from PackageJson::parse ([#725](https://github.com/oxc-project/oxc-resolver/pull/725)) (by @Boshen) - #725
|
||||
- split src/cache.rs into logical modules ([#714](https://github.com/oxc-project/oxc-resolver/pull/714)) (by @Boshen) - #714
|
||||
|
||||
### <!-- 6 -->🧪 Testing
|
||||
|
||||
- add memory leak test ([#726](https://github.com/oxc-project/oxc-resolver/pull/726)) (by @Boshen) - #726
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
* @renovate[bot]
|
||||
|
||||
## [11.8.2](https://github.com/oxc-project/oxc-resolver/compare/v11.8.1...v11.8.2) - 2025-09-18
|
||||
|
||||
### <!-- 4 -->⚡ Performance
|
||||
|
||||
- bypass file system read cache if memory cache is available ([#707](https://github.com/oxc-project/oxc-resolver/pull/707)) (by @Brooooooklyn) - #707
|
||||
|
||||
### <!-- 6 -->🧪 Testing
|
||||
|
||||
- enable Windows global pnp case ([#703](https://github.com/oxc-project/oxc-resolver/pull/703)) (by @JounQin) - #703
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Brooooooklyn
|
||||
* @JounQin
|
||||
|
||||
## [11.8.1](https://github.com/oxc-project/oxc-resolver/compare/v11.8.0...v11.8.1) - 2025-09-16
|
||||
|
||||
### <!-- 9 -->💼 Other
|
||||
|
||||
- Revert "perf: use `memmap` to speed up file reading" ([#701](https://github.com/oxc-project/oxc-resolver/pull/701)) (by @Boshen) - #701
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
|
||||
## [11.8.0](https://github.com/oxc-project/oxc-resolver/compare/v11.7.2...v11.8.0) - 2025-09-15
|
||||
|
||||
### <!-- 0 -->🚀 Features
|
||||
|
||||
- add benchmark for package.json deserialization ([#698](https://github.com/oxc-project/oxc-resolver/pull/698)) (by @Boshen) - #698
|
||||
|
||||
### <!-- 4 -->⚡ Performance
|
||||
|
||||
- use `memmap` to speed up file reading ([#696](https://github.com/oxc-project/oxc-resolver/pull/696)) (by @Boshen) - #696
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
* @renovate[bot]
|
||||
|
||||
## [11.7.2](https://github.com/oxc-project/oxc-resolver/compare/v11.7.1...v11.7.2) - 2025-09-12
|
||||
|
||||
### <!-- 4 -->⚡ Performance
|
||||
|
||||
- use `GetFileAttributesExW` for symlink metadata lookup on Windows ([#691](https://github.com/oxc-project/oxc-resolver/pull/691)) (by @sapphi-red) - #691
|
||||
|
||||
### Contributors
|
||||
|
||||
* @sapphi-red
|
||||
* @renovate[bot]
|
||||
|
||||
## [11.7.0](https://github.com/oxc-project/oxc-resolver/compare/v11.6.2...v11.7.0) - 2025-08-25
|
||||
|
||||
### <!-- 0 -->🚀 Features
|
||||
|
||||
- *(tsconfig)* support `files` / `include` / `exclude` ([#659](https://github.com/oxc-project/oxc-resolver/pull/659)) (by @shulaoda)
|
||||
- feat(tsconfig) support `allowJs` in `compilerOptions` ([#658](https://github.com/oxc-project/oxc-resolver/pull/658)) (by @shulaoda) - #658
|
||||
- *(tsconfig)* complete inheritance of `compilerOptions` fields ([#657](https://github.com/oxc-project/oxc-resolver/pull/657)) (by @shulaoda)
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- *(tsconfig)* respect Yarn PnP when resolving `extends` paths ([#656](https://github.com/oxc-project/oxc-resolver/pull/656)) (by @shulaoda)
|
||||
|
||||
### <!-- 6 -->🧪 Testing
|
||||
|
||||
- *(tsconfig)* tweak jsx `extends` tests ([#666](https://github.com/oxc-project/oxc-resolver/pull/666)) (by @shulaoda)
|
||||
|
||||
### <!-- 9 -->💼 Other
|
||||
|
||||
- Add comprehensive tests for tsconfig extends functionality ([#660](https://github.com/oxc-project/oxc-resolver/pull/660)) (by @Copilot) - #660
|
||||
|
||||
### Contributors
|
||||
|
||||
* @shulaoda
|
||||
* @renovate[bot]
|
||||
* @Copilot
|
||||
|
||||
## [11.6.2](https://github.com/oxc-project/oxc-resolver/compare/v11.6.1...v11.6.2) - 2025-08-20
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- allow resolving `package?query#fragment` for packages with exports field ([#655](https://github.com/oxc-project/oxc-resolver/pull/655)) (by @sapphi-red) - #655
|
||||
|
||||
### <!-- 4 -->⚡ Performance
|
||||
|
||||
- improve `pattern_key_compare` ([#639](https://github.com/oxc-project/oxc-resolver/pull/639)) (by @Boshen) - #639
|
||||
- most specifiers don't have escaped characters ([#636](https://github.com/oxc-project/oxc-resolver/pull/636)) (by @Boshen) - #636
|
||||
|
||||
### <!-- 6 -->🧪 Testing
|
||||
|
||||
- make tests pass on Windows ([#654](https://github.com/oxc-project/oxc-resolver/pull/654)) (by @sapphi-red) - #654
|
||||
|
||||
### Contributors
|
||||
|
||||
* @sapphi-red
|
||||
* @renovate[bot]
|
||||
* @Boshen
|
||||
|
||||
## [11.6.0](https://github.com/oxc-project/oxc-resolver/compare/v11.5.2...v11.6.0) - 2025-07-18
|
||||
|
||||
### <!-- 0 -->🚀 Features
|
||||
|
||||
- support pass closure to restriction ([#604](https://github.com/oxc-project/oxc-resolver/pull/604)) (by @JounQin) - #604
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- support for resolving empty tsconfig file ([#602](https://github.com/oxc-project/oxc-resolver/pull/602)) (by @JounQin) - #602
|
||||
|
||||
### <!-- 9 -->💼 Other
|
||||
|
||||
- Expose the `ExtendsField` enum of TsConfig ([#607](https://github.com/oxc-project/oxc-resolver/pull/607)) (by @ostenbom) - #607
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
* @JounQin
|
||||
* @renovate[bot]
|
||||
* @ostenbom
|
||||
|
||||
## [11.5.0](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v11.4.0...oxc_resolver-v11.5.0) - 2025-07-06
|
||||
|
||||
### <!-- 0 -->🚀 Features
|
||||
|
||||
- return proper errors when failed to find or read yarn pnp manifest ([#590](https://github.com/oxc-project/oxc-resolver/pull/590)) (by @Boshen) - #590
|
||||
- add `yarn_pnp` logic to `FileSystem` ([#589](https://github.com/oxc-project/oxc-resolver/pull/589)) (by @Boshen) - #589
|
||||
- *(resolver)* rework yarn manifest file look up ([#586](https://github.com/oxc-project/oxc-resolver/pull/586)) (by @Boshen)
|
||||
|
||||
### <!-- 2 -->🚜 Refactor
|
||||
|
||||
- remove `fs_cache` feature flag ([#588](https://github.com/oxc-project/oxc-resolver/pull/588)) (by @Boshen) - #588
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
|
||||
## [11.4.0](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v11.3.0...oxc_resolver-v11.4.0) - 2025-07-01
|
||||
|
||||
### <!-- 0 -->🚀 Features
|
||||
|
||||
- bump `pnp` to 0.11.0 ([#577](https://github.com/oxc-project/oxc-resolver/pull/577)) (by @Boshen) - #577
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
|
||||
## [11.3.0](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v11.2.1...oxc_resolver-v11.3.0) - 2025-06-26
|
||||
|
||||
### <!-- 0 -->🚀 Features
|
||||
|
||||
- align yarn pnp implementation ([#576](https://github.com/oxc-project/oxc-resolver/pull/576)) (by @Boshen) - #576
|
||||
- *(resolver)* allow `exports` field in `require('../directory')` ([#572](https://github.com/oxc-project/oxc-resolver/pull/572)) (by @Boshen)
|
||||
- *(napi)* add `ResolveResult::builtin` information ([#575](https://github.com/oxc-project/oxc-resolver/pull/575)) (by @Boshen)
|
||||
|
||||
### <!-- 3 -->📚 Documentation
|
||||
|
||||
- document `allowPackageExportsInDirectoryResolve` (by @Boshen)
|
||||
|
||||
### Contributors
|
||||
|
||||
* @Boshen
|
||||
|
||||
## [11.2.1](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v11.2.0...oxc_resolver-v11.2.1) - 2025-06-23
|
||||
|
||||
### <!-- 1 -->🐛 Bug Fixes
|
||||
|
||||
- avoid crash when encountering tsconfig circular extends ([#570](https://github.com/oxc-project/oxc-resolver/pull/570))
|
||||
- *(napi)* ensure `pnp_manifest` is included with `yarn_pnp` feature ([#555](https://github.com/oxc-project/oxc-resolver/pull/555))
|
||||
|
||||
### <!-- 10 -->💼 Other
|
||||
|
||||
- *(rust)* `debug = false` in `[profile.dev]` and `[profile.test]` ([#554](https://github.com/oxc-project/oxc-resolver/pull/554))
|
||||
|
||||
### <!-- 3 -->📚 Documentation
|
||||
|
||||
- add ts config
|
||||
- update `alias` and `fallback` options type and description ([#557](https://github.com/oxc-project/oxc-resolver/pull/557))
|
||||
|
||||
## [11.2.0](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v11.1.0...oxc_resolver-v11.2.0) - 2025-06-05
|
||||
|
||||
### <!-- 0 -->Features
|
||||
|
||||
- *(napi)* add `tracing-subscriber` feature; turned on by default ([#546](https://github.com/oxc-project/oxc-resolver/pull/546))
|
||||
|
||||
## [11.1.0](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v11.0.0...oxc_resolver-v11.1.0) - 2025-06-01
|
||||
|
||||
### <!-- 0 -->Features
|
||||
|
||||
- support module type for TS files ([#538](https://github.com/oxc-project/oxc-resolver/pull/538))
|
||||
|
||||
## [11.0.0](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v10.0.0...oxc_resolver-v11.0.0) - 2025-05-28
|
||||
|
||||
### <!-- 0 -->Features
|
||||
|
||||
- implement module type resolution algorithm `ESM_FILE_FORMAT` from the spec ([#535](https://github.com/oxc-project/oxc-resolver/pull/535))
|
||||
|
||||
### <!-- 3 -->Documentation
|
||||
|
||||
- *(README)* clarify algorithm specification
|
||||
|
||||
### <!-- 7 -->Chore
|
||||
|
||||
- *(deps)* lock file maintenance rust crates ([#530](https://github.com/oxc-project/oxc-resolver/pull/530))
|
||||
|
||||
## [10.0.0](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v9.0.2...oxc_resolver-v10.0.0) - 2025-05-20
|
||||
|
||||
### <!-- 0 -->Features
|
||||
|
||||
- *(napi)* upgrade NAPI-RS to 3.0.0-beta.1 ([#525](https://github.com/oxc-project/oxc-resolver/pull/525))
|
||||
|
||||
### <!-- 4 -->Refactor
|
||||
|
||||
- [**breaking**] set clippy `avoid-breaking-exported-api = false` ([#519](https://github.com/oxc-project/oxc-resolver/pull/519))
|
||||
|
||||
### <!-- 7 -->Chore
|
||||
|
||||
- *(deps)* lock file maintenance ([#523](https://github.com/oxc-project/oxc-resolver/pull/523))
|
||||
- *(deps)* update dependency rust to v1.87.0 ([#520](https://github.com/oxc-project/oxc-resolver/pull/520))
|
||||
- sync napi cfg on global_allocator
|
||||
- *(napi)* adjust mimalloc features ([#515](https://github.com/oxc-project/oxc-resolver/pull/515))
|
||||
|
||||
## [9.0.1](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v9.0.0...oxc_resolver-v9.0.1) - 2025-05-09
|
||||
|
||||
### <!-- 1 -->Bug Fixes
|
||||
|
||||
- oxc_resolver_napi dependency version
|
||||
|
||||
## [9.0.0](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v8.0.0...oxc_resolver-v9.0.0) - 2025-05-09
|
||||
|
||||
### <!-- 1 -->Bug Fixes
|
||||
|
||||
- hash import does not need to load from node_modules ([#501](https://github.com/oxc-project/oxc-resolver/pull/501))
|
||||
|
||||
### <!-- 7 -->Chore
|
||||
|
||||
- add `--tsconfig` to example ([#505](https://github.com/oxc-project/oxc-resolver/pull/505))
|
||||
- publish `oxc_napi_resolver` ([#496](https://github.com/oxc-project/oxc-resolver/pull/496))
|
||||
|
||||
## [8.0.0](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v7.0.1...oxc_resolver-v8.0.0) - 2025-05-01
|
||||
|
||||
### <!-- 1 -->Bug Fixes
|
||||
|
||||
- fix incorrect return of package.json when a workspace module has `node_modules` ([#482](https://github.com/oxc-project/oxc-resolver/pull/482))
|
||||
|
||||
### <!-- 2 -->Performance
|
||||
|
||||
- cache whether a path is `node_modules` or inside `node_modules` ([#490](https://github.com/oxc-project/oxc-resolver/pull/490))
|
||||
- remove a useless `load_as_directory` call ([#487](https://github.com/oxc-project/oxc-resolver/pull/487))
|
||||
|
||||
### <!-- 4 -->Refactor
|
||||
|
||||
- [**breaking**] remove `description_files` option ([#488](https://github.com/oxc-project/oxc-resolver/pull/488))
|
||||
- [**breaking**] remove `modules` options ([#484](https://github.com/oxc-project/oxc-resolver/pull/484))
|
||||
|
||||
## [7.0.0](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v6.0.2...oxc_resolver-v7.0.0) - 2025-04-29
|
||||
|
||||
### <!-- 1 -->Bug Fixes
|
||||
|
||||
- return the enclosing `package.json` if it is inside `node_modules` ([#476](https://github.com/oxc-project/oxc-resolver/pull/476))
|
||||
|
||||
### <!-- 4 -->Refactor
|
||||
|
||||
- add `Debug` to `FsCachedPath` ([#478](https://github.com/oxc-project/oxc-resolver/pull/478))
|
||||
|
||||
## [6.0.1](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v6.0.0...oxc_resolver-v6.0.1) - 2025-04-25
|
||||
|
||||
### <!-- 1 -->Bug Fixes
|
||||
|
||||
- handle package.json and tsconfig.json with BOM ([#463](https://github.com/oxc-project/oxc-resolver/pull/463))
|
||||
|
||||
### <!-- 2 -->Performance
|
||||
|
||||
- avoid double call to `parse_package_specifier` ([#465](https://github.com/oxc-project/oxc-resolver/pull/465))
|
||||
|
||||
## [6.0.0](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v5.3.0...oxc_resolver-v6.0.0) - 2025-04-22
|
||||
|
||||
### <!-- 1 -->Bug Fixes
|
||||
|
||||
- properly handle DOS device paths in strip_windows_prefix ([#455](https://github.com/oxc-project/oxc-resolver/pull/455))
|
||||
|
||||
## [5.3.0](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v5.2.0...oxc_resolver-v5.3.0) - 2025-04-19
|
||||
|
||||
### <!-- 0 -->Features
|
||||
|
||||
- deserialize `preserve_value_imports` and `imports_not_used_as_values` from `compilerOptions` ([#457](https://github.com/oxc-project/oxc-resolver/pull/457))
|
||||
- deserialize `target` from `compilerOptions` ([#456](https://github.com/oxc-project/oxc-resolver/pull/456))
|
||||
|
||||
## [5.2.0](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v5.1.1...oxc_resolver-v5.2.0) - 2025-04-08
|
||||
|
||||
### <!-- 1 -->Bug Fixes
|
||||
|
||||
- resolve `${configDir}` in tsconfig `compilerOptions.baseUrl` ([#450](https://github.com/oxc-project/oxc-resolver/pull/450))
|
||||
|
||||
## [5.1.1](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v5.1.0...oxc_resolver-v5.1.1) - 2025-04-04
|
||||
|
||||
### <!-- 1 -->Bug Fixes
|
||||
|
||||
- handle query and fragment in pacakge.json `exports` and `imports` field ([#443](https://github.com/oxc-project/oxc-resolver/pull/443))
|
||||
|
||||
## [5.1.0](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v5.0.1...oxc_resolver-v5.1.0) - 2025-04-02
|
||||
|
||||
### <!-- 0 -->Features
|
||||
|
||||
- resolve emitDecoratorMetadata in tsconfig ([#439](https://github.com/oxc-project/oxc-resolver/pull/439))
|
||||
|
||||
### <!-- 3 -->Documentation
|
||||
|
||||
- fix an incorrect comment on `Context::missing_dependencies`
|
||||
|
||||
## [5.0.0](https://github.com/oxc-project/oxc-resolver/compare/oxc_resolver-v4.2.0...oxc_resolver-v5.0.0) - 2025-03-07
|
||||
|
||||
### <!-- 0 -->Features
|
||||
@@ -129,48 +852,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- use `fs::canonicalize` to cover symlink edge cases ([#284](https://github.com/oxc-project/oxc-resolver/pull/284))
|
||||
- extensionAlias cannot resolve mathjs ([#273](https://github.com/oxc-project/oxc-resolver/pull/273))
|
||||
|
||||
---
|
||||
|
||||
## [0.5.2](https://github.com/web-infra-dev/rspack-resolver/compare/rspack_resolver-v0.5.1...rspack_resolver-v0.5.2) - 2025-02-28
|
||||
|
||||
### Added
|
||||
|
||||
- *(pnp)* support link (#49)
|
||||
|
||||
### Other
|
||||
|
||||
- bump pnp 0.9.1 (#50)
|
||||
|
||||
## [0.5.1](https://github.com/web-infra-dev/rspack-resolver/compare/rspack_resolver-v0.5.0...rspack_resolver-v0.5.1) - 2025-02-11
|
||||
|
||||
### Fixed
|
||||
|
||||
- 🐛 pnp feat respect options.enable_pnp (#47)
|
||||
|
||||
## [0.4.0](https://github.com/web-infra-dev/rspack-resolver/compare/rspack_resolver-v0.3.6...rspack_resolver-v0.4.0) - 2024-12-26
|
||||
|
||||
### Feat
|
||||
|
||||
- Implements the PnP manifest lookup within the resolver ([#39](https://github.com/web-infra-dev/rspack-resolver/pull/39))
|
||||
|
||||
## [0.3.6](https://github.com/web-infra-dev/rspack-resolver/compare/rspack_resolver-v0.3.5...rspack_resolver-v0.3.6) - 2024-12-13
|
||||
|
||||
### Fixed
|
||||
|
||||
- alias match request end with slash (#35)
|
||||
|
||||
## [0.3.5](https://github.com/web-infra-dev/rspack-resolver/compare/rspack_resolver-v0.3.4...rspack_resolver-v0.3.5) - 2024-10-21
|
||||
|
||||
### Fixed
|
||||
|
||||
- resolve mathjs error when using `extensionAlias` ([#31](https://github.com/web-infra-dev/rspack-resolver/pull/31))
|
||||
|
||||
## [0.3.4](https://github.com/web-infra-dev/rspack-resolver/compare/rspack_resolver-v0.3.3...rspack_resolver-v0.3.4) - 2024-10-21
|
||||
|
||||
### Added
|
||||
|
||||
- rebase and refine extension-alias error format ([#30](https://github.com/web-infra-dev/rspack-resolver/pull/30))
|
||||
|
||||
## [1.12.0](https://github.com/oxc-project/oxc_resolver/compare/oxc_resolver-v1.11.0...oxc_resolver-v1.12.0) - 2024-09-25
|
||||
|
||||
### Added
|
||||
|
||||
Generated
+680
-585
File diff suppressed because it is too large
Load Diff
+39
-19
@@ -12,7 +12,7 @@ keywords = ["node", "resolve", "cjs", "esm", "enhanced-resolve"]
|
||||
license = "MIT"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/unrs/unrs-resolver"
|
||||
rust-version = "1.85.0"
|
||||
rust-version = "1.88.0"
|
||||
description = "ESM / CJS module resolution"
|
||||
|
||||
[workspace.dependencies]
|
||||
@@ -33,9 +33,6 @@ repository.workspace = true
|
||||
rust-version.workspace = true
|
||||
description.workspace = true
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[[bench]]
|
||||
name = "resolver"
|
||||
harness = false
|
||||
@@ -43,6 +40,8 @@ harness = false
|
||||
[lints.clippy]
|
||||
all = { level = "warn", priority = -1 }
|
||||
cargo = { level = "warn", priority = -1 }
|
||||
# `simd-json` -> `halfbrown` pulls in `hashbrown` 0.16, while `indexmap`/`serde_json` pull in 0.17.
|
||||
multiple_crate_versions = "allow"
|
||||
# restriction
|
||||
dbg_macro = "warn"
|
||||
todo = "warn"
|
||||
@@ -63,6 +62,7 @@ rc_mutex = "warn"
|
||||
rest_pat_in_fully_bound_structs = "warn"
|
||||
unnecessary_safety_comment = "warn"
|
||||
undocumented_unsafe_blocks = "warn"
|
||||
too_many_arguments = "allow"
|
||||
pedantic = { level = "warn", priority = -1 }
|
||||
# This rule is too pedantic, I don't want to force this because naming things are hard.
|
||||
module_name_repetitions = "allow"
|
||||
@@ -72,43 +72,58 @@ doc_markdown = "allow"
|
||||
nursery = { level = "warn", priority = -1 }
|
||||
literal_string_with_formatting_args = "allow"
|
||||
missing_const_for_fn = "allow"
|
||||
# cargo
|
||||
multiple_crate_versions = "allow"
|
||||
|
||||
[[example]]
|
||||
name = "resolver"
|
||||
name = "dir"
|
||||
|
||||
[dependencies]
|
||||
cfg-if = "1"
|
||||
compact_str = "0.9"
|
||||
fast-glob = "1"
|
||||
indexmap = { version = "2", features = ["serde"] }
|
||||
json-strip-comments = "1"
|
||||
json-strip-comments = "3.1"
|
||||
nodejs-built-in-modules = "1.0.0"
|
||||
once_cell = "1" # Use `std::sync::OnceLock::get_or_try_init` when it is stable.
|
||||
papaya = "0.2"
|
||||
rustc-hash = { version = "2" }
|
||||
serde = { version = "1", features = ["derive"] } # derive for Deserialize from package.json
|
||||
serde_json = { version = "1", features = ["preserve_order"] } # preserve_order: package_json.exports requires order such as `["require", "import", "default"]`
|
||||
serde_json = { version = "1", features = [
|
||||
"preserve_order",
|
||||
] } # preserve_order: package_json.exports requires order such as `["require", "import", "default"]`
|
||||
simdutf8 = { version = "0.1" }
|
||||
thiserror = "2"
|
||||
tracing = "0.1"
|
||||
url = "2"
|
||||
|
||||
pnp = { version = "0.11.0", optional = true }
|
||||
percent-encoding = "2"
|
||||
pnp = { version = "0.12.8", optional = true }
|
||||
|
||||
document-features = { version = "0.2.11", optional = true }
|
||||
document-features = { version = "0.2.12", optional = true }
|
||||
|
||||
[target.'cfg(any(target_os = "macos", target_os = "linux"))'.dependencies]
|
||||
rustix = { version = "1.1.4", features = ["fs"] }
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
windows = { version = "0.62.2", features = ["Win32_Storage_FileSystem"] }
|
||||
|
||||
[target.'cfg(target_endian = "little")'.dependencies]
|
||||
# simd-json only works on little-endian systems
|
||||
simd-json = { version = "0.17.0", default-features = false, features = ["runtime-detection"] }
|
||||
self_cell = "1" # Used by simd implementation for self-referential struct
|
||||
|
||||
[dev-dependencies]
|
||||
criterion2 = { version = "3.0.1", default-features = false }
|
||||
criterion2 = { version = "3.0.3", default-features = false }
|
||||
dirs = { version = "6.0.0" }
|
||||
normalize-path = { version = "0.2.1" }
|
||||
fancy-regex = { version = "^0.18.0", default-features = false, features = ["std"] }
|
||||
pico-args = "0.5.0"
|
||||
rayon = { version = "1.10.0" }
|
||||
vfs = "0.12.1" # for testing with in memory file system
|
||||
rayon = { version = "1.12.0" }
|
||||
vfs = "0.13.0" # for testing with in memory file system
|
||||
walkdir = "2" # for loading benchmark fixtures
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dev-dependencies]
|
||||
windows-sys = { version = "0.61.2", features = ["Win32_Storage", "Win32_Storage_FileSystem"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
## Enables the [PackageJson::raw_json] API,
|
||||
## which returns the `package.json` with `serde_json::Value`.
|
||||
package_json_raw_json_api = []
|
||||
## [Yarn Plug'n'Play](https://yarnpkg.com/features/pnp)
|
||||
yarn_pnp = ["pnp"]
|
||||
# For codspeed benchmark
|
||||
@@ -124,6 +139,11 @@ debug = false
|
||||
# and we don't rely on it for debugging that much.
|
||||
debug = false
|
||||
|
||||
[profile.wasm-test]
|
||||
inherits = "test"
|
||||
debug = true
|
||||
opt-level = "z" # Avoid too many locals errors during wasmtime testing
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
||||
@@ -1,31 +1,3 @@
|
||||
> [!NOTE]
|
||||
>
|
||||
> This is a fork of [oxc-resolver] and [rspack-resolver], and will be used in [eslint-plugin-import-x] and [eslint-import-resolver-typescript] cause 100% compatible with [enhanced-resolve] is the non-goal of [oxc-resolver] itself, we add [enhanced-resolve] specific features like [`pnp support`](https://github.com/web-infra-dev/rspack/issues/2236).
|
||||
>
|
||||
> We also fix several bugs reported by [eslint-plugin-import-x] and [eslint-import-resolver-typescript] users:
|
||||
>
|
||||
> - takes `paths` and `references` into account [at the same time](https://github.com/unrs/unrs-resolver/pull/12)
|
||||
> - `references` should [take higher priority](https://github.com/unrs/unrs-resolver/pull/13)
|
||||
> - support `pnpapi` core module and [package deep link](https://github.com/un-ts/eslint-plugin-import-x/issues/253)
|
||||
> - enable [more targets](https://github.com/unrs/unrs-resolver/pull/29) support
|
||||
> - absolute path aliasing [should not be skipped](https://github.com/import-js/eslint-import-resolver-typescript/issues/401)
|
||||
> - use [napi-postinstall] for [legacy npm versions](https://github.com/unrs/unrs-resolver/issues/56)
|
||||
> - Raspberry PI 4 aarch64 [compatibility issue](https://github.com/unrs/unrs-resolver/issues/64) and [import-js/eslint-import-resolver-typescript#406](https://github.com/import-js/eslint-import-resolver-typescript/issues/406) due to [mimalloc-safe]
|
||||
> - support `load_as_directory` for [`pnp` mode](https://github.com/import-js/eslint-import-resolver-typescript/issues/409)
|
||||
> - [resolve parent base url correctly](https://github.com/import-js/eslint-import-resolver-typescript/issues/437) by normalizing as absolute path
|
||||
>
|
||||
> The list could be longer in the future, but we don't want to make it too long here.
|
||||
>
|
||||
> We also sync with [oxc-resolver] and [rspack-resolver] regularly to keep up with the latest changes:
|
||||
>
|
||||
> - `oxc-resolver`: [#15](https://github.com/unrs/unrs-resolver/pull/15), [#49](https://github.com/unrs/unrs-resolver/pull/49), [#62](https://github.com/unrs/unrs-resolver/pull/62), [#86](https://github.com/unrs/unrs-resolver/pull/86) and [#94](https://github.com/unrs/unrs-resolver/pull/94)
|
||||
> - `rspack-resolver`(planned): [#59](https://github.com/unrs/unrs-resolver/issues/59)
|
||||
>
|
||||
> Last but not least, we prepare some bug fix PRs first on our side and PR back into upstream projects, and we will keep doing this in the future:
|
||||
>
|
||||
> - `oxc-resolver`: [#84](https://github.com/unrs/unrs-resolver/pull/84) with [oxc-resolver#455](https://github.com/oxc-project/oxc-resolver/pull/455)
|
||||
> - `rspack-resolver`: [#7](https://github.com/unrs/unrs-resolver/pull/7) with [rspack-resolver#54](https://github.com/web-infra-dev/rspack-resolver/pull/54), which is eventually replaced by [oxc-resolver#443](https://github.com/oxc-project/oxc-resolver/pull/443)
|
||||
|
||||
<div align="center">
|
||||
|
||||
[![Crates.io][crates-badge]][crates-url]
|
||||
@@ -42,7 +14,7 @@
|
||||
|
||||
# UnRS Resolver
|
||||
|
||||
Rust port of [enhanced-resolve].
|
||||
Rust port of [enhanced-resolve], [tsconfig-paths-webpack-plugin] and [tsconfck]
|
||||
|
||||
- Released on [crates.io][crates-url] and [npm][npm-url].
|
||||
- Implements the [ESM](https://nodejs.org/api/esm.html#resolution-algorithm) and [CommonJS](https://nodejs.org/api/modules.html#all-together) module resolution algorithm specification.
|
||||
@@ -51,6 +23,7 @@ Rust port of [enhanced-resolve].
|
||||
- support paths alias defined in `tsconfig.compilerOptions.paths`
|
||||
- support project references defined `tsconfig.references`
|
||||
- support [template variable ${configDir} for substitution of config files directory path](https://github.com/microsoft/TypeScript/pull/58042)
|
||||
- Built-in tsconfig discovery ([tsconfck])
|
||||
- Supports in-memory file system via the `FileSystem` trait.
|
||||
- Contains `tracing` instrumentation.
|
||||
|
||||
@@ -63,20 +36,48 @@ See `index.d.ts` for `resolveSync` and `ResolverFactory` API.
|
||||
Quick example:
|
||||
|
||||
```javascript
|
||||
import assert from 'node:assert';
|
||||
import path from 'node:path';
|
||||
import assert from "node:assert";
|
||||
import path from "node:path";
|
||||
|
||||
import resolve, { ResolverFactory } from 'unrs-resolver';
|
||||
import resolve, { ResolverFactory } from "unrs-resolver";
|
||||
|
||||
// `resolve`
|
||||
assert(resolve.sync(process.cwd(), './index.js').path, path.resolve('index.js'));
|
||||
assert(resolve.sync(process.cwd(), "./index.js").path, path.resolve("index.js"));
|
||||
|
||||
// `ResolverFactory`
|
||||
const resolver = new ResolverFactory();
|
||||
assert(resolver.sync(process.cwd(), './index.js').path, path.resolve('index.js'));
|
||||
assert(resolver.sync(process.cwd(), "./index.js").path, path.resolve("index.js"));
|
||||
```
|
||||
|
||||
### Supports WASM
|
||||
#### File-based Resolution
|
||||
|
||||
For file-based resolution with automatic tsconfig discovery, use `resolveFileSync` or `resolveFileAsync`:
|
||||
|
||||
```javascript
|
||||
const resolver = new ResolverFactory();
|
||||
|
||||
// Resolves from a file path (not directory)
|
||||
const result = resolver.resolveFileSync("/path/to/file.ts", "./module");
|
||||
|
||||
// Async version
|
||||
const result = await resolver.resolveFileAsync("/path/to/file.ts", "./module");
|
||||
```
|
||||
|
||||
**Key Differences:**
|
||||
|
||||
- `sync(directory, specifier)` - Takes a **directory path**, uses manually configured tsconfig if provided
|
||||
- `resolveFileSync(file, specifier)` - Takes a **file path**, automatically discovers tsconfig.json by traversing parent directories
|
||||
|
||||
**Why use `resolveFileSync`?**
|
||||
|
||||
When resolving from a specific file (e.g., in bundlers, linters, or language servers), `resolveFileSync` automatically finds the correct `tsconfig.json` by:
|
||||
|
||||
- Traversing parent directories from the file location
|
||||
- Respecting TypeScript project references
|
||||
- Honoring `include`, `exclude`, and `files` fields to determine which tsconfig applies
|
||||
- Ensuring tsconfig `paths` aliases work correctly based on the file's context
|
||||
|
||||
#### Supports WASM
|
||||
|
||||
See https://stackblitz.com/edit/unrs-resolver for usage example.
|
||||
|
||||
@@ -154,11 +155,11 @@ To support both CJS and ESM with the same cache:
|
||||
|
||||
```javascript
|
||||
const esmResolver = new ResolverFactory({
|
||||
conditionNames: ['node', 'import'],
|
||||
conditionNames: ["node", "import"],
|
||||
});
|
||||
|
||||
const cjsResolver = esmResolver.cloneWithOptions({
|
||||
conditionNames: ['node', 'require'],
|
||||
conditionNames: ["node", "require"],
|
||||
});
|
||||
```
|
||||
|
||||
@@ -202,8 +203,7 @@ See [index.d.ts](https://github.com/unrs/unrs-resolver/blob/main/napi/index.d.ts
|
||||
| aliasFields | [] | A list of alias fields in description files |
|
||||
| extensionAlias | {} | An object which maps extension to extension aliases |
|
||||
| conditionNames | [] | A list of exports field condition names |
|
||||
| descriptionFiles | ["package.json"] | A list of description files to read from |
|
||||
| enforceExtension | false | Enforce that a extension from extensions must be used |
|
||||
| enforceExtension | false | Enforce that an extension from extensions must be used |
|
||||
| exportsFields | ["exports"] | A list of exports fields in description files |
|
||||
| extensions | [".js", ".json", ".node"] | A list of extensions which should be tried for files |
|
||||
| fallback | {} | Same as `alias`, but only used if default resolving fails |
|
||||
@@ -211,7 +211,7 @@ See [index.d.ts](https://github.com/unrs/unrs-resolver/blob/main/napi/index.d.ts
|
||||
| fullySpecified | false | Request passed to resolve is already fully specified and extensions or main files are not resolved for it (they are still resolved for internal requests) |
|
||||
| mainFields | ["main"] | A list of main fields in description files |
|
||||
| mainFiles | ["index"] | A list of main files in directories |
|
||||
| modules | ["node_modules"] | A list of directories to resolve modules from, can be absolute path or folder name |
|
||||
| modules | ["node_modules"] | A list of directories to resolve modules from, can be absolute path or folder name. Absolute `NODE_PATH` entries are appended automatically when set. |
|
||||
| resolveToContext | false | Resolve to a context instead of a file |
|
||||
| preferRelative | false | Prefer to resolve module requests as relative request and fallback to resolving as module |
|
||||
| preferAbsolute | false | Prefer to resolve server-relative urls as absolute paths before falling back to resolve in roots |
|
||||
@@ -225,13 +225,14 @@ See [index.d.ts](https://github.com/unrs/unrs-resolver/blob/main/napi/index.d.ts
|
||||
| Field | Default | Description |
|
||||
| ------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| tsconfig | None | TypeScript related config for resolver |
|
||||
| tsconfig.configFile | | A relative path to the tsconfig file based on `cwd`, or an absolute path of tsconfig file. |
|
||||
| tsconfig.configFile | | A relative path to the tsconfig file based on `cwd`, or an absolute path to the tsconfig file. |
|
||||
| tsconfig.references | `[]` | - 'auto': inherits from TypeScript config <br/> - `string []`: relative path (based on directory of the referencing tsconfig file) or absolute path of referenced project's tsconfig |
|
||||
|
||||
### Unimplemented Options
|
||||
|
||||
| Field | Default | Description |
|
||||
| ---------------- | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| descriptionFiles | ["package.json"] | A list of description files to read from |
|
||||
| cachePredicate | function() { return true }; | A function which decides whether a request should be cached or not. An object is passed to the function with `path` and `request` properties. |
|
||||
| cacheWithContext | true | If unsafe cache is enabled, includes `request.context` in the cache key |
|
||||
| plugins | [] | A list of additional resolve plugins which should be applied |
|
||||
@@ -321,22 +322,15 @@ Irrelevant tests
|
||||
|
||||
UnRS partially copies code from the following projects.
|
||||
|
||||
| Project | License |
|
||||
| --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
|
||||
| [webpack/enhanced-resolve](https://github.com/webpack/enhanced-resolve) | [MIT](https://github.com/webpack/enhanced-resolve/blob/main/LICENSE) |
|
||||
| [dividab/tsconfig-paths](https://github.com/dividab/tsconfig-paths) | [MIT](https://github.com/dividab/tsconfig-paths/blob/master/LICENSE) |
|
||||
| [parcel-bundler/parcel](https://github.com/parcel-bundler/parcel) | [MIT](https://github.com/parcel-bundler/parcel/blob/v2/LICENSE) |
|
||||
| [tmccombs/json-comments-rs](https://github.com/tmccombs/json-comments-rs) | [Apache 2.0](https://github.com/tmccombs/json-comments-rs/blob/main/LICENSE) |
|
||||
| [oxc-project/oxc-resolver](https://github.com/oxc-project/oxc-resolver) | [MIT](https://github.com/oxc-project/oxc-resolver/blob/main/LICENSE) |
|
||||
| [web-infra-dev/rspack-resolver](https://github.com/web-infra-dev/rspack-resolver) | [MIT](https://github.com/web-infra-dev/rspack-resolver/blob/main/LICENSE) |
|
||||
| Project | License |
|
||||
| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
|
||||
| [webpack/enhanced-resolve](https://github.com/webpack/enhanced-resolve) | [MIT](https://github.com/webpack/enhanced-resolve/blob/main/LICENSE) |
|
||||
| [dividab/tsconfig-paths](https://github.com/dividab/tsconfig-paths) | [MIT](https://github.com/dividab/tsconfig-paths/blob/master/LICENSE) |
|
||||
| [parcel-bundler/parcel](https://github.com/parcel-bundler/parcel) | [MIT](https://github.com/parcel-bundler/parcel/blob/v2/LICENSE) |
|
||||
| [tmccombs/json-comments-rs](https://github.com/tmccombs/json-comments-rs) | [Apache 2.0](https://github.com/tmccombs/json-comments-rs/blob/main/LICENSE) |
|
||||
| [dominikg/tsconfck](https://github.com/dominikg/tsconfck) | [MIT](https://github.com/dominikg/tsconfck/blob/main/packages/tsconfck/LICENSE) |
|
||||
|
||||
[enhanced-resolve]: https://github.com/webpack/enhanced-resolve
|
||||
[oxc-resolver]: https://github.com/oxc-project/oxc-resolver
|
||||
[rspack-resolver]: https://github.com/web-infra-dev/rspack-resolver
|
||||
[eslint-plugin-import-x]: https://github.com/un-ts/eslint-plugin-import-x
|
||||
[eslint-import-resolver-typescript]: https://github.com/import-js/eslint-import-resolver-typescript
|
||||
[napi-postinstall]: https://github.com/un-ts/napi-postinstall
|
||||
[mimalloc-safe]: https://github.com/napi-rs/mimalloc-safe
|
||||
[tsconfig-paths-webpack-plugin]: https://github.com/dividab/tsconfig-paths-webpack-plugin
|
||||
[license-badge]: https://img.shields.io/badge/license-MIT-blue.svg
|
||||
[license-url]: https://github.com/unrs/unrs-resolver/blob/main/LICENSE
|
||||
@@ -344,13 +338,14 @@ UnRS partially copies code from the following projects.
|
||||
[ci-url]: https://github.com/unrs/unrs-resolver/actions/workflows/ci.yml?query=event%3Apush+branch%3Amain
|
||||
[code-coverage-badge]: https://codecov.io/github/unrs/unrs-resolver/branch/main/graph/badge.svg
|
||||
[code-coverage-url]: https://codecov.io/gh/unrs/unrs-resolver
|
||||
[sponsors-badge]: https://img.shields.io/github/sponsors/JounQin
|
||||
[sponsors-url]: https://github.com/sponsors/JounQin
|
||||
[sponsors-badge]: https://img.shields.io/github/sponsors/Boshen
|
||||
[sponsors-url]: https://github.com/sponsors/Boshen
|
||||
[codspeed-badge]: https://img.shields.io/endpoint?url=https://codspeed.io/badge.json
|
||||
[codspeed-url]: https://codspeed.io/unrs/unrs-resolver
|
||||
[crates-badge]: https://img.shields.io/crates/d/unrs_resolver?label=crates.io
|
||||
[crates-badge]: https://img.shields.io/crates/dr/unrs_resolver
|
||||
[crates-url]: https://crates.io/crates/unrs_resolver
|
||||
[docs-badge]: https://img.shields.io/docsrs/unrs_resolver
|
||||
[docs-url]: https://docs.rs/unrs_resolver
|
||||
[docs-url]: https://docs.rs/unrs_resolver/latest/unrs_resolver/
|
||||
[npm-badge]: https://img.shields.io/npm/dw/unrs-resolver?label=npm
|
||||
[npm-url]: https://www.npmjs.com/package/unrs-resolver
|
||||
[npm-url]: https://npmx.dev/package/unrs-resolver
|
||||
[tsconfck]: https://github.com/dominikg/tsconfck
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
## Security contact information
|
||||
|
||||
To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security).
|
||||
Tidelift will coordinate the fix and disclosure.
|
||||
+650
-22
@@ -6,16 +6,19 @@ use std::{
|
||||
|
||||
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
|
||||
use rayon::prelude::*;
|
||||
use unrs_resolver::{FileSystem as FileSystemTrait, FileSystemOs, PackageJson};
|
||||
|
||||
use memory_fs::BenchMemoryFS;
|
||||
|
||||
fn data() -> Vec<(PathBuf, &'static str)> {
|
||||
let cwd = env::current_dir().unwrap();
|
||||
let f1 = cwd.join("fixtures/enhanced_resolve");
|
||||
let f1 = cwd.join("fixtures/enhanced-resolve");
|
||||
let f2 = f1.join("test/fixtures");
|
||||
vec![
|
||||
// real packages
|
||||
(cwd.clone(), "@napi-rs/cli"),
|
||||
(cwd.clone(), "@napi-rs/wasm-runtime"),
|
||||
(cwd.clone(), "vitest"),
|
||||
(cwd.clone(), "vite-plus"),
|
||||
(cwd.clone(), "emnapi"),
|
||||
(cwd, "typescript"),
|
||||
// relative path
|
||||
@@ -79,7 +82,7 @@ fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<(
|
||||
}
|
||||
|
||||
fn create_symlinks() -> io::Result<PathBuf> {
|
||||
let root = env::current_dir()?.join("fixtures/enhanced_resolve");
|
||||
let root = env::current_dir()?.join("fixtures/enhanced-resolve");
|
||||
let dirname = root.join("test");
|
||||
let temp_path = dirname.join("temp_symlinks");
|
||||
let create_symlink_fixtures = || -> io::Result<()> {
|
||||
@@ -92,19 +95,19 @@ fn create_symlinks() -> io::Result<PathBuf> {
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
if !temp_path.exists() {
|
||||
if let Err(err) = create_symlink_fixtures() {
|
||||
let _ = fs::remove_dir_all(&temp_path);
|
||||
return Err(err);
|
||||
}
|
||||
if !temp_path.exists()
|
||||
&& let Err(err) = create_symlink_fixtures()
|
||||
{
|
||||
let _ = fs::remove_dir_all(&temp_path);
|
||||
return Err(err);
|
||||
}
|
||||
Ok(temp_path)
|
||||
}
|
||||
|
||||
fn unrs_resolver() -> unrs_resolver::Resolver {
|
||||
use unrs_resolver::{AliasValue, ResolveOptions, Resolver};
|
||||
fn resolve_options() -> unrs_resolver::ResolveOptions {
|
||||
use unrs_resolver::{AliasValue, ResolveOptions};
|
||||
let alias_value = AliasValue::from("./");
|
||||
Resolver::new(ResolveOptions {
|
||||
ResolveOptions {
|
||||
extensions: vec![".ts".into(), ".js".into()],
|
||||
condition_names: vec!["webpack".into(), "require".into()],
|
||||
alias_fields: vec![vec!["browser".into()]],
|
||||
@@ -140,32 +143,47 @@ fn unrs_resolver() -> unrs_resolver::Resolver {
|
||||
("@@@".into(), vec![alias_value]),
|
||||
],
|
||||
..ResolveOptions::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn bench_resolver(c: &mut Criterion) {
|
||||
fn unrs_resolver_memory() -> unrs_resolver::ResolverGeneric<BenchMemoryFS> {
|
||||
use unrs_resolver::ResolverGeneric;
|
||||
let fs = BenchMemoryFS::new();
|
||||
ResolverGeneric::new_with_file_system(fs, resolve_options())
|
||||
}
|
||||
|
||||
fn unrs_resolver_real() -> unrs_resolver::Resolver {
|
||||
use unrs_resolver::Resolver;
|
||||
Resolver::new(resolve_options())
|
||||
}
|
||||
|
||||
fn bench_resolver_memory(c: &mut Criterion) {
|
||||
let data = data();
|
||||
let cwd = env::current_dir().unwrap();
|
||||
let symlink_test_dir = cwd.join("fixtures/enhanced-resolve/test/temp_symlinks");
|
||||
|
||||
// check validity
|
||||
for (path, request) in &data {
|
||||
assert!(unrs_resolver().resolve(path, request).is_ok(), "{} {request}", path.display());
|
||||
assert!(
|
||||
unrs_resolver_memory().resolve(path, request).is_ok(),
|
||||
"{} {request}",
|
||||
path.display()
|
||||
);
|
||||
}
|
||||
|
||||
let symlink_test_dir = create_symlinks().expect("Create symlink fixtures failed");
|
||||
|
||||
let symlinks_range = 0u32..10000;
|
||||
|
||||
for i in symlinks_range.clone() {
|
||||
assert!(
|
||||
unrs_resolver().resolve(&symlink_test_dir, &format!("./file{i}")).is_ok(),
|
||||
unrs_resolver_memory().resolve(&symlink_test_dir, &format!("./file{i}")).is_ok(),
|
||||
"file{i}.js"
|
||||
);
|
||||
}
|
||||
|
||||
let mut group = c.benchmark_group("resolver");
|
||||
let mut group = c.benchmark_group("resolver_memory");
|
||||
|
||||
group.bench_with_input(BenchmarkId::from_parameter("single-thread"), &data, |b, data| {
|
||||
let unrs_resolver = unrs_resolver();
|
||||
let unrs_resolver = unrs_resolver_memory();
|
||||
b.iter(|| {
|
||||
for (path, request) in data {
|
||||
_ = unrs_resolver.resolve(path, request);
|
||||
@@ -173,8 +191,17 @@ fn bench_resolver(c: &mut Criterion) {
|
||||
});
|
||||
});
|
||||
|
||||
group.bench_with_input(BenchmarkId::from_parameter("drop"), &data, |b, data| {
|
||||
b.iter(|| {
|
||||
let unrs_resolver = unrs_resolver_memory(); // Measure `Drop` performance.
|
||||
for (path, request) in data {
|
||||
_ = unrs_resolver.resolve(path, request);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
group.bench_with_input(BenchmarkId::from_parameter("multi-thread"), &data, |b, data| {
|
||||
let unrs_resolver = unrs_resolver();
|
||||
let unrs_resolver = unrs_resolver_memory();
|
||||
b.iter(|| {
|
||||
data.par_iter().for_each(|(path, request)| {
|
||||
_ = unrs_resolver.resolve(path, request);
|
||||
@@ -186,7 +213,79 @@ fn bench_resolver(c: &mut Criterion) {
|
||||
BenchmarkId::from_parameter("resolve from symlinks"),
|
||||
&symlinks_range,
|
||||
|b, data| {
|
||||
let unrs_resolver = unrs_resolver();
|
||||
let unrs_resolver = unrs_resolver_memory();
|
||||
b.iter(|| {
|
||||
for i in data.clone() {
|
||||
assert!(
|
||||
unrs_resolver.resolve(&symlink_test_dir, &format!("./file{i}")).is_ok(),
|
||||
"file{i}.js"
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
group.bench_with_input(BenchmarkId::from_parameter("find tsconfig"), &data, |b, data| {
|
||||
let unrs_resolver = unrs_resolver_memory();
|
||||
let paths = data
|
||||
.iter()
|
||||
.map(|(path, request)| unrs_resolver.resolve(path, request).unwrap().into_path_buf())
|
||||
.collect::<Vec<_>>();
|
||||
b.iter(|| {
|
||||
for path in &paths {
|
||||
let _ = unrs_resolver.find_tsconfig(path);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_resolver_real(c: &mut Criterion) {
|
||||
let data = data();
|
||||
let symlink_test_dir = create_symlinks().expect("Create symlink fixtures failed");
|
||||
|
||||
// check validity
|
||||
for (path, request) in &data {
|
||||
assert!(
|
||||
unrs_resolver_real().resolve(path, request).is_ok(),
|
||||
"{} {request}",
|
||||
path.display()
|
||||
);
|
||||
}
|
||||
|
||||
let symlinks_range = 0u32..10000;
|
||||
|
||||
for i in symlinks_range.clone() {
|
||||
assert!(
|
||||
unrs_resolver_real().resolve(&symlink_test_dir, &format!("./file{i}")).is_ok(),
|
||||
"file{i}.js"
|
||||
);
|
||||
}
|
||||
|
||||
let mut group = c.benchmark_group("resolver_real");
|
||||
|
||||
group.bench_with_input(BenchmarkId::from_parameter("single-thread"), &data, |b, data| {
|
||||
let unrs_resolver = unrs_resolver_real();
|
||||
b.iter(|| {
|
||||
for (path, request) in data {
|
||||
_ = unrs_resolver.resolve(path, request);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
group.bench_with_input(BenchmarkId::from_parameter("multi-thread"), &data, |b, data| {
|
||||
let unrs_resolver = unrs_resolver_real();
|
||||
b.iter(|| {
|
||||
data.par_iter().for_each(|(path, request)| {
|
||||
_ = unrs_resolver.resolve(path, request);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
group.bench_with_input(
|
||||
BenchmarkId::from_parameter("resolve from symlinks"),
|
||||
&symlinks_range,
|
||||
|b, data| {
|
||||
let unrs_resolver = unrs_resolver_real();
|
||||
b.iter(|| {
|
||||
for i in data.clone() {
|
||||
assert!(
|
||||
@@ -199,5 +298,534 @@ fn bench_resolver(c: &mut Criterion) {
|
||||
);
|
||||
}
|
||||
|
||||
criterion_group!(resolver, bench_resolver);
|
||||
fn bench_package_json_deserialization(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("package_json_deserialization");
|
||||
|
||||
// Prepare different sizes of package.json content
|
||||
let small_json = r#"{
|
||||
"name": "test-package",
|
||||
"version": "1.0.0"
|
||||
}"#;
|
||||
|
||||
let medium_json = r##"{
|
||||
"name": "test-package",
|
||||
"version": "1.0.0",
|
||||
"main": "./lib/index.js",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./lib/index.js",
|
||||
"./feature": "./lib/feature.js"
|
||||
},
|
||||
"imports": {
|
||||
"#internal": "./src/internal.js"
|
||||
},
|
||||
"browser": {
|
||||
"./lib/node.js": "./lib/browser.js"
|
||||
},
|
||||
"sideEffects": false
|
||||
}"##;
|
||||
|
||||
let large_json = r##"{
|
||||
"name": "test-package",
|
||||
"version": "1.0.0",
|
||||
"main": "./lib/index.js",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./lib/index.mjs",
|
||||
"require": "./lib/index.cjs",
|
||||
"browser": "./lib/browser.js"
|
||||
},
|
||||
"./feature": {
|
||||
"import": "./lib/feature.mjs",
|
||||
"require": "./lib/feature.cjs"
|
||||
},
|
||||
"./utils": "./lib/utils.js",
|
||||
"./internal/*": "./lib/internal/*.js"
|
||||
},
|
||||
"imports": {
|
||||
"#internal": "./src/internal.js",
|
||||
"#utils/*": "./src/utils/*.js"
|
||||
},
|
||||
"browser": {
|
||||
"./lib/node.js": "./lib/browser.js",
|
||||
"module-a": "./browser/module-a.js",
|
||||
"module-b": "module-c",
|
||||
"./lib/replaced.js": "./lib/browser"
|
||||
},
|
||||
"sideEffects": ["*.css", "*.scss"],
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.21",
|
||||
"react": "^18.0.0",
|
||||
"express": "^4.18.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.0.0",
|
||||
"eslint": "^8.0.0",
|
||||
"jest": "^29.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"build": "tsc",
|
||||
"lint": "eslint src"
|
||||
}
|
||||
}"##;
|
||||
|
||||
// Load real complex package.json from fixtures
|
||||
let complex_json_path = env::current_dir()
|
||||
.unwrap()
|
||||
.join("fixtures/enhanced-resolve/test/fixtures/browser-module/package.json");
|
||||
let complex_json =
|
||||
fs::read_to_string(&complex_json_path).expect("Failed to read complex package.json");
|
||||
|
||||
let test_path = PathBuf::from("/test/package.json");
|
||||
let test_realpath = test_path.clone();
|
||||
#[cfg(feature = "yarn_pnp")]
|
||||
let fs = FileSystemOs::new(false);
|
||||
#[cfg(not(feature = "yarn_pnp"))]
|
||||
let fs = FileSystemOs::new();
|
||||
|
||||
let data = [
|
||||
("small", small_json.to_string()),
|
||||
("medium", medium_json.to_string()),
|
||||
("large", large_json.to_string()),
|
||||
("complex_real", complex_json),
|
||||
];
|
||||
|
||||
for (name, json) in data {
|
||||
group.bench_function(name, |b| {
|
||||
b.iter_with_setup_wrapper(|runner| {
|
||||
let json = json.clone().into_bytes();
|
||||
runner.run(|| {
|
||||
PackageJson::parse(&fs, test_path.clone(), test_realpath.clone(), json)
|
||||
.expect("Failed to parse JSON");
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
group.finish();
|
||||
}
|
||||
|
||||
fn bench_tsconfig_paths_aliases(c: &mut Criterion) {
|
||||
use unrs_resolver::{
|
||||
ResolveOptions, ResolverGeneric, TsconfigDiscovery, TsconfigOptions, TsconfigReferences,
|
||||
};
|
||||
|
||||
let mut group = c.benchmark_group("tsconfig_paths_aliases_memory");
|
||||
let alias_count = 200usize;
|
||||
let (fs, importer, tsconfig_path, requests) =
|
||||
BenchMemoryFS::with_large_tsconfig_paths_fixture(alias_count);
|
||||
let resolver = ResolverGeneric::new_with_file_system(
|
||||
fs,
|
||||
ResolveOptions {
|
||||
tsconfig: Some(TsconfigDiscovery::Manual(TsconfigOptions {
|
||||
config_file: tsconfig_path,
|
||||
references: TsconfigReferences::Disabled,
|
||||
})),
|
||||
extensions: vec![".ts".into(), ".js".into()],
|
||||
..ResolveOptions::default()
|
||||
},
|
||||
);
|
||||
|
||||
// Check validity by resolving every alias once.
|
||||
for request in &requests {
|
||||
assert!(
|
||||
resolver.resolve_file(&importer, request).is_ok(),
|
||||
"alias_count={alias_count} request={request}"
|
||||
);
|
||||
}
|
||||
|
||||
group.bench_with_input(
|
||||
BenchmarkId::from_parameter("query each alias"),
|
||||
&requests,
|
||||
|b, requests| {
|
||||
b.iter(|| {
|
||||
for request in requests {
|
||||
_ = resolver.resolve_file(&importer, request);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
resolver,
|
||||
bench_resolver_memory,
|
||||
bench_resolver_real,
|
||||
bench_package_json_deserialization,
|
||||
bench_tsconfig_paths_aliases
|
||||
);
|
||||
criterion_main!(resolver);
|
||||
|
||||
mod memory_fs {
|
||||
//! Memory-based file system implementation for benchmarks.
|
||||
//!
|
||||
//! This module provides an in-memory file system that loads all fixture data
|
||||
//! and node_modules packages at initialization time, eliminating filesystem I/O
|
||||
//! variance during benchmark execution. This ensures stable, reproducible benchmark results.
|
||||
|
||||
use std::{
|
||||
fs, io,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use std::sync::LazyLock;
|
||||
use unrs_resolver::{FileMetadata, FileSystem, ResolveError};
|
||||
use walkdir::WalkDir;
|
||||
|
||||
/// Memory-based file system for benchmarks to eliminate I/O variance
|
||||
#[derive(Clone)]
|
||||
pub struct BenchMemoryFS {
|
||||
files: FxHashMap<PathBuf, Vec<u8>>,
|
||||
directories: FxHashSet<PathBuf>,
|
||||
symlinks: FxHashMap<PathBuf, PathBuf>,
|
||||
}
|
||||
|
||||
static BENCH_FS: LazyLock<BenchMemoryFS> = LazyLock::new(|| {
|
||||
let mut fs = BenchMemoryFS {
|
||||
files: FxHashMap::default(),
|
||||
directories: FxHashSet::default(),
|
||||
symlinks: FxHashMap::default(),
|
||||
};
|
||||
fs.load_fixtures();
|
||||
fs
|
||||
});
|
||||
|
||||
impl BenchMemoryFS {
|
||||
/// Create a new memory file system and load all fixtures
|
||||
pub fn new() -> Self {
|
||||
// Return a clone of the pre-loaded static FS
|
||||
BENCH_FS.clone()
|
||||
}
|
||||
|
||||
pub fn with_large_tsconfig_paths_fixture(
|
||||
alias_count: usize,
|
||||
) -> (Self, PathBuf, PathBuf, Vec<String>) {
|
||||
let fs = Self::new();
|
||||
let cwd = std::env::current_dir().unwrap();
|
||||
let root = cwd.join(format!("fixtures/tsconfig/bench-tsconfig-paths/{alias_count}"));
|
||||
let importer = root.join("app/main.ts");
|
||||
let tsconfig_path = root.join("tsconfig.json");
|
||||
assert!(
|
||||
fs.files.contains_key(&importer),
|
||||
"missing benchmark fixture: {}",
|
||||
importer.display()
|
||||
);
|
||||
assert!(
|
||||
fs.files.contains_key(&tsconfig_path),
|
||||
"missing benchmark fixture: {}",
|
||||
tsconfig_path.display()
|
||||
);
|
||||
let requests = (0..alias_count).map(|i| format!("@pkg{i:04}/file")).collect();
|
||||
(fs, importer, tsconfig_path, requests)
|
||||
}
|
||||
|
||||
fn add_parent_directories(&mut self, path: &Path) {
|
||||
// Add all parent directories of a path
|
||||
for ancestor in path.ancestors().skip(1) {
|
||||
self.directories.insert(ancestor.to_path_buf());
|
||||
}
|
||||
}
|
||||
|
||||
fn load_fixtures(&mut self) {
|
||||
let cwd = std::env::current_dir().unwrap();
|
||||
|
||||
// Add all parent directories for the cwd
|
||||
self.add_parent_directories(&cwd);
|
||||
|
||||
// Load fixtures from enhanced-resolve
|
||||
self.load_directory_tree(&cwd.join("fixtures/enhanced-resolve"));
|
||||
self.load_directory_tree(&cwd.join("fixtures/tsconfig/bench-tsconfig-paths"));
|
||||
|
||||
// Load specific node_modules packages for benchmarks
|
||||
self.load_node_modules_packages(&cwd);
|
||||
|
||||
// Create symlink fixtures for benchmark (10000 symlinks)
|
||||
self.create_symlink_fixtures(&cwd);
|
||||
}
|
||||
|
||||
fn load_directory_tree(&mut self, root: &Path) {
|
||||
if !root.exists() {
|
||||
return;
|
||||
}
|
||||
for entry in WalkDir::new(root).follow_links(false).into_iter().filter_map(Result::ok) {
|
||||
let path = entry.path();
|
||||
let Ok(metadata) = fs::symlink_metadata(path) else { continue };
|
||||
|
||||
// Store with absolute paths
|
||||
let abs_path = path.to_path_buf();
|
||||
|
||||
if metadata.is_symlink() {
|
||||
if let Ok(target) = fs::read_link(path) {
|
||||
self.symlinks.insert(abs_path.clone(), target);
|
||||
self.add_parent_directories(&abs_path);
|
||||
}
|
||||
} else if metadata.is_dir() {
|
||||
self.directories.insert(abs_path.clone());
|
||||
self.add_parent_directories(&abs_path);
|
||||
} else if metadata.is_file()
|
||||
&& let Ok(content) = fs::read(path)
|
||||
{
|
||||
self.files.insert(abs_path.clone(), content);
|
||||
self.add_parent_directories(&abs_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn load_node_modules_packages(&mut self, cwd: &Path) {
|
||||
let node_modules = cwd.join("node_modules");
|
||||
if !node_modules.exists() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only load these specific packages needed for benchmarks
|
||||
let packages =
|
||||
["@napi-rs/cli", "@napi-rs/wasm-runtime", "vite-plus", "emnapi", "typescript"];
|
||||
|
||||
for package_name in packages {
|
||||
let package_path = node_modules.join(package_name);
|
||||
if !package_path.exists() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// For scoped packages, also register the parent scope directory
|
||||
if package_name.starts_with('@')
|
||||
&& let Some(parent) = package_path.parent()
|
||||
&& parent != node_modules
|
||||
{
|
||||
self.directories.insert(parent.to_path_buf());
|
||||
self.add_parent_directories(parent);
|
||||
}
|
||||
|
||||
// Check if it's a symlink and resolve it
|
||||
if let Ok(metadata) = fs::symlink_metadata(&package_path) {
|
||||
if metadata.is_symlink() {
|
||||
// Add the symlink itself
|
||||
if let Ok(target) = fs::read_link(&package_path) {
|
||||
self.symlinks.insert(package_path.clone(), target.clone());
|
||||
self.add_parent_directories(&package_path);
|
||||
|
||||
// Resolve the symlink target (relative to node_modules)
|
||||
let resolved_target = if target.is_relative() {
|
||||
package_path.parent().unwrap().join(&target)
|
||||
} else {
|
||||
target
|
||||
};
|
||||
|
||||
// Load the actual package directory
|
||||
if resolved_target.exists() {
|
||||
self.load_package_files(&resolved_target);
|
||||
}
|
||||
|
||||
// ALSO load via the symlink path itself, because the resolver
|
||||
// might query using the symlink path
|
||||
self.load_package_files(&package_path);
|
||||
}
|
||||
} else {
|
||||
// Regular directory, load it directly
|
||||
self.load_package_files(&package_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn load_package_files(&mut self, package_root: &Path) {
|
||||
// Load package files with limited depth to avoid loading entire dependency trees
|
||||
for entry in WalkDir::new(package_root)
|
||||
.follow_links(true) // Follow symlinks within the package
|
||||
.max_depth(5) // Load a bit deeper to get dist/ and lib/ directories
|
||||
.into_iter()
|
||||
.filter_map(Result::ok)
|
||||
{
|
||||
let path = entry.path();
|
||||
let Ok(metadata) = fs::metadata(path) else { continue };
|
||||
let abs_path = path.to_path_buf();
|
||||
|
||||
if metadata.is_dir() {
|
||||
self.directories.insert(abs_path.clone());
|
||||
self.add_parent_directories(&abs_path);
|
||||
} else if metadata.is_file() {
|
||||
// Only load essential file types
|
||||
if let Some(ext) = path.extension() {
|
||||
let ext_str = ext.to_str();
|
||||
if matches!(
|
||||
ext_str,
|
||||
Some("json" | "js" | "mjs" | "cjs" | "ts" | "mts" | "cts" | "d.ts")
|
||||
) && let Ok(content) = fs::read(path)
|
||||
{
|
||||
self.files.insert(abs_path.clone(), content);
|
||||
self.add_parent_directories(&abs_path);
|
||||
}
|
||||
} else if path.file_name() == Some(std::ffi::OsStr::new("package.json")) {
|
||||
// Also load package.json even if extension check fails
|
||||
if let Ok(content) = fs::read(path) {
|
||||
self.files.insert(abs_path.clone(), content);
|
||||
self.add_parent_directories(&abs_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_symlink_fixtures(&mut self, cwd: &Path) {
|
||||
// Create temp_symlinks directory
|
||||
let temp_path = cwd.join("fixtures/enhanced-resolve/test/temp_symlinks");
|
||||
self.directories.insert(temp_path.clone());
|
||||
self.add_parent_directories(&temp_path);
|
||||
|
||||
// Create index.js
|
||||
let index_path = temp_path.join("index.js");
|
||||
self.files.insert(index_path, b"console.log('Hello, World!')".to_vec());
|
||||
|
||||
// Create 10000 symlinks pointing to index.js
|
||||
// These are created in memory during initialization, not during benchmark execution
|
||||
for i in 0..10000 {
|
||||
let symlink_path = temp_path.join(format!("file{i}.js"));
|
||||
self.symlinks.insert(symlink_path, PathBuf::from("index.js"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for BenchMemoryFS {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl FileSystem for BenchMemoryFS {
|
||||
#[cfg(not(feature = "yarn_pnp"))]
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
#[cfg(feature = "yarn_pnp")]
|
||||
fn new(_yarn_pnp: bool) -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn read(&self, path: &Path) -> io::Result<Vec<u8>> {
|
||||
// Try direct lookup first
|
||||
if let Some(bytes) = self.files.get(path) {
|
||||
return Ok(bytes.clone());
|
||||
}
|
||||
|
||||
// Try following symlinks
|
||||
let mut current = path.to_path_buf();
|
||||
let mut visited = FxHashSet::default();
|
||||
|
||||
while let Some(target) = self.symlinks.get(¤t) {
|
||||
if !visited.insert(current.clone()) {
|
||||
return Err(io::Error::other("Circular symlink"));
|
||||
}
|
||||
|
||||
current = if target.is_relative() {
|
||||
current.parent().unwrap().join(target)
|
||||
} else {
|
||||
target.clone()
|
||||
};
|
||||
|
||||
if let Some(bytes) = self.files.get(¤t) {
|
||||
return Ok(bytes.clone());
|
||||
}
|
||||
}
|
||||
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
format!("File not found: {}", path.display()),
|
||||
))
|
||||
}
|
||||
|
||||
fn read_to_string(&self, path: &Path) -> io::Result<String> {
|
||||
let bytes = self.read(path)?;
|
||||
String::from_utf8(bytes).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
|
||||
}
|
||||
|
||||
fn metadata(&self, path: &Path) -> io::Result<FileMetadata> {
|
||||
// Check if it's a file (direct)
|
||||
if self.files.contains_key(path) {
|
||||
return Ok(FileMetadata::new(true, false, false));
|
||||
}
|
||||
|
||||
// Check if it's a directory (direct)
|
||||
if self.directories.contains(path) {
|
||||
return Ok(FileMetadata::new(false, true, false));
|
||||
}
|
||||
|
||||
// Follow symlinks to find the target
|
||||
let mut current = path.to_path_buf();
|
||||
let mut visited = FxHashSet::default();
|
||||
|
||||
while let Some(target) = self.symlinks.get(¤t) {
|
||||
if !visited.insert(current.clone()) {
|
||||
return Err(io::Error::other("Circular symlink"));
|
||||
}
|
||||
|
||||
current = if target.is_relative() {
|
||||
current.parent().unwrap().join(target)
|
||||
} else {
|
||||
target.clone()
|
||||
};
|
||||
|
||||
if self.files.contains_key(¤t) {
|
||||
return Ok(FileMetadata::new(true, false, false));
|
||||
} else if self.directories.contains(¤t) {
|
||||
return Ok(FileMetadata::new(false, true, false));
|
||||
}
|
||||
}
|
||||
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
format!("Path not found: {}", path.display()),
|
||||
))
|
||||
}
|
||||
|
||||
fn symlink_metadata(&self, path: &Path) -> io::Result<FileMetadata> {
|
||||
// Check if it's a symlink first (before resolving)
|
||||
if self.symlinks.contains_key(path) {
|
||||
return Ok(FileMetadata::new(false, false, true));
|
||||
}
|
||||
|
||||
// Otherwise, fall back to regular metadata
|
||||
self.metadata(path)
|
||||
}
|
||||
|
||||
fn read_link(&self, path: &Path) -> Result<PathBuf, ResolveError> {
|
||||
self.symlinks.get(path).cloned().ok_or_else(|| {
|
||||
ResolveError::from(io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
format!("Not a symlink: {}", path.display()),
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
fn canonicalize(&self, path: &Path) -> io::Result<PathBuf> {
|
||||
// Follow symlinks to resolve the canonical path
|
||||
let mut current = path.to_path_buf();
|
||||
let mut visited = FxHashSet::default();
|
||||
|
||||
while let Some(target) = self.symlinks.get(¤t) {
|
||||
if !visited.insert(current.clone()) {
|
||||
return Err(io::Error::other("Circular symlink"));
|
||||
}
|
||||
|
||||
current = if target.is_relative() {
|
||||
current.parent().unwrap().join(target)
|
||||
} else {
|
||||
target.clone()
|
||||
};
|
||||
}
|
||||
|
||||
// Verify the final path exists
|
||||
if self.files.contains_key(¤t) || self.directories.contains(¤t) {
|
||||
Ok(current)
|
||||
} else {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
format!("Path not found: {}", path.display()),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,8 @@ allow = [
|
||||
"Apache-2.0",
|
||||
"Unicode-3.0",
|
||||
"BSD-2-Clause",
|
||||
"MPL-2.0",
|
||||
"Zlib",
|
||||
# "Apache-2.0 WITH LLVM-exception",
|
||||
]
|
||||
# The confidence threshold for detecting a license from license text.
|
||||
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"$schema": "https://dprint.dev/schemas/v0.json",
|
||||
"lineWidth": 120,
|
||||
"typescript": {
|
||||
"quoteStyle": "preferSingle",
|
||||
"binaryExpression.operatorPosition": "sameLine"
|
||||
},
|
||||
"json": {
|
||||
"indentWidth": 2
|
||||
},
|
||||
"toml": {
|
||||
},
|
||||
"excludes": [
|
||||
"fixtures/**",
|
||||
"CHANGELOG.md",
|
||||
"CHANGELOG_OLD.md",
|
||||
"pnpm-workspace.yaml",
|
||||
"pnpm-lock.yaml",
|
||||
"napi/*.{cjs,js,mjs,d.ts}",
|
||||
"!napi/test.mjs"
|
||||
],
|
||||
"plugins": [
|
||||
"https://plugins.dprint.dev/typescript-0.93.3.wasm",
|
||||
"https://plugins.dprint.dev/json-0.19.4.wasm",
|
||||
"https://plugins.dprint.dev/markdown-0.17.8.wasm",
|
||||
"https://plugins.dprint.dev/g-plane/pretty_yaml-v0.5.0.wasm",
|
||||
"https://plugins.dprint.dev/toml-0.6.3.wasm"
|
||||
]
|
||||
}
|
||||
@@ -3,7 +3,9 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use pico_args::Arguments;
|
||||
use unrs_resolver::{AliasValue, ResolveOptions, Resolver, TsconfigOptions, TsconfigReferences};
|
||||
use unrs_resolver::{
|
||||
AliasValue, ResolveOptions, Resolver, TsconfigDiscovery, TsconfigOptions, TsconfigReferences,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let mut args = Arguments::from_env();
|
||||
@@ -30,10 +32,15 @@ fn main() {
|
||||
condition_names: vec!["node".into(), "import".into()],
|
||||
// CJS
|
||||
// condition_names: vec!["node".into(), "require".into()],
|
||||
tsconfig: tsconfig_path.map(|config_file| TsconfigOptions {
|
||||
config_file,
|
||||
references: TsconfigReferences::Auto,
|
||||
}),
|
||||
tsconfig: Some(tsconfig_path.map_or_else(
|
||||
|| TsconfigDiscovery::Auto,
|
||||
|config_file| {
|
||||
TsconfigDiscovery::Manual(TsconfigOptions {
|
||||
config_file,
|
||||
references: TsconfigReferences::Auto,
|
||||
})
|
||||
},
|
||||
)),
|
||||
..ResolveOptions::default()
|
||||
};
|
||||
|
||||
@@ -45,7 +52,7 @@ fn main() {
|
||||
println!("Resolution: {}", resolution.full_path().to_string_lossy());
|
||||
println!("Module Type: {:?}", resolution.module_type());
|
||||
println!(
|
||||
"package json: {:?}",
|
||||
"package.json: {:?}",
|
||||
resolution.package_json().map(|p| p.path.to_string_lossy())
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// See documentation at <https://docs.rs/unrs_resolver>
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use pico_args::Arguments;
|
||||
use unrs_resolver::{AliasValue, ResolveOptions, Resolver, TsconfigDiscovery};
|
||||
|
||||
fn main() {
|
||||
let mut args = Arguments::from_env();
|
||||
|
||||
let path = args.free_from_str::<PathBuf>().expect("path");
|
||||
let specifier = args.free_from_str::<String>().expect("specifier");
|
||||
|
||||
assert!(path.is_file(), "{} must be a file that will be resolved against.", path.display());
|
||||
assert!(path.is_absolute(), "{} must be an absolute path.", path.display());
|
||||
|
||||
println!("path: {}", path.to_string_lossy());
|
||||
println!("specifier: {specifier}");
|
||||
|
||||
let options = ResolveOptions {
|
||||
alias_fields: vec![vec!["browser".into()]],
|
||||
alias: vec![("asdf".into(), vec![AliasValue::from("./test.js")])],
|
||||
extensions: vec![".js".into(), ".ts".into()],
|
||||
extension_alias: vec![(".js".into(), vec![".ts".into(), ".js".into()])],
|
||||
// ESM
|
||||
condition_names: vec!["node".into(), "import".into()],
|
||||
// CJS
|
||||
// condition_names: vec!["node".into(), "require".into()],
|
||||
tsconfig: Some(TsconfigDiscovery::Auto),
|
||||
..ResolveOptions::default()
|
||||
};
|
||||
|
||||
println!();
|
||||
|
||||
match Resolver::new(options).resolve_file(path, &specifier) {
|
||||
Err(error) => println!("Error: {error}"),
|
||||
Ok(resolution) => {
|
||||
println!("Resolution: {}", resolution.full_path().to_string_lossy());
|
||||
println!("Module Type: {:?}", resolution.module_type());
|
||||
println!(
|
||||
"package.json: {:?}",
|
||||
resolution.package_json().map(|p| p.path.to_string_lossy())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
use std::{env, fs};
|
||||
|
||||
use rayon::prelude::*;
|
||||
|
||||
use unrs_resolver::{ResolveOptions, Resolver};
|
||||
|
||||
fn main() {
|
||||
let cwd = env::current_dir().expect("Failed to get current directory");
|
||||
let node_modules = cwd.join("node_modules");
|
||||
|
||||
if !node_modules.exists() {
|
||||
eprintln!("node_modules directory not found at {}", node_modules.display());
|
||||
return;
|
||||
}
|
||||
|
||||
// Collect all package names
|
||||
let mut packages = Vec::new();
|
||||
|
||||
let entries = fs::read_dir(&node_modules).expect("Failed to read node_modules directory");
|
||||
|
||||
for entry in entries.filter_map(Result::ok) {
|
||||
let path = entry.path();
|
||||
if !path.is_dir() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let dir_name = path.file_name().unwrap().to_string_lossy();
|
||||
|
||||
// Skip dot directories
|
||||
if dir_name.starts_with('.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if dir_name.starts_with('@') {
|
||||
// Skip @types packages
|
||||
if dir_name == "@types" {
|
||||
continue;
|
||||
}
|
||||
// Scoped package - read subdirectories
|
||||
if let Ok(scope_entries) = fs::read_dir(&path) {
|
||||
for scope_entry in scope_entries.filter_map(Result::ok) {
|
||||
let scope_path = scope_entry.path();
|
||||
if scope_path.is_dir() {
|
||||
let package_name = scope_path.file_name().unwrap().to_string_lossy();
|
||||
packages.push(format!("{dir_name}/{package_name}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Regular package
|
||||
packages.push(dir_name.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
let options = ResolveOptions {
|
||||
condition_names: vec!["node".into(), "import".into()],
|
||||
..ResolveOptions::default()
|
||||
};
|
||||
let resolver = Resolver::new(options);
|
||||
|
||||
packages.par_iter().for_each(|package| {
|
||||
if let Err(err) = resolver.resolve(&cwd, package) {
|
||||
eprintln!("{package}: {err}");
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export {}
|
||||
@@ -0,0 +1 @@
|
||||
{"main": "./lib/main"}
|
||||
@@ -0,0 +1 @@
|
||||
export {}
|
||||
@@ -0,0 +1 @@
|
||||
export {}
|
||||
@@ -0,0 +1 @@
|
||||
export {}
|
||||
@@ -0,0 +1 @@
|
||||
export {}
|
||||
@@ -0,0 +1 @@
|
||||
export {}
|
||||
@@ -0,0 +1 @@
|
||||
export {}
|
||||
@@ -0,0 +1 @@
|
||||
export {}
|
||||
@@ -0,0 +1 @@
|
||||
export {}
|
||||
@@ -0,0 +1 @@
|
||||
export {}
|
||||
@@ -0,0 +1 @@
|
||||
{"name": "hash-import", "imports": {"#internal": "./src/internal.d.ts"}}
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
module.exports = {}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"name": "@babel/generator", "main": "index.js"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"name": "@types/babel__generator", "types": "index.d.ts"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"name": "@types/debug", "types": "index.d.ts"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"name": "completely-empty"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
module.exports = {}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"name": "debug", "main": "index.js"}
|
||||
Generated
Vendored
Generated
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "exports-dts-for-mjs",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.mjs"
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
module.exports = {}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"name": "no-types", "main": "index.js"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"name": "with-both-types-fields", "types": "./types.d.ts", "typings": "./typings.d.ts"}
|
||||
Generated
Vendored
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export {}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"name": "with-exports", "exports": { ".": { "types": "./types/index.d.ts", "import": "./esm/index.mjs" } }}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"name": "with-self-ref", "exports": {".": {"types": "./types/index.d.ts"}}}
|
||||
Generated
Vendored
Generated
Vendored
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"name": "with-subpath", "typesVersions": {"*": {"sub/*": ["dist/*"]}}}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"name": "with-types-versions", "typesVersions": { "*": { "*": ["dist/*"] } }, "types": "dist/index.d.ts" }
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"name": "with-types", "types": "./types/index.d.ts"}
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"name": "with-typings", "typings": "types.d.ts"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {}
|
||||
@@ -0,0 +1 @@
|
||||
export {}
|
||||
@@ -0,0 +1 @@
|
||||
export {}
|
||||
@@ -0,0 +1 @@
|
||||
export {}
|
||||
@@ -0,0 +1 @@
|
||||
{"compilerOptions": {"baseUrl": ".", "paths": {"@lib/*": ["lib/*"]}}}
|
||||
Vendored
Vendored
Vendored
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user