nx: Cannot build library which depends on publishable lib in sub folder

Expected Behavior

It should be possible to build a publishable lib that depends on another publishable lib that resides in a sub folder.

Current Behavior

The issue I have is similar to https://github.com/nrwl/nx/issues/602 which is already fixed and working. However, if I have my libs in sub folders (e.g. libs/platform/my-lib) then it still fails with 'rootDir' is expected to contain all source files.

Failure Information (for bugs)

Steps to Reproduce

  1. I created a new nx angular workspace and added 2 publishable libs in the directory ‘platform’.
yarn create nx-workspace
nx g lib core --directory platform --publishable --simple-module-name
nx g lib common --directory platform --publishable --simple-module-name
  1. Created 1 class in each lib. The class in common uses the one from core like so:
import { Foo } from '@my-org/platform-core';

export class Bar {

  public run(): void {
    new Foo().run();
  }
}
  1. In addition I modified the tsconfig.json on root level from
"@my-org/platform/core": ["libs/platform/core/src/index.ts"],
"@my-org/platform/common": ["libs/platform/common/src/index.ts"]

to

"@my-org/platform-core": ["libs/platform/core/src/index.ts"],
"@my-org/platform-common": ["libs/platform/common/src/index.ts"]

(not sure why its created like this although in the package.json the libs are named “@my-org/platform-core” and “@my-org/platform-common”) However, it does not make any difference. So even if I keep it like @my-org/platform/core (in tsconfig.json and the import in the class in common lib) the error is the same.

  1. Then run nx build platform-core (works!) nx build platform-common (fails)

See also: https://github.com/mrucelum/nx_publishable_lib

Context

@nrwl/angular : 9.2.1 @nrwl/cli : 9.2.1 @nrwl/cypress : 9.2.1 @nrwl/eslint-plugin-nx : Not Found @nrwl/express : Not Found @nrwl/jest : 9.2.1 @nrwl/linter : Not Found @nrwl/nest : Not Found @nrwl/next : Not Found @nrwl/node : Not Found @nrwl/react : Not Found @nrwl/schematics : Not Found @nrwl/tao : 9.2.1 @nrwl/web : Not Found @nrwl/workspace : 9.2.1 typescript : 3.8.3

Failure Logs

Compiling TypeScript sources through ngc
ERROR: libs/platform/core/src/index.ts:1:15 - error TS6059: File '~/nx_publishable_lib/libs/platform/core/src/lib/foo.ts' is not under 'rootDir' '~\nx_publishable_lib\libs\platform\common\src'. 'rootDir' is expected to contain all source files.

1 export * from './lib/foo';
                ~~~~~~~~~~~
libs/platform/common/src/lib/bar.ts:1:21 - error TS6059: File '~/nx_publishable_lib/libs/platform/core/src/index.ts' is not under 'rootDir' '~\nx_publishable_lib\libs\platform\common\src'. 'rootDir' is expected to contain all source files.

1 import { Foo } from '@my-org/platform-core';
                      ~~~~~~~~~~~~~~~~~~~~~~~

An unhandled exception occurred: libs/platform/core/src/index.ts:1:15 - error TS6059: File '~/nx_publishable_lib/libs/platform/core/src/lib/foo.ts' is not under 'rootDir' '~\nx_publishable_lib\libs\platform\common\src'. 'rootDir' is expected to contain all source files.

1 export * from './lib/foo';
                ~~~~~~~~~~~
libs/platform/common/src/lib/bar.ts:1:21 - error TS6059: File '~/nx_publishable_lib/libs/platform/core/src/index.ts' is not under 'rootDir' '~\nx_publishable_lib\libs\platform\common\src'. 'rootDir' is expected to contain all source files.

1 import { Foo } from '@my-org/platform-core';

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 22
  • Comments: 34 (13 by maintainers)

Commits related to this issue

Most upvoted comments

Same here. It prevents me from using incremental compilation with: nx build my-app --with-deps.

Is there a solution on the horizon?

Hey all, sorry for the long wait 😞 .

So we basically just merged #2840 and it should have been already released with v10.0.3. Just upgrading won’t work as we didn’t do any migration because that would have been difficult & probably suboptimal.

So what changed?

So what did I add in the PR. Basically we’re currently trying to optimize the incremental build story & the PR is a first step in that direction. So the PR now clearly distinguishes between --publishable and --buildable. While they were aliases before, now there’s a difference.

--publishable now requires you to pass in a required --importPath param, which should be the npm name you plan to use when releasing the package (e.g. @myorg/my-awesome-package or simply my-awesome-package). We require that --importPath explicitly as we didn’t want to do any guesswork here. That importPath is what the TSConfig path mappings will use & what will be in your package.json

--buildable instead doesn’t do any TSConfig path manipulation or require any additional work. It is basically kind of the --publishable from Nx v9. Why would you need a buildable library? For incremental building. See our docs for more info and an example repo.

How can I fix my workspace?

The best is to generate a new Nx v10 workspace, create a similar scenario you’re having in your app & have a look at the differences. It should mostly be the TSConfig path mappings & package.json names.


If you have questions, or if there are still issues, please let me/us know and open a new issue 😃

I just spent 2 solid hours debugging the error

error TS6059: File ‘/some/path/index.ts’ is not under ‘rootDir’ ‘/some/other/path/src’. ‘rootDir’ is expected to contain all source files.

I finally understood where it came from 🤯.

I generated a bunch of libraries, some of them were in nested folders.

I messed up and didn’t the name of the library would be concatenated so I generated something like this

libs
  folder1
    folder1-name1
    folder1-name2

and couldn’t bother rename them just yet (I’m working on a huge and 100% independent task so a long lived branch isn’t an issue here and wanted to do that at the end).

At some point, I ended up renaming the libs everywhere in angular.json and nx.json because their names were

folder1-folder1-name1
folder1-folder1-name2

So I did rename them to

folder1-name1
folder1-name2

Same for the TS mapping as it was annoying.

So I renamed them everywhere. Or at least that’s what I thought. But I completely forgot about the fact that buildable libs have their own name written in their package.json and the name was still based on the old one which I didn’t find with the global text search when looking for folder1-folder1-name1 as in the package.json it was { "name": "@corp/folder1/folder1-name1" }.

Taking the time to share in case anyone else does that or simply for my future self. I’m sure I’ll re-read this thread desperately in a few years 🤦

I struggled a lot with this over the last few days trying many many things, I have some core helpers and types which I wanted to include in a publishable UMD app. In the end, for me, it was very simple to bypass the 'rootDir' is expected to contain all source files. error.

Maybe this helps some of you, I added the helper and the types like normal.

import { colorSchemesFindHexById } from '@org-name/shared/helpers/color';
import {
    WidgetInitOptions,
    WidgetCommunicationData,
    InitProps,
} from '@org-name/shared';

Then I have added the exact locations of where these things can be found to the tsconfig.json in the app:

"compilerOptions": {
    ...
    "rootDirs": [
        "../../libs/shared/src/helpers/color",
        "../../libs/shared/src/models"
    ]
},

the problem with me was due to using @scope/prefix-name in lib package.json and @scope/prefix/name in tsconfig.base.json

I renamed all lines to @scope/prefix-name and added the other lib as a dependency, the error stopped

oh, another thing I did was use the @nrwl/web:package builder instead of @nrwl/workspace:tsc

@Splaktar

it was a nightmare

Agree… Really no clue of what was going on

(multiple days) to debug

Uch. I was lucky enough to find out where it was coming from in ~2 hours for this one 🍀

I finally just changed the libs to no longer nest and it finally fixed it.

   
We already had at least 3 nested libs so I knew they were working just fine and something else was wrong image

For clarity, your fix was to just change the name in the package.json of the nested or parent lib?

In my case I had indeed to only change the name in package.json of the library to match the name defined as a custom TS path that I was using in all my imports. I believe the reason this is working in dev mode is probably because it just doesn’t use the incremental compilation of nx with the --with-deps options that we’ve got for the build command. Probably just reads from the tsconfig.base.json file which defines the name of the imports through the paths property. But then, when building the app with --with-deps it does that by block of work and build intermediate libraries. When trying to link an import to another library, it doesn’t refer to the tsconfig.base.json anymore, it just looks into the dist folder for a library with this package name (sort of what it does when importing a lib from node_nodules) but in the dist folder. At least that’s my assumption.

On NX side, I get a tiny check to make sure that all the package.json in libraries have a name which exists in the tsconfig.base.json in the paths property may be useful. If not, at least display a warning saying hey this is probably not gonna work

Hello folks, we have the same issue in our project. That’s why I decided to create a demonstration project to help here. As far as I can see, the build error boils down to a wrong dependency graph calculation when nested folders are involved. Maybe some affected people can provide some more probes/reports? It looks like it is Windows only so far and I would like to confirm it or prove it wrong.

Issue: https://github.com/nrwl/nx/issues/2955 Repo: https://github.com/georgiee/nx-debug-nested-dep-graph

Thank you.

For the record: this error will still appear under windows if you are referencing code that hasn’t been built into the dist folder correctly. For example referencing lib level generated code like a prisma client which isn’t automatically copied to the dist folder will cause this somewhat unhelpful error.

I fixed exact issue by adding to each library’s tsconfig.lib.json one line:

"paths": { "@yourscope/*": ["dist/libs/*"] }

This will allow typescript to load your libs instead of compiling them. Also make sure you build them in order they depend on each other.

@mrucelum Thx for reporting and for the detailed reproduction steps. Helps a lot to save time on our side 🙂

I followed your steps and also cloned your repo and the build works for me. but only of course if I made the adjustments to the tsconfig.json you mentioned (In addition I modified the tsconfig.json on root level from)

The problem right now is the following: by default, we define the path mapping of libraries in tsconfig.json just following their path structure, meaning you end up with @my-org/platform/core as you’ve seen. That works fine as long as you don’t have publishable libraries.

Publishable libraries (aka buildable libraries) are intended to be buildable on their own (and not as part of an app) & publishable to NPM for instance. That’s also why they have their own package.json like

{
  "name": "@my-org/platform-core",
  "version": "0.0.1",
  "peerDependencies": {
    "@angular/common": "^9.1.0",
    "@angular/core": "^9.1.0",
    "tslib": "^1.10.0"
  }
}

A valid package name cannot have muliple / in there, basically a name like @my-org/platform/core is not allowed. The problem from that is that they are no more in sync now with what is being used in the default tsconfig mapping with nested libraries.

I’ll give this a look. Meanwhile manually adjusting those libraries should work. Otherwise let me know.

@simondotm see my comment above, this way I was able to remove the tsconfig path from my lib

At first glance this looks like a clever solution, but isn’t it going to cause developer havok as their IDE is parsing “built” code that is potentially out of date from the library source code they might be working on?

the problem I had was when the repo was cloned and failed to run the server, as it looked for the library in the dist directory and there was none. so now i put your build on the postinstall hook. but I understood what you said and it really is not the best solution, just a workaround to move on. what is certain is that all paths are configured in tsconfig.base.json. as usual

@Splaktar exactly, that is no more necessary. Publishable libraries need to have a correct path mapping since they are made for publishing and therefore need to follow those rules. In fact, when you generate a new publishable lib, you have to explicitly provide an --importPath.

Buildable libs don’t have that restriction.

We’re on it, sorry for the delay.

@benjamincharity Besides using scope you describe a very different error. You should create a separate issue if you want a chance of being recognized. Don’t forget to provide a minimal example that reproduces the error.