Skip to content

Commit a5f534a

Browse files
authored
Make fix find more transitives (#558)
1 parent c5553a3 commit a5f534a

9 files changed

Lines changed: 193 additions & 171 deletions

File tree

package-lock.json

Lines changed: 52 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
"@socketsecurity/sdk": "1.4.35",
112112
"@types/blessed": "0.1.25",
113113
"@types/cmd-shim": "5.0.2",
114+
"@types/js-yaml": "4.0.9",
114115
"@types/micromatch": "4.0.9",
115116
"@types/mock-fs": "4.13.4",
116117
"@types/node": "22.15.18",
@@ -139,6 +140,7 @@
139140
"hpagent": "1.2.0",
140141
"husky": "9.1.7",
141142
"ignore": "7.0.4",
143+
"js-yaml": "npm:@zkochan/js-yaml@0.0.7",
142144
"knip": "5.56.0",
143145
"lint-staged": "16.0.0",
144146
"magic-string": "0.30.17",

src/commands/fix/npm-fix.mts

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
fetchPackagePackument,
1010
readPackageJson
1111
} from '@socketsecurity/registry/lib/packages'
12+
import { naturalCompare } from '@socketsecurity/registry/lib/sorts'
1213

1314
import {
1415
getBaseGitBranch,
@@ -60,16 +61,16 @@ type InstallOptions = {
6061
}
6162

6263
async function install(
63-
idealTree: SafeNode,
64+
arb: SafeArborist,
6465
options: InstallOptions
65-
): Promise<void> {
66+
): Promise<SafeNode> {
6667
const { cwd = process.cwd() } = {
6768
__proto__: null,
6869
...options
6970
} as InstallOptions
70-
const arb = new Arborist({ path: cwd })
71-
arb.idealTree = idealTree
72-
await arb.reify()
71+
const newArb = new Arborist({ path: cwd })
72+
newArb.idealTree = await arb.buildIdealTree()
73+
return await newArb.reify()
7374
}
7475

7576
export async function npmFix(
@@ -95,12 +96,14 @@ export async function npmFix(
9596
spinner?.start()
9697

9798
const { pkgPath: rootPath } = pkgEnvDetails
99+
98100
const arb = new SafeArborist({
99101
path: rootPath,
100102
...SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
101103
})
102-
// Calling arb.reify() creates the arb.diff object and nulls-out arb.idealTree.
103-
await arb.reify()
104+
// Calling arb.reify() creates the arb.diff object, nulls-out arb.idealTree,
105+
// and populates arb.actualTree.
106+
let actualTree = await arb.reify()
104107

105108
const alertsMap = purls.length
106109
? await getAlertsMapFromPurls(purls, getAlertMapOptions({ limit }))
@@ -129,7 +132,10 @@ export async function npmFix(
129132
spinner?.stop()
130133

131134
let count = 0
132-
infoByPkgNameLoop: for (const { 0: name, 1: infos } of infoByPkgName) {
135+
const sortedInfoEntries = [...infoByPkgName.entries()].sort((a, b) =>
136+
naturalCompare(a[0], b[0])
137+
)
138+
infoByPkgNameLoop: for (const { 0: name, 1: infos } of sortedInfoEntries) {
133139
logger.log(`Processing vulnerable package: ${name}`)
134140
logger.indent()
135141
spinner?.indent()
@@ -159,12 +165,11 @@ export async function npmFix(
159165

160166
logger.log(`Checking workspace: ${workspaceName}`)
161167

162-
arb.idealTree = null
163168
// eslint-disable-next-line no-await-in-loop
164-
await arb.buildIdealTree()
169+
actualTree = await install(arb, { cwd })
165170

166171
const oldVersions = arrayUnique(
167-
findPackageNodes(arb.idealTree!, name)
172+
findPackageNodes(actualTree, name)
168173
.map(n => n.target?.version ?? n.version)
169174
.filter(Boolean)
170175
)
@@ -174,7 +179,7 @@ export async function npmFix(
174179
`Unexpected condition: Lockfile entries not found for ${name}.\n`
175180
)
176181
if (isDebug()) {
177-
console.dir(arb.idealTree!, { depth: 999 })
182+
console.dir(actualTree, { depth: 999 })
178183
}
179184
continue
180185
}
@@ -190,7 +195,7 @@ export async function npmFix(
190195
const oldId = `${name}@${oldVersion}`
191196
const oldPurl = idToPurl(oldId)
192197

193-
const node = findPackageNode(arb.idealTree!, name, oldVersion)
198+
const node = findPackageNode(actualTree, name, oldVersion)
194199
if (!node) {
195200
logger.warn(
196201
`Unexpected condition: Arborist node not found, skipping ${oldId}`
@@ -238,7 +243,8 @@ export async function npmFix(
238243
updateNode(node, newVersion, newVersionPackument)
239244
updatePackageJsonFromNode(
240245
editablePkgJson,
241-
arb.idealTree!,
246+
// eslint-disable-next-line no-await-in-loop
247+
await arb.buildIdealTree(),
242248
node,
243249
newVersion,
244250
rangeStyle
@@ -261,7 +267,7 @@ export async function npmFix(
261267
let errored = false
262268
try {
263269
// eslint-disable-next-line no-await-in-loop
264-
await install(arb.idealTree!, { cwd })
270+
actualTree = await install(arb, { cwd })
265271
if (test) {
266272
spinner?.info(`Testing ${newId} in ${workspaceName}`)
267273
// eslint-disable-next-line no-await-in-loop
@@ -358,8 +364,6 @@ export async function npmFix(
358364
if (isCi) {
359365
// eslint-disable-next-line no-await-in-loop
360366
await gitResetAndClean(baseBranch, cwd)
361-
// eslint-disable-next-line no-await-in-loop
362-
await install(arb.idealTree!, { cwd })
363367
}
364368
if (errored) {
365369
if (!isCi) {
@@ -369,8 +373,6 @@ export async function npmFix(
369373
removeNodeModules(cwd),
370374
editablePkgJson.save({ ignoreWhitespace: true })
371375
])
372-
// eslint-disable-next-line no-await-in-loop
373-
await install(arb.idealTree!, { cwd })
374376
}
375377
spinner?.failAndStop(
376378
`Update failed for ${oldId} in ${workspaceName}`,

0 commit comments

Comments
 (0)