rebuild.js 2.2 KB

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