tsx: import in referenced typescript project fail to load
Bug description
When working with composite projects, our tests failed because it seems that tsx is not taking the reference project’s baseUrl or path into consideration.
Reproduction
Test project:
https://github.com/steabert/esbuild-kit-tsx-composite.git
To reproduce the issue:
yarn install
yarn fail
Running yarn bundle and yarn types shows the result with e.g. esbuild or tsc.
It seems this does not work with ts-node either, but I don’t know how they handle composite typescript projects.
Environment
npx envinfo --system --npmPackages tsx --binaries
System:
OS: Linux 5.4 Ubuntu 20.04.4 LTS (Focal Fossa)
CPU: (8) x64 Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
Memory: 23.58 GB / 31.21 GB
Container: Yes
Shell: 5.0.17 - /bin/bash
Binaries:
Node: 16.14.2 - ~/.node/bin/node
Yarn: 3.2.3 - ~/.npm-global/bin/yarn
npm: 8.5.0 - ~/.node/bin/npm
npmPackages:
tsx: 3.9.0 => 3.9.0
Can you contribute a fix?
- I’m interested in opening a pull request for this issue.
About this issue
- Original URL
- State: open
- Created 2 years ago
- Reactions: 5
- Comments: 20 (10 by maintainers)
I was able to get this working using a custom
exportsfield on all my monorepopackage.jsonfiles, and then passing--conditionstotsx:Then
If people are stuck on this, I had success with vite-node combined with vite-tsconfig-paths.
It also plays nice with vitest as it’s reusing the same pipeline. 👍
I’m very sorry for this triple post, but I played some more with my TypeScript monorepo and I think I gained interesting insights for this issue.
Big picture
First, the “one true way” of connecting TypeScript projects together is project references. This is the only mechanism that enables TypeScript to split the dependency chain between multiple TypeScript projects and use each project’s
tsconfig.json.Custom
tsconfig.jsonfiles are handled by this mechanism as well:Without references, if you require a TypeScript file from an external package (through either monorepo workspaces or paths alias, I personally recommend avoiding paths alias as you break your package isolation), only the
tsconfig.jsonfile of the root package will be used, this is why external packages paths alias break, because the root package is not aware of their internals (and it should not be 😄).How to have this implemented in tsx
Project references were discussed in esbuild repository, and the conclusion was that it’s beyond the scope of esbuild, but could be implemented as a plugin!
A plugin exists: esbuild-plugin-ts-references but it’s not working on paths alias, it’s only rewriting the import statements to link directly to the references. But it shows that it’s possible with esbuild API to walk through each package’s
tsconfig.jsonby following references and build some kind of map.So the solution would be to write an esbuild plugin similar to esbuild-plugin-ts-references that can rewrite imports based on the file’s local
tsconfig.jsongathered through references analysis. The main blocker is thattsxis using esbuild’s Transform API and not the Build API, so it can’t consume a plugin.@privatenumber How hard of a requirement is it to use the Transform API vs the Build API? Reading esbuild doc it seems like Transform is just a small subset of Build?
Another solution would be to have
tsxdo the references analysis work outside of esbuild to build the map and then apply the rewrites somehow with the Transform API, but I’m not familiar with it enough to know if it’s possible. 😅edit: It seems like if we can construct the map
<tsconfigPath, filePaths>, we could be able to pass the righttsconfig.jsoncontent here: https://github.com/esbuild-kit/cjs-loader/blob/94a69f9e6d41225cb8a132938a3b9b077c15f966/src/index.ts#L74edit 2: I gave my “projects map” idea a try, I think I’m pretty close to making it works but I have a nasty recursive bug somewhere that I can’t figure out. 🤔
But I’m able to :
tsconfigtsconfigfile given a file path when calling esbuildtransformPlease note that it’s not “performance” oriented, right now I’m just trying to understand the code and make it works. 😅
Here are the forks :
And I test against this project:
pnpm --filter cli devedit 3: My recursion bug is fixed and the code for https://github.com/jgoux/esm-loader/tree/feat-project-references is fully functional! 🎊