manifest.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. 'use strict'
  2. const fetch = require('npm-registry-fetch')
  3. const fetchPackument = require('./packument')
  4. const optCheck = require('../../util/opt-check')
  5. const pickManifest = require('npm-pick-manifest')
  6. const ssri = require('ssri')
  7. module.exports = manifest
  8. function manifest (spec, opts) {
  9. opts = optCheck(opts)
  10. return getManifest(spec, opts).then(manifest => {
  11. return annotateManifest(spec, manifest, opts)
  12. })
  13. }
  14. function getManifest (spec, opts) {
  15. opts = opts.concat({
  16. fullMetadata: opts.enjoyBy ? true : opts.fullMetadata
  17. })
  18. return fetchPackument(spec, opts).then(packument => {
  19. try {
  20. return pickManifest(packument, spec.fetchSpec, {
  21. defaultTag: opts.defaultTag,
  22. enjoyBy: opts.enjoyBy,
  23. includeDeprecated: opts.includeDeprecated
  24. })
  25. } catch (err) {
  26. if (err.code === 'ETARGET' && packument._cached && !opts.offline) {
  27. opts.log.silly(
  28. 'registry:manifest',
  29. `no matching version for ${spec.name}@${spec.fetchSpec} in the cache. Forcing revalidation.`
  30. )
  31. opts = opts.concat({
  32. preferOffline: false,
  33. preferOnline: true
  34. })
  35. return fetchPackument(spec, opts.concat({
  36. // Fetch full metadata in case ETARGET was due to corgi delay
  37. fullMetadata: true
  38. })).then(packument => {
  39. return pickManifest(packument, spec.fetchSpec, {
  40. defaultTag: opts.defaultTag,
  41. enjoyBy: opts.enjoyBy
  42. })
  43. })
  44. } else {
  45. throw err
  46. }
  47. }
  48. })
  49. }
  50. function annotateManifest (spec, manifest, opts) {
  51. const shasum = manifest.dist && manifest.dist.shasum
  52. manifest._integrity = manifest.dist && manifest.dist.integrity
  53. manifest._shasum = shasum
  54. if (!manifest._integrity && shasum) {
  55. // Use legacy dist.shasum field if available.
  56. manifest._integrity = ssri.fromHex(shasum, 'sha1').toString()
  57. }
  58. manifest._resolved = (
  59. manifest.dist && manifest.dist.tarball
  60. )
  61. if (!manifest._resolved) {
  62. const registry = fetch.pickRegistry(spec, opts)
  63. const uri = registry.replace(/\/?$/, '/') + spec.escapedName
  64. const err = new Error(
  65. `Manifest for ${manifest.name}@${manifest.version} from ${uri} is missing a tarball url (pkg.dist.tarball). Guessing a default.`
  66. )
  67. err.code = 'ENOTARBALL'
  68. err.manifest = manifest
  69. if (!manifest._warnings) { manifest._warnings = [] }
  70. manifest._warnings.push(err.message)
  71. manifest._resolved =
  72. `${registry}/${manifest.name}/-/${manifest.name}-${manifest.version}.tgz`
  73. }
  74. return manifest
  75. }