shrinkwrap.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. const { resolve, basename } = require('node:path')
  2. const { unlink } = require('node:fs/promises')
  3. const { log } = require('proc-log')
  4. const BaseCommand = require('../base-cmd.js')
  5. class Shrinkwrap extends BaseCommand {
  6. static description = 'Lock down dependency versions for publication'
  7. static name = 'shrinkwrap'
  8. static ignoreImplicitWorkspace = false
  9. async exec () {
  10. // if has a npm-shrinkwrap.json, nothing to do
  11. // if has a package-lock.json, rename to npm-shrinkwrap.json
  12. // if has neither, load the actual tree and save that as npm-shrinkwrap.json
  13. //
  14. // loadVirtual, fall back to loadActual
  15. // rename shrinkwrap file type, and tree.meta.save()
  16. if (this.npm.global) {
  17. const er = new Error('`npm shrinkwrap` does not work for global packages')
  18. er.code = 'ESHRINKWRAPGLOBAL'
  19. throw er
  20. }
  21. const Arborist = require('@npmcli/arborist')
  22. const path = this.npm.prefix
  23. const sw = resolve(path, 'npm-shrinkwrap.json')
  24. const arb = new Arborist({ ...this.npm.flatOptions, path })
  25. const tree = await arb.loadVirtual().catch(() => arb.loadActual())
  26. const { meta } = tree
  27. const newFile = meta.hiddenLockfile || !meta.loadedFromDisk
  28. const oldFilename = meta.filename
  29. const notSW = !newFile && basename(oldFilename) !== 'npm-shrinkwrap.json'
  30. // The computed lockfile version of a hidden lockfile is always 3 even if the actual value of the property is a different.
  31. // When shrinkwrap is run with only a hidden lockfile we want to set the shrinkwrap lockfile version as whatever was explicitly requested with a fallback to the actual value from the hidden
  32. // lockfile.
  33. if (meta.hiddenLockfile) {
  34. meta.lockfileVersion = arb.options.lockfileVersion ||
  35. meta.originalLockfileVersion
  36. }
  37. meta.hiddenLockfile = false
  38. meta.filename = sw
  39. await meta.save()
  40. const updatedVersion = meta.originalLockfileVersion !== meta.lockfileVersion
  41. ? meta.lockfileVersion
  42. : null
  43. if (newFile) {
  44. let message = 'created a lockfile as npm-shrinkwrap.json'
  45. if (updatedVersion) {
  46. message += ` with version ${updatedVersion}`
  47. }
  48. log.notice('', message)
  49. } else if (notSW) {
  50. await unlink(oldFilename)
  51. let message = 'package-lock.json has been renamed to npm-shrinkwrap.json'
  52. if (updatedVersion) {
  53. message += ` and updated to version ${updatedVersion}`
  54. }
  55. log.notice('', message)
  56. } else if (updatedVersion) {
  57. log.notice('', `npm-shrinkwrap.json updated to version ${updatedVersion}`)
  58. } else {
  59. log.notice('', 'npm-shrinkwrap.json up to date')
  60. }
  61. }
  62. }
  63. module.exports = Shrinkwrap