directory.js 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. 'use strict'
  2. const BB = require('bluebird')
  3. const Fetcher = require('../fetch')
  4. const glob = BB.promisify(require('glob'))
  5. const packDir = require('../util/pack-dir')
  6. const readJson = require('../util/read-json')
  7. const path = require('path')
  8. const pipe = BB.promisify(require('mississippi').pipe)
  9. const through = require('mississippi').through
  10. const readFileAsync = BB.promisify(require('fs').readFile)
  11. const fetchDirectory = module.exports = Object.create(null)
  12. Fetcher.impl(fetchDirectory, {
  13. packument (spec, opts) {
  14. return this.manifest(spec, opts).then(manifest => {
  15. return Object.assign({}, manifest, {
  16. 'dist-tags': {
  17. 'latest': manifest.version
  18. },
  19. time: {
  20. [manifest.version]: (new Date()).toISOString()
  21. },
  22. versions: {
  23. [manifest.version]: manifest
  24. }
  25. })
  26. })
  27. },
  28. // `directory` manifests come from the actual manifest/lockfile data.
  29. manifest (spec, opts) {
  30. const pkgPath = path.join(spec.fetchSpec, 'package.json')
  31. const srPath = path.join(spec.fetchSpec, 'npm-shrinkwrap.json')
  32. return BB.join(
  33. readFileAsync(pkgPath).then(readJson).catch({ code: 'ENOENT' }, err => {
  34. err.code = 'ENOPACKAGEJSON'
  35. throw err
  36. }),
  37. readFileAsync(srPath).then(readJson).catch({ code: 'ENOENT' }, () => null),
  38. (pkg, sr) => {
  39. pkg._shrinkwrap = sr
  40. pkg._hasShrinkwrap = !!sr
  41. pkg._resolved = spec.fetchSpec
  42. pkg._integrity = false // Don't auto-calculate integrity
  43. pkg._shasum = false // Don't auto-calculate shasum either
  44. return pkg
  45. }
  46. ).then(pkg => {
  47. if (!pkg.bin && pkg.directories && pkg.directories.bin) {
  48. const dirBin = pkg.directories.bin
  49. return glob(path.join(spec.fetchSpec, dirBin, '/**'), { nodir: true }).then(matches => {
  50. matches.forEach(filePath => {
  51. const relative = path.relative(spec.fetchSpec, filePath)
  52. if (relative && relative[0] !== '.') {
  53. if (!pkg.bin) { pkg.bin = {} }
  54. pkg.bin[path.basename(relative)] = relative
  55. }
  56. })
  57. }).then(() => pkg)
  58. } else {
  59. return pkg
  60. }
  61. })
  62. },
  63. // As of npm@5, the npm installer doesn't pack + install directories: it just
  64. // creates symlinks. This code is here because `npm pack` still needs the
  65. // ability to create a tarball from a local directory.
  66. tarball (spec, opts) {
  67. const stream = through()
  68. this.manifest(spec, opts).then(mani => {
  69. return pipe(this.fromManifest(mani, spec, opts), stream)
  70. }).catch(err => stream.emit('error', err))
  71. return stream
  72. },
  73. // `directory` tarballs are generated in a very similar way to git tarballs.
  74. fromManifest (manifest, spec, opts) {
  75. const stream = through()
  76. packDir(manifest, manifest._resolved, manifest._resolved, stream, opts).catch(err => {
  77. stream.emit('error', err)
  78. })
  79. return stream
  80. }
  81. })