codekingpro/portable-devtools
114k
1const { resolve } = require('node:path')
2const { output } = require('proc-log')
3const npa = require('npm-package-arg')
4const semver = require('semver')
5const ArboristWorkspaceCmd = require('../arborist-cmd.js')
6
7class Rebuild extends ArboristWorkspaceCmd {
8 static description = 'Rebuild a package'
9 static name = 'rebuild'
10 static params = [
11 'global',
12 'bin-links',
13 'foreground-scripts',
14 'ignore-scripts',
15 ...super.params,
16 ]
17
18 static usage = ['[<package-spec>] ...]']
19
20 static async completion (opts, npm) {
21 const completion = require('../utils/installed-deep.js')
22 return completion(npm, opts)
23 }
24
25 async exec (args) {
26 const globalTop = resolve(this.npm.globalDir, '..')
27 const where = this.npm.global ? globalTop : this.npm.prefix
28 const Arborist = require('@npmcli/arborist')
29 const arb = new Arborist({
30 ...this.npm.flatOptions,
31 path: where,
32 // TODO when extending ReifyCmd
33 // workspaces: this.workspaceNames,
34 })
35
36 if (args.length) {
37 // get the set of nodes matching the name that we want rebuilt
38 const tree = await arb.loadActual()
39 const specs = args.map(arg => {
40 const spec = npa(arg)
41 if (spec.rawSpec === '*') {
42 return spec
43 }
44
45 if (spec.type !== 'range' && spec.type !== 'version' && spec.type !== 'directory') {
46 throw new Error('`npm rebuild` only supports SemVer version/range specifiers')
47 }
48
49 return spec
50 })
51 const nodes = tree.inventory.filter(node => this.isNode(specs, node))
52
53 await arb.rebuild({ nodes })
54 } else {
55 await arb.rebuild()
56 }
57
58 output.standard('rebuilt dependencies successfully')
59 }
60
61 isNode (specs, node) {
62 return specs.some(spec => {
63 if (spec.type === 'directory') {
64 return node.path === spec.fetchSpec
65 }
66
67 if (spec.name !== node.name) {
68 return false
69 }
70
71 if (spec.rawSpec === '' || spec.rawSpec === '*') {
72 return true
73 }
74
75 const { version } = node.package
76 // TODO: add tests for a package with missing version
77 return semver.satisfies(version, spec.fetchSpec)
78 })
79 }
80}
81
82module.exports = Rebuild
83 