• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict'
2
3const BB = require('bluebird')
4
5const cacache = require('cacache')
6const Fetcher = require('../fetch')
7const fs = require('fs')
8const pipe = BB.promisify(require('mississippi').pipe)
9const through = require('mississippi').through
10
11const readFileAsync = BB.promisify(fs.readFile)
12const statAsync = BB.promisify(fs.stat)
13
14const MAX_BULK_SIZE = 2 * 1024 * 1024 // 2MB
15
16// `file` packages refer to local tarball files.
17const fetchFile = module.exports = Object.create(null)
18
19Fetcher.impl(fetchFile, {
20  packument (spec, opts) {
21    return BB.reject(new Error('Not implemented yet'))
22  },
23
24  manifest (spec, opts) {
25    // We can't do much here. `finalizeManifest` will take care of
26    // calling `tarball` to fill out all the necessary details.
27    return BB.resolve(null)
28  },
29
30  // All the heavy lifting for `file` packages is done here.
31  // They're never cached. We just read straight out of the file.
32  // TODO - maybe they *should* be cached?
33  tarball (spec, opts) {
34    const src = spec._resolved || spec.fetchSpec
35    const stream = through()
36    statAsync(src).then(stat => {
37      if (spec._resolved) { stream.emit('manifest', spec) }
38      if (stat.size <= MAX_BULK_SIZE) {
39        // YAY LET'S DO THING IN BULK
40        return readFileAsync(src).then(data => {
41          if (opts.cache) {
42            return cacache.put(
43              opts.cache, `pacote:tarball:file:${src}`, data, {
44                integrity: opts.integrity
45              }
46            ).then(integrity => ({ data, integrity }))
47          } else {
48            return { data }
49          }
50        }).then(info => {
51          if (info.integrity) { stream.emit('integrity', info.integrity) }
52          stream.write(info.data, () => {
53            stream.end()
54          })
55        })
56      } else {
57        let integrity
58        const cacheWriter = !opts.cache
59          ? BB.resolve(null)
60          : (pipe(
61            fs.createReadStream(src),
62            cacache.put.stream(opts.cache, `pacote:tarball:${src}`, {
63              integrity: opts.integrity
64            }).on('integrity', d => { integrity = d })
65          ))
66        return cacheWriter.then(() => {
67          if (integrity) { stream.emit('integrity', integrity) }
68          return pipe(fs.createReadStream(src), stream)
69        })
70      }
71    }).catch(err => stream.emit('error', err))
72    return stream
73  },
74
75  fromManifest (manifest, spec, opts) {
76    return this.tarball(manifest || spec, opts)
77  }
78})
79