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