dir.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. const Fetcher = require('./fetcher.js')
  2. const FileFetcher = require('./file.js')
  3. const { Minipass } = require('minipass')
  4. const tarCreateOptions = require('./util/tar-create-options.js')
  5. const packlist = require('npm-packlist')
  6. const tar = require('tar')
  7. const _prepareDir = Symbol('_prepareDir')
  8. const { resolve } = require('path')
  9. const _readPackageJson = Symbol.for('package.Fetcher._readPackageJson')
  10. const runScript = require('@npmcli/run-script')
  11. const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved')
  12. class DirFetcher extends Fetcher {
  13. constructor (spec, opts) {
  14. super(spec, opts)
  15. // just the fully resolved filename
  16. this.resolved = this.spec.fetchSpec
  17. this.tree = opts.tree || null
  18. this.Arborist = opts.Arborist || null
  19. }
  20. // exposes tarCreateOptions as public API
  21. static tarCreateOptions (manifest) {
  22. return tarCreateOptions(manifest)
  23. }
  24. get types () {
  25. return ['directory']
  26. }
  27. [_prepareDir] () {
  28. return this.manifest().then(mani => {
  29. if (!mani.scripts || !mani.scripts.prepare) {
  30. return
  31. }
  32. // we *only* run prepare.
  33. // pre/post-pack is run by the npm CLI for publish and pack,
  34. // but this function is *also* run when installing git deps
  35. const stdio = this.opts.foregroundScripts ? 'inherit' : 'pipe'
  36. // hide the banner if silent opt is passed in, or if prepare running
  37. // in the background.
  38. const banner = this.opts.silent ? false : stdio === 'inherit'
  39. return runScript({
  40. pkg: mani,
  41. event: 'prepare',
  42. path: this.resolved,
  43. stdio,
  44. banner,
  45. env: {
  46. npm_package_resolved: this.resolved,
  47. npm_package_integrity: this.integrity,
  48. npm_package_json: resolve(this.resolved, 'package.json'),
  49. },
  50. })
  51. })
  52. }
  53. [_tarballFromResolved] () {
  54. if (!this.tree && !this.Arborist) {
  55. throw new Error('DirFetcher requires either a tree or an Arborist constructor to pack')
  56. }
  57. const stream = new Minipass()
  58. stream.resolved = this.resolved
  59. stream.integrity = this.integrity
  60. const { prefix, workspaces } = this.opts
  61. // run the prepare script, get the list of files, and tar it up
  62. // pipe to the stream, and proxy errors the chain.
  63. this[_prepareDir]()
  64. .then(async () => {
  65. if (!this.tree) {
  66. const arb = new this.Arborist({ path: this.resolved })
  67. this.tree = await arb.loadActual()
  68. }
  69. return packlist(this.tree, { path: this.resolved, prefix, workspaces })
  70. })
  71. .then(files => tar.c(tarCreateOptions(this.package), files)
  72. .on('error', er => stream.emit('error', er)).pipe(stream))
  73. .catch(er => stream.emit('error', er))
  74. return stream
  75. }
  76. manifest () {
  77. if (this.package) {
  78. return Promise.resolve(this.package)
  79. }
  80. return this[_readPackageJson](this.resolved + '/package.json')
  81. .then(mani => this.package = {
  82. ...mani,
  83. _integrity: this.integrity && String(this.integrity),
  84. _resolved: this.resolved,
  85. _from: this.from,
  86. })
  87. }
  88. packument () {
  89. return FileFetcher.prototype.packument.apply(this)
  90. }
  91. }
  92. module.exports = DirFetcher