[6a3a178] | 1 | const Fetcher = require('./fetcher.js')
|
---|
| 2 | const FileFetcher = require('./file.js')
|
---|
| 3 | const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved')
|
---|
| 4 | const pacoteVersion = require('../package.json').version
|
---|
| 5 | const fetch = require('npm-registry-fetch')
|
---|
| 6 | const ssri = require('ssri')
|
---|
| 7 | const Minipass = require('minipass')
|
---|
| 8 | // The default registry URL is a string of great magic.
|
---|
| 9 | const magic = /^https?:\/\/registry\.npmjs\.org\//
|
---|
| 10 |
|
---|
| 11 | const _cacheFetches = Symbol.for('pacote.Fetcher._cacheFetches')
|
---|
| 12 | const _headers = Symbol('_headers')
|
---|
| 13 | class RemoteFetcher extends Fetcher {
|
---|
| 14 | constructor (spec, opts) {
|
---|
| 15 | super(spec, opts)
|
---|
| 16 | this.resolved = this.spec.fetchSpec
|
---|
| 17 | if (magic.test(this.resolved) && !magic.test(this.registry + '/'))
|
---|
| 18 | this.resolved = this.resolved.replace(magic, this.registry + '/')
|
---|
| 19 |
|
---|
| 20 | // nam is a fermented pork sausage that is good to eat
|
---|
| 21 | const nameat = this.spec.name ? `${this.spec.name}@` : ''
|
---|
| 22 | this.pkgid = opts.pkgid ? opts.pkgid : `remote:${nameat}${this.resolved}`
|
---|
| 23 | }
|
---|
| 24 |
|
---|
| 25 | // Don't need to cache tarball fetches in pacote, because make-fetch-happen
|
---|
| 26 | // will write into cacache anyway.
|
---|
| 27 | get [_cacheFetches] () {
|
---|
| 28 | return false
|
---|
| 29 | }
|
---|
| 30 |
|
---|
| 31 | [_tarballFromResolved] () {
|
---|
| 32 | const stream = new Minipass()
|
---|
| 33 | const fetchOpts = {
|
---|
| 34 | ...this.opts,
|
---|
| 35 | headers: this[_headers](),
|
---|
| 36 | spec: this.spec,
|
---|
| 37 | integrity: this.integrity,
|
---|
| 38 | algorithms: [ this.pickIntegrityAlgorithm() ],
|
---|
| 39 | }
|
---|
| 40 | fetch(this.resolved, fetchOpts).then(res => {
|
---|
| 41 | const hash = res.headers.get('x-local-cache-hash')
|
---|
| 42 | if (hash) {
|
---|
| 43 | this.integrity = decodeURIComponent(hash)
|
---|
| 44 | }
|
---|
| 45 |
|
---|
| 46 | res.body.on('error',
|
---|
| 47 | /* istanbul ignore next - exceedingly rare and hard to simulate */
|
---|
| 48 | er => stream.emit('error', er)
|
---|
| 49 | ).pipe(stream)
|
---|
| 50 | }).catch(er => stream.emit('error', er))
|
---|
| 51 |
|
---|
| 52 | return stream
|
---|
| 53 | }
|
---|
| 54 |
|
---|
| 55 | [_headers] () {
|
---|
| 56 | return {
|
---|
| 57 | // npm will override this, but ensure that we always send *something*
|
---|
| 58 | 'user-agent': this.opts.userAgent ||
|
---|
| 59 | `pacote/${pacoteVersion} node/${process.version}`,
|
---|
| 60 | ...(this.opts.headers || {}),
|
---|
| 61 | 'pacote-version': pacoteVersion,
|
---|
| 62 | 'pacote-req-type': 'tarball',
|
---|
| 63 | 'pacote-pkg-id': this.pkgid,
|
---|
| 64 | ...(this.integrity ? { 'pacote-integrity': String(this.integrity) }
|
---|
| 65 | : {}),
|
---|
| 66 | ...(this.opts.headers || {}),
|
---|
| 67 | }
|
---|
| 68 | }
|
---|
| 69 |
|
---|
| 70 | get types () {
|
---|
| 71 | return ['remote']
|
---|
| 72 | }
|
---|
| 73 |
|
---|
| 74 | // getting a packument and/or manifest is the same as with a file: spec.
|
---|
| 75 | // unpack the tarball stream, and then read from the package.json file.
|
---|
| 76 | packument () {
|
---|
| 77 | return FileFetcher.prototype.packument.apply(this)
|
---|
| 78 | }
|
---|
| 79 |
|
---|
| 80 | manifest () {
|
---|
| 81 | return FileFetcher.prototype.manifest.apply(this)
|
---|
| 82 | }
|
---|
| 83 | }
|
---|
| 84 | module.exports = RemoteFetcher
|
---|