* fix: handle lockfile conflicts in optimistic install
* test: move sharedWorkspaceLockfile out of WorkspaceState.settings
`sharedWorkspaceLockfile` is not in `WORKSPACE_STATE_SETTING_KEYS`, so
placing it inside `WorkspaceState.settings` broke type checking. Pass
it directly on the `CheckDepsStatusOptions` instead.
* chore: add lockfile/fs project reference to installing/commands tsconfig
`@pnpm/lockfile.fs` was added as a runtime dependency but the tsconfig
project references were not updated. meta-updater enforces this in CI.
* perf: restore optimistic-repeat-install fast-path for conflict-free state
The first iteration of the conflict-detection fix unconditionally read
pnpm-lock.yaml on every install - once in installDeps and again inside
checkDepsStatus - defeating the point of optimisticRepeatInstall, which
was to skip reading the lockfile entirely when nothing changed.
Restore the fast path by:
- Dropping the redundant lockfile read from installDeps. checkDepsStatus
already returns upToDate: false when the lockfile is conflicted, so
the pre-check was dead weight.
- Gating the conflict check inside checkDepsStatus on the lockfile's
mtime: if it hasn't been touched since the last successful install,
it cannot have grown conflict markers, so the read is skipped.
Conflict markers introduced after a successful install (e.g. via
git pull/merge) still update the lockfile mtime, so the correctness
fix is preserved.
* perf: make lockfile-conflict check synchronous
findConflictedLockfileDir awaits its work serially with no concurrent
operations to interleave, so the async overhead (Promise.all microtasks,
event-loop hops) buys nothing. Convert to a plain for-loop with
fs.statSync and a new wantedLockfileHasMergeConflictsSync export.
Also resolves a test-mock issue: the previous version called safeStat
from deps/status, which is jest-mocked across the test file. The mocked
safeStat returned undefined (or stale stats from earlier tests), causing
the conflict check to silently no-op. Switching to fs.statSync bypasses
the mock and gets the real mtime of the temp lockfile the regression
tests write.
---------
Co-authored-by: Zoltan Kochan <z@kochan.io>
* fix: refresh ignored builds when allowBuilds changes
* refactor: extract isBuildExplicitlyDisallowed into @pnpm/building.policy
Removes the duplicated ignored-build filter from deps-installer and
deps-restorer and exposes it as `isBuildExplicitlyDisallowed` on
`@pnpm/building.policy`, alongside `createAllowBuildFunction`.
* fix: respect ignoredWorkspaceStateSettings in allowBuilds stale-state check
The fallback that flagged installs when allowBuilds went from unset to
non-empty bypassed the ignoredSettings filter, so callers that explicitly
opted out of allowBuilds tracking (via ignoredWorkspaceStateSettings)
could still be forced into a redundant install.
---------
Co-authored-by: Zoltan Kochan <z@kochan.io>
* chore: upgrade @typescript/native-preview to 7.0.0-dev.20260421.2
- Add explicit `types: ["node"]` to the shared tsconfig because tsgo
20260421 no longer auto-acquires `@types/*` from `node_modules`.
- Refactor test files to explicitly import jest globals (`describe`,
`it`, `test`, `expect`, `beforeEach`, etc.) from `@jest/globals`
instead of relying on `@types/jest` ambient declarations. Under the
new tsgo build, `import { jest } from '@jest/globals'` shadows the
ambient `jest` namespace, breaking `@types/jest`'s `declare var
describe: jest.Describe;` globals.
- Add `@jest/globals` to each package's devDependencies where tests
now import from it, and add `@types/node` to packages that need it
but were relying on hoisted resolution.
- Replace `fail()` calls with `throw new Error(...)` since `fail` is
no longer globally available.
* chore: fix remaining tsgo type-strictness errors
- Strip `as <PnpmType>` casts on objects passed to toMatchObject /
toStrictEqual / toEqual; @jest/globals rejects the typed objects
(which include AsymmetricMatchers) vs. the repo-specific type.
- Type `jest.fn<...>()` explicitly where the mock's signature matters
for toHaveBeenCalledWith.
- Replace `beforeEach(() => X)` with `beforeEach(() => { X })` so the
return value is void, as the stricter jest typing requires.
- Use `expect.objectContaining({...})` in one place where the full
expected object triggered stricter type resolution.
- Cast `prompt.mock.calls` arg through `as unknown as Record<...>[]`
for patch.test.ts's nested-array matchers.
- Fix off-by-one `<reference path>` in pnpm/test/getConfig.test.ts
that only surfaced now.
- Move `@jest/globals` from devDependencies to dependencies in the
two `__utils__` packages that import it from `src/`.
- Clean up unused imports from the @jest/globals migration.
* chore: address Copilot review on #11332
- Move misplaced `@jest/globals` imports to the top import block in
checkEngine, run.ts, and workspace/root-finder tests where the
script dropped them below executable code.
- Replace `try { await x(); throw new Error('should have thrown') } catch`
in bins/linker, lockfile/fs, and resolving/local-resolver tests with
`await expect(x()).rejects.toMatchObject({...})`. The old pattern
swallowed an unrelated `throw` if the under-test call silently
succeeded, which would fail on the catch-block assertion with a
misleading message.
Add n/prefer-node-protocol rule and autofix all bare builtin imports
to use the node: prefix. Simplify the simple-import-sort builtins
pattern to just ^node: since all imports now use the prefix.
Add eslint-plugin-simple-import-sort to enforce consistent import ordering:
- Node.js builtins first
- External packages second
- Relative imports last
- Named imports sorted alphabetically within each statement
* fix: detect overrides and other lockfile-affecting setting changes in optimisticRepeatInstall
When optimisticRepeatInstall was enabled, changing overrides,
packageExtensions, ignoredOptionalDependencies, patchedDependencies,
or peersSuffixMaxLength would not trigger a reinstall because these
settings were not tracked in the workspace state file.
* refactor: extract WORKSPACE_STATE_SETTING_KEYS to prevent type/runtime drift
The settings key list in createWorkspaceState's pick() call must stay
in sync with the WorkspaceStateSettings type. Extract a shared const
array so both the type and runtime pick are derived from a single
source, preventing the class of bug fixed in the previous commit.
* test: use `import type` in more places
Several tests are failing because a module isn't being mocked. This is
due to the mocked module being imported before the mock being set up.
Switching to `import type` should elide the import fully.
* build: replace ts-jest with simple transformer
* chore: remove `ts-jest`
* chore: remove babel dependencies from root project
* ci: use Node.js 22.13.0 (instead of 22.12.0)
Node.js 22.13.0 introduces the `stripTypeScriptTypes` function
* fix: copilot feedback