Skip to content

[Infra] shamefullyHoist hides undeclared imports; nodeLinker: hoisted is redundant #5328

Description

@Han5991

Problem

pnpm-workspace.yaml carries two hoisting settings inherited verbatim from the pre-pnpm-11 .npmrc (#3700):

nodeLinker: hoisted
shamefullyHoist: true

shamefullyHoist: true is publicHoistPattern: '*' — every transitive package is republished at the root of node_modules. A workspace package can therefore import a module it never declared in its own package.json, and nothing complains: not install, not build, not CI. The declaration is simply missing, and the import rides on someone else's copy.

nodeLinker: hoisted is a separate problem. Its .npmrc annotation read "Use the Node-modules linker (default), not pnpm's PnP", which is wrong on its own terms — pnpm's default is the node-modules linker, but its default mode is isolated, not hoisted. On top of being unnecessary, the pair is a combination pnpm has an open bug on: nodeLinker: hoisted with shamefullyHoist: true is pnpm/pnpm#6620, spurious ModuleNotFoundErrors that only clear after toggling the setting off and back on.

Evidence

Flipped shamefullyHoist to false locally (pnpm 11.10.0), recreated node_modules, and ran build / test / typecheck / Storybook / Next builds. Eight undeclared imports surfaced — each verified by checking the missing module against the importing package's own package.json:

Package Undeclared module Symptom
root scripts/ @babel/core, glob, chokidar, @testing-library/jest-dom, @stylexjs/babel-plugin pnpm build fails at @astryxdesign/core
lab, charts, richtext @babel/cli, @babel/core, @babel/preset-react, @babel/preset-typescript, @stylexjs/babel-plugin build:esmsh: babel: command not found
lab, charts, richtext @testing-library/react 27 test files load 0 tests
core @types/babel__core TS7016
storybook @heroicons/react, @stylexjs/stylex, @lexical/react, lexical storybook:build fails to resolve
docsite @babel/parser next build type error after a clean compile
cli @heroicons/react, @stylexjs/stylex, lucide-react, recharts 145+ TS errors in assets/templates/**, which tsconfig.strict.json includes and CI runs (ci.yml)

All eight are devDependencies, so no published package is missing a runtime dependency today — the cost is in-repo hygiene and the absence of a guard against the next one.

Scope Check

  • linkWorkspacePackages: true was audited and must stay: 64 internal deps are declared as bare "*" (only 4 use workspace:*), and pnpm ≥ 10 defaults this to false, which would resolve them from the registry instead of local source — silently, with no error.
  • Three failures found during the sweep are pre-existing and unrelated, each baselined with hoisting restored: 7 test files (plainDate, Calendar, DateInputTouch, Schedule, TransferListSelector, 2 CLI suites — 69 failing cases on main vs 56 with the change), lab typecheck (relative .doc.mjs imports plus a Drawer onClose prop error; CI runs typecheck:docs, which passes), and the template-viewer build (packages/build aliases the @astryxdesign/core prefix to core/src, so core/locales/*.json rewrites to a nonexistent path; CI does not build this app).
  • No symlink-hostile environment exists in the repo: no Dockerfile, no react-native, all CI runners are Ubuntu — so nothing depends on the flat layout for platform reasons.

Proposed Direction

Declare what each package actually imports, then drop both settings in the same change — splitting them would land dependency declarations whose correctness cannot be demonstrated while the flag is still on.

Deliberately left alone: linkWorkspacePackages, and any move back toward nodeLinker: hoisted.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions