import fs from 'fs' import promisesAll from 'promises-all' import mkdirp from 'mkdirp' import shortid from 'shortid' import lowdb from 'lowdb' import FileSync from 'lowdb/adapters/FileSync' const uploadDir = './uploads' const db = lowdb(new FileSync('db.json')) // Seed an empty DB db.defaults({ uploads: [] }).write() // Ensure upload directory exists mkdirp.sync(uploadDir) const storeFS = ({ stream, filename }) => { const id = shortid.generate() const path = `${uploadDir}/${id}-${filename}` return new Promise((resolve, reject) => stream .on('error', error => { if (stream.truncated) // Delete the truncated file fs.unlinkSync(path) reject(error) }) .pipe(fs.createWriteStream(path)) .on('error', error => reject(error)) .on('finish', () => resolve({ id, path })) ) } const storeDB = file => db .get('uploads') .push(file) .last() .write() const processUpload = async upload => { const { stream, filename, mimetype, encoding } = await upload const { id, path } = await storeFS({ stream, filename }) return storeDB({ id, filename, mimetype, encoding, path }) } export default { Query: { uploads: () => db.get('uploads').value() }, Mutation: { singleUpload: (obj, { file }) => processUpload(file), async multipleUpload(obj, { files }) { const { resolve, reject } = await promisesAll.all( files.map(processUpload) ) if (reject.length) reject.forEach(({ name, message }) => // eslint-disable-next-line no-console console.error(`${name}: ${message}`) ) return resolve } } }