diff --git a/HELP.md b/HELP.md index 3f52b437..9be8dfb1 100644 --- a/HELP.md +++ b/HELP.md @@ -408,10 +408,22 @@ const plugins = [ __dirname + '/plugin.js' ]; +const filePicker = { + data: { + FilePicker: { + key: 'key' + } + } +}; + +// override option from json/modules.json +const modules = {filePicker}; + app.use(cloudcmd({ socket, /* used by Config, Edit (optional) and Console (required) */ config, /* config data (optional) */ plugins, /* optional */ + modules, /* optional */ })); server.listen(port); diff --git a/README.md b/README.md index 7a70f6a6..479fd17a 100644 --- a/README.md +++ b/README.md @@ -93,10 +93,22 @@ const plugins = [ __dirname + '/plugin.js' ]; +const filePicker = { + data: { + FilePicker: { + key: 'key', + } + } +}; + +// override option from json/modules.json +const modules = {filePicker}; + app.use(cloudcmd({ socket, /* used by Config, Edit (optional) and Console (required) */ config, /* config data (optional) */ plugins, /* optional */ + modules, /* optional */ })); server.listen(port); diff --git a/client/client.js b/client/client.js index ddbb7139..ec3bac2b 100644 --- a/client/client.js +++ b/client/client.js @@ -2,6 +2,7 @@ const itype = require('itype/legacy'); const rendy = require('rendy'); +const exec = require('execon'); const Images = require('./dom/images'); const join = require('join-io/www/join'); @@ -134,7 +135,7 @@ function CloudCmdProto(Util, DOM) { const prefix = CloudCmd.PREFIX; const pathFull = prefix + CloudCmd.DIRCLIENT_MODULES + path; - Util.exec(doBefore); + exec(doBefore); return DOM.load.js(pathFull, func || function(error) { @@ -172,7 +173,7 @@ function CloudCmdProto(Util, DOM) { */ this.init = (prefix, config) => { const func = () => { - Util.exec.series([ + exec.series([ initModules, baseInit, loadPlugins, @@ -208,7 +209,7 @@ function CloudCmdProto(Util, DOM) { if (config.onePanelMode) CloudCmd.MIN_ONE_PANEL_WIDTH = Infinity; - Util.exec.if(document.body.scrollIntoViewIfNeeded, func, funcBefore); + exec.if(document.body.scrollIntoViewIfNeeded, func, funcBefore); }; function loadPlugins(callback) { @@ -263,7 +264,7 @@ function CloudCmdProto(Util, DOM) { }; function initModules(callback) { - Util.exec.if(CloudCmd.Key, () => { + exec.if(CloudCmd.Key, () => { Key = new CloudCmd.Key(); CloudCmd.Key = Key; Key.bind(); @@ -278,13 +279,11 @@ function CloudCmdProto(Util, DOM) { }); Files.get('modules', (error, modules) => { - const STORAGE = 'storage'; const showLoad = Images.show.load; const doBefore = { - 'edit' : showLoad, - 'menu' : showLoad, - 'storage/_filepicker' : showLoad + 'edit': showLoad, + 'menu': showLoad, }; const load = (name, path, dobefore) => { @@ -302,32 +301,17 @@ function CloudCmdProto(Util, DOM) { if (!modules) modules = []; - modules.forEach((module) => { - const isStr = itype.string(module); - - if (!isStr) - return; - + modules.local.forEach((module) => { load(null, module, doBefore[module]); }); - const storageObj = Util.findObjByNameInArr(modules, STORAGE); - const mod = Util.getNamesFromObjArray(storageObj); - - mod.forEach((name) => { - const path = STORAGE + '/_' + name.toLowerCase(); - - load(name, path, doBefore[path]); - }); - callback(); }); } function baseInit(callback) { - var dirPath = '', - files = DOM.getFiles(); - + const files = DOM.getFiles(); + /* выделяем строку с первым файлом */ if (files) DOM.setCurrentFile(files[0], { @@ -337,8 +321,8 @@ function CloudCmdProto(Util, DOM) { history: !location.hash }); - dirPath = DOM.getCurrentDirPath(), - Listeners = CloudCmd.Listeners; + const dirPath = DOM.getCurrentDirPath(); + Listeners = CloudCmd.Listeners; Listeners.init(); Listeners.setOnPanel('left'); @@ -346,9 +330,9 @@ function CloudCmdProto(Util, DOM) { Listeners.initKeysPanel(); - Storage.get(dirPath, function(error, data) { + Storage.get(dirPath, (error, data) => { if (!data) { - data = getJSONfromFileTable(); + data = getJSONfromFileTable(); Storage.set(dirPath, data); } }); @@ -356,18 +340,16 @@ function CloudCmdProto(Util, DOM) { callback(); } - this.execFromModule = function(moduleName, funcName) { - var args = [].slice.call(arguments, 2), - obj = CloudCmd[moduleName], - isObj = itype.object(obj); + this.execFromModule = (moduleName, funcName, ...args) => { + const obj = CloudCmd[moduleName]; + const isObj = itype.object(obj); - Util.exec.if(isObj, - function() { - var obj = CloudCmd[moduleName], - func = obj[funcName]; - - func.apply(null, args); - }, obj); + exec.if(isObj, () => { + const obj = CloudCmd[moduleName]; + const func = obj[funcName]; + + func(...args); + }, obj); }; this.refresh = function(panelParam, options, callback) { @@ -437,7 +419,7 @@ function CloudCmdProto(Util, DOM) { DOM.setCurrentByName(name); } - Util.exec(callback); + exec(callback); }); }); }; @@ -511,7 +493,7 @@ function CloudCmdProto(Util, DOM) { }); } - Util.exec(callback); + exec(callback); }); } diff --git a/client/dom/load-remote.js b/client/dom/load-remote.js index 5622b693..e5debcce 100644 --- a/client/dom/load-remote.js +++ b/client/dom/load-remote.js @@ -19,9 +19,7 @@ module.exports = (name, options, callback = options) => { Files.get('modules', (error, modules) => { const online = config('online') && navigator.onLine; - - const remoteObj = findObjByNameInArr(modules, 'remote'); - const module = findObjByNameInArr(remoteObj, name); + const module = findObjByNameInArr(modules.remote, name); const isArray = itype.array(module.local); const version = module.version; diff --git a/client/modules/cloud.js b/client/modules/cloud.js index 5f3fb95a..f4879b5a 100644 --- a/client/modules/cloud.js +++ b/client/modules/cloud.js @@ -53,9 +53,7 @@ function loadFiles(callback) { load.js('//api.filepicker.io/v1/filepicker.js', () => { Files.get('modules', (error, modules) => { - const storage = Util.findObjByNameInArr(modules, 'storage'); - const picker = Util.findObjByNameInArr(storage, 'FilePicker'); - const key = picker && picker.key; + const {key} = modules.data.FilePicker; filepicker.setKey(key); diff --git a/common/util.js b/common/util.js index 7a5b5566..4af3d0b7 100644 --- a/common/util.js +++ b/common/util.js @@ -120,24 +120,6 @@ function UtilProto(exec) { return ret; }; - /** - * get values from Object Array name properties - * or - * @pObj - */ - this.getNamesFromObjArray = function(arr) { - var ret = []; - - if (!Array.isArray(arr)) - throw Error('arr should be array!'); - - ret = arr.map(function(item) { - return item.name; - }); - - return ret; - }; - /** * find object by name in arrray * diff --git a/json/modules.json b/json/modules.json index 31ed77a8..a1d375f9 100644 --- a/json/modules.json +++ b/json/modules.json @@ -1,57 +1,56 @@ -[ - "edit", - "edit-file", - "edit-names", - "menu", - "view", - "help", - "markdown", - "config", - "contact", - "upload", - "operation", - "konsole", - "terminal", - "cloud", [{ - "name": "remote", - "data": [{ - "name": "jquery", - "version": "3.1.1", - "local": "/modules/jquery/dist/jquery.min.js", - "remote": "//ajax.googleapis.com/ajax/libs/jquery/{{ version }}/jquery.min.js" - }, { - "name": "socket", - "version": "1.7.3", - "local": "/socket.io/socket.io.js", - "remote": "https://cdnjs.cloudflare.com/ajax/libs/socket.io/{{ version }}/socket.io.js" - }, { - "name": "fancybox", - "version": "2.1.6", - "local": [ - "/modules/fancybox/source/jquery.fancybox.css", - "/modules/fancybox/source/jquery.fancybox.pack.js" - ], - "remote": [ - "//cdnjs.cloudflare.com/ajax/libs/fancybox/{{ version }}/css/jquery.fancybox.min.css", - "//cdnjs.cloudflare.com/ajax/libs/fancybox/{{ version }}/js/jquery.fancybox.min.js" - ] - }, { - "name": "menu", - "version": "1.0.2", - "local": [ - "/modules/menu/menu-io.min.css", - "/modules/menu/menu-io.min.js" - ], - "remote": [ - "//cdn.jsdelivr.net/menu-io/{{ version }}/menu-io.min.js", - "//cdn.jsdelivr.net/menu-io/{{ version }}/menu-io.min.css" - ] - }] +{ + "local": [ + "edit", + "edit-file", + "edit-names", + "menu", + "view", + "help", + "markdown", + "config", + "contact", + "upload", + "operation", + "konsole", + "terminal", + "cloud" + ], + "remote": [{ + "name": "jquery", + "version": "3.1.1", + "local": "/modules/jquery/dist/jquery.min.js", + "remote": "//ajax.googleapis.com/ajax/libs/jquery/{{ version }}/jquery.min.js" }, { - "name": "storage", - "data": [{ - "name" : "FilePicker", - "key" : "AACq5fTfzRY2E_Rw_4kyaz" - }] - }] -] + "name": "socket", + "version": "1.7.3", + "local": "/socket.io/socket.io.js", + "remote": "https://cdnjs.cloudflare.com/ajax/libs/socket.io/{{ version }}/socket.io.js" + }, { + "name": "fancybox", + "version": "2.1.6", + "local": [ + "/modules/fancybox/source/jquery.fancybox.css", + "/modules/fancybox/source/jquery.fancybox.pack.js" + ], + "remote": [ + "//cdnjs.cloudflare.com/ajax/libs/fancybox/{{ version }}/css/jquery.fancybox.min.css", + "//cdnjs.cloudflare.com/ajax/libs/fancybox/{{ version }}/js/jquery.fancybox.min.js" + ] + }, { + "name": "menu", + "version": "1.0.2", + "local": [ + "/modules/menu/menu-io.min.css", + "/modules/menu/menu-io.min.js" + ], + "remote": [ + "//cdn.jsdelivr.net/menu-io/{{ version }}/menu-io.min.js", + "//cdn.jsdelivr.net/menu-io/{{ version }}/menu-io.min.css" + ] + }], + "data": { + "FilePicker": { + "key": "AACq5fTfzRY2E_Rw_4kyaz" + } + } +} diff --git a/package.json b/package.json index 04858920..cb0bf0f0 100644 --- a/package.json +++ b/package.json @@ -111,6 +111,7 @@ "copymitter": "^2.0.0", "criton": "^1.0.0", "currify": "^2.0.3", + "deepmerge": "^1.3.2", "deepword": "^1.3.0", "dword": "^4.1.0", "edward": "^4.2.0", diff --git a/server/cloudcmd.js b/server/cloudcmd.js index a7ebca66..3972cf1e 100644 --- a/server/cloudcmd.js +++ b/server/cloudcmd.js @@ -6,6 +6,7 @@ const DIR_ROOT = DIR + '../'; const cloudfunc = require(DIR + 'cloudfunc'); const auth = require(DIR + 'auth'); const config = require(DIR + 'config'); +const modulas = require(DIR + 'modulas'); const rest = require(DIR + 'rest'); const route = require(DIR + 'route'); const validate = require(DIR + 'validate'); @@ -48,6 +49,8 @@ module.exports = (params) => { const p = params || {}; const options = p.config || {}; const plugins = p.plugins; + const modules = p.modules; + const keys = Object.keys(options); let prefix; @@ -88,7 +91,7 @@ module.exports = (params) => { if (p.socket) listen(prefix, p.socket); - return cloudcmd(prefix, plugins); + return cloudcmd(prefix, plugins, modules); }; function defaultValue(value, previous) { @@ -183,7 +186,7 @@ function listen(prefix, socket) { }); } -function cloudcmd(prefix, plugins) { +function cloudcmd(prefix, plugins, modules) { const isOption = (name) => { return config(name); }; @@ -266,6 +269,8 @@ function cloudcmd(prefix, plugins) { auth(), config.middle, + modules && modulas(modules), + restafary({ prefix: cloudfunc.apiURL + '/fs', root diff --git a/server/modulas.js b/server/modulas.js new file mode 100644 index 00000000..4dd245a1 --- /dev/null +++ b/server/modulas.js @@ -0,0 +1,16 @@ +'use strict'; + +const deepmerge = require('deepmerge'); +const originalModules = require('../json/modules'); + +module.exports = (modules = {}) => { + const result = deepmerge(originalModules, modules); + + return (req, res, next) => { + if (req.url !== '/json/modules.json') + return next(); + + res.send(result); + }; +}; + diff --git a/server/server.js b/server/server.js index 5505fd4e..5fa7f31c 100644 --- a/server/server.js +++ b/server/server.js @@ -38,7 +38,7 @@ module.exports = (options) => { config: options, socket: io(server, { path: prefix() + '/socket.io' - }) + }), })); if (port < 0 || port > 65535) diff --git a/test/before.js b/test/before.js index f4b3c609..211b82eb 100644 --- a/test/before.js +++ b/test/before.js @@ -19,7 +19,7 @@ module.exports = (options, fn = options) => { options = {}; } - const {config, plugins} = options; + const {config, plugins, modules} = options; const app = express(); const server = http.createServer(app); @@ -35,7 +35,8 @@ module.exports = (options, fn = options) => { app.use(cloudcmd({ socket, plugins, - config: assign(defaultConfig(), config) + config: assign(defaultConfig(), config), + modules, })); server.listen(() => { diff --git a/test/server/modulas.js b/test/server/modulas.js new file mode 100644 index 00000000..3f7e08b9 --- /dev/null +++ b/test/server/modulas.js @@ -0,0 +1,67 @@ +'use strict'; + +const path = require('path'); +const test = require('tape'); + +const promisify = require('es6-promisify'); +const pullout = require('pullout'); +const request = require('request'); + +const modulesPath = path.join(__dirname, '..', '..', 'json', 'modules.json'); +const localModules = require(modulesPath); + +const warp = (fn, ...a) => (...b) => fn(...b, ...a); +const _pullout = promisify(pullout); + +const get = promisify((url, fn) => { + fn(null, request(url)); +}); + +const before = require('../before'); + +test('cloudcmd: modules', (t) => { + const modules = { + data: { + FilePicker: { + key: 'hello' + } + } + }; + + const expected = Object.assign({}, localModules); + + expected.data.FilePicker.key = 'hello'; + + before({modules}, (port, after) => { + get(`http://localhost:${port}/json/modules.json`) + .then(warp(_pullout, 'string')) + .then(JSON.parse) + .then((result) => { + t.deepEqual(result, expected, 'should equal'); + t.end(); + after(); + }) + .catch(console.error); + }); +}); + +test('cloudcmd: modules: wrong route', (t) => { + const modules = { + hello: 'world' + }; + + const expected = Object.assign({}, localModules, modules); + + before({modules}, (port, after) => { + get(`http://localhost:${port}/package.json`) + .then(warp(_pullout, 'string')) + .then(JSON.parse) + .then((result) => { + t.notDeepEqual(result, expected, 'should not be equal'); + t.end(); + after(); + }) + .catch(console.error); + }); +}); +