UNPKG

kyper-grout

Version:

Library to communicate with tessellate application building/managing service.

266 lines (250 loc) 6.77 kB
import { isArray, isString, each } from 'lodash'; import matter from './Matter'; import File from './File'; import Folder from './Folder'; import jszip from 'jszip'; import filesave from 'node-safe-filesaver'; //Convenience vars const { logger } = matter.utils; export default class Directory { constructor(project) { logger.debug({ description: 'Directory object constructed.', func: 'constructor', obj: 'Directory', dir: this }); if(!project) { throw new Error('Project is required to create directory'); } this.project = project; } /** * @description File within directory */ File(path) { const file = new File(this.project, path); logger.debug({ description: 'Projects file action called.', path, project: this, file, func: 'File', obj: 'Directory' }); return file; } /** * @description Firebase reference of directory */ get fbRef() { logger.debug({ description: 'Url created for directory fbRef.', url: this.project.fbRef, func: 'fbRef', obj: 'Directory' }); return this.project.fbRef; } /** * @description Get directory */ get() { logger.log({ description: 'Directory get called.', func: 'get', obj: 'Directory' }); return new Promise(resolve => { this.fbRef.once('value', filesSnap => { logger.info({ description: 'Directory loaded from firebase.', func: 'get', obj: 'Directory' }); this.fbData = filesSnap.val(); resolve(this); }); }); } /** * @description Download files from firebase */ downloadFiles() { logger.debug({ description: 'Download files called.', func: 'downloadFiles', obj: 'Directory' }); return this.get().then((directory) => { directory = directory.fbData; let zip = new jszip(); let promiseArray = []; let handleZip = (fbChildren) => { each(fbChildren, child => { if (!child.meta || child.meta.entityType === 'folder') { delete child.meta; return handleZip(child); } let promise = this.File(child.meta.path).getContent().then((content) => { return zip.file(child.meta.path, content); }); promiseArray.push(promise); }); }; handleZip(directory); return Promise.all(promiseArray).then(() => { let content = zip.generate({type: 'blob'}); return filesave.saveAs(content, `${this.project.name}-devShare-export.zip`); }); }); } /** * @description Get synced files list from firebase */ sync(callback) { // TODO: get files list from firebase logger.debug({ description: 'Directory sync called.', func: 'sync', obj: 'Directory' }); this.listenerCallback = callback; return this.fbRef.on('value', this.listenerCallback); } /** * @description Get synced files list from firebase */ unsync() { // TODO: get files list from firebase logger.debug({ description: 'Directory sync called.', func: 'sync', obj: 'Directory' }); return this.fbRef.off('value', this.listenerCallback); } /** * @description Add a new file or files * @param {Object|Array} fileData - Array of objects or single object containing file data * @param {Object} fileData.path - Path of file relative to project */ addFile(path, content) { let file = new File(this.project, path, content); return file.save(); } /** * @description Add a folder * @param {string} path - Path of where the folder should be saved * @param {String} name - optionally provide name of folder */ addFolder(path) { let folder = new Folder(this.project, path); return folder.save(); } /** * @description Add multiple files/folders to project files * @param {Array} files - Array of file objects to upload */ upload(files) { //TODO: Allow for options of where to add the file to if(!isArray(files)){ return this.addToFb(files); } else { logger.warn({ description: 'Upload called with multiple files.', files, project: this.project, func: 'upload', obj: 'Directory' }); let promises = []; each(files, file => { promises.push(this.addToFb(file)); }); return Promise.all(promises).then(resultsArray => { logger.info({ description: 'Directory uploaded successfully.', resultsArray, func: 'upload', obj: 'Directory' }); return Promise.resolve(this); }); } } /** * @description Remove object from files (folder or file) */ remove(objData) { //TODO: Delete file from S3 as well if it exists return this.delFromFb(objData); } /** * @description Add a file to Firebase * @param {Object} fileData - Data object for new file * @param {String} fileData.path - Path of file within project * @param {String} fileData.content - Content of file */ addToFb(addData) { logger.debug({ description: 'Add to fb called.', addData, func: 'addToFb', obj: 'Directory' }); if (!addData) { logger.debug({ description: 'Object data is required to add.', addData, func: 'addToFb', obj: 'Directory' }); return Promise.reject({ message: 'Object data is required to add.' }); } //Array of files/folder to upload if (isArray(addData)) { let promises = []; addData.forEach(file => { promises.push(this.addToFb(file)); }); return Promise.all(promises); } const { size, path, name, type } = addData; if (size) { return this.addLocalToFb(addData); } if (!path) { logger.error({ description: 'Invalid file data. Path must be included.', func: 'addToFb', obj: 'Directory' }); return Promise.reject({ message: 'Invalid file data. Path must be included.' }); } if (type && type === 'folder') { return new Folder(this.project, path, name).save(); } else { return new File(this.project, path, name).save(); } } /** * @description Delete a file or folder from Firebase * @param {Object} objData - Data of file or folder * @param {String} path - Path of file or folder */ delFromFb(path) { logger.debug({ description: 'Del from fb called.', path, func: 'delFromFb', obj: 'Directory' }); if (!path || !isString(path)) { logger.error({ description: 'Invalid file path. Path must be included.', func: 'delFromFb', obj: 'Directory' }); return Promise.reject({ message: 'Invalid file path. Path must be included to delete.' }); } let file = new File(this.project, path); return new Promise((resolve, reject) => { file.fbRef.remove(file, err => { if(err){ logger.error({ description: 'Error deleting from Firebase.', func: 'delFromFb', obj: 'Directory' }); return reject(err); } logger.info({ description: 'Successfully deleted.', func: 'delFromFb', obj: 'Directory' }); resolve({message: 'Delete successful.'}); }); }); } }