pack.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. const util = require('util')
  2. const log = require('npmlog')
  3. const pacote = require('pacote')
  4. const libpack = require('libnpmpack')
  5. const npa = require('npm-package-arg')
  6. const path = require('path')
  7. const { getContents, logTar } = require('./utils/tar.js')
  8. const writeFile = util.promisify(require('fs').writeFile)
  9. const BaseCommand = require('./base-command.js')
  10. class Pack extends BaseCommand {
  11. /* istanbul ignore next - see test/lib/load-all-commands.js */
  12. static get description () {
  13. return 'Create a tarball from a package'
  14. }
  15. /* istanbul ignore next - see test/lib/load-all-commands.js */
  16. static get name () {
  17. return 'pack'
  18. }
  19. /* istanbul ignore next - see test/lib/load-all-commands.js */
  20. static get params () {
  21. return [
  22. 'dry-run',
  23. 'json',
  24. 'pack-destination',
  25. 'workspace',
  26. 'workspaces',
  27. 'include-workspace-root',
  28. ]
  29. }
  30. /* istanbul ignore next - see test/lib/load-all-commands.js */
  31. static get usage () {
  32. return ['[[<@scope>/]<pkg>...]']
  33. }
  34. exec (args, cb) {
  35. this.pack(args).then(() => cb()).catch(cb)
  36. }
  37. execWorkspaces (args, filters, cb) {
  38. this.packWorkspaces(args, filters).then(() => cb()).catch(cb)
  39. }
  40. async pack (args) {
  41. if (args.length === 0)
  42. args = ['.']
  43. const unicode = this.npm.config.get('unicode')
  44. const dryRun = this.npm.config.get('dry-run')
  45. const json = this.npm.config.get('json')
  46. // Get the manifests and filenames first so we can bail early on manifest
  47. // errors before making any tarballs
  48. const manifests = []
  49. for (const arg of args) {
  50. const spec = npa(arg)
  51. const manifest = await pacote.manifest(spec, this.npm.flatOptions)
  52. if (!manifest._id)
  53. throw new Error('Invalid package, must have name and version')
  54. const filename = `${manifest.name}-${manifest.version}.tgz`
  55. .replace(/^@/, '').replace(/\//, '-')
  56. manifests.push({ arg, filename, manifest })
  57. }
  58. // Load tarball names up for printing afterward to isolate from the
  59. // noise generated during packing
  60. const tarballs = []
  61. for (const { arg, filename, manifest } of manifests) {
  62. const tarballData = await libpack(arg, this.npm.flatOptions)
  63. const pkgContents = await getContents(manifest, tarballData)
  64. const tarballFilename = path.resolve(this.npm.config.get('pack-destination'), filename)
  65. if (!dryRun)
  66. await writeFile(tarballFilename, tarballData)
  67. tarballs.push(pkgContents)
  68. }
  69. if (json) {
  70. this.npm.output(JSON.stringify(tarballs, null, 2))
  71. return
  72. }
  73. for (const tar of tarballs) {
  74. logTar(tar, { log, unicode })
  75. this.npm.output(tar.filename.replace(/^@/, '').replace(/\//, '-'))
  76. }
  77. }
  78. async packWorkspaces (args, filters) {
  79. // If they either ask for nothing, or explicitly include '.' in the args,
  80. // we effectively translate that into each workspace requested
  81. const useWorkspaces = args.length === 0 || args.includes('.')
  82. if (!useWorkspaces) {
  83. this.npm.log.warn('Ignoring workspaces for specified package(s)')
  84. return this.pack(args)
  85. }
  86. await this.setWorkspaces(filters)
  87. return this.pack([...this.workspacePaths, ...args.filter(a => a !== '.')])
  88. }
  89. }
  90. module.exports = Pack