Skip to content

Commit a1bd68a

Browse files
committed
fix: use @npmcli/package-json to parse package.json
1 parent cc56959 commit a1bd68a

File tree

8 files changed

+90
-127
lines changed

8 files changed

+90
-127
lines changed

workspaces/arborist/lib/arborist/build-ideal-tree.js

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// mixin implementing the buildIdealTree method
22
const localeCompare = require('@isaacs/string-locale-compare')('en')
3-
const rpj = require('read-package-json-fast')
3+
const PackageJson = require('@npmcli/package-json')
44
const npa = require('npm-package-arg')
55
const pacote = require('pacote')
66
const cacache = require('cacache')
@@ -268,7 +268,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
268268
root = await this.#globalRootNode()
269269
} else {
270270
try {
271-
const pkg = await rpj(this.path + '/package.json')
271+
const { content: pkg } = await PackageJson.normalize(this.path)
272272
root = await this.#rootNodeFromPackage(pkg)
273273
} catch (err) {
274274
if (err.code === 'EJSONPARSE') {
@@ -448,7 +448,6 @@ module.exports = cls => class IdealTreeBuilder extends cls {
448448
const paths = await readdirScoped(nm).catch(() => [])
449449
for (const p of paths) {
450450
const name = p.replace(/\\/g, '/')
451-
tree.package.dependencies = tree.package.dependencies || {}
452451
const updateName = this[_updateNames].includes(name)
453452
if (this[_updateAll] || updateName) {
454453
if (updateName) {
@@ -1288,14 +1287,13 @@ This is a one-time fix-up, please be patient...
12881287
})
12891288
}
12901289

1291-
#linkFromSpec (name, spec, parent) {
1290+
async #linkFromSpec (name, spec, parent) {
12921291
const realpath = spec.fetchSpec
12931292
const { installLinks, legacyPeerDeps } = this
1294-
return rpj(realpath + '/package.json').catch(() => ({})).then(pkg => {
1295-
const link = new Link({ name, parent, realpath, pkg, installLinks, legacyPeerDeps })
1296-
this.#linkNodes.add(link)
1297-
return link
1298-
})
1293+
const { content: pkg } = await PackageJson.normalize(realpath).catch(() => { return { content: {} } })
1294+
const link = new Link({ name, parent, realpath, pkg, installLinks, legacyPeerDeps })
1295+
this.#linkNodes.add(link)
1296+
return link
12991297
}
13001298

13011299
// load all peer deps and meta-peer deps into the node's parent

workspaces/arborist/lib/arborist/load-actual.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
const { relative, dirname, resolve, join, normalize } = require('node:path')
44

5-
const rpj = require('read-package-json-fast')
5+
const PackageJson = require('@npmcli/package-json')
66
const { readdirScoped } = require('@npmcli/fs')
77
const { walkUp } = require('walk-up-path')
88
const ancestorPath = require('common-ancestor-path')
@@ -279,7 +279,7 @@ module.exports = cls => class ActualLoader extends cls {
279279
}
280280

281281
try {
282-
const pkg = await rpj(join(real, 'package.json'))
282+
const { content: pkg } = await PackageJson.normalize(real)
283283
params.pkg = pkg
284284
if (useRootOverrides && root.overrides) {
285285
params.overrides = root.overrides.getNodeRule({ name: pkg.name, version: pkg.version })

workspaces/arborist/lib/arborist/load-virtual.js

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1+
const { resolve } = require('node:path')
12
// mixin providing the loadVirtual method
23
const mapWorkspaces = require('@npmcli/map-workspaces')
3-
4-
const { resolve } = require('node:path')
5-
4+
const PackageJson = require('@npmcli/package-json')
65
const nameFromFolder = require('@npmcli/name-from-folder')
6+
77
const consistentResolve = require('../consistent-resolve.js')
88
const Shrinkwrap = require('../shrinkwrap.js')
99
const Node = require('../node.js')
1010
const Link = require('../link.js')
1111
const relpath = require('../relpath.js')
1212
const calcDepFlags = require('../calc-dep-flags.js')
13-
const rpj = require('read-package-json-fast')
1413
const treeCheck = require('../tree-check.js')
1514

1615
const flagsSuspect = Symbol.for('flagsSuspect')
@@ -54,23 +53,18 @@ module.exports = cls => class VirtualLoader extends cls {
5453

5554
// when building the ideal tree, we pass in a root node to this function
5655
// otherwise, load it from the root package json or the lockfile
56+
const pkg = await PackageJson.normalize(this.path).then(p => p.content).catch(() => s.data.packages[''] || {})
57+
// TODO clean this up
5758
const {
58-
root = await this.#loadRoot(s),
59+
root = await this[setWorkspaces](this.#loadNode('', pkg, true))
5960
} = options
60-
6161
this.#rootOptionProvided = options.root
6262

6363
await this.#loadFromShrinkwrap(s, root)
6464
root.assertRootOverrides()
6565
return treeCheck(this.virtualTree)
6666
}
6767

68-
async #loadRoot (s) {
69-
const pj = this.path + '/package.json'
70-
const pkg = await rpj(pj).catch(() => s.data.packages['']) || {}
71-
return this[setWorkspaces](this.#loadNode('', pkg, true))
72-
}
73-
7468
async #loadFromShrinkwrap (s, root) {
7569
if (!this.#rootOptionProvided) {
7670
// root is never any of these things, but might be a brand new
@@ -219,11 +213,7 @@ To fix:
219213
// we always need to read the package.json for link targets
220214
// outside node_modules because they can be changed by the local user
221215
if (!link.target.parent) {
222-
const pj = link.realpath + '/package.json'
223-
const pkg = await rpj(pj).catch(() => null)
224-
if (pkg) {
225-
link.target.package = pkg
226-
}
216+
await PackageJson.normalize(link.realpath).then(p => link.target.package = p.content).catch(() => null)
227217
}
228218
}
229219
}

workspaces/arborist/lib/arborist/rebuild.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
11
// Arborist.rebuild({path = this.path}) will do all the binlinks and
22
// bundle building needed. Called by reify, and by `npm rebuild`.
33

4+
const PackageJson = require('@npmcli/package-json')
5+
const binLinks = require('bin-links')
46
const localeCompare = require('@isaacs/string-locale-compare')('en')
5-
const { depth: dfwalk } = require('treeverse')
67
const promiseAllRejectLate = require('promise-all-reject-late')
7-
const rpj = require('read-package-json-fast')
8-
const binLinks = require('bin-links')
98
const runScript = require('@npmcli/run-script')
109
const { callLimit: promiseCallLimit } = require('promise-call-limit')
11-
const { resolve } = require('node:path')
10+
const { depth: dfwalk } = require('treeverse')
1211
const { isNodeGypPackage, defaultGypInstallScript } = require('@npmcli/node-gyp')
1312
const { log, time } = require('proc-log')
13+
const { resolve } = require('node:path')
1414

1515
const boolEnv = b => b ? '1' : ''
16-
const sortNodes = (a, b) =>
17-
(a.depth - b.depth) || localeCompare(a.path, b.path)
16+
const sortNodes = (a, b) => (a.depth - b.depth) || localeCompare(a.path, b.path)
1817

1918
const _checkBins = Symbol.for('checkBins')
2019

@@ -250,7 +249,7 @@ module.exports = cls => class Builder extends cls {
250249
// add to the set then remove while we're reading the pj, so we
251250
// don't accidentally hit it multiple times.
252251
set.add(node)
253-
const pkg = await rpj(node.path + '/package.json').catch(() => ({}))
252+
const { content: pkg } = await PackageJson.normalize(node.path).catch(() => { return { content: {} } })
254253
set.delete(node)
255254

256255
const { scripts = {} } = pkg

workspaces/arborist/lib/arborist/reify.js

Lines changed: 23 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,33 @@
11
// mixin implementing the reify method
2-
const onExit = require('../signal-handling.js')
3-
const pacote = require('pacote')
4-
const AuditReport = require('../audit-report.js')
5-
const { subset, intersects } = require('semver')
6-
const npa = require('npm-package-arg')
7-
const semver = require('semver')
8-
const debug = require('../debug.js')
9-
const { walkUp } = require('walk-up-path')
10-
const { log, time } = require('proc-log')
11-
const rpj = require('read-package-json-fast')
12-
const hgi = require('hosted-git-info')
13-
14-
const { dirname, resolve, relative, join } = require('node:path')
15-
const { depth: dfwalk } = require('treeverse')
16-
const {
17-
lstat,
18-
mkdir,
19-
rm,
20-
symlink,
21-
} = require('node:fs/promises')
22-
const { moveFile } = require('@npmcli/fs')
232
const PackageJson = require('@npmcli/package-json')
3+
const hgi = require('hosted-git-info')
4+
const npa = require('npm-package-arg')
245
const packageContents = require('@npmcli/installed-package-contents')
6+
const pacote = require('pacote')
7+
const promiseAllRejectLate = require('promise-all-reject-late')
258
const runScript = require('@npmcli/run-script')
9+
const { callLimit: promiseCallLimit } = require('promise-call-limit')
2610
const { checkEngine, checkPlatform } = require('npm-install-checks')
11+
const { depth: dfwalk } = require('treeverse')
12+
const { dirname, resolve, relative, join } = require('node:path')
13+
const { log, time } = require('proc-log')
14+
const { lstat, mkdir, rm, symlink, } = require('node:fs/promises')
15+
const { moveFile } = require('@npmcli/fs')
16+
const { subset, intersects } = require('semver')
17+
const { walkUp } = require('walk-up-path')
2718

28-
const treeCheck = require('../tree-check.js')
29-
const relpath = require('../relpath.js')
19+
const AuditReport = require('../audit-report.js')
3020
const Diff = require('../diff.js')
31-
const retirePath = require('../retire-path.js')
32-
const promiseAllRejectLate = require('promise-all-reject-late')
33-
const { callLimit: promiseCallLimit } = require('promise-call-limit')
34-
const optionalSet = require('../optional-set.js')
3521
const calcDepFlags = require('../calc-dep-flags.js')
22+
const debug = require('../debug.js')
23+
const onExit = require('../signal-handling.js')
24+
const optionalSet = require('../optional-set.js')
25+
const relpath = require('../relpath.js')
26+
const retirePath = require('../retire-path.js')
27+
const treeCheck = require('../tree-check.js')
28+
const { defaultLockfileVersion } = require('../shrinkwrap.js')
3629
const { saveTypeMap, hasSubKey } = require('../add-rm-pkg-deps.js')
3730

38-
const Shrinkwrap = require('../shrinkwrap.js')
39-
const { defaultLockfileVersion } = Shrinkwrap
40-
4131
// Part of steps (steps need refactoring before we can do anything about these)
4232
const _retireShallowNodes = Symbol.for('retireShallowNodes')
4333
const _loadBundlesAndUpdateTrees = Symbol.for('loadBundlesAndUpdateTrees')
@@ -803,7 +793,7 @@ module.exports = cls => class Reifier extends cls {
803793
})
804794
// store nodes don't use Node class so node.package doesn't get updated
805795
if (node.isInStore) {
806-
const pkg = await rpj(join(node.path, 'package.json'))
796+
const { content: pkg } = await PackageJson.normalize(node.path)
807797
node.package.scripts = pkg.scripts
808798
}
809799
return
@@ -1432,8 +1422,7 @@ module.exports = cls => class Reifier extends cls {
14321422
if (options.saveType) {
14331423
const depType = saveTypeMap.get(options.saveType)
14341424
pkg[depType][name] = newSpec
1435-
// rpj will have moved it here if it was in both
1436-
// if it is empty it will be deleted later
1425+
// PackageJson.normalize will have moved it here if it was in both, if it is empty it will be deleted later
14371426
if (options.saveType === 'prod' && pkg.optionalDependencies) {
14381427
delete pkg.optionalDependencies[name]
14391428
}
@@ -1474,7 +1463,7 @@ module.exports = cls => class Reifier extends cls {
14741463
const exactVersion = node => {
14751464
for (const edge of node.edgesIn) {
14761465
try {
1477-
if (semver.subset(edge.spec, node.version)) {
1466+
if (subset(edge.spec, node.version)) {
14781467
return false
14791468
}
14801469
} catch {

workspaces/arborist/lib/node.js

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,28 @@
2828
// where we need to quickly find all instances of a given package name within a
2929
// tree.
3030

31-
const semver = require('semver')
31+
const PackageJson = require('@npmcli/package-json')
3232
const nameFromFolder = require('@npmcli/name-from-folder')
33+
const npa = require('npm-package-arg')
34+
const semver = require('semver')
35+
const util = require('node:util')
36+
const { getPaths: getBinPaths } = require('bin-links')
37+
const { log } = require('proc-log')
38+
const { resolve, relative, dirname, basename } = require('node:path')
39+
const { walkUp } = require('walk-up-path')
40+
41+
const CaseInsensitiveMap = require('./case-insensitive-map.js')
3342
const Edge = require('./edge.js')
3443
const Inventory = require('./inventory.js')
3544
const OverrideSet = require('./override-set.js')
36-
const { normalize } = require('read-package-json-fast')
37-
const { getPaths: getBinPaths } = require('bin-links')
38-
const npa = require('npm-package-arg')
45+
const consistentResolve = require('./consistent-resolve.js')
3946
const debug = require('./debug.js')
4047
const gatherDepSet = require('./gather-dep-set.js')
48+
const printableTree = require('./printable.js')
49+
const querySelectorAll = require('./query-selector-all.js')
50+
const relpath = require('./relpath.js')
4151
const treeCheck = require('./tree-check.js')
42-
const { walkUp } = require('walk-up-path')
43-
const { log } = require('proc-log')
4452

45-
const { resolve, relative, dirname, basename } = require('node:path')
46-
const util = require('node:util')
4753
const _package = Symbol('_package')
4854
const _parent = Symbol('_parent')
4955
const _target = Symbol.for('_target')
@@ -58,13 +64,6 @@ const _delistFromMeta = Symbol.for('_delistFromMeta')
5864
const _explain = Symbol('_explain')
5965
const _explanation = Symbol('_explanation')
6066

61-
const relpath = require('./relpath.js')
62-
const consistentResolve = require('./consistent-resolve.js')
63-
64-
const printableTree = require('./printable.js')
65-
const CaseInsensitiveMap = require('./case-insensitive-map.js')
66-
67-
const querySelectorAll = require('./query-selector-all.js')
6867

6968
class Node {
7069
#global
@@ -121,14 +120,25 @@ class Node {
121120
// package's dependencies in a virtual root.
122121
this.sourceReference = sourceReference
123122

124-
// TODO if this came from pacote.manifest we don't have to do this,
125-
// we can be told to skip this step
126-
const pkg = sourceReference ? sourceReference.package
127-
: normalize(options.pkg || {})
123+
// have to set the internal package ref before assigning the parent, because this.package is read when adding to inventory
124+
if (sourceReference) {
125+
this[_package] = sourceReference.package
126+
} else {
127+
// TODO if this came from pacote.manifest we don't have to do this, we can be told to skip this step
128+
const pkg = new PackageJson()
129+
let content = {}
130+
// TODO this is overly guarded. If pkg is not an object we should not allow it at all.
131+
if (options.pkg && typeof options.pkg === 'object') {
132+
content = options.pkg
133+
}
134+
pkg.fromContent(content)
135+
pkg.syncNormalize()
136+
this[_package] = pkg.content
137+
}
128138

129139
this.name = name ||
130-
nameFromFolder(path || pkg.name || realpath) ||
131-
pkg.name ||
140+
nameFromFolder(path || this.package.name || realpath) ||
141+
this.package.name ||
132142
null
133143

134144
// should be equal if not a link
@@ -156,13 +166,13 @@ class Node {
156166
// probably what we're getting from pacote, which IS trustworthy.
157167
//
158168
// Otherwise, hopefully a shrinkwrap will help us out.
159-
const resolved = consistentResolve(pkg._resolved)
160-
if (resolved && !(/^file:/.test(resolved) && pkg._where)) {
169+
const resolved = consistentResolve(this.package._resolved)
170+
if (resolved && !(/^file:/.test(resolved) && this.package._where)) {
161171
this.resolved = resolved
162172
}
163173
}
164-
this.integrity = integrity || pkg._integrity || null
165-
this.hasShrinkwrap = hasShrinkwrap || pkg._hasShrinkwrap || false
174+
this.integrity = integrity || this.package._integrity || null
175+
this.hasShrinkwrap = hasShrinkwrap || this.package._hasShrinkwrap || false
166176
this.installLinks = installLinks
167177
this.legacyPeerDeps = legacyPeerDeps
168178

@@ -203,17 +213,13 @@ class Node {
203213
this.edgesIn = new Set()
204214
this.edgesOut = new CaseInsensitiveMap()
205215

206-
// have to set the internal package ref before assigning the parent,
207-
// because this.package is read when adding to inventory
208-
this[_package] = pkg && typeof pkg === 'object' ? pkg : {}
209-
210216
if (overrides) {
211217
this.overrides = overrides
212218
} else if (loadOverrides) {
213-
const overrides = this[_package].overrides || {}
219+
const overrides = this.package.overrides || {}
214220
if (Object.keys(overrides).length > 0) {
215221
this.overrides = new OverrideSet({
216-
overrides: this[_package].overrides,
222+
overrides: this.package.overrides,
217223
})
218224
}
219225
}
@@ -314,7 +320,7 @@ class Node {
314320
}
315321

316322
return getBinPaths({
317-
pkg: this[_package],
323+
pkg: this.package,
318324
path: this.path,
319325
global: this.global,
320326
top: this.globalTop,
@@ -328,11 +334,11 @@ class Node {
328334
}
329335

330336
get version () {
331-
return this[_package].version || ''
337+
return this.package.version || ''
332338
}
333339

334340
get packageName () {
335-
return this[_package].name || null
341+
return this.package.name || null
336342
}
337343

338344
get pkgid () {

0 commit comments

Comments
 (0)