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