Skip to content

Commit d438d61

Browse files
committed
feat(arborist): refactor arborist bin to use consistent timing/logging
This attempts to make the arborist bin script behave more like the npm cli with regards to the handing of timing and logging. It also adds the a `logfile` argument to write logs to a file instead of (or in addition to) stderr. This can be helpful for benchmarking performance of loggins or terminal display.
1 parent ce1c2bf commit d438d61

17 files changed

Lines changed: 490 additions & 359 deletions

package-lock.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10434,6 +10434,7 @@
1043410434
"json-stringify-nice": "^1.1.4",
1043510435
"mkdirp": "^1.0.4",
1043610436
"mkdirp-infer-owner": "^2.0.0",
10437+
"nopt": "^5.0.0",
1043710438
"npm-install-checks": "^4.0.0",
1043810439
"npm-package-arg": "^9.0.0",
1043910440
"npm-pick-manifest": "^7.0.0",
@@ -11353,6 +11354,7 @@
1135311354
"mkdirp": "^1.0.4",
1135411355
"mkdirp-infer-owner": "^2.0.0",
1135511356
"nock": "^13.2.0",
11357+
"nopt": "^5.0.0",
1135611358
"npm-install-checks": "^4.0.0",
1135711359
"npm-package-arg": "^9.0.0",
1135811360
"npm-pick-manifest": "^7.0.0",

workspaces/arborist/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,3 +333,13 @@ pruning nodes from the tree.
333333

334334
Note: `devOptional` is only set in the shrinkwrap/package-lock file if
335335
_neither_ `dev` nor `optional` are set, as it would be redundant.
336+
337+
## BIN
338+
339+
Arborist ships with a cli that can be used to run arborist specific commands outside of the context of the npm CLI. This script is currently not part of the public API and is subject to breaking changes outside of major version bumps.
340+
341+
To see the usage run:
342+
343+
```
344+
npx @npmcli/arborist --help
345+
```

workspaces/arborist/bin/actual.js

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,19 @@
11
const Arborist = require('../')
2-
const print = require('./lib/print-tree.js')
3-
const options = require('./lib/options.js')
4-
require('./lib/logging.js')
5-
require('./lib/timers.js')
62

7-
const start = process.hrtime()
8-
new Arborist(options).loadActual(options).then(tree => {
9-
const end = process.hrtime(start)
10-
if (!process.argv.includes('--quiet')) {
11-
print(tree)
12-
}
3+
const printTree = require('./lib/print-tree.js')
134

14-
console.error(`read ${tree.inventory.size} deps in ${end[0] * 1000 + end[1] / 1e6}ms`)
15-
if (options.save) {
16-
tree.meta.save()
17-
}
18-
if (options.saveHidden) {
19-
tree.meta.hiddenLockfile = true
20-
tree.meta.filename = options.path + '/node_modules/.package-lock.json'
21-
tree.meta.save()
22-
}
23-
}).catch(er => console.error(er))
5+
module.exports = (options, time) => new Arborist(options)
6+
.loadActual(options)
7+
.then(time)
8+
.then(async ({ timing, result: tree }) => {
9+
printTree(tree)
10+
if (options.save) {
11+
await tree.meta.save()
12+
}
13+
if (options.saveHidden) {
14+
tree.meta.hiddenLockfile = true
15+
tree.meta.filename = options.path + '/node_modules/.package-lock.json'
16+
await tree.meta.save()
17+
}
18+
return `read ${tree.inventory.size} deps in ${timing.ms}`
19+
})

workspaces/arborist/bin/audit.js

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
const Arborist = require('../')
22

3-
const print = require('./lib/print-tree.js')
4-
const options = require('./lib/options.js')
5-
require('./lib/timers.js')
6-
require('./lib/logging.js')
3+
const printTree = require('./lib/print-tree.js')
4+
const log = require('./lib/logging.js')
75

86
const Vuln = require('../lib/vuln.js')
97
const printReport = report => {
108
for (const vuln of report.values()) {
11-
console.log(printVuln(vuln))
9+
log.info(printVuln(vuln))
1210
}
1311
if (report.topVulns.size) {
14-
console.log('\n# top-level vulnerabilities')
12+
log.info('\n# top-level vulnerabilities')
1513
for (const vuln of report.topVulns.values()) {
16-
console.log(printVuln(vuln))
14+
log.info(printVuln(vuln))
1715
}
1816
}
1917
}
@@ -33,22 +31,21 @@ const printVuln = vuln => {
3331

3432
const printAdvisory = a => `${a.title}${a.url ? ' ' + a.url : ''}`
3533

36-
const start = process.hrtime()
37-
process.emit('time', 'audit script')
38-
const arb = new Arborist(options)
39-
arb.audit(options).then(tree => {
40-
process.emit('timeEnd', 'audit script')
41-
const end = process.hrtime(start)
42-
if (options.fix) {
43-
print(tree)
44-
}
45-
if (!options.quiet) {
46-
printReport(arb.auditReport)
47-
}
48-
if (options.fix) {
49-
console.error(`resolved ${tree.inventory.size} deps in ${end[0] + end[1] / 1e9}s`)
50-
}
51-
if (tree.meta && options.save) {
52-
tree.meta.save()
53-
}
54-
}).catch(er => console.error(er))
34+
module.exports = (options, time) => {
35+
const arb = new Arborist(options)
36+
return arb
37+
.audit(options)
38+
.then(time)
39+
.then(async ({ timing, result: tree }) => {
40+
if (options.fix) {
41+
printTree(tree)
42+
}
43+
printReport(arb.auditReport)
44+
if (tree.meta && options.save) {
45+
await tree.meta.save()
46+
}
47+
return options.fix
48+
? `resolved ${tree.inventory.size} deps in ${timing.seconds}`
49+
: `done in ${timing.seconds}`
50+
})
51+
}

workspaces/arborist/bin/funding.js

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,38 @@
1-
const options = require('./lib/options.js')
2-
require('./lib/logging.js')
3-
require('./lib/timers.js')
4-
51
const Arborist = require('../')
6-
const a = new Arborist(options)
7-
const query = options._.shift()
8-
const start = process.hrtime()
9-
a.loadVirtual().then(tree => {
10-
// only load the actual tree if the virtual one doesn't have modern metadata
11-
if (!tree.meta || !(tree.meta.originalLockfileVersion >= 2)) {
12-
console.error('old metadata, load actual')
13-
throw 'load actual'
14-
} else {
15-
console.error('meta ok, return virtual tree')
16-
return tree
17-
}
18-
}).catch(() => a.loadActual()).then(tree => {
19-
const end = process.hrtime(start)
20-
if (!query) {
21-
for (const node of tree.inventory.values()) {
22-
if (node.package.funding) {
23-
console.log(node.name, node.location, node.package.funding)
2+
3+
const log = require('./lib/logging.js')
4+
5+
module.exports = (options, time) => {
6+
const query = options._.shift()
7+
const a = new Arborist(options)
8+
return a
9+
.loadVirtual()
10+
.then(tree => {
11+
// only load the actual tree if the virtual one doesn't have modern metadata
12+
if (!tree.meta || !(tree.meta.originalLockfileVersion >= 2)) {
13+
log.error('old metadata, load actual')
14+
throw 'load actual'
15+
} else {
16+
log.error('meta ok, return virtual tree')
17+
return tree
2418
}
25-
}
26-
} else {
27-
for (const node of tree.inventory.query('name', query)) {
28-
if (node.package.funding) {
29-
console.log(node.name, node.location, node.package.funding)
19+
})
20+
.catch(() => a.loadActual())
21+
.then(time)
22+
.then(({ timing, result: tree }) => {
23+
if (!query) {
24+
for (const node of tree.inventory.values()) {
25+
if (node.package.funding) {
26+
log.info(node.name, node.location, node.package.funding)
27+
}
28+
}
29+
} else {
30+
for (const node of tree.inventory.query('name', query)) {
31+
if (node.package.funding) {
32+
log.info(node.name, node.location, node.package.funding)
33+
}
34+
}
3035
}
31-
}
32-
}
33-
console.error(`read ${tree.inventory.size} deps in ${end[0] * 1000 + end[1] / 1e6}ms`)
34-
})
36+
return `read ${tree.inventory.size} deps in ${timing.ms}`
37+
})
38+
}

workspaces/arborist/bin/ideal.js

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,14 @@
11
const Arborist = require('../')
22

3-
const { inspect } = require('util')
4-
const options = require('./lib/options.js')
5-
const print = require('./lib/print-tree.js')
6-
require('./lib/logging.js')
7-
require('./lib/timers.js')
3+
const printTree = require('./lib/print-tree.js')
84

9-
const start = process.hrtime()
10-
new Arborist(options).buildIdealTree(options).then(tree => {
11-
const end = process.hrtime(start)
12-
print(tree)
13-
console.error(`resolved ${tree.inventory.size} deps in ${end[0] + end[1] / 10e9}s`)
14-
if (tree.meta && options.save) {
15-
tree.meta.save()
16-
}
17-
}).catch(er => {
18-
const opt = { depth: Infinity, color: true }
19-
console.error(er.code === 'ERESOLVE' ? inspect(er, opt) : er)
20-
process.exitCode = 1
21-
})
5+
module.exports = (options, time) => new Arborist(options)
6+
.buildIdealTree(options)
7+
.then(time)
8+
.then(async ({ timing, result: tree }) => {
9+
printTree(tree)
10+
if (tree.meta && options.save) {
11+
await tree.meta.save()
12+
}
13+
return `resolved ${tree.inventory.size} deps in ${timing.seconds}`
14+
})

0 commit comments

Comments
 (0)