dts-bundle-generator: Bug With Symlinked Packages in Monorepo
Bug report
I’m using dts-bundle-generator in my experimental monorepo. I found it irreplaceable, especially if I bundle in some of my devDependencies and they would not exist as packages in published npm package, but their TypeScript declarations need to be inlined. I don’t know any other tool that does this. Well done 👍. And thank you 🙏.
I use pnpm to install packages. So I have following directory structure which describes pnpm behaviour the best:
packages/
packageA
node_modules
packageB -> ../../../packageB
*.ts
packageB
*.ts
We can see that packageB is going to be a symbolic link.
When using dts-bundle-generator I get a compiler error, saying that I cannot import this or that. Example:

Additional context
The test that reproduces this issue is here: https://github.com/zaripych/dts-bundle-generator/commit/49ad3a6d1035bc790268f55d048ec89fb44382f0
I fixed it by making these changes: https://github.com/zaripych/dts-bundle-generator/commit/794a1a3c38135ec65c27e3c6e6a6604135ae1981#diff-5a014ac4d87f713ea8b9c8dd8966ce3b77df4ecc8e263b4baf9b9469bf9f2917
Would it be possible to incorporate these changes in the main repo?
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 1
- Comments: 21 (8 by maintainers)
Because it switches the compiler to another way of working, which is a build mode or know as composite projects (or referenced projects) that aren’t supported right now (see #93).
Ok I was able to run this on wsl, here is my observations:
by default (if you don’t change the config file) you get bunch errors like
error TS2307: Cannot find module or its corresponding type declarations., by digging into the issue I found out that this is the behaviour of the compiler - it treats files innode_modulesas something that shouldn’t have an emit so it doesn’t generate any output for them (that’s what we’ve discussed above, I agree with the compiler and having a code that handles this correctly is kind of strange and I wouldn’t like to do this). Even though I don’t quite understand why these files are treated as files fromnode_modules, I’d expect them to be treated as local ones, because after resolve they don’t havenode_modulesin their paths. But I think this is the questions to the compiler team:if you add
followSymlinks: falseto the config, then it warns with… the same issue actually but different errors - now the tool complains about files that are in the compilation but they are notd.tsones. But later the building ended with an errorError: Cannot find symbol for node: Plugin. After debugging this problem I figured out, that for some reason the compiler decides to load types forjestpackage and it causes this error (it comes directly from its types). If you add"types": ["node"],to tsconfig for the tool the problem goes away. But then of course the compilation fails because in the declaration bundle it finds something that shouldn’t be there, for example a function’s body, and it comes directly from the warning.So I’d say probably the best solution here is to use
paths. Alternatively you can ask the compiler team why the compiler doesn’t generate an output for files that were resolved fromnode_modulesto a local folder (outside ofnode_modules; so basically the case is the following:node_modules/@internal-package/src/index.ts->../internal-package/src/index.ts, but the compiler treats this file as “comes from node_modules” and doesn’t generate an output for it).Another solution could be set up the right order of building packages and compile them first and then bundle the declarations.
@zaripych sorry for late reply.
After reading this thread again I think that I’m not going to implement compiling files from the
node_modulesfolder, this is not how the compiler works, this is not how the other tools are supposed to work and by adding this “feature” we might allow and “support” to use an incorrect and a kind of bad practice of developing and maintaining packages (think about this in wide, not your particular example that you’d like to solve). Once it is added, it won’t be possible to remove it. This is just not right.But the good news, it looks like the issue might be related to the way how the linking of packages via
pnpmworks and how pnpm links dependencies inside thenode_modulesfolder and I think that this is something that the tool can add and maintain (and probably should, if there is a problem).Is it possible for you to create a repro for your issue (with
pnpmusage and gettingError: Cannot find symbol for node: Pluginerror) so I can take a look what’s is going on there? I think it would be much helpful to understand why exactly the current solution doesn’t work forpnpm’s workspaces.Below some replies to your messages and questions.
For supporting composite projects there is an issue, see #93. But IIRC there were some issues with supporting this, because the compiler’s API for composite projects is different it it might not be possible to get the output for everything. Also, there might be a question how to treat your composite parts - as an “externals” or “internals” (but it is possible that I’m messing it up with other tool https://github.com/timocov/ts-transformer-properties-rename).
If you run it against
d.tsfiles, it won’t compile any ts files and will use these files as it. It is not perfect and blazing fast, but at least something and if you already compiled your project, you don’t need to compile it once again.If you’re talking about incremental compilation that the compiler supports this might be tricky. From what I’ve seen, the compiler doesn’t store anything about the compilation besides the deps tree, last modified dates and some other meta information that helps the compiler to say “nothing has changed from the last compilation so nothing to do”. But once you change a file, the compiler will compile the project anyway. So from my observations the compiler doesn’t store or cache any results in that way.
The way how the compilation of composite projects works is that the compiler for a dependency doesn’t use
tsfile but use.d.tscompiled file (that’s whydeclaration: trueis required for dependencies) (it is looking similar to what we were talking about above, isn’t it? 😄).On the other side, the tool requires the files to be compiler and type checked because the tool relies on that and this cannot be omitted.
@timocov the config didn’t help, and it prevented from other npm packages mounted by
pnpmfrom working as well. To clarify, with following config:dts-bundle-generatorgives me error:But with this it works 👍
The
Pluginin the error message probably refers to therollup’sPlugintype that I meant to expose in the interface of my package.Basically the
dts-bundle-generatordoesn’t work withpnpmunless it follows symlinks and doesn’t work with my monorepo setup, unless I pre-bundle the entire dependency tree manually first. If you insist that this is an ok behaviour for this product - it’s unfortunate for me.