1'use strict' 2 3const index = require('./entry-index') 4const memo = require('./memoization') 5const write = require('./content/write') 6const Flush = require('minipass-flush') 7const { PassThrough } = require('minipass-collect') 8const Pipeline = require('minipass-pipeline') 9 10const putOpts = (opts) => ({ 11 algorithms: ['sha512'], 12 ...opts, 13}) 14 15module.exports = putData 16 17async function putData (cache, key, data, opts = {}) { 18 const { memoize } = opts 19 opts = putOpts(opts) 20 const res = await write(cache, data, opts) 21 const entry = await index.insert(cache, key, res.integrity, { ...opts, size: res.size }) 22 if (memoize) { 23 memo.put(cache, entry, data, opts) 24 } 25 26 return res.integrity 27} 28 29module.exports.stream = putStream 30 31function putStream (cache, key, opts = {}) { 32 const { memoize } = opts 33 opts = putOpts(opts) 34 let integrity 35 let size 36 let error 37 38 let memoData 39 const pipeline = new Pipeline() 40 // first item in the pipeline is the memoizer, because we need 41 // that to end first and get the collected data. 42 if (memoize) { 43 const memoizer = new PassThrough().on('collect', data => { 44 memoData = data 45 }) 46 pipeline.push(memoizer) 47 } 48 49 // contentStream is a write-only, not a passthrough 50 // no data comes out of it. 51 const contentStream = write.stream(cache, opts) 52 .on('integrity', (int) => { 53 integrity = int 54 }) 55 .on('size', (s) => { 56 size = s 57 }) 58 .on('error', (err) => { 59 error = err 60 }) 61 62 pipeline.push(contentStream) 63 64 // last but not least, we write the index and emit hash and size, 65 // and memoize if we're doing that 66 pipeline.push(new Flush({ 67 async flush () { 68 if (!error) { 69 const entry = await index.insert(cache, key, integrity, { ...opts, size }) 70 if (memoize && memoData) { 71 memo.put(cache, entry, memoData, opts) 72 } 73 pipeline.emit('integrity', integrity) 74 pipeline.emit('size', size) 75 } 76 }, 77 })) 78 79 return pipeline 80} 81