oven-sh / bun

Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one
https://bun.sh
Other
74.47k stars 2.78k forks source link

Allow explicitly hoisting certain packages using `public-hoist-pattern` #6160

Open aaditmshah opened 1 year ago

aaditmshah commented 1 year ago

What is the problem this feature would solve?

Bun, like pnpm, doesn't automatically hoist packages to the root node_modules folder. This is the right thing to do. However, there are a handful of scenarios where we genuinely do need to hoist transitive dependencies. One of those scenarios is when we use the better-typescript-lib package.

This package, as the name describes, provides better type definitions for the built-in typescript libraries. For example, it provides stricter type definitions for JSON.parse, JSON.stringify, and fetch().json(), which helps developers catch more bugs at compile time. All you need to do to use this library is install it. It provides the type definitions as transitive dependencies.

  /better-typescript-lib@2.4.0(typescript@5.1.6):
    resolution:
      {
        integrity: sha512-LMFX7HPN5qlJiW5IlJiicTT2XcJJ8wRTq3D1YinmZzqNQ0lKX409EK+4cmkuMZTkfyZXBxOca29zvZwIGt9Q3Q==,
      }
    peerDependencies:
      typescript: ">=4.5.2"
    dependencies:
      "@typescript/lib-decorators": /@better-typescript-lib/decorators@2.4.0(typescript@5.1.6)
      "@typescript/lib-dom": /@better-typescript-lib/dom@2.4.0(typescript@5.1.6)
      "@typescript/lib-es2015": /@better-typescript-lib/es2015@2.4.0(typescript@5.1.6)
      "@typescript/lib-es2016": /@better-typescript-lib/es2016@2.4.0(typescript@5.1.6)
      "@typescript/lib-es2017": /@better-typescript-lib/es2017@2.4.0(typescript@5.1.6)
      "@typescript/lib-es2018": /@better-typescript-lib/es2018@2.4.0(typescript@5.1.6)
      "@typescript/lib-es2019": /@better-typescript-lib/es2019@2.4.0(typescript@5.1.6)
      "@typescript/lib-es2020": /@better-typescript-lib/es2020@2.4.0(typescript@5.1.6)
      "@typescript/lib-es2021": /@better-typescript-lib/es2021@2.4.0(typescript@5.1.6)
      "@typescript/lib-es2022": /@better-typescript-lib/es2022@2.4.0(typescript@5.1.6)
      "@typescript/lib-es2023": /@better-typescript-lib/es2023@2.4.0(typescript@5.1.6)
      "@typescript/lib-es5": /@better-typescript-lib/es5@2.4.0(typescript@5.1.6)
      "@typescript/lib-es6": /@better-typescript-lib/es6@2.4.0(typescript@5.1.6)
      "@typescript/lib-esnext": /@better-typescript-lib/esnext@2.4.0(typescript@5.1.6)
      "@typescript/lib-scripthost": /@better-typescript-lib/scripthost@2.4.0(typescript@5.1.6)
      "@typescript/lib-webworker": /@better-typescript-lib/webworker@2.4.0(typescript@5.1.6)
      typescript: 5.1.6
    dev: true

These transitive dependencies, such as @typescript/lib-es5, are hoisted to the root node_modules folder by package managers like yarn and npm. And, when the TypeScript compiler sees @typescript/lib-* packages in the root node_modules folder it replaces the built-in type definitions for that library with the type definitions provided by the package. For example, the type definitions in es5.d.ts would be replaced by the type definitions provided by @typescript/lib-es5.

Unfortunately, because bun doesn't hoist packages, we can't use better-typescript-lib with bun. This is a shame, because better-typescript-lib is an indispensable package for me. I ❤️ both bun and better-typescript-lib. It would be awesome if I could use both of them together.

References

What is the feature you are proposing to solve the problem?

Like bun, pnpm also doesn't automatically hoist packages to the root node_modules folder. However, it does provide an escape hatch, public-hoist-pattern, which can be used to hoist only certain packages. Thus, we can use better-typescript-lib with pnpm by adding the following line to our .npmrc file.

public-hoist-pattern[]=@typescript/*

I especially like this solution, because we're being explicit about which packages we want to hoist. And, as the Zen of Python states, "Explicit is better than implicit." It would be awesome if bun also implemented the public-hoist-pattern config option. Implementing something like public-hoist-pattern in the bunfig.toml file would be the easiest way to enable better-typescript-lib to be used with bun.

References

What alternatives have you considered?

There are three alternatives here.

  1. 😢 Don't use bun. I would have to fall back to using pnpm again, which is not bad, but I would love to use bun.
  2. 😭 Don't use better-typescript-lib. If I want to continue using bun then I'd have to give up on using better-typescript-lib, which is currently a deal-breaker for me.
  3. 🤔 Change better-typescript-lib to somehow work with bun. As one of the contributors of the better-typescript-lib package, I could try to find a solution to make better-typescript-lib work with bun. However, I have absolutely no idea how to make it work with bun. If there's a way to make better-typescript-lib work with bun by making a change in better-typescript-lib itself, then I'm all ears.
taichi221228 commented 6 months ago

@aaditmshah

This is specific to better-typescript-lib, but from what I see in the node_modules output, it only contains TypeScript type definitions. This means it can be directly imported in tsconfig.json. This is quite a forceful workaround, but it allows better-typescript-lib to work with Bun.

{
  // ...
  "include": ["node_modules/better-typescript-lib/node_modules/@typescript/**/*.d.ts"]
  // ...
}