• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict'
2
3const Collect = require('minipass-collect')
4const { Minipass } = require('minipass')
5const Pipeline = require('minipass-pipeline')
6
7const index = require('./entry-index')
8const memo = require('./memoization')
9const read = require('./content/read')
10
11async function getData (cache, key, opts = {}) {
12  const { integrity, memoize, size } = opts
13  const memoized = memo.get(cache, key, opts)
14  if (memoized && memoize !== false) {
15    return {
16      metadata: memoized.entry.metadata,
17      data: memoized.data,
18      integrity: memoized.entry.integrity,
19      size: memoized.entry.size,
20    }
21  }
22
23  const entry = await index.find(cache, key, opts)
24  if (!entry) {
25    throw new index.NotFoundError(cache, key)
26  }
27  const data = await read(cache, entry.integrity, { integrity, size })
28  if (memoize) {
29    memo.put(cache, entry, data, opts)
30  }
31
32  return {
33    data,
34    metadata: entry.metadata,
35    size: entry.size,
36    integrity: entry.integrity,
37  }
38}
39module.exports = getData
40
41async function getDataByDigest (cache, key, opts = {}) {
42  const { integrity, memoize, size } = opts
43  const memoized = memo.get.byDigest(cache, key, opts)
44  if (memoized && memoize !== false) {
45    return memoized
46  }
47
48  const res = await read(cache, key, { integrity, size })
49  if (memoize) {
50    memo.put.byDigest(cache, key, res, opts)
51  }
52  return res
53}
54module.exports.byDigest = getDataByDigest
55
56const getMemoizedStream = (memoized) => {
57  const stream = new Minipass()
58  stream.on('newListener', function (ev, cb) {
59    ev === 'metadata' && cb(memoized.entry.metadata)
60    ev === 'integrity' && cb(memoized.entry.integrity)
61    ev === 'size' && cb(memoized.entry.size)
62  })
63  stream.end(memoized.data)
64  return stream
65}
66
67function getStream (cache, key, opts = {}) {
68  const { memoize, size } = opts
69  const memoized = memo.get(cache, key, opts)
70  if (memoized && memoize !== false) {
71    return getMemoizedStream(memoized)
72  }
73
74  const stream = new Pipeline()
75  // Set all this up to run on the stream and then just return the stream
76  Promise.resolve().then(async () => {
77    const entry = await index.find(cache, key)
78    if (!entry) {
79      throw new index.NotFoundError(cache, key)
80    }
81
82    stream.emit('metadata', entry.metadata)
83    stream.emit('integrity', entry.integrity)
84    stream.emit('size', entry.size)
85    stream.on('newListener', function (ev, cb) {
86      ev === 'metadata' && cb(entry.metadata)
87      ev === 'integrity' && cb(entry.integrity)
88      ev === 'size' && cb(entry.size)
89    })
90
91    const src = read.readStream(
92      cache,
93      entry.integrity,
94      { ...opts, size: typeof size !== 'number' ? entry.size : size }
95    )
96
97    if (memoize) {
98      const memoStream = new Collect.PassThrough()
99      memoStream.on('collect', data => memo.put(cache, entry, data, opts))
100      stream.unshift(memoStream)
101    }
102    stream.unshift(src)
103    return stream
104  }).catch((err) => stream.emit('error', err))
105
106  return stream
107}
108
109module.exports.stream = getStream
110
111function getStreamDigest (cache, integrity, opts = {}) {
112  const { memoize } = opts
113  const memoized = memo.get.byDigest(cache, integrity, opts)
114  if (memoized && memoize !== false) {
115    const stream = new Minipass()
116    stream.end(memoized)
117    return stream
118  } else {
119    const stream = read.readStream(cache, integrity, opts)
120    if (!memoize) {
121      return stream
122    }
123
124    const memoStream = new Collect.PassThrough()
125    memoStream.on('collect', data => memo.put.byDigest(
126      cache,
127      integrity,
128      data,
129      opts
130    ))
131    return new Pipeline(stream, memoStream)
132  }
133}
134
135module.exports.stream.byDigest = getStreamDigest
136
137function info (cache, key, opts = {}) {
138  const { memoize } = opts
139  const memoized = memo.get(cache, key, opts)
140  if (memoized && memoize !== false) {
141    return Promise.resolve(memoized.entry)
142  } else {
143    return index.find(cache, key)
144  }
145}
146module.exports.info = info
147
148async function copy (cache, key, dest, opts = {}) {
149  const entry = await index.find(cache, key, opts)
150  if (!entry) {
151    throw new index.NotFoundError(cache, key)
152  }
153  await read.copy(cache, entry.integrity, dest, opts)
154  return {
155    metadata: entry.metadata,
156    size: entry.size,
157    integrity: entry.integrity,
158  }
159}
160
161module.exports.copy = copy
162
163async function copyByDigest (cache, key, dest, opts = {}) {
164  await read.copy(cache, key, dest, opts)
165  return key
166}
167
168module.exports.copy.byDigest = copyByDigest
169
170module.exports.hasContent = read.hasContent
171