From 6d15b2724c79e4571a23644c315d813a9ca63919 Mon Sep 17 00:00:00 2001 From: AndrewGHC Date: Thu, 1 Sep 2016 16:27:34 +0200 Subject: [PATCH 1/7] Correctly locates all files, without excluding documents with multiple file fields where one field is undefined --- lib/index.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/lib/index.js b/lib/index.js index afba43f..0d1d5f1 100644 --- a/lib/index.js +++ b/lib/index.js @@ -47,7 +47,10 @@ function getAllFileObjects() { }).then(function(results) { var files = results.reduce(function(c, r) { return c.concat(r); - }, []); + }, []).filter(function(file) { + return file.fileName !== 'DELETE'; + }); + return Promise.resolve(files); }); } @@ -90,19 +93,24 @@ function getObjectsWithFilesFromSchema(schema) { query.select(schema.fields.concat('createdAt')); query.ascending('createdAt'); query.limit(1000); - schema.fields.forEach(function(field) { - query.exists(field); + + var checks = schema.fields.map(function(field) { + return new Parse.Query(schema.className).exists(field); }); + query._orQuery(checks); + return getAllObjects(query).then(function(results) { return results.reduce(function(current, result){ return current.concat( schema.fields.map(function(field){ + var fName = result.get(field) ? result.get(field).name() : 'DELETE'; + var fUrl = result.get(field) ? result.get(field).url() : 'DELETE'; return { className: schema.className, objectId: result.id, fieldName: field, - fileName: result.get(field).name(), - url: result.get(field).url() + fileName: fName, + url: fUrl } }) ); From fab89e5f9ac455bf61fd7e151800486383c6e248 Mon Sep 17 00:00:00 2001 From: Arthur Cinader Date: Thu, 29 Sep 2016 09:23:10 -0700 Subject: [PATCH 2/7] minor typo --- lib/transfer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/transfer.js b/lib/transfer.js index ce55f68..e21cb9b 100644 --- a/lib/transfer.js +++ b/lib/transfer.js @@ -194,7 +194,7 @@ function _shouldTransferFile(file) { /** * Request file from URL and upload with filesAdapter - * @param {Ibject} file the file info object + * @param {Object} file the file info object */ function _transferFile(file) { return new Promise(function(resolve, reject) { From a22f0694d33c54c7df1c0394044eb8ffad628fd8 Mon Sep 17 00:00:00 2001 From: Ben Packard Date: Sat, 29 Oct 2016 09:37:39 -0400 Subject: [PATCH 3/7] Fixed typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9e5ff96..def9b44 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ and Parse Server [issue #1582](https://github.com/ParsePlatform/parse-server/iss ## Installation 1. Clone the repo: `git clone git@github.com:parse-server-modules/parse-files-utils.git` -2. cd into repo: `cd parse-file-utils` +2. cd into repo: `cd parse-files-utils` 3. Install dependencies: `npm install` ## Usage From af6a1f590cee4f72640079ff3a03ac77b8d825a1 Mon Sep 17 00:00:00 2001 From: Olivier Proulx Date: Fri, 16 Dec 2016 11:13:29 -0500 Subject: [PATCH 4/7] Adding azure parameters for config.example.js --- config.example.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config.example.js b/config.example.js index aee49f7..61d475e 100644 --- a/config.example.js +++ b/config.example.js @@ -25,6 +25,11 @@ module.exports = { gcs_keyFilename: "credentials.json", gcs_bucket: "BUCKET_NAME", + // For Azure configuration + azure_account: "STORAGE_ACCOUNT_NAME", + azure_container: "BLOB_CONTAINER", + azure_accessKey: "ACCESS_KEY", + // Or set filesAdapter to a Parse Server file adapter // filesAdapter: new FileAdapter({ // filesSubDirectory: './downloaded_files' From 46c64a2409c1df4c75b8db9bee753bb5aa862e45 Mon Sep 17 00:00:00 2001 From: Reid Weber Date: Mon, 9 Jan 2017 15:00:23 -0800 Subject: [PATCH 5/7] fix RangeError: Maximum call stack size exceeded --- lib/transfer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/transfer.js b/lib/transfer.js index e21cb9b..6a7096e 100644 --- a/lib/transfer.js +++ b/lib/transfer.js @@ -136,7 +136,7 @@ function _processFiles(files, handler) { if (_shouldTransferFile(file)) { _transferFile(file).then(callback, callback); } else { - callback(); + process.nextTick(callback); } }, function(error) { if (error) { From bf262f34913690294678f5b8fa009cc9270a1476 Mon Sep 17 00:00:00 2001 From: rvitorper Date: Wed, 25 Jan 2017 11:17:06 -0200 Subject: [PATCH 6/7] Changed code so that it migrates files that are inside an array --- lib/index.js | 88 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 76 insertions(+), 12 deletions(-) diff --git a/lib/index.js b/lib/index.js index 8c51345..cf3c428 100644 --- a/lib/index.js +++ b/lib/index.js @@ -73,7 +73,7 @@ function onlyFiles(schemas) { return schemas.map(function(schema) { var fileFields = Object.keys(schema.fields).filter(function(key){ var value = schema.fields[key]; - return value.type == "File"; + return value.type == "File" || value.type == "Array"; }); if (fileFields.length > 0) { return { @@ -102,6 +102,80 @@ function getAllObjects(baseQuery) { return next(); } +// Cases covered: +// i - It is a single File +// ii - It is a single Array with no files +// iii - It is a single Array with only files +// iv - There are multiple Arrays with only files +// v - There are multiple Arrays with no files +// vi - There are multiple Arrays with file and non-file elements + +var ARRAY_WITH_FILES = 1; +var ARRAY_NO_FILES = 2; +var FILE = 3; + +function classifier(element, schema) { + var toRet = FILE; + var hasArray = false; + var hasFile = false; + var data = []; + var fields = schema.fields; + + + fields.forEach(function(key) { + if(Array.isArray(element.get(key))) { + hasArray = true; + element.get(key).forEach(function(item) { + if(item instanceof Parse.File) { + hasFile = true; + var fName = item._name; + var fUrl = item._url; + data.push({ + className: schema.className, + objectId: item.id, + fieldName: key, + fileName: fName, + url: fUrl + }); + } + }); + } + }); + + if(hasArray && hasFile) toRet = ARRAY_WITH_FILES; + else if(hasArray) toRet = ARRAY_NO_FILES; + + var returnObj = { + code: toRet, + data: data, + }; + + return returnObj; +} + +function checkArrays(result, schema) { + var status = classifier(result, schema); + if(status.code === ARRAY_WITH_FILES) { + return status.data + } + else if(status.code === ARRAY_NO_FILES) { + return [] + } + else { + return schema.fields.map(function(field){ + var fName = result.get(field) ? result.get(field).name() : 'DELETE'; + var fUrl = result.get(field) ? result.get(field).url() : 'DELETE'; + return { + className: schema.className, + objectId: result.id, + fieldName: field, + fileName: fName, + url: fUrl + } + }) + } +} + function getObjectsWithFilesFromSchema(schema) { var query = new Parse.Query(schema.className); query.select(schema.fields.concat('createdAt')); @@ -116,17 +190,7 @@ function getObjectsWithFilesFromSchema(schema) { return getAllObjects(query).then(function(results) { return results.reduce(function(current, result){ return current.concat( - schema.fields.map(function(field){ - var fName = result.get(field) ? result.get(field).name() : 'DELETE'; - var fUrl = result.get(field) ? result.get(field).url() : 'DELETE'; - return { - className: schema.className, - objectId: result.id, - fieldName: field, - fileName: fName, - url: fUrl - } - }) + checkArrays(result, schema) ); }, []); }); From c82f08be65826b7841ac043d03eafde75a457472 Mon Sep 17 00:00:00 2001 From: rvitorper Date: Wed, 25 Jan 2017 11:20:44 -0200 Subject: [PATCH 7/7] Renamed function name --- lib/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/index.js b/lib/index.js index cf3c428..620b5fb 100644 --- a/lib/index.js +++ b/lib/index.js @@ -114,7 +114,7 @@ var ARRAY_WITH_FILES = 1; var ARRAY_NO_FILES = 2; var FILE = 3; -function classifier(element, schema) { +function check(element, schema) { var toRet = FILE; var hasArray = false; var hasFile = false; @@ -154,7 +154,7 @@ function classifier(element, schema) { } function checkArrays(result, schema) { - var status = classifier(result, schema); + var status = check(result, schema); if(status.code === ARRAY_WITH_FILES) { return status.data }