Skip to content
Open
Show file tree
Hide file tree
Changes from 9 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