@npmcli/arborist 2.2.9 → 2.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/lib/logging.js +10 -2
- package/bin/lib/options.js +7 -1
- package/bin/lib/timers.js +6 -2
- package/bin/virtual.js +2 -1
- package/lib/add-rm-pkg-deps.js +84 -82
- package/lib/arborist/build-ideal-tree.js +261 -73
- package/lib/arborist/index.js +4 -1
- package/lib/arborist/load-actual.js +28 -2
- package/lib/arborist/load-virtual.js +9 -6
- package/lib/arborist/rebuild.js +5 -4
- package/lib/arborist/reify.js +210 -49
- package/lib/audit-report.js +13 -6
- package/lib/debug.js +8 -1
- package/lib/diff.js +70 -11
- package/lib/index.js +1 -0
- package/lib/inventory.js +1 -1
- package/lib/link.js +13 -7
- package/lib/node.js +66 -24
- package/lib/printable.js +20 -2
- package/lib/shrinkwrap.js +5 -5
- package/lib/tree-check.js +46 -1
- package/lib/update-root-package-json.js +14 -2
- package/lib/vuln.js +3 -0
- package/package.json +5 -8
- package/lib/dep-spec.js +0 -43
package/bin/lib/logging.js
CHANGED
|
@@ -20,13 +20,21 @@ const levelMap = new Map(levels.reduce((set, level, index) => {
|
|
|
20
20
|
}, []))
|
|
21
21
|
|
|
22
22
|
const { inspect, format } = require('util')
|
|
23
|
+
const colors = process.stderr.isTTY
|
|
24
|
+
const magenta = colors ? msg => `\x1B[35m${msg}\x1B[39m` : m => m
|
|
23
25
|
if (loglevel !== 'silent') {
|
|
24
26
|
process.on('log', (level, ...args) => {
|
|
25
27
|
if (levelMap.get(level) < levelMap.get(loglevel))
|
|
26
28
|
return
|
|
27
|
-
const pref = `${process.pid} ${level} `
|
|
29
|
+
const pref = `${process.pid} ${magenta(level)} `
|
|
28
30
|
if (level === 'warn' && args[0] === 'ERESOLVE')
|
|
29
|
-
args[2] = inspect(args[2], { depth: 10 })
|
|
31
|
+
args[2] = inspect(args[2], { depth: 10, colors })
|
|
32
|
+
else {
|
|
33
|
+
args = args.map(a => {
|
|
34
|
+
return typeof a === 'string' ? a
|
|
35
|
+
: inspect(a, { depth: 10, colors })
|
|
36
|
+
})
|
|
37
|
+
}
|
|
30
38
|
const msg = pref + format(...args).trim().split('\n').join(`\n${pref}`)
|
|
31
39
|
console.error(msg)
|
|
32
40
|
})
|
package/bin/lib/options.js
CHANGED
|
@@ -33,7 +33,13 @@ for (const arg of process.argv.slice(2)) {
|
|
|
33
33
|
options.omit.push(arg.substr('--omit='.length))
|
|
34
34
|
} else if (/^--before=/.test(arg))
|
|
35
35
|
options.before = new Date(arg.substr('--before='.length))
|
|
36
|
-
else if (
|
|
36
|
+
else if (/^-w.+/.test(arg)) {
|
|
37
|
+
options.workspaces = options.workspaces || []
|
|
38
|
+
options.workspaces.push(arg.replace(/^-w/, ''))
|
|
39
|
+
} else if (/^--workspace=/.test(arg)) {
|
|
40
|
+
options.workspaces = options.workspaces || []
|
|
41
|
+
options.workspaces.push(arg.replace(/^--workspace=/, ''))
|
|
42
|
+
} else if (/^--[^=]+=/.test(arg)) {
|
|
37
43
|
const [key, ...v] = arg.replace(/^--/, '').split('=')
|
|
38
44
|
const val = v.join('=')
|
|
39
45
|
options[key] = val === 'false' ? false : val === 'true' ? true : val
|
package/bin/lib/timers.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const timers = Object.create(null)
|
|
2
|
+
const { format } = require('util')
|
|
2
3
|
|
|
3
4
|
process.on('time', name => {
|
|
4
5
|
if (timers[name])
|
|
@@ -6,17 +7,20 @@ process.on('time', name => {
|
|
|
6
7
|
timers[name] = process.hrtime()
|
|
7
8
|
})
|
|
8
9
|
|
|
10
|
+
const dim = process.stderr.isTTY ? msg => `\x1B[2m${msg}\x1B[22m` : m => m
|
|
11
|
+
const red = process.stderr.isTTY ? msg => `\x1B[31m${msg}\x1B[39m` : m => m
|
|
9
12
|
process.on('timeEnd', name => {
|
|
10
13
|
if (!timers[name])
|
|
11
14
|
throw new Error('timer not started! ' + name)
|
|
12
15
|
const res = process.hrtime(timers[name])
|
|
13
16
|
delete timers[name]
|
|
14
|
-
|
|
17
|
+
const msg = format(`${process.pid} ${name}`, res[0] * 1e3 + res[1] / 1e6)
|
|
18
|
+
console.error(dim(msg))
|
|
15
19
|
})
|
|
16
20
|
|
|
17
21
|
process.on('exit', () => {
|
|
18
22
|
for (const name of Object.keys(timers)) {
|
|
19
|
-
console.error('Dangling timer:
|
|
23
|
+
console.error(red('Dangling timer:'), name)
|
|
20
24
|
process.exitCode = 1
|
|
21
25
|
}
|
|
22
26
|
})
|
package/bin/virtual.js
CHANGED
|
@@ -8,7 +8,8 @@ require('./lib/timers.js')
|
|
|
8
8
|
const start = process.hrtime()
|
|
9
9
|
new Arborist(options).loadVirtual().then(tree => {
|
|
10
10
|
const end = process.hrtime(start)
|
|
11
|
-
|
|
11
|
+
if (!options.quiet)
|
|
12
|
+
print(tree)
|
|
12
13
|
if (options.save)
|
|
13
14
|
tree.meta.save()
|
|
14
15
|
console.error(`read ${tree.inventory.size} deps in ${end[0] * 1000 + end[1] / 1e6}ms`)
|
package/lib/add-rm-pkg-deps.js
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
1
|
// add and remove dependency specs to/from pkg manifest
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const others = new Set([
|
|
5
|
-
'dependencies',
|
|
6
|
-
'optionalDependencies',
|
|
7
|
-
'devDependencies',
|
|
8
|
-
'peerDependenciesMeta',
|
|
9
|
-
'peerDependencies',
|
|
10
|
-
])
|
|
11
|
-
|
|
12
|
-
switch (type) {
|
|
13
|
-
case 'prod':
|
|
14
|
-
others.delete('dependencies')
|
|
15
|
-
break
|
|
16
|
-
case 'dev':
|
|
17
|
-
others.delete('devDependencies')
|
|
18
|
-
others.delete('peerDependencies')
|
|
19
|
-
others.delete('peerDependenciesMeta')
|
|
20
|
-
break
|
|
21
|
-
case 'optional':
|
|
22
|
-
others.delete('optionalDependencies')
|
|
23
|
-
break
|
|
24
|
-
case 'peer':
|
|
25
|
-
case 'peerOptional':
|
|
26
|
-
others.delete('devDependencies')
|
|
27
|
-
others.delete('peerDependencies')
|
|
28
|
-
others.delete('peerDependenciesMeta')
|
|
29
|
-
break
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
for (const other of others)
|
|
33
|
-
deleteSubKey(pkg, other, name)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const add = ({pkg, add, saveBundle, saveType}) => {
|
|
3
|
+
const add = ({pkg, add, saveBundle, saveType, log}) => {
|
|
37
4
|
for (const spec of add)
|
|
38
|
-
addSingle({pkg, spec, saveBundle, saveType})
|
|
5
|
+
addSingle({pkg, spec, saveBundle, saveType, log})
|
|
39
6
|
|
|
40
7
|
return pkg
|
|
41
8
|
}
|
|
42
9
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
10
|
+
// Canonical source of both the map between saveType and where it correlates to
|
|
11
|
+
// in the package, and the names of all our dependencies attributes
|
|
12
|
+
const saveTypeMap = new Map([
|
|
13
|
+
['dev', 'devDependencies'],
|
|
14
|
+
['optional', 'optionalDependencies'],
|
|
15
|
+
['prod', 'dependencies'],
|
|
16
|
+
['peerOptional', 'peerDependencies'],
|
|
17
|
+
['peer', 'peerDependencies'],
|
|
18
|
+
])
|
|
46
19
|
|
|
20
|
+
const addSingle = ({pkg, spec, saveBundle, saveType, log}) => {
|
|
47
21
|
const { name, rawSpec } = spec
|
|
48
|
-
removeFromOthers(name, saveType, pkg)
|
|
49
|
-
const type = saveType === 'prod' ? 'dependencies'
|
|
50
|
-
: saveType === 'optional' ? 'optionalDependencies'
|
|
51
|
-
: saveType === 'peer' || saveType === 'peerOptional' ? 'peerDependencies'
|
|
52
|
-
: saveType === 'dev' ? 'devDependencies'
|
|
53
|
-
: /* istanbul ignore next */ null
|
|
54
22
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
23
|
+
// if the user does not give us a type, we infer which type(s)
|
|
24
|
+
// to keep based on the same order of priority we do when
|
|
25
|
+
// building the tree as defined in the _loadDeps method of
|
|
26
|
+
// the node class.
|
|
27
|
+
if (!saveType)
|
|
28
|
+
saveType = inferSaveType(pkg, spec.name)
|
|
29
|
+
|
|
30
|
+
if (saveType === 'prod') {
|
|
31
|
+
// a production dependency can only exist as production (rpj ensures it
|
|
32
|
+
// doesn't coexist w/ optional)
|
|
33
|
+
deleteSubKey(pkg, 'devDependencies', name, 'dependencies', log)
|
|
34
|
+
deleteSubKey(pkg, 'peerDependencies', name, 'dependencies', log)
|
|
35
|
+
} else if (saveType === 'dev') {
|
|
36
|
+
// a dev dependency may co-exist as peer, or optional, but not production
|
|
37
|
+
deleteSubKey(pkg, 'dependencies', name, 'devDependencies', log)
|
|
38
|
+
} else if (saveType === 'optional') {
|
|
39
|
+
// an optional dependency may co-exist as dev (rpj ensures it doesn't
|
|
40
|
+
// coexist w/ prod)
|
|
41
|
+
deleteSubKey(pkg, 'peerDependencies', name, 'optionalDependencies', log)
|
|
42
|
+
} else { // peer or peerOptional is all that's left
|
|
43
|
+
// a peer dependency may coexist as dev
|
|
44
|
+
deleteSubKey(pkg, 'dependencies', name, 'peerDependencies', log)
|
|
45
|
+
deleteSubKey(pkg, 'optionalDependencies', name, 'peerDependencies', log)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const depType = saveTypeMap.get(saveType)
|
|
49
|
+
|
|
50
|
+
pkg[depType] = pkg[depType] || {}
|
|
51
|
+
if (rawSpec !== '' || pkg[depType][name] === undefined)
|
|
52
|
+
pkg[depType][name] = rawSpec || '*'
|
|
53
|
+
if (saveType === 'optional') {
|
|
54
|
+
// Affordance for previous npm versions that require this behaviour
|
|
55
|
+
pkg.dependencies = pkg.dependencies || {}
|
|
56
|
+
pkg.dependencies[name] = pkg.optionalDependencies[name]
|
|
57
|
+
}
|
|
58
58
|
|
|
59
59
|
if (saveType === 'peer' || saveType === 'peerOptional') {
|
|
60
60
|
const pdm = pkg.peerDependenciesMeta || {}
|
|
@@ -79,47 +79,49 @@ const addSingle = ({pkg, spec, saveBundle, saveType}) => {
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
return 'peer'
|
|
97
|
-
} else if (devDeps && devDeps[name] !== undefined)
|
|
98
|
-
return 'dev'
|
|
99
|
-
else if (optDeps && optDeps[name] !== undefined)
|
|
100
|
-
return 'optional'
|
|
101
|
-
else
|
|
102
|
-
return 'prod'
|
|
82
|
+
// Finds where the package is already in the spec and infers saveType from that
|
|
83
|
+
const inferSaveType = (pkg, name) => {
|
|
84
|
+
for (const saveType of saveTypeMap.keys()) {
|
|
85
|
+
if (hasSubKey(pkg, saveTypeMap.get(saveType), name)) {
|
|
86
|
+
if (
|
|
87
|
+
saveType === 'peerOptional' &&
|
|
88
|
+
(!hasSubKey(pkg, 'peerDependenciesMeta', name) ||
|
|
89
|
+
!pkg.peerDependenciesMeta[name].optional)
|
|
90
|
+
)
|
|
91
|
+
return 'peer'
|
|
92
|
+
return saveType
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return 'prod'
|
|
103
96
|
}
|
|
104
97
|
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
98
|
+
const hasSubKey = (pkg, depType, name) => {
|
|
99
|
+
return pkg[depType] && Object.prototype.hasOwnProperty.call(pkg[depType], name)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Removes a subkey and warns about it if it's being replaced
|
|
103
|
+
const deleteSubKey = (pkg, depType, name, replacedBy, log) => {
|
|
104
|
+
if (hasSubKey(pkg, depType, name)) {
|
|
105
|
+
if (replacedBy && log)
|
|
106
|
+
log.warn('idealTree', `Removing ${depType}.${name} in favor of ${replacedBy}.${name}`)
|
|
107
|
+
delete pkg[depType][name]
|
|
108
|
+
|
|
109
|
+
// clean up peerDependenciesMeta if we are removing something from peerDependencies
|
|
110
|
+
if (depType === 'peerDependencies' && pkg.peerDependenciesMeta) {
|
|
111
|
+
delete pkg.peerDependenciesMeta[name]
|
|
112
|
+
if (!Object.keys(pkg.peerDependenciesMeta).length)
|
|
113
|
+
delete pkg.peerDependenciesMeta
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (!Object.keys(pkg[depType]).length)
|
|
117
|
+
delete pkg[depType]
|
|
110
118
|
}
|
|
111
119
|
}
|
|
112
120
|
|
|
113
121
|
const rm = (pkg, rm) => {
|
|
114
|
-
for (const
|
|
115
|
-
'dependencies',
|
|
116
|
-
'optionalDependencies',
|
|
117
|
-
'peerDependencies',
|
|
118
|
-
'peerDependenciesMeta',
|
|
119
|
-
'devDependencies',
|
|
120
|
-
]) {
|
|
122
|
+
for (const depType of new Set(saveTypeMap.values())) {
|
|
121
123
|
for (const name of rm)
|
|
122
|
-
deleteSubKey(pkg,
|
|
124
|
+
deleteSubKey(pkg, depType, name)
|
|
123
125
|
}
|
|
124
126
|
if (pkg.bundleDependencies) {
|
|
125
127
|
pkg.bundleDependencies = pkg.bundleDependencies
|
|
@@ -130,4 +132,4 @@ const rm = (pkg, rm) => {
|
|
|
130
132
|
return pkg
|
|
131
133
|
}
|
|
132
134
|
|
|
133
|
-
module.exports = { add, rm }
|
|
135
|
+
module.exports = { add, rm, saveTypeMap, hasSubKey }
|