jaredpalmer / tsdx

Zero-config CLI for TypeScript package development
https://tsdx.io
MIT License
11.26k stars 508 forks source link

yarn 2 berry: tsdx tried to access babel-jest, but it isn't declared in its dependencies; #688

Open sgratzl opened 4 years ago

sgratzl commented 4 years ago

Current Behavior

when using v0.13.2 with yarn 2 berry, I get the following error when running tsdx test

Error: tsdx tried to access babel-jest, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound.

see also: https://github.com/jaredpalmer/tsdx/blob/3c65bdf90860c45a619b8a23720e41f8e251a4ef/src/createJestConfig.ts#L12

Expected behavior

all modules that are references using require or require.resolve have to be part of the dependencies of the package.

Suggested solution(s)

add babel-jest to the direct dependencies

Additional context

Your environment

Software Version(s)
TSDX 0.13.2
TypeScript 3.8.3
Browser n.a
npm/Yarn yarn 2 berry
Node 12.16.1
Operating System win
agilgur5 commented 4 years ago

So babel-jest isn't a direct dependency because it's a dependency of Jest, and Jest's default config is very similar -- we want to configure JS the same and use the same babel-jest version (though realistically, I don't think the yarn.lock would change at all with the addition of a babel-jest dependency). The require.resolve is necessary as plain string throws some errors.

It's a bit weird that Berry would punish require.resolve but not plain string. Requiring that every sub-dependency specified in a config also be a direct dependency gets you the ESLint shareable config problem. Several libraries reference "optional dependencies" this way too (and babel-jest is only necessary for JS users), expecting the dependency to be installed if needed.

TSDX also doesn't have support for Berry yet -- there is #458 for that -- I'd be surprised if this were the only issue encountered while using Berry. I'm not sure all the dependencies support it either.

ghost commented 4 years ago

For a temporary resolution, you can switch to pnp loose mode. Set pnpMode: loose in your yarnrc

sgratzl commented 4 years ago

so far I was able to manage it to get it work together with yarn 2 in my monorepo: https://github.com/upsetjs/upsetjs. It required some customization (like the rollup-plugin-pnp-resolve for rollup: https://github.com/upsetjs/upsetjs/blob/master/packages/model/tsdx.config.js) but doable.

merceyz commented 4 years ago

If you look at the dependency tree it's really just luck/hoisting that makes tsdx test work at all.

$ yarn why babel-jest -R
└─ mylib@workspace:.
   └─ tsdx@npm:0.13.3 (via npm:^0.13.3)
      └─ jest@npm:24.9.0 (via npm:^24.8.0)
         └─ jest-cli@npm:24.9.0 (via npm:^24.9.0)
            ├─ @jest/core@npm:24.9.0 (via npm:^24.9.0)
            │  ├─ @jest/reporters@npm:24.9.0 (via npm:^24.9.0)
            │  │  └─ jest-runtime@npm:24.9.0 (via npm:^24.9.0)
            │  │     └─ jest-config@npm:24.9.0 (via npm:^24.9.0)
            │  │        └─ babel-jest@npm:24.9.0 [11af2] (via npm:^24.9.0 [11af2])
            │  ├─ jest-config@npm:24.9.0 (via npm:^24.9.0)
            │  └─ jest-runtime@npm:24.9.0 (via npm:^24.9.0)
            └─ jest-config@npm:24.9.0 (via npm:^24.9.0)

we want to configure JS the same and use the same babel-jest version

@agilgur5 There is no guarantee you'll actually get the same version as jest has in its tree without declaring it, there might be some other dependency that declares babel-jest as a dependency, in which case the version that gets hoisted to the top is undefined behaviour.

TSDX also doesn't have support for Berry yet -- there is #458 for that -- I'd be surprised if this were the only issue encountered while using Berry. I'm not sure all the dependencies support it either.

From running npx tsdx create mylib lint and test is the only things that doesn't work, one of which can be fixed rather easily by declaring the dependencies you need to use.

agilgur5 commented 4 years ago

If you look at the dependency tree it's really just luck/hoisting that makes tsdx test work at all.

Per my previous comment, Jest itself does the same for its default config. It's officially documented behavior, not luck.

From running npx tsdx create mylib lint and test is the only things that doesn't work, one of which can be fixed rather easily by declaring the dependencies you need to use.

The comment above and issue itself say that build doesn't work. Neither mentions lint. In any case, there is a good bit of investigation, work, and automated tests to do. I've never used Berry either. This issue has 0 upvotes and the other 2, so the work/benefit ratio is quite low.

You're welcome to contribute that work if you want that integration to exist faster.

cspotcode commented 3 years ago

In case this is helpful:

I think module.createRequire() is the correct approach when trying to load dependencies that you must assume are declared by a different package.json and not your own.

https://nodejs.org/api/module.html#module_module_createrequire_filename

cspotcode commented 3 years ago

What is tsdx's intended behavior when choosing a version of babel-jest?

Jest's documentation says that projects are supposed to declare their own dependency on babel-jest, suggesting that users should not depend on a version being hoisted from jest's dependency tree: https://jestjs.io/docs/en/getting-started#using-babel

I assume that tsdx intends to bundle its own copy of babel-jest to simplify end-user configuration. What is the intent if a project declares its own babel-jest dependency, with a different version than the one bundled by tsdx?