UNPKG

28

Version:

Command line utility to download and upload 28.io queries.

244 lines (220 loc) 8.88 kB
'use strict'; require('colors'); var Q = require('q'); var read = require('read'); var http = require('http'); var https = require('https'); var VFS = require('./vfs').VFS; var Client = (function(){ var Options = { OVERWRITE_ALWAYS: 0, OVERWRITE_NEVER: 1, OVERWRITE_ASK: 2, OVERWRITE_IF_NEWER: 3 }; exports.Options = Options; var loc = function(isOriginRemote){ return isOriginRemote ? 'remote' : 'local'; }; var logDiff = function(diff, simulate){ var msg; if(diff.type === 'write') { if(diff.isOriginRemote) { msg = ('<< '.green) + ('↙ '.blue) + diff.query; } else { msg = ('>> '.green) + ('↗ '.blue) + diff.query; } } else { msg = ('✗'.red) + ' <' + loc(!diff.isOriginRemote) + '>/' + diff.query; } if(simulate === true) { msg += ' (simulate)'; } if(diff.type === 'write') { console.log(msg); } else { console.log(msg.red); } }; var addDiff = function(diff){ return function(diffs){ var defered = Q.defer(); setTimeout(function() { diffs.push(diff); defered.resolve(diffs); }, 1); return defered.promise; }; }; function Client($28, projectEndpoint, projectToken, localProjectPath){ this.vfs = new VFS($28, projectEndpoint, projectToken, localProjectPath); } Client.prototype.syncImpl = function(localQueries, remoteQueries, overwrite, deleteOrphaned, simulate, isOriginRemote){ var that = this; var promises = []; var origin = isOriginRemote ? remoteQueries : localQueries; var target = isOriginRemote ? localQueries : remoteQueries; Object.keys(origin).forEach(function(query) { var targetQuery = target[query]; var diff = { type: 'write', query: query, isOriginRemote: isOriginRemote }; if(targetQuery) { var originLastModified = origin[query].lastModified; var targetLastModified = targetQuery.lastModified; if(overwrite === Options.OVERWRITE_ALWAYS) { promises.push(addDiff(diff)); } else if(overwrite === Options.OVERWRITE_IF_NEWER) { if((new Date(originLastModified)).getTime() > (new Date(targetLastModified)).getTime()){ promises.push(addDiff(diff)); } } else if(overwrite === Options.OVERWRITE_ASK) { promises.push(function (diffs) { var defered = Q.defer(); read({ prompt: 'Overwrite: <' + loc(!isOriginRemote) + '>/' + query + ' (' + targetLastModified + ') with <' + loc(isOriginRemote) + '>/' + query + ' (' + originLastModified + ')? Y/[N]', default: 'N' }, function (er, value) { if (er) { defered.reject(er); } if (value !== undefined && value.toUpperCase() === 'Y') { diffs.push(diff); } defered.resolve(diffs); }); return defered.promise; }); } else if(overwrite === Options.OVERWRITE_NEVER) { //Do nothing } else { throw new Error('Invalid overwrite value: ' + overwrite); } } else { promises.push(addDiff(diff)); } }); if(deleteOrphaned === true) { Object.keys(target).forEach(function(query) { if(origin[query] === undefined) { promises.push(addDiff({ type: 'delete', query: query, isOriginRemote: isOriginRemote })); } }); } promises.push(function(diffs){ return that.commit(simulate, diffs); }); return promises.reduce(Q.when, new Q([])); }; Client.prototype.writeLocalQuery = function(diff){ return this.vfs.writeLocalQuery(diff.query).then(function(){ logDiff(diff); }); }; Client.prototype.writeRemoteQuery = function(diff){ return this.vfs.writeRemoteQuery(diff.query) .then(function(compileError){ logDiff(diff); if(compileError) { compileError.query = diff.query; throw compileError; } }); }; Client.prototype.deleteLocalQuery = function(diff){ return this.vfs.deleteLocalQuery(diff.query).then(function(){ logDiff(diff); }); }; Client.prototype.deleteRemoteQuery = function(diff){ return this.vfs.deleteRemoteQuery(diff.query).then(function(){ logDiff(diff); }); }; Client.prototype.commit = function(simulate, diffs){ var that = this; var modulePromises = []; var queryPromises = []; diffs.forEach(function(diff){ var container = diff.query.substring(0, 'modules'.length) === 'modules' ? modulePromises : queryPromises; if(simulate) { logDiff(diff, simulate); } else if(diff.type === 'write'){ if(diff.isOriginRemote) { container.push(function(){ return that.writeLocalQuery(diff); }); } else { container.push(function(){ return that.writeRemoteQuery(diff); }); } } else { if(diff.isOriginRemote) { container.push(function(){ return that.deleteLocalQuery(diff); }); } else { container.push(function(){ return that.deleteRemoteQuery(diff); }); } } }); var handler = function(results){ var errors = []; results.forEach(function (result) { if (result.state !== 'fulfilled') { errors.push(result.reason); } }); if(errors.length > 0) { throw errors; } return results; }; return [ function(){ var promises = []; modulePromises.forEach(function(promise){ promises.push(promise()); }); return Q.allSettled(promises).then(handler); }, function(){ var promises = []; queryPromises.forEach(function(promise){ promises.push(promise()); }); return Q.allSettled(promises).then(handler); } ].reduce(Q.when, new Q([])); }; Client.prototype.sync = function(overwrite, deleteOrphaned, simulate, ignore, isOriginRemote, concurrency){ if (concurrency === undefined) { http.globalAgent.maxSockets = 8; https.globalAgent.maxSockets = 8; console.log('Concurrency limit: 8.'.grey); } else { http.globalAgent.maxSockets = concurrency; https.globalAgent.maxSockets = concurrency; console.log('Concurrency limit: ' + concurrency + '.'.grey); } var that = this; return Q.all([ this.vfs.getLocalQueries(), this.vfs.getRemoteQueries() ]) .then(function(queries){ var localQueries = ignore(queries[0]); var remoteQueries = ignore(queries[1]); return that.syncImpl(localQueries, remoteQueries, overwrite, deleteOrphaned, simulate, isOriginRemote); }); }; Client.prototype.download = function(overwrite, deleteOrphaned, simulate, ignore, concurrency){ return this.sync(overwrite, deleteOrphaned, simulate, ignore, true, concurrency); }; Client.prototype.upload = function(overwrite, deleteOrphaned, simulate, ignore, concurrency){ return this.sync(overwrite, deleteOrphaned, simulate, ignore, false, concurrency); }; Client.prototype.truncate = function(simulate, ignore){ var that = this; return this.vfs.getRemoteQueries().then(function(queries){ var remoteQueries = ignore(queries); return that.syncImpl({}, remoteQueries, Options.OVERWRITE_ALWAYS, true, simulate, false); }); }; return Client; })(); exports.Client = Client;