@@ -50,6 +50,7 @@ module.exports = function (modulePath, options) {
5050 '@nx/eslint' ,
5151 '@nx/vite' ,
5252 '@nx/jest' ,
53+ '@nx/docker' ,
5354 '@nx/js' ,
5455 '@nx/next' ,
5556 '@nx/storybook' ,
@@ -61,7 +62,6 @@ module.exports = function (modulePath, options) {
6162 '@nx/workspace' ,
6263 '@nx/module-federation' ,
6364 '@nx/rspack' ,
64- '@nx/docker' ,
6565 '@nx/eslint-plugin' ,
6666 '@nx/angular' ,
6767 '@nx/create-nx-plugin' ,
@@ -109,155 +109,136 @@ module.exports = function (modulePath, options) {
109109 return options . defaultResolver ( modulePath , options ) ;
110110 }
111111
112- const packagesPath = '../' ;
112+ // Find workspace root - avoid filesystem lookups inside node_modules
113+ // For PNPM workspaces, we know the structure: workspace/packages/packageName
114+ let workspaceRoot = options . rootDir ;
115+
116+ // If we're in a packages subdirectory, go up two levels to workspace root
117+ if ( workspaceRoot . includes ( '/packages/' ) ) {
118+ const packagesIndex = workspaceRoot . lastIndexOf ( '/packages/' ) ;
119+ workspaceRoot = workspaceRoot . substring ( 0 , packagesIndex ) ;
120+ } else {
121+ // Fallback: go up directories until we find packages/ (but check pnpm-lock.yaml for validation)
122+ while ( workspaceRoot && workspaceRoot !== path . dirname ( workspaceRoot ) ) {
123+ const pnpmLock = path . join ( workspaceRoot , 'pnpm-lock.yaml' ) ;
124+ const packagesDir = path . join ( workspaceRoot , 'packages' ) ;
125+ if ( fs . existsSync ( pnpmLock ) && fs . existsSync ( packagesDir ) ) {
126+ break ;
127+ }
128+ workspaceRoot = path . dirname ( workspaceRoot ) ;
129+ }
130+ }
131+
132+ const packagesPath = path . join ( workspaceRoot , 'packages' ) ;
133+
134+ // Handle main @nx /* package imports (e.g., '@nx/devkit', '@nx/js')
135+ const nxPackageMatch = modulePath . match ( / ^ @ n x \/ ( [ ^ / ] + ) $ / ) ;
136+ if ( nxPackageMatch ) {
137+ const packageName = nxPackageMatch [ 1 ] ;
113138
114- // TS Solution: Allow specific workspace packages to be resolved to TypeScript source
115- const tsWorkspacePackages = {
116- '@nx/rollup' : path . resolve (
117- options . rootDir ,
118- `${ packagesPath } rollup/index.ts`
119- ) ,
120- '@nx/eslint' : path . resolve (
121- options . rootDir ,
122- `${ packagesPath } eslint/index.ts`
123- ) ,
124- '@nx/vite' : path . resolve ( options . rootDir , `${ packagesPath } vite/index.ts` ) ,
125- '@nx/jest' : path . resolve ( options . rootDir , `${ packagesPath } jest/index.ts` ) ,
126- '@nx/js' : path . resolve ( options . rootDir , `${ packagesPath } js/src/index.ts` ) ,
127- // Additional packages where tests are working
128- '@nx/next' : path . resolve ( options . rootDir , `${ packagesPath } next/index.ts` ) ,
129- '@nx/storybook' : path . resolve (
130- options . rootDir ,
131- `${ packagesPath } storybook/index.ts`
132- ) ,
133- '@nx/rsbuild' : path . resolve (
134- options . rootDir ,
135- `${ packagesPath } rsbuild/index.ts`
136- ) ,
137- '@nx/react-native' : path . resolve (
138- options . rootDir ,
139- `${ packagesPath } react-native/index.ts`
140- ) ,
141- '@nx/express' : path . resolve (
142- options . rootDir ,
143- `${ packagesPath } express/index.ts`
144- ) ,
145- '@nx/web' : path . resolve ( options . rootDir , `${ packagesPath } web/index.ts` ) ,
146- '@nx/vue' : path . resolve ( options . rootDir , `${ packagesPath } vue/index.ts` ) ,
147- '@nx/workspace' : path . resolve (
148- options . rootDir ,
149- `${ packagesPath } workspace/index.ts`
150- ) ,
151- '@nx/module-federation' : path . resolve (
152- options . rootDir ,
153- `${ packagesPath } module-federation/index.ts`
154- ) ,
155- '@nx/react' : path . resolve (
156- options . rootDir ,
157- `${ packagesPath } react/index.ts`
158- ) ,
159- '@nx/remix' : path . resolve (
160- options . rootDir ,
161- `${ packagesPath } remix/index.ts`
162- ) ,
163- '@nx/webpack' : path . resolve (
164- options . rootDir ,
165- `${ packagesPath } webpack/index.ts`
166- ) ,
167- '@nx/playwright' : path . resolve (
168- options . rootDir ,
169- `${ packagesPath } playwright/index.ts`
170- ) ,
171- '@nx/rspack' : path . resolve (
172- options . rootDir ,
173- `${ packagesPath } rspack/src/index.ts`
174- ) ,
175- } ;
139+ // Check if this package exists in workspace
140+ const packageDir = path . join ( packagesPath , packageName ) ;
176141
177- if ( tsWorkspacePackages [ modulePath ] ) {
178- return tsWorkspacePackages [ modulePath ] ;
142+ // Try different entry points based on package structure
143+ const possibleEntries = [
144+ path . join ( packageDir , 'index.ts' ) ,
145+ path . join ( packageDir , 'src' , 'index.ts' ) ,
146+ ] ;
147+
148+ for ( const entry of possibleEntries ) {
149+ if ( fs . existsSync ( entry ) && fs . lstatSync ( entry ) . isFile ( ) ) {
150+ return entry ;
151+ }
152+ }
179153 }
180154
181- // Handle @nx /js/src/* paths
182- if ( modulePath . startsWith ( '@nx/js/src/' ) ) {
183- const relativePath = modulePath . replace ( '@nx/js/src/' , '' ) ;
184- return path . resolve (
185- options . rootDir ,
186- `${ packagesPath } js/src/` ,
187- relativePath + '.ts'
188- ) ;
155+ // Handle @nx /*/src/* subpath imports (e.g., '@nx/devkit/src/utils/something')
156+ const nxSubpathMatch = modulePath . match ( / ^ @ n x \/ ( [ ^ / ] + ) \/ s r c \/ ( .+ ) $ / ) ;
157+ if ( nxSubpathMatch ) {
158+ const packageName = nxSubpathMatch [ 1 ] ;
159+ const subpath = nxSubpathMatch [ 2 ] ;
160+
161+ // Try different patterns for subpath resolution
162+ const possiblePaths = [
163+ path . join ( packagesPath , packageName , 'src' , subpath + '.ts' ) , // Direct file
164+ path . join ( packagesPath , packageName , 'src' , subpath , 'index.ts' ) , // Directory with index.ts
165+ ] ;
166+
167+ for ( const possiblePath of possiblePaths ) {
168+ if (
169+ fs . existsSync ( possiblePath ) &&
170+ fs . lstatSync ( possiblePath ) . isFile ( )
171+ ) {
172+ return possiblePath ;
173+ }
174+ }
189175 }
190176
191- // Handle @nx /eslint/src/* paths
192- if ( modulePath . startsWith ( '@nx/eslint/src/' ) ) {
193- const relativePath = modulePath . replace ( '@nx/eslint/src/' , '' ) ;
194- return path . resolve (
195- options . rootDir ,
196- `${ packagesPath } eslint/src/` ,
197- relativePath + '.ts'
198- ) ;
177+ // Handle @nx /* other subpaths (e.g., '@nx/devkit/testing', '@nx/devkit/package.json')
178+ const nxOtherMatch = modulePath . match ( / ^ @ n x \/ ( [ ^ / ] + ) \/ ( .+ ) $ / ) ;
179+ if ( nxOtherMatch ) {
180+ const packageName = nxOtherMatch [ 1 ] ;
181+ const subpath = nxOtherMatch [ 2 ] ;
182+
183+ const packageDir = path . join ( packagesPath , packageName ) ;
184+
185+ // Try different patterns for subpath resolution
186+ const possiblePaths = [
187+ path . join ( packageDir , subpath ) , // For files like package.json
188+ path . join ( packageDir , subpath + '.ts' ) ,
189+ path . join ( packageDir , 'src' , subpath + '.ts' ) ,
190+ ] ;
191+
192+ for ( const possiblePath of possiblePaths ) {
193+ if (
194+ fs . existsSync ( possiblePath ) &&
195+ fs . lstatSync ( possiblePath ) . isFile ( )
196+ ) {
197+ return possiblePath ;
198+ }
199+ }
199200 }
200201
201- if ( modulePath . startsWith ( '@nx/docker/generators' ) ) {
202- return path . resolve (
203- options . rootDir ,
204- `${ packagesPath } docker/generators.ts`
202+ // Handle nx/src/* imports (direct nx package imports)
203+ const nxSrcMatch = modulePath . match ( / ^ n x \/ s r c \/ ( .+ ) $ / ) ;
204+ if ( nxSrcMatch ) {
205+ const subpath = nxSrcMatch [ 1 ] ;
206+ const resolvedPath = path . join (
207+ packagesPath ,
208+ 'nx' ,
209+ 'src' ,
210+ subpath + '.ts'
205211 ) ;
212+ if ( fs . existsSync ( resolvedPath ) && fs . lstatSync ( resolvedPath ) . isFile ( ) ) {
213+ return resolvedPath ;
214+ }
206215 }
207216
208- // Handle other packages with src/* structure where tests are working
209- const srcPackages = [
210- 'rspack' ,
211- 'nx' ,
212- 'eslint-plugin' ,
213- 'react' ,
214- 'vite' ,
215- 'rollup' ,
216- 'workspace' ,
217- 'angular' ,
218- 'next' ,
219- 'node' ,
220- 'web' ,
221- 'webpack' ,
222- 'cypress' ,
223- 'jest' ,
224- ] ;
225- for ( const pkg of srcPackages ) {
226- if ( modulePath . startsWith ( `@nx/${ pkg } /src/` ) ) {
227- const relativePath = modulePath . replace ( `@nx/${ pkg } /src/` , '' ) ;
228- return path . resolve (
229- options . rootDir ,
230- `${ packagesPath } ${ pkg } /src/` ,
231- relativePath + '.ts'
232- ) ;
233- }
217+ // Handle nx/package.json specifically
218+ if ( modulePath === 'nx/package.json' ) {
219+ return path . join ( packagesPath , 'nx' , 'package.json' ) ;
234220 }
235221
236- // Handle nx/src/* paths (for direct nx package imports)
237- if ( modulePath . startsWith ( 'nx/src/' ) ) {
238- const relativePath = modulePath . replace ( 'nx/src/' , '' ) ;
239- return path . resolve (
240- options . rootDir ,
241- ` ${ packagesPath } nx/src/` ,
242- relativePath + '.ts'
243- ) ;
222+ // Handle other nx/* patterns
223+ const nxOtherPatternMatch = modulePath . match ( / ^ n x \/ ( . + ) $ / ) ;
224+ if ( nxOtherPatternMatch ) {
225+ const subpath = nxOtherPatternMatch [ 1 ] ;
226+ const resolvedPath = path . join ( packagesPath , 'nx' , subpath + '.ts' ) ;
227+ if ( fs . existsSync ( resolvedPath ) ) {
228+ return resolvedPath ;
229+ }
244230 }
245231
246- // Block other Nx packages from auto-resolution
232+ // Block excluded Nx packages from auto-resolution
247233 if (
248234 modulePath . startsWith ( '@nx/' ) &&
249235 ! modulePath . startsWith ( '@nx/powerpack-' ) &&
250236 ! excludedPackages . some ( ( pkg ) => modulePath . startsWith ( pkg ) )
251237 ) {
252- throw new Error ( 'custom resolution blocked' ) ;
253- }
254-
255- if ( modulePath . startsWith ( 'nx/' ) && ! modulePath . startsWith ( 'nx/src/' ) )
256- throw new Error ( 'custom resolution blocked' ) ;
257-
258- if ( modulePath . includes ( '@nx/workspace' ) ) {
259- throw new Error (
260- 'Reference to local Nx package found. Use local version instead.'
238+ // If we get here, it means the workspace package couldn't be resolved above
239+ // This might indicate a missing file or incorrect import
240+ console . warn (
241+ `[resolver] Could not resolve workspace package: ${ modulePath } `
261242 ) ;
262243 }
263244
0 commit comments