diff --git a/package.json b/package.json index fa25cf1..fe278ec 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "prepublishOnly": "npm run test" }, "dependencies": { + "eslint-import-context": "^0.2.0", "is-bun-module": "^2.0.0", "js-yaml": "^4.1.0", "oxc-resolver": "^11.6.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5402b15..25da446 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + eslint-import-context: + specifier: ^0.2.0 + version: 0.2.0(oxc-resolver@11.6.1) is-bun-module: specifier: ^2.0.0 version: 2.0.0 @@ -903,6 +906,15 @@ packages: peerDependencies: eslint: '>=7.0.0' + eslint-import-context@0.2.0: + resolution: {integrity: sha512-F4FrHeflgq2N4jzy7DMdugV342PcYUSa7SzlsE2Ph/e22uTkppT/OPq9oZu3jCHwzbni8OhnAPOsEYsV8WFsOg==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + peerDependencies: + oxc-resolver: ^11.0.0 + peerDependenciesMeta: + oxc-resolver: + optional: true + eslint-plugin-prettier@5.5.4: resolution: {integrity: sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==} engines: {node: ^14.18.0 || >=16.0.0} @@ -1045,6 +1057,9 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} + get-tsconfig@4.10.1: + resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1276,6 +1291,9 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve@1.22.10: resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} engines: {node: '>= 0.4'} @@ -2259,6 +2277,13 @@ snapshots: dependencies: eslint: 9.33.0 + eslint-import-context@0.2.0(oxc-resolver@11.6.1): + dependencies: + get-tsconfig: 4.10.1 + stable-hash-x: 0.2.0 + optionalDependencies: + oxc-resolver: 11.6.1 + eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.33.0))(eslint@9.33.0)(prettier@3.6.2): dependencies: eslint: 9.33.0 @@ -2408,6 +2433,10 @@ snapshots: gensync@1.0.0-beta.2: {} + get-tsconfig@4.10.1: + dependencies: + resolve-pkg-maps: 1.0.0 + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -2608,6 +2637,8 @@ snapshots: resolve-from@4.0.0: {} + resolve-pkg-maps@1.0.0: {} + resolve@1.22.10: dependencies: is-core-module: 2.16.1 diff --git a/src/resolve.ts b/src/resolve.ts index 56a4d69..8b0467c 100644 --- a/src/resolve.ts +++ b/src/resolve.ts @@ -1,5 +1,3 @@ -import process from "node:process"; - import { isBunBuiltin } from "is-bun-module"; import { defaultOptions } from "./constants.js"; @@ -8,6 +6,7 @@ import type { NextImportResolver, Options, ResolvedResult } from "./types.js"; import { findClosestPackageRoot, findWorkspacePackages, + getResolveRoots, hasBunPrefix, hasNodePrefix, isNodeBuiltin, @@ -74,7 +73,7 @@ export function resolve( return resolveRelativePath(sourceFile, modulePath, restOptions); } - const resolveRoots = roots?.length ? roots : [process.cwd()]; + const resolveRoots = getResolveRoots(roots); const workspacePackages = findWorkspacePackages(resolveRoots, packages); @@ -111,7 +110,7 @@ export function createNextImportResolver( ...config, }; - const resolveRoots = roots?.length ? roots : [process.cwd()]; + const resolveRoots = getResolveRoots(roots); const workspacePackages = findWorkspacePackages(resolveRoots, packages); diff --git a/src/utils.ts b/src/utils.ts index 2c8e100..d9805de 100755 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,7 +1,9 @@ import fs from "node:fs"; import module from "node:module"; import path from "node:path"; +import process from "node:process"; +import { useRuleContext } from "eslint-import-context"; import yaml from "js-yaml"; import type { TsconfigOptions } from "oxc-resolver"; import { stableHash } from "stable-hash-x"; @@ -536,3 +538,16 @@ export function findWorkspacePackages( return sortPathsByDepth([...roots]); } + +/** + * Get the resolve roots. if `roots` is not provided, it will use the current working directory. + * + * @param roots {string[]} - the root directories + * @returns {string[]} - the resolve roots + */ +export function getResolveRoots(roots?: string[]): string[] { + if (roots?.length) return [...roots]; + + const context = useRuleContext(); + return [context?.cwd ?? process.cwd()]; +} diff --git a/tests/utils.spec.ts b/tests/utils.spec.ts index ccd6f88..7ae7a86 100644 --- a/tests/utils.spec.ts +++ b/tests/utils.spec.ts @@ -1,3 +1,5 @@ +import process from "node:process"; + import { hasBunPrefix, hashObject, @@ -207,4 +209,50 @@ describe("utils", () => { expect(isNodeBuiltin("bun:fs")).toBe(false); }); }); + + describe("test getResolveRoots", () => { + const originalProcessCwd = process.cwd.bind(null); + let mockCwd: string; + + beforeEach(() => { + mockCwd = "/mock/cwd"; + process.cwd = () => mockCwd; + }); + + afterEach(() => { + process.cwd = originalProcessCwd; + vi.resetModules(); + vi.clearAllMocks(); + }); + + it("returns the provided roots if given", async () => { + const { getResolveRoots } = await import("@/utils.js"); + const roots = ["/foo/bar", "/baz"]; + expect(getResolveRoots(roots)).toEqual(roots); + }); + + it("returns context.cwd if available (mock eslint-import-context)", async () => { + vi.doMock("eslint-import-context", () => ({ + useRuleContext: () => ({ cwd: "/context/cwd" }), + })); + const { getResolveRoots } = await import("@/utils.js"); + expect(getResolveRoots()).toEqual(["/context/cwd"]); + }); + + it("returns process.cwd() if context is undefined (mock eslint-import-context)", async () => { + vi.doMock("eslint-import-context", () => ({ + useRuleContext: () => undefined, + })); + const { getResolveRoots } = await import("@/utils.js"); + expect(getResolveRoots()).toEqual([mockCwd]); + }); + + it("returns process.cwd() if cwd is not available (mock eslint-import-context)", async () => { + vi.doMock("eslint-import-context", () => ({ + useRuleContext: () => ({}), + })); + const { getResolveRoots } = await import("@/utils.js"); + expect(getResolveRoots()).toEqual([mockCwd]); + }); + }); });