Merge remote-tracking branch 'upstream/main' into chore/merge_upstream

This commit is contained in:
JounQin
2026-05-18 20:49:40 +08:00
687 changed files with 14405 additions and 5919 deletions
+3
View File
@@ -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"]
-7
View File
@@ -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.
+10 -23
View File
@@ -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
+15
View File
@@ -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"]
}
]
}
+5 -18
View File
@@ -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 -12
View File
@@ -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
View File
@@ -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
+6 -6
View File
@@ -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
+38
View File
@@ -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
+2 -2
View File
@@ -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
+23 -17
View File
@@ -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 .
+24
View File
@@ -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
-45
View File
@@ -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
+2
View File
@@ -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
View File
@@ -1 +1 @@
22.17.0
24.14.0
-6
View File
@@ -1,6 +0,0 @@
{
"printWidth": 120,
"semi": false,
"singleQuote": true,
"plugins": ["prettier-plugin-pkg"]
}
+4 -4
View File
@@ -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"
+1
View File
@@ -0,0 +1 @@
vp staged
+3
View File
@@ -0,0 +1,3 @@
{
"recommendations": ["oxc.oxc-vscode"]
}
+8
View File
@@ -0,0 +1,8 @@
{
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.formatOnSave": true,
"editor.formatOnSaveMode": "file",
"editor.codeActionsOnSave": {
"source.fixAll.oxc": "explicit"
}
}
+289
View File
@@ -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
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
@AGENTS.md
Generated
+680 -585
View File
File diff suppressed because it is too large Load Diff
+39 -19
View File
@@ -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"]
+55 -60
View File
@@ -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
+4
View File
@@ -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
View File
@@ -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(&current) {
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(&current) {
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(&current) {
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(&current) {
return Ok(FileMetadata::new(true, false, false));
} else if self.directories.contains(&current) {
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(&current) {
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(&current) || self.directories.contains(&current) {
Ok(current)
} else {
Err(io::Error::new(
io::ErrorKind::NotFound,
format!("Path not found: {}", path.display()),
))
}
}
}
}
+2
View File
@@ -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
View File
@@ -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"
]
}
+13 -6
View File
@@ -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())
);
}
+46
View File
@@ -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())
);
}
}
}
+66
View File
@@ -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"}
+1
View File
@@ -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 {}
+1
View File
@@ -0,0 +1 @@
export {}
@@ -0,0 +1 @@
{"name": "hash-import", "imports": {"#internal": "./src/internal.d.ts"}}
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
module.exports = {}
+1
View File
@@ -0,0 +1 @@
{"name": "@babel/generator", "main": "index.js"}
@@ -0,0 +1 @@
export {}
@@ -0,0 +1 @@
{"name": "@types/babel__generator", "types": "index.d.ts"}
+1
View File
@@ -0,0 +1 @@
export {}
+1
View File
@@ -0,0 +1 @@
{"name": "@types/debug", "types": "index.d.ts"}
+1
View File
@@ -0,0 +1 @@
{"name": "completely-empty"}
+1
View File
@@ -0,0 +1 @@
module.exports = {}
+1
View File
@@ -0,0 +1 @@
{"name": "debug", "main": "index.js"}
+8
View File
@@ -0,0 +1,8 @@
{
"name": "exports-dts-for-mjs",
"exports": {
".": {
"import": "./dist/index.mjs"
}
}
}
+1
View File
@@ -0,0 +1 @@
module.exports = {}
+1
View File
@@ -0,0 +1 @@
{"name": "no-types", "main": "index.js"}
@@ -0,0 +1 @@
{"name": "with-both-types-fields", "types": "./types.d.ts", "typings": "./typings.d.ts"}
+1
View File
@@ -0,0 +1 @@
export {}
+1
View File
@@ -0,0 +1 @@
{"name": "with-exports", "exports": { ".": { "types": "./types/index.d.ts", "import": "./esm/index.mjs" } }}
+1
View File
@@ -0,0 +1 @@
export {}
+1
View File
@@ -0,0 +1 @@
{"name": "with-self-ref", "exports": {".": {"types": "./types/index.d.ts"}}}
+1
View File
@@ -0,0 +1 @@
{"name": "with-subpath", "typesVersions": {"*": {"sub/*": ["dist/*"]}}}
@@ -0,0 +1 @@
export {}
+1
View File
@@ -0,0 +1 @@
export {}
+1
View File
@@ -0,0 +1 @@
{"name": "with-types-versions", "typesVersions": { "*": { "*": ["dist/*"] } }, "types": "dist/index.d.ts" }
+1
View File
@@ -0,0 +1 @@
{"name": "with-types", "types": "./types/index.d.ts"}
+1
View File
@@ -0,0 +1 @@
{"name": "with-typings", "typings": "types.d.ts"}
+1
View File
@@ -0,0 +1 @@
export {}
@@ -0,0 +1 @@
export {}
+1
View File
@@ -0,0 +1 @@
export {}
@@ -0,0 +1 @@
export {}
@@ -0,0 +1 @@
{"compilerOptions": {"baseUrl": ".", "paths": {"@lib/*": ["lib/*"]}}}

Some files were not shown because too many files have changed in this diff Show More