refactor(pnpm): rename managerData.pnpmShrinkwrap to pnpmLockFile
The field holds the path to pnpm-lock.yaml, and pnpm has not called that file
a shrinkwrap since v5, so the old name reads as a different artifact than the
one it points at.
Co-authored-by: Jamie Tanna <jamie.tanna@mend.io>
Refs #45216
The object counterpart to `prefer-coerce-array`: `x ?? {}` becomes
`coerceObject(x)`. The rule flags a `??` whose default is a bare `{}`
literal, so a populated default or an asserted `({} as Foo)` still
passes; a `x ?? y ?? {}` chain maps onto `coerceObject(x, y)`.
Every hit across `lib/` converted cleanly, so no disable comments were
needed.
To prevent the possibility of a npm package name including shell
metacharacters (which is unlikely, but potentially possible through a
well-crafted payload), which could lead to command execution, we can
make sure they are quoted appropriately.
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
* fix(npm): use packageName for pnpm overrides with range selectors in minimumReleaseAgeExclude
For pnpm.overrides entries with version range selectors (e.g. "pkg@<=1.0.0"),
depName contains the full override key including the selector, which is needed
to correctly update package.json. However this caused invalid entries in
minimumReleaseAgeExclude like "fast-xml-parser@<=5.3.5@5.5.7" instead of
"fast-xml-parser@5.5.7", breaking pnpm install with ERR_PNPM_INVALID_MINIMUM_RELEASE_AGE_EXCLUDE.
Fix by using packageName (bare npm package name parsed by @pnpm/parse-overrides)
instead of depName when constructing minimumReleaseAgeExclude entries. Falls back
to depName for dependency types where packageName is not set.
Made-with: Cursor
* test(npm): format pnpm override minimumReleaseAgeExclude test
Use codeBlock helper for expected pnpm-workspace.yaml contents per review.
* test(npm): avoid string concat in shrinkwrap exclude test
Use template literal instead of + to satisfy restrict-plus-operands.
* fix(npm): replace malformed minimumReleaseAgeExclude entries
Skip invalid package@version lines (extra @ after package prefix) when
matching excludes, and replace them instead of appending versions.
* test(npm): cover valid vs malformed exclude matching
* Update lib/modules/manager/npm/artifacts.spec.ts
Co-authored-by: Michael Kriese <michael.kriese@gmx.de>
* Update lib/modules/manager/npm/artifacts.spec.ts
Co-authored-by: Michael Kriese <michael.kriese@gmx.de>
* test(npm): use codeBlock for expected workspace contents
* fix(npm): remove stale malformed minimumReleaseAgeExclude entries
When a valid exclude entry exists for the same package, drop leftover
malformed lines from the prior double-@ bug instead of leaving them.
* test(npm): avoid string concat in codeBlock expectations
Use template literal instead of + '\n' for prefer-template.
---------
Co-authored-by: Tapio Oikarinen <tapio.oikarinen@hoxhunt.com>
Co-authored-by: Martijn van der Meij <Squixx@users.noreply.github.com>
Co-authored-by: Michael Kriese <michael.kriese@gmx.de>
As noted in #40774, if a `pnpm-lock.yaml` isn't found, the
`pnpmShrinkwrap` is undefined, which then results in `upath.dirname`
throwing an error.
We can make sure that we have a value, and exit out early if not.
This is a short-term fix, and we should follow-up to make it so we can
find the `pnpm-workspace.yaml` if there's not a lockfile.
As noted in #40611, we shouldn't reference the same version multiple
times in the same exclude directive.
This also handles the case where we could end up with multiple comments
for a given package.
This is slightly more complex logic, and slightly simplifes by
extracting out to a new helper method.
We also need to make sure that we use `getIn` so we get the raw node, so
we can look at the comment inside the `minimumReleaseAgeExclude`'s list,
but before the first element.
As noted in #40610, when `newVersion` contains a caret (or other
npm-specific versioning constraints) a generated
`minimumReleaseAgeExclude` directive will result in
ERR_PNPM_INVALID_MINIMUM_RELEASE_AGE_EXCLUDE Invalid value in
minimumReleaseAgeExclude: Invalid versions union. Found: "...". Use
exact versions only.
To handle this better, we can make sure we use `newVersion` over
`newValue`, as it'll provide the raw version number.
We also need to update an unrelated to test to make sure it's using
`newVersion`.