nrwl / nx

Smart Monorepos · Fast CI
https://nx.dev
MIT License
23.69k stars 2.36k forks source link

library importing other library using wildcard path mapping fails with "is not under 'rootDir'" #11583

Closed jonathan-barner closed 9 months ago

jonathan-barner commented 2 years ago

Current Behavior

When one library imports from another, I get .../packages/lib1/src/lib/lib1.ts' is not under 'rootDir' 'packages/lib2' Note that this doesn't happen if an app imports the library in the same way - presumably because an app uses executor @nrwl/node:webpack rather the a library's @nrwl/js:tsc.

Expected Behavior

library should import. This is a new project, no migration, therefore it's not the same like https://github.com/nrwl/nx/issues/10785#issuecomment-1159017136.

Steps to Reproduce

  1. Start from scratch:
    npx create-nx-workspace badlibs --preset=ts --nxCloud==false
    cd badlibs
    nx generate @nrwl/js:library --name=lib1 --buildable
    nx generate @nrwl/js:library --name=lib2 --buildable
  2. Add the following to tsconfig.base.json:
    "paths": {
      "lib1/*": ["packages/lib1/*"]
    }
  3. Add the following to packages\lib2\src\lib\lib2.ts:
    import { lib1 } from 'lib1/src/lib/lib1';
  4. Build all by running: nx affected:build -all --skip-nx-cache

Result:

    ×  nx run lib2:build
       Compiling TypeScript files for project "lib2"...
packages/lib2/src/lib/lib2.ts:1:22 - error TS6059: File 'C:/mono/badlibs/packages/lib1/src/lib/lib1.ts' is not under 'rootDir' 'packages/lib2'. 'rootDir' is expected to contain all source files.

       1 import { lib1 } from 'lib1/src/lib/lib1';

Failure Logs

Environment

   Node : 14.20.0
   OS   : win32 x64
   npm  : 6.14.17

   nx : 14.5.6
   @nrwl/angular : Not Found
   @nrwl/cypress : Not Found
   @nrwl/detox : Not Found
   @nrwl/devkit : 14.5.6
   @nrwl/eslint-plugin-nx : 14.5.6
   @nrwl/express : Not Found
   @nrwl/jest : 14.5.6
   @nrwl/js : 14.5.6
   @nrwl/linter : 14.5.6
   @nrwl/nest : Not Found
   @nrwl/next : Not Found
   @nrwl/node : Not Found
   @nrwl/nx-cloud : Not Found
   @nrwl/nx-plugin : Not Found
   @nrwl/react : Not Found
   @nrwl/react-native : Not Found
   @nrwl/schematics : Not Found
   @nrwl/storybook : Not Found
   @nrwl/web : Not Found
   @nrwl/workspace : 14.5.6
   typescript : 4.7.4
   ---------------------------------------
   Local workspace plugins:
   ---------------------------------------
   Community plugins:
jonathan-barner commented 2 years ago

Looking into nx code, I found a workaround that unblocks this for me. I don't know enough the nx codebase to say whether this is the actual fix...

edit .\node_modules\@nrwl\js\src\utils\typescript\compile-typescript-files.js After const tscOptions = { add rootDir, so the code looks like this:

        const tscOptions = {
            rootDir: normalizedOptions.root,
lininu commented 2 years ago

The same issue 🥲

xeinebiu commented 2 years ago

Looking into nx code, I found a workaround that unblocks this for me. I don't know enough the nx codebase to say whether this is the actual fix...

edit .\node_modules\@nrwl\js\src\utils\typescript\compile-typescript-files.js After const tscOptions = { add rootDir, so the code looks like this:

        const tscOptions = {
          rootDir: normalizedOptions.root,

Facing the same issue. Will go with this solution for the moment.

Thank you

jonathan-barner commented 2 years ago

I've tested the below suggestion - got: Cannot find module 'lib1/src/lib/lib1' Setting "traceResolution": true I see:

   'baseUrl' option is set to 'C:/mono/badlibs', using this value to resolve non-relative module name 'lib1/src/lib/lib1'.
   'paths' option is specified, looking for a pattern to match module name 'lib1/src/lib/lib1'.
   Module name 'lib1/src/lib/lib1', matched pattern 'lib1/*'.
   Trying substitution '../lib1/*', candidate module location: '../lib1/src/lib/lib1'.
   Loading module as file / folder, candidate module location 'C:/mono/lib1/src/lib/lib1', target file type 'TypeScript'

So looks like the substitution is treated to start from baseUrl. And indeed, setting it to "lib1/*": ["../badlibs/packages/lib1/*"] finds the file - but I still get the original error is not under 'rootDir'.

From: rbong @.> Sent: 2022 Sep 05 11:36 PM To: nrwl/nx @.> Cc: Barner, Jonathan @.>; Author @.> Subject: Re: [nrwl/nx] library importing other library using wildcard path mapping fails with "is not under 'rootDir'" (Issue #11583)

I believe the proper fix is to use the relative path, not path from the root. So, assuming all of your packages are in packages/ instead of: "paths": { "lib1/": ["packages/lib1/"] } Use: "paths": { "lib1/": ["../lib1/*"] }

sebpalluel commented 2 years ago

Same issue with this architecture: graph-5

When i do nx run wallet:build it gives me this and a bunch of this kind of error for the other related library:

libs/server/polygon/src/index.ts:2:15 - error TS6059: File '/Users/sebpalluel/Documents/dev/blockchain-wallet/libs/server/polygon/src/lib/polygon.module.ts' is not under 'rootDir' 'libs/server/wallet'. 'rootDir' is expected to contain all source files.

2 export * from './lib/polygon.module';

I've tried everything I could but the build is breaking in wallet as if it couldn't support library nested with a depth that is > 2. When I'm importing the ethers library and moving the code from wallet into nestjs-server it's working properly.

kevinpastor commented 1 year ago

I had this issue in one of our monorepo and it was caused by the fact that one of our library's name wasn't valid. We had something like @organisation/test-utils/e2e which we ended up renaming to @organisation/test-utils-e2e (take note of the / usage).

bobbypiper commented 1 year ago

I've been fighting with this issue on and off for the last few days - I finally managed to figure the problem for me at least; thought it worth posting here if it helps anyone.

Check that your library package.json name hasn't changed; I think my editor was trying to autocorrect the created library name for new libraries (to be fair they do break the required pattern as @kevinpastor points out @acme/foo/bar - in my case the @acme was missing from the name

eliyahu-kriel commented 1 year ago

same problem

dany-fedorov commented 1 year ago

Very confusing, but... I had a dynamic import like this.

    const { AllCapsulesRegistry } = await import(
      '@cfg/all-capsules-registry/lib/AllCapsulesRegistry'
    );

I managed to remove the error when I changed this import to inline format + prettier-ignore comment so that it does not change on formatting

    // prettier-ignore
    const {AllCapsulesRegistry} = await import('@cfg/all-capsules-registry/lib/AllCapsulesRegistry');

Found this by accident. ??? The exact same import formatted the same way in other places in code of the same target does not break the typescript. Also, it does not break when this is not a wildcard mapping, but a mapping to index.ts.


After some tweaking I figured out that what is breaking is a whitespace after the module string and before the closing parenthesis. So, this works

    const { AllCapsulesRegistry } = await import(
      '@cfg/all-capsules-registry/lib/AllCapsulesRegistry');

and this does not

    const {AllCapsulesRegistry} = await import('@cfg/all-capsules-registry/lib/AllCapsulesRegistry' ); // <- single whitespace here `' );`

Still confusing, could it be a typescript bug?


$ npx nx --version 15.6.3 $ npx tsc --version Version 4.9.5

redplane commented 1 year ago

Still happens in 16.1.0.

Any solution for this ?

sahalkdr commented 1 year ago

https://medium.com/@thearunmalik/angular-monorepo-multiple-libs-and-rootdir-issue-7b8270cbc167

this solution worked for me

kopach commented 1 year ago

Solution provided by @jonathan-barner worked for me. The only difference, is that for "@nrwl/js@15.9.4" this code is now located under @nrwl/workspace package. So, by using pnpm's patch mechanism I've patched src/utilities/typescript/compilation.js file for @nrwl/workspace package with the following change

@@ -81,7 +81,7 @@ function getNormalizedTsConfig(options) {
     const tsConfig = (0, ts_config_1.readTsConfig)(options.tsConfig);
     tsConfig.options.outDir = options.outputPath;
     tsConfig.options.noEmitOnError = true;
-    tsConfig.options.rootDir = options.rootDir;
+    tsConfig.options.rootDir = '.';
     if (tsConfig.options.incremental && !tsConfig.options.tsBuildInfoFile) {
         tsConfig.options.tsBuildInfoFile = (0, devkit_1.joinPathFragments)(options.outputPath, 'tsconfig.tsbuildinfo');
     }

btw, options.root equals undefined for me all the time. So, tsConfig.options.rootDir = undefined would also work


Update: Fix also works for @nx/workspace@16.10.0

zkWildfire commented 1 year ago

Solution provided by @jonathan-barner worked for me. The only difference, is that for "@nrwl/js@15.9.4" this code is now located under @nrwl/workspace package. So, by using pnpm's patch mechanism I've patched src/utilities/typescript/compilation.js file for @nrwl/workspace package with the following change

@@ -81,7 +81,7 @@ function getNormalizedTsConfig(options) {
     const tsConfig = (0, ts_config_1.readTsConfig)(options.tsConfig);
     tsConfig.options.outDir = options.outputPath;
     tsConfig.options.noEmitOnError = true;
-    tsConfig.options.rootDir = options.rootDir;
+    tsConfig.options.rootDir = '.';
     if (tsConfig.options.incremental && !tsConfig.options.tsBuildInfoFile) {
         tsConfig.options.tsBuildInfoFile = (0, devkit_1.joinPathFragments)(options.outputPath, 'tsconfig.tsbuildinfo');
     }

btw, options.root equals undefined for me all the time. So, tsConfig.options.rootDir = undefined would also work

Update: Fix also works for @nx/workspace@16.10.0

I tried this fix in my workspace and a few others I found in similar threads, but none of them solved my problem. What did end up solving my problem was adding rootDir as a key in the options map to the @nx/js:tsc executor:

{
    "name": "common",
    "$schema": "../../node_modules/nx/schemas/project-schema.json",
    "sourceRoot": "libs/common/src",
    "projectType": "library",
    "targets": {
        "build": {
            "executor": "@nx/js:tsc",
            "outputs": ["{options.outputPath}"],
            "options": {
                "outputPath": "dist/libs/common",
                "main": "libs/common/src/index.ts",
                "tsConfig": "libs/common/tsconfig.lib.json",
                "assets": ["libs/common/*.md"],
                "rootDir": "../.." // <<<<<<<<<<<
            }
        },
        // ...

This project.json file is in libs/common for me, so the path passed to rootDir sets it to the root of my workspace.

For whatever reason, this issue only seems to affect a single one of my TypeScript libraries despite having several TS libraries that have dependencies between them. There aren't any circular dependencies, and as far as I can tell, there's nothing special about the one library that's affected by this bug.

Edit: Looks like this was actually caused by a few files getting added to my tsconfig.lib.json via VSCode's automated refactoring (caused by moving a file from one project to another). Once I removed those entries, I was able to remove the rootDir entry from my project.json too.

mandarini commented 1 year ago

related: https://github.com/nrwl/nx/issues/11289

This is potentially fixable if you align all the build target names to be the same. For anyone having that error, solution: https://github.com/nrwl/nx/pull/17798#issuecomment-1609701216

leosvelperez commented 9 months ago

Hey all!

The original issue in this thread is caused by a mismatch between the TS path mapping and the name of each library in their package.json (as mentioned in https://github.com/nrwl/nx/issues/11583#issuecomment-1386074846). Those must match so Nx can remap the TS path mappings correctly at build time to point to the build outputs of the dependencies.

Following the reproduction steps in the original post (using the latest version instead), the TS path mappings end up with:

{
  ...
  "compilerOptions": {
    ...
    "paths": {
      "lib1/*": ["lib1/*"],
      ...
    }
  }
  ...
}

While the libs/lib1/package.json file has the name @badlibs/lib1. Note how lib1 in the TS path mapping is different than @badlibs/lib1 in the library's package.json. That causes the issue. To fix it, either update the TS path mapping to @badlibs/lib1/* or update the name in the package.json to lib1.

Please note that the @nx/js:library generator produced the correct TS path mapping and library name in the package.json, but the TS path mapping was manually updated later to something else. I understand it might not be clear that both things need to be in sync. We'll discuss this internally and come up with something to improve this and make this constraint more apparent.

Also, note that this error is pretty generic and can occur due to a number of things:

I'm going to close this issue since what was originally reported happened due to a misconfiguration, and this comment explains how to solve it. If you still have issues after following the recommendations here and in the linked issues, please create a new issue with clear steps to reproduce it or better yet, with a reproduction repository so we can troubleshoot it as quickly as possible.

github-actions[bot] commented 8 months ago

This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.