Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/pm/global-store.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ An entry only lives in the global store when it can be safely shared. Entries fa

- the package has a **patch** applied via `bun patch` — the patched contents are project-specific;
- the package is listed in **`trustedDependencies`** (or trusted via `bun add --trust`) — its lifecycle script may mutate the install directory, and a script running through the project symlink would mutate the shared copy;
- the package **exposes TypeScript declarations** — Bun runs the same entry-point resolution TypeScript uses (modelled on [arethetypeswrong.github.io](https://arethetypeswrong.github.io/)) against each package's `package.json`. `"exports"` with a `"types"` condition (including dual `.d.mts`/`.d.cts` objects and array-of-fallbacks), `"exports"` whose resolved JS target has a sibling declaration, top-level `"types"` / `"typings"`, non-empty `"typesVersions"`, and the implicit `index.d.ts` fallback all count. TypeScript resolves peer types (e.g. `React.FunctionComponent` in a package that never declared `@types/react` as a peer dependency) by walking `node_modules` ancestors from the declaration file's realpath; if that realpath is in the shared store those walks never reach the project's `@types/*`. Keeping type-shipping packages project-local puts their realpath back under `node_modules/.bun/<storepath>/`, whose ancestor walk reaches the hidden hoisted layer at `node_modules/.bun/node_modules/`.
- the package, or **any** dependency it links to, is a `workspace:`, `file:`, or `link:` dependency — those resolve to project-local paths that other projects can't see.

Ineligibility propagates: if `your-app` depends on `internal-utils` which is a workspace package, `internal-utils` is project-local, and so is every entry that links to it. An entry that loses eligibility between installs (newly patched, newly trusted) is detached from the global store and rebuilt project-locally on the next install; the shared entry is left untouched.
Expand All @@ -135,6 +136,8 @@ When packages live under the project's `node_modules/.bun/`, Node's module resol

In practice this only affects **true phantom dependencies**: a package doing `require('helper')` for something it never declared in `dependencies`, `peerDependencies`, or `peerDependenciesMeta`. If you hit this, add the helper to the consuming package's dependencies (the right fix) or set `globalStore = false`.

TypeScript triggers the same walk for peer type references inside a package's `.d.ts` files. Packages that ship types are detected (see [What stays project-local](#what-stays-project-local)) and kept out of the global store so their ancestor walk still reaches the project's `@types/*`; purely JavaScript packages with phantom `require('helper')` calls are the remaining case.

Note that [`publicHoistPattern`](/runtime/bunfig#install-publichoistpattern) and [`hoistPattern`](/runtime/bunfig#install-hoistpattern) hoist into the project's `node_modules`, which packages inside the global store can't reach. They still work for resolving hoisted packages from your own source code.

### `node_modules` is mostly symlinks
Expand Down
Loading
Loading