diff --git a/client/client.js b/client/client.js index 28f36737..00f8f77b 100644 --- a/client/client.js +++ b/client/client.js @@ -97,7 +97,6 @@ function CloudCmdProto(DOM) { */ this.loadDir = (params, callback) => { const p = params; - const refresh = p.isRefresh; const { @@ -354,7 +353,7 @@ function CloudCmdProto(DOM) { * */ function ajaxLoad(path, options, panel, callback) { - const create = (error, json) => { + const create = async (error, json) => { const {RESTful} = DOM; const name = options.currentName || Info.name; const obj = jonny.parse(json); @@ -373,25 +372,23 @@ function CloudCmdProto(DOM) { order, }); - RESTful.read(path + query, 'json', (error, obj) => { - if (error) - return; + const newObj = await RESTful.read(path + query, 'json'); + + /* eslint require-atomic-updates:0 */ + options.sort = sort; + options.order = order; + + createFileTable(newObj, panel, options, () => { + if (isRefresh && !noCurrent) + DOM.setCurrentByName(name); - options.sort = sort; - options.order = order; - - createFileTable(obj, panel, options, () => { - if (isRefresh && !noCurrent) - DOM.setCurrentByName(name); - - exec(callback); - }); - - if (!CloudCmd.config('dirStorage')) - return; - - Storage.set(path, obj); + exec(callback); }); + + if (!CloudCmd.config('dirStorage')) + return; + + Storage.set(path, newObj); }; if (!options) diff --git a/client/dom/files.js b/client/dom/files.js index 9897df93..1c638275 100644 --- a/client/dom/files.js +++ b/client/dom/files.js @@ -123,17 +123,12 @@ function getConfig(callback) { let is; if (!Promises.config) - Promises.config = new Promise((resolve, reject) => { + Promises.config = () => { is = true; - RESTful.Config.read((error, data) => { - if (error) - return reject(error); - - resolve(data); - }); - }); + return RESTful.Config.read(); + }; - Promises.config.then((data) => { + Promises.config().then((data) => { is = false; callback(null, data); diff --git a/client/dom/index.js b/client/dom/index.js index e2811916..e89891bc 100644 --- a/client/dom/index.js +++ b/client/dom/index.js @@ -8,7 +8,7 @@ const jonny = require('jonny/legacy'); const tryToCatch = require('try-to-catch/legacy'); const Util = require('../../common/util'); -const tryToPromisify = require('../../common/try-to-promisify'); +const callbackify = require('../../common/callbackify'); const Images = require('./images'); const load = require('./load'); @@ -17,6 +17,8 @@ const RESTful = require('./rest'); const Storage = require('./storage'); const Dialog = require('./dialog'); +const read = callbackify(RESTful.read); + const currentFile = require('./current-file'); const DOMTree = require('./dom-tree'); @@ -83,7 +85,7 @@ function CmdProto() { promptNew('file'); }; - function promptNew(typeName, type) { + async function promptNew(typeName, type) { const {Dialog} = DOM; const dir = DOM.getCurrentDirPath(); const msg = 'New ' + typeName || 'File'; @@ -97,31 +99,24 @@ function CmdProto() { }; const name = getName(); - const cancel = false; - Dialog.prompt(msg, name, {cancel}).then((name) => { - if (!name) - return; + const [, newName] = await tryToCatch(Dialog.prompt, msg, name); + + if (!newName) + return; + + const path = (type) => { + const result = dir + newName; - const path = (type) => { - const result = dir + name; - - if (!type) - return result; - - return result + type; - }; + if (!type) + return result; - RESTful.write(path(type), (error) => { - if (error) - return; - - const currentName = name; - - CloudCmd.refresh({ - currentName, - }); - }); + return result + type; + }; + + await RESTful.write(path(type)); + await CloudCmd.refresh({ + currentName: newName, }); } @@ -236,7 +231,7 @@ function CmdProto() { * get size * @currentFile */ - this.loadCurrentSize = (callback, currentFile) => { + this.loadCurrentSize = callbackify(async (currentFile) => { const current = currentFile || DOM.getCurrentFile(); const query = '?size'; const link = DOM.getCurrentPath(current); @@ -246,15 +241,13 @@ function CmdProto() { if (name === '..') return; - RESTful.read(link + query, (error, size) => { - if (error) - return; - - DOM.setCurrentSize(size, current); - exec(callback, current); - Images.hide(); - }); - }; + const size = await RESTful.read(link + query); + + DOM.setCurrentSize(size, current); + Images.hide(); + + return current; + }); /** * load hash @@ -266,7 +259,7 @@ function CmdProto() { const query = '?hash'; const link = DOM.getCurrentPath(current); - RESTful.read(link + query, callback); + read(link + query, callback); }; /** @@ -279,7 +272,7 @@ function CmdProto() { const query = '?time'; const link = DOM.getCurrentPath(current); - RESTful.read(link + query, callback); + read(link + query, callback); }; /** @@ -349,7 +342,7 @@ function CmdProto() { } if (isDir) - return RESTful.read(path, func); + return read(path, func); DOM.checkStorageHash(path, (error, equal, hashNew) => { if (error) @@ -359,7 +352,7 @@ function CmdProto() { return DOM.getDataFromStorage(path, callback); hash = hashNew; - RESTful.read(path, func); + read(path, func); }); }; @@ -370,9 +363,10 @@ function CmdProto() { * @currentFile */ this.saveCurrentData = (url, data, callback, query = '') => { - DOM.RESTful.write(url + query, data, (error) => { - !error && DOM.saveDataToStorage(url, data); - }); + RESTful.write(url + query, data) + .then(() => { + DOM.saveDataToStorage(url, data); + }); }; /** @@ -543,7 +537,6 @@ function CmdProto() { */ this.checkStorageHash = (name, callback) => { const {parallel} = exec; - const loadHash = DOM.loadCurrentHash; const nameHash = name + '-hash'; const getStoreHash = exec.with(Storage.get, nameHash); @@ -553,7 +546,7 @@ function CmdProto() { if (typeof callback !== 'function') throw Error('callback should be a function!'); - parallel([loadHash, getStoreHash], (error, loadHash, storeHash) => { + parallel([DOM.loadCurrentHash, getStoreHash], (error, loadHash, storeHash) => { let equal; const isContain = /error/.test(loadHash); @@ -776,10 +769,7 @@ function CmdProto() { to : dirPath + to, }; - const [error] = await tryToPromisify(RESTful.mv, files); - - if (error) - return; + await RESTful.mv(files); DOM.setCurrentName(to, current); Storage.remove(dirPath); diff --git a/client/dom/rest.js b/client/dom/rest.js index f6acd1b9..e6c84b7b 100644 --- a/client/dom/rest.js +++ b/client/dom/rest.js @@ -3,15 +3,18 @@ /* global CloudCmd, DOM */ const itype = require('itype/legacy'); +const {promisify} = require('es6-promisify'); const {FS} = require('../../common/cloudfunc'); const {encode} = require('../../common/entity'); -module.exports = new RESTful(); - const Images = require('./images'); const load = require('./load'); +const imgPosition = { + top: true, +}; + module.exports._replaceHash = replaceHash; function replaceHash(url) { /* @@ -21,204 +24,198 @@ function replaceHash(url) { return url.replace(/#/g, '%23'); } -function RESTful() { - this.delete = (url, data, callback) => { - const isFunc = itype.function(data); - - if (!callback && isFunc) { - callback = data; - data = null; - } - - sendRequest({ - method : 'DELETE', - url : FS + url, - data, - callback, - imgPosition : { top: !!data }, - }); - }; +module.exports.delete = promisify((url, data, callback) => { + const isFunc = itype.function(data); - this.patch = (url, data, callback) => { - const isFunc = itype.function(data); - - if (!callback && isFunc) { - callback = data; - data = null; - } - - const imgPosition = { - top: true, - }; - + if (!callback && isFunc) { + callback = data; + data = null; + } + + sendRequest({ + method : 'DELETE', + url : FS + url, + data, + callback, + imgPosition : { top: !!data }, + }); +}); + +module.exports.patch = promisify((url, data, callback) => { + const isFunc = itype.function(data); + + if (!callback && isFunc) { + callback = data; + data = null; + } + + sendRequest({ + method: 'PATCH', + url: FS + url, + data, + callback, + imgPosition, + }); +}); + +module.exports.write = promisify((url, data, callback) => { + const isFunc = itype.function(data); + + if (!callback && isFunc) { + callback = data; + data = null; + } + + sendRequest({ + method: 'PUT', + url: FS + url, + data, + callback, + imgPosition, + }); +}); + +module.exports.read = promisify((url, dataType, callback) => { + const notLog = !url.includes('?'); + const isFunc = itype.function(dataType); + + if (!callback && isFunc) { + callback = dataType; + dataType = 'text'; + } + + sendRequest({ + method: 'GET', + url: FS + url, + callback, + notLog, + dataType, + }); +}); + +module.exports.cp = promisify((data, callback) => { + sendRequest({ + method: 'PUT', + url: '/cp', + data, + callback, + imgPosition, + }); +}); + +module.exports.pack = promisify((data, callback) => { + sendRequest({ + method: 'PUT', + url: '/pack', + data, + callback, + }); +}); + +module.exports.extract = promisify((data, callback) => { + sendRequest({ + method : 'PUT', + url : '/extract', + data, + callback, + }); +}); + +module.exports.mv = promisify((data, callback) => { + sendRequest({ + method : 'PUT', + url : '/mv', + data, + callback, + imgPosition, + }); +}); + +module.exports.Config = { + read: promisify((callback) => { + sendRequest({ + method: 'GET', + url: '/config', + callback, + imgPosition, + notLog: true, + }); + }), + + write: promisify((data, callback) => { sendRequest({ method: 'PATCH', - url: FS + url, + url: '/config', data, callback, imgPosition, }); - }; - - this.write = (url, data, callback) => { - const isFunc = itype.function(data); - - if (!callback && isFunc) { - callback = data; - data = null; - } - - sendRequest({ - method: 'PUT', - url: FS + url, - data, - callback, - imgPosition : { top: true }, - }); - }; - - this.read = (url, dataType, callback) => { - const notLog = !url.includes('?'); - const isFunc = itype.function(dataType); - - if (!callback && isFunc) { - callback = dataType; - dataType = 'text'; - } - + }), +}; + +module.exports.Markdown = { + read: promisify((url, callback) => { sendRequest({ method: 'GET', - url: FS + url, + url: '/markdown' + url, callback, - notLog, - dataType, + imgPosition, + notLog: true, }); - }; + }), - this.cp = (data, callback) => { + render: promisify((data, callback) => { sendRequest({ method: 'PUT', - url: '/cp', + url: '/markdown', data, callback, - imgPosition : { top: true }, + imgPosition, + notLog: true, }); - }; + }), +}; + +function sendRequest(params) { + const p = params; + const {prefixURL} = CloudCmd; - this.pack = (data, callback) => { - sendRequest({ - method : 'PUT', - url : '/pack', - data, - callback, - }); - }; + p.url = prefixURL + p.url; + p.url = encodeURI(p.url); - this.extract = function(data, callback) { - sendRequest({ - method : 'PUT', - url : '/extract', - data, - callback, - }); - }; + p.url = replaceHash(p.url); - this.mv = function(data, callback) { - sendRequest({ - method : 'PUT', - url : '/mv', - data, - callback, - imgPosition : { top: true }, - }); - }; - - this.Config = { - read(callback) { - sendRequest({ - method : 'GET', - url : '/config', - callback, - imgPosition : { top: true }, - notLog : true, - }); + load.ajax({ + method : p.method, + url : p.url, + data : p.data, + dataType : p.dataType, + error : (jqXHR) => { + const response = jqXHR.responseText; + + const { + statusText, + status, + } = jqXHR; + + const text = status === 404 ? response : statusText; + const encoded = encode(text); + + Images.show.error(encoded); + + setTimeout(() => { + DOM.Dialog.alert(encoded); + }, 100); + + p.callback(Error(text)); }, - - write(data, callback) { - sendRequest({ - method : 'PATCH', - url : '/config', - data, - callback, - imgPosition : { top: true }, - }); + success: (data) => { + Images.hide(); + + if (!p.notLog) + CloudCmd.log(data); + + p.callback(null, data); }, - }; - - this.Markdown = { - read(url, callback) { - sendRequest({ - method : 'GET', - url : '/markdown' + url, - callback, - imgPosition : { top: true }, - notLog : true, - }); - }, - - render(data, callback) { - sendRequest({ - method : 'PUT', - url : '/markdown', - data, - callback, - imgPosition : { top: true }, - notLog : true, - }); - }, - }; - - function sendRequest(params) { - const p = params; - const {prefixURL} = CloudCmd; - - p.url = prefixURL + p.url; - p.url = encodeURI(p.url); - - p.url = replaceHash(p.url); - - load.ajax({ - method : p.method, - url : p.url, - data : p.data, - dataType : p.dataType, - error : (jqXHR) => { - const response = jqXHR.responseText; - - const { - statusText, - status, - } = jqXHR; - - const text = status === 404 ? response : statusText; - const encoded = encode(text); - - Images.show.error(encoded); - - setTimeout(() => { - DOM.Dialog.alert(encoded); - }, 100); - - p.callback(Error(text)); - }, - success: (data) => { - Images.hide(); - - if (!p.notLog) - CloudCmd.log(data); - - p.callback(null, data); - }, - }); - } + }); } diff --git a/client/key/index.js b/client/key/index.js index 82156cdf..bdf4f5bf 100644 --- a/client/key/index.js +++ b/client/key/index.js @@ -286,7 +286,7 @@ function KeyProto() { exec.if(isSelected, () => { DOM.toggleSelectedFile(current); }, (callback) => { - DOM.loadCurrentSize(callback, current); + DOM.loadCurrentSize(current, callback); }); event.preventDefault(); diff --git a/client/modules/config.js b/client/modules/config.js index b22905dd..db9cbea5 100644 --- a/client/modules/config.js +++ b/client/modules/config.js @@ -217,10 +217,7 @@ function onSave(obj) { function saveHttp(obj) { const {RESTful} = DOM; - RESTful.Config.write(obj, (error) => { - if (error) - return; - + RESTful.Config.write(obj).then(() => { onSave(obj); }); } diff --git a/client/modules/menu.js b/client/modules/menu.js index ef1c6b67..fbb994e6 100644 --- a/client/modules/menu.js +++ b/client/modules/menu.js @@ -243,15 +243,11 @@ function _uploadTo(nameModule) { function uploadFromCloud() { Images.show.load('top'); - CloudCmd.execFromModule('Cloud', 'saveFile', (currentName, data) => { + CloudCmd.execFromModule('Cloud', 'saveFile', async (currentName, data) => { const path = DOM.getCurrentDirPath() + currentName; - RESTful.write(path, data, (error) => { - if (error) - return; - - CloudCmd.refresh({currentName}); - }); + await RESTful.write(path, data); + await CloudCmd.refresh({currentName}); }); } diff --git a/client/modules/operation/index.js b/client/modules/operation/index.js index c96dda52..cbbd82e2 100644 --- a/client/modules/operation/index.js +++ b/client/modules/operation/index.js @@ -12,6 +12,7 @@ const exec = require('execon'); const loadJS = require('load.js').js; const {encode} = require('../../../common/entity'); +const callbackify = require('../../../common/callbackify'); const RESTful = require('../../dom/rest'); const removeExtension = require('./remove-extension'); @@ -32,15 +33,12 @@ const Operation = {}; let Loaded; -let { - cp: copyFn, - mv: moveFn, - delete: deleteFn, - extract: extractFn, -} = RESTful; - -let packZipFn = RESTful.pack; -let packTarFn = RESTful.pack; +let copyFn = callbackify(RESTful.copy); +let moveFn = callbackify(RESTful.mv); +let deleteFn = callbackify(RESTful.delete); +let extractFn = callbackify(RESTful.extract); +let packZipFn = callbackify(RESTful.pack); +let packTarFn = callbackify(RESTful.pack); const Info = DOM.CurrentInfo; const showLoad = Images.show.load.bind(null, 'top'); @@ -185,12 +183,12 @@ function onConnect(operator) { } function onDisconnect() { - packZipFn = RESTful.pack; - packTarFn = RESTful.pack; - deleteFn = RESTful.delete; - copyFn = RESTful.cp; - moveFn = RESTful.mv; - extractFn = RESTful.extract; + packZipFn = callbackify(RESTful.pack); + packTarFn = callbackify(RESTful.pack); + deleteFn = callbackify(RESTful.delete); + copyFn = callbackify(RESTful.cp); + moveFn = callbackify(RESTful.mv); + extractFn = callbackify(RESTful.extract); } function getPacker(type) { diff --git a/client/modules/user-menu/default-menu.js b/client/modules/user-menu/default-menu.js index 3a0eaa23..52789421 100644 --- a/client/modules/user-menu/default-menu.js +++ b/client/modules/user-menu/default-menu.js @@ -14,7 +14,7 @@ module.exports = { await DOM.renameCurrent(); }, - 'C - Create User Menu File': async ({DOM, CloudCmd, tryToPromisify}) => { + 'C - Create User Menu File': async ({DOM, CloudCmd, tryToCatch}) => { const { Dialog, RESTful, @@ -24,7 +24,7 @@ module.exports = { const {dirPath} = CurrentInfo; const path = `${dirPath}/.cloudcmd.menu.js`; - const [e] = await tryToPromisify(RESTful.write, path, data); + const [e] = await tryToCatch(RESTful.write, path, data); if (e) return Dialog.alert(e); diff --git a/client/modules/user-menu/index.js b/client/modules/user-menu/index.js index 03a048f2..6b618a95 100644 --- a/client/modules/user-menu/index.js +++ b/client/modules/user-menu/index.js @@ -11,8 +11,6 @@ const createElement = require('@cloudcmd/create-element'); const tryCatch = require('try-catch'); const tryToCatch = require('try-to-catch/legacy'); -const tryToPromisify = require('../../../common/try-to-promisify.js'); - const Images = require('../../dom/images'); const Dialog = require('../../dom/dialog'); const getUserMenu = require('./get-user-menu'); @@ -124,7 +122,7 @@ const runUserMenu = async (value, options, userMenu) => { const [e] = await tryToCatch(userMenu[value], { DOM, CloudCmd, - tryToPromisify, + tryToCatch, }); if (e) diff --git a/common/callbackify.js b/common/callbackify.js new file mode 100644 index 00000000..f661eed7 --- /dev/null +++ b/common/callbackify.js @@ -0,0 +1,14 @@ +'use strict'; + +const success = (f) => (data) => f(null, data); + +module.exports = (promise) => { + return (...a) => { + const fn = a.pop(); + + promise(...a) + .then(success(fn)) + .catch(fn); + }; +}; + diff --git a/common/callbackify.spec.js b/common/callbackify.spec.js new file mode 100644 index 00000000..0b7f6d8c --- /dev/null +++ b/common/callbackify.spec.js @@ -0,0 +1,31 @@ +'use strict'; + +const test = require('supertape'); +const callbackify = require('./callbackify'); + +test('cloudcmd: common: callbackify: error', (t) => { + const promise = async () => { + throw Error('hello'); + }; + + const fn = callbackify(promise); + + fn((e) => { + t.equal(e.message, 'hello'); + t.end(); + }); +}); + +test('cloudcmd: common: callbackify', (t) => { + const promise = async () => { + return 'hi'; + }; + + const fn = callbackify(promise); + + fn((e, data) => { + t.equal(data, 'hi'); + t.end(); + }); +}); +