From ee32d8ced7a26e6b65ea8c8d5537dd54a78b823e Mon Sep 17 00:00:00 2001 From: Jayden Seric Date: Wed, 3 Jan 2018 20:07:38 +1100 Subject: [PATCH] Updated apollo-upload-server to v4.0.0-alpha.2. Also updated server-side error handling accordingly. --- api/package-lock.json | 50 +++++++++++++++++++++++++++++++++---------- api/package.json | 3 ++- api/resolvers.mjs | 31 +++++++++++++++++++-------- 3 files changed, 63 insertions(+), 21 deletions(-) diff --git a/api/package-lock.json b/api/package-lock.json index eb5d409..84f4edc 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -3,6 +3,15 @@ "requires": true, "lockfileVersion": 1, "dependencies": { + "@babel/runtime": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0-beta.36.tgz", + "integrity": "sha512-M76nk/SBqgICwp/QnL2ju7YrHHGjkKO1WwzqujFAdwIpf5RdZ7Q9Qt9kkGv0bOGj1h2Ki+LdfvMTJH0JhQi8sw==", + "requires": { + "core-js": "2.5.3", + "regenerator-runtime": "0.11.1" + } + }, "@std/esm": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/@std/esm/-/esm-0.18.0.tgz", @@ -24,9 +33,9 @@ } }, "acorn": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", - "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz", + "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==", "dev": true }, "acorn-jsx": { @@ -147,10 +156,11 @@ } }, "apollo-upload-server": { - "version": "4.0.0-alpha.1", - "resolved": "https://registry.npmjs.org/apollo-upload-server/-/apollo-upload-server-4.0.0-alpha.1.tgz", - "integrity": "sha512-uW0TtcSXDkOoJD6NlMwD4I4deMaZO61GpnouvCLiDRm4FwpeEVLVUVpSk4/s++La+TXXgzoKNb8ixfPwUAjiGw==", + "version": "4.0.0-alpha.2", + "resolved": "https://registry.npmjs.org/apollo-upload-server/-/apollo-upload-server-4.0.0-alpha.2.tgz", + "integrity": "sha512-iUBgiAWrrOXI8pN9mVVIFr2BnVRw7prP5eInMeTPru8C9LZ82IdI8FHE37+NzCZVLCDK0gsgNOcYPl7cjXqELg==", "requires": { + "@babel/runtime": "7.0.0-beta.36", "busboy": "0.2.14", "object-path": "0.11.4" } @@ -264,6 +274,11 @@ "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", "dev": true }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, "boxen": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", @@ -922,7 +937,7 @@ "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==", "dev": true, "requires": { - "acorn": "5.2.1", + "acorn": "5.3.0", "acorn-jsx": "3.0.1" } }, @@ -2389,9 +2404,9 @@ "dev": true }, "is-generator-function": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.6.tgz", - "integrity": "sha1-nnFlPNFf/zQcecQVFGChMdMen8Q=" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", + "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==" }, "is-glob": { "version": "2.0.1", @@ -2602,7 +2617,7 @@ "fresh": "0.5.2", "http-assert": "1.3.0", "http-errors": "1.6.2", - "is-generator-function": "1.0.6", + "is-generator-function": "1.0.7", "koa-compose": "4.0.0", "koa-convert": "1.2.0", "koa-is-json": "1.0.0", @@ -3241,6 +3256,14 @@ "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", "dev": true }, + "promises-all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/promises-all/-/promises-all-1.0.0.tgz", + "integrity": "sha1-pDGMuNRWifZzkE4hVg8DI5cCgg8=", + "requires": { + "bluebird": "3.5.1" + } + }, "ps-tree": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.0.tgz", @@ -3429,6 +3452,11 @@ } } }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, "regex-cache": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", diff --git a/api/package.json b/api/package.json index f65ea96..629de47 100644 --- a/api/package.json +++ b/api/package.json @@ -7,7 +7,7 @@ }, "dependencies": { "@std/esm": "^0.18.0", - "apollo-upload-server": "^4.0.0-alpha.1", + "apollo-upload-server": "^4.0.0-alpha.2", "dotenv": "^4.0.0", "graphql": "^0.11.7", "graphql-server-koa": "^1.3.2", @@ -19,6 +19,7 @@ "koa-router": "^7.3.0", "lowdb": "^1.0.0", "mkdirp": "^0.5.1", + "promises-all": "^1.0.0", "shortid": "^2.2.8" }, "devDependencies": { diff --git a/api/resolvers.mjs b/api/resolvers.mjs index 1017458..0c7855b 100644 --- a/api/resolvers.mjs +++ b/api/resolvers.mjs @@ -1,4 +1,5 @@ -import { createWriteStream } from 'fs' +import { createWriteStream, unlinkSync } from 'fs' +import { all } from 'promises-all' import mkdirp from 'mkdirp' import shortid from 'shortid' import lowdb from 'lowdb' @@ -14,19 +15,23 @@ db.defaults({ uploads: [] }).write() // Ensure upload directory exists mkdirp.sync(uploadDir) -const storeUpload = async ({ stream, filename }) => { +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 + unlinkSync(path) + reject(error) + }) + .on('end', () => resolve({ id, path })) .pipe(createWriteStream(path)) - .on('finish', () => resolve({ id, path })) - .on('error', reject) ) } -const recordFile = file => +const storeDB = file => db .get('uploads') .push(file) @@ -35,8 +40,8 @@ const recordFile = file => const processUpload = async upload => { const { stream, filename, mimetype, encoding } = await upload - const { id, path } = await storeUpload({ stream, filename }) - return recordFile({ id, filename, mimetype, encoding, path }) + const { id, path } = await storeFS({ stream, filename }) + return storeDB({ id, filename, mimetype, encoding, path }) } export default { @@ -46,6 +51,14 @@ export default { }, Mutation: { singleUpload: (obj, { file }) => processUpload(file), - multipleUpload: (obj, { files }) => Promise.all(files.map(processUpload)) + multipleUpload: async (obj, { files }) => { + const { resolve, reject } = await all(files.map(processUpload)) + if (reject.length) + reject.forEach(({ name, message }) => + // eslint-disable-next-line no-console + console.error(`${name}: ${message}`) + ) + return resolve + } } }