(args)
| 31 | } |
| 32 | |
| 33 | async exec (args) { |
| 34 | const globalTop = resolve(this.npm.globalDir, '..') |
| 35 | const where = this.npm.global ? globalTop : this.npm.prefix |
| 36 | const Arborist = require('@npmcli/arborist') |
| 37 | const { policy: allowScriptsPolicy } = await resolveAllowScripts(this.npm) |
| 38 | const arb = new Arborist({ |
| 39 | ...this.npm.flatOptions, |
| 40 | path: where, |
| 41 | allowScripts: allowScriptsPolicy, |
| 42 | // TODO when extending ReifyCmd |
| 43 | // workspaces: this.workspaceNames, |
| 44 | }) |
| 45 | |
| 46 | if (args.length) { |
| 47 | // get the set of nodes matching the name that we want rebuilt |
| 48 | const tree = await arb.loadActual() |
| 49 | const specs = args.map(arg => { |
| 50 | const spec = npa(arg) |
| 51 | if (spec.rawSpec === '*') { |
| 52 | return spec |
| 53 | } |
| 54 | |
| 55 | if (spec.type !== 'range' && spec.type !== 'version' && spec.type !== 'directory') { |
| 56 | throw new Error('`npm rebuild` only supports SemVer version/range specifiers') |
| 57 | } |
| 58 | |
| 59 | return spec |
| 60 | }) |
| 61 | const nodes = [...tree.inventory.filter(node => this.isNode(specs, node))] |
| 62 | |
| 63 | await strictAllowScriptsPreflight({ arb, npm: this.npm }) |
| 64 | await arb.rebuild({ nodes }) |
| 65 | } else { |
| 66 | await arb.loadActual() |
| 67 | await strictAllowScriptsPreflight({ arb, npm: this.npm }) |
| 68 | await arb.rebuild() |
| 69 | } |
| 70 | |
| 71 | // Phase 1 advisory: list any packages whose install scripts ran (or |
| 72 | // would have run) and are not yet covered by allowScripts. Rebuild |
| 73 | // doesn't go through reifyFinish, so the walker is invoked here. |
| 74 | const unreviewed = await checkAllowScripts({ arb, npm: this.npm }) |
| 75 | if (unreviewed.length > 0) { |
| 76 | const count = unreviewed.length |
| 77 | const noun = count === 1 ? 'package has' : 'packages have' |
| 78 | // `npm approve-scripts` writes to a project package.json, which doesn't |
| 79 | // exist for global rebuilds. Point global users at `npm config set`, |
| 80 | // which writes the `allow-scripts` setting to their user .npmrc. |
| 81 | const names = unreviewed.map(({ node }) => trustedDisplay(node).name) |
| 82 | const remediation = this.npm.global |
| 83 | ? `Run \`${configSetAllowScripts(names)}\` to allow their scripts.` |
| 84 | : 'Run `npm approve-scripts --allow-scripts-pending` to review.' |
| 85 | log.warn( |
| 86 | 'rebuild', |
| 87 | `${count} ${noun} install scripts not yet covered by allowScripts. ` + |
| 88 | remediation |
| 89 | ) |
| 90 | } |
nothing calls this directly
no test coverage detected