upload-apollo-client/api/storeUpload.mjs
Jayden Seric 8a46155f91 Simplify the example by removing the DB.
This avoids trying to figure out how to fix concurrent writes conflicting with `lowdb` v2, see: https://github.com/typicode/lowdb/issues/478 .
2021-06-11 17:24:42 +10:00

43 lines
1.5 KiB
JavaScript

import { createWriteStream, unlink } from 'fs';
import shortId from 'shortid';
import UPLOAD_DIRECTORY_URL from './config/UPLOAD_DIRECTORY_URL.mjs';
/**
* Stores a GraphQL file upload in the filesystem.
* @param {Promise<object>} upload GraphQL file upload.
* @returns {Promise<string>} Resolves the stored file name.
*/
export default async function storeUpload(upload) {
const { createReadStream, filename } = await upload;
const stream = createReadStream();
const storedFileName = `${shortId.generate()}-${filename}`;
const storedFileUrl = new URL(storedFileName, UPLOAD_DIRECTORY_URL);
// Store the file in the filesystem.
await new Promise((resolve, reject) => {
// Create a stream to which the upload will be written.
const writeStream = createWriteStream(storedFileUrl);
// When the upload is fully written, resolve the promise.
writeStream.on('finish', resolve);
// If there's an error writing the file, remove the partially written file
// and reject the promise.
writeStream.on('error', (error) => {
unlink(storedFileUrl, () => {
reject(error);
});
});
// In Node.js <= v13, errors are not automatically propagated between piped
// streams. If there is an error receiving the upload, destroy the write
// stream with the corresponding error.
stream.on('error', (error) => writeStream.destroy(error));
// Pipe the upload into the write stream.
stream.pipe(writeStream);
});
return storedFileName;
}