shrinkwrap.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. const { resolve, basename } = require('path')
  2. const util = require('util')
  3. const fs = require('fs')
  4. const { unlink } = fs.promises || { unlink: util.promisify(fs.unlink) }
  5. const Arborist = require('@npmcli/arborist')
  6. const log = require('npmlog')
  7. const BaseCommand = require('./base-command.js')
  8. class Shrinkwrap extends BaseCommand {
  9. /* istanbul ignore next - see test/lib/load-all-commands.js */
  10. static get description () {
  11. return 'Lock down dependency versions for publication'
  12. }
  13. /* istanbul ignore next - see test/lib/load-all-commands.js */
  14. static get name () {
  15. return 'shrinkwrap'
  16. }
  17. exec (args, cb) {
  18. this.shrinkwrap().then(() => cb()).catch(cb)
  19. }
  20. async shrinkwrap () {
  21. // if has a npm-shrinkwrap.json, nothing to do
  22. // if has a package-lock.json, rename to npm-shrinkwrap.json
  23. // if has neither, load the actual tree and save that as npm-shrinkwrap.json
  24. // in all cases, re-cast to current lockfile version
  25. //
  26. // loadVirtual, fall back to loadActual
  27. // rename shrinkwrap file type, and tree.meta.save()
  28. if (this.npm.config.get('global')) {
  29. const er = new Error('`npm shrinkwrap` does not work for global packages')
  30. er.code = 'ESHRINKWRAPGLOBAL'
  31. throw er
  32. }
  33. const path = this.npm.prefix
  34. const sw = resolve(path, 'npm-shrinkwrap.json')
  35. const arb = new Arborist({ ...this.npm.flatOptions, path })
  36. const tree = await arb.loadVirtual().catch(() => arb.loadActual())
  37. const { meta } = tree
  38. const newFile = meta.hiddenLockfile || !meta.loadedFromDisk
  39. const oldFilename = meta.filename
  40. const notSW = !newFile && basename(oldFilename) !== 'npm-shrinkwrap.json'
  41. meta.hiddenLockfile = false
  42. meta.filename = sw
  43. await meta.save()
  44. if (newFile)
  45. log.notice('', 'created a lockfile as npm-shrinkwrap.json')
  46. else if (notSW) {
  47. await unlink(oldFilename)
  48. log.notice('', 'package-lock.json has been renamed to npm-shrinkwrap.json')
  49. } else if (meta.originalLockfileVersion !== this.npm.lockfileVersion)
  50. log.notice('', `npm-shrinkwrap.json updated to version ${this.npm.lockfileVersion}`)
  51. else
  52. log.notice('', 'npm-shrinkwrap.json up to date')
  53. }
  54. }
  55. module.exports = Shrinkwrap