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