• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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