fix(config) configManager: totally move away from singletone

This commit is contained in:
coderaiser 2019-06-04 18:49:03 +03:00
parent 2abe7d688d
commit b6ed7da0a7
16 changed files with 127 additions and 115 deletions

15
HELP.md
View file

@ -671,8 +671,6 @@ const app = require('express')();
const port = 1337;
const prefix = '/';
const {createConfigManager} = cloudcmd;
const server = http.createServer(app);
const socket = io.listen(server, {
path: `{prefix}socket.io`
@ -699,13 +697,22 @@ const modules = {
filePicker,
};
const {
createConfigManager,
configPath,
} = cloudcmd;
const configManager = createConfigManager({
configPath,
}),
app.use(prefix, cloudcmd({
socket, // used by Config, Edit (optional) and Console (required)
config, // config data (optional)
plugins, // DEPRECATED, use User Menu instead
modules, // optional
configManager: createConfigManager(), //optional
}));
configManager, // optional
));
server.listen(port);
```

View file

@ -107,11 +107,21 @@ const modules = {
filePicker,
};
const {
createConfigManager,
configPath,
} = cloudcmd;
const configManager = createConfigManager({
configPath,
}),
app.use(prefix, cloudcmd({
socket, // used by Config, Edit (optional) and Console (required)
config, // config data (optional)
plugins, // DEPRECATED, use User Menu instead
modules, // optional
configManager, // optional
}));
server.listen(port);

View file

@ -6,10 +6,19 @@ const Info = require('../package');
const DIR_SERVER = '../server/';
const {promisify} = require('util');
const wraptile = require('wraptile');
const exit = require(DIR_SERVER + 'exit');
const config = require(DIR_SERVER + 'config');
const {
createConfig,
configPath,
} = require(DIR_SERVER + 'config');
const config = createConfig({
configPath,
});
const env = require(DIR_SERVER + 'env');
const prefixer = require(DIR_SERVER + '/prefixer');
@ -208,14 +217,14 @@ function main() {
if (args['show-config'])
showConfig();
const startWraped = wraptile(start, options);
const startWraped = wraptile(start, options, config);
const distribute = require('../server/distribute');
const importConfig = promisify(distribute.import);
const caller = (fn) => fn();
importConfig(config)
.then(args.save ? caller(config.save) : noop)
.then(startWraped(options));
.then(startWraped);
}
function validateRoot(root, config) {
@ -237,14 +246,14 @@ function version() {
console.log('v' + Info.version);
}
function start(config) {
function start(options, config) {
const SERVER = DIR_SERVER + 'server';
if (!args.server)
return;
const server = require(SERVER);
server(config);
server(options, config);
}
function port(arg) {

View file

@ -9,7 +9,11 @@ const fs = require('fs');
const cloudfunc = require(DIR_COMMON + 'cloudfunc');
const authentication = require(DIR + 'auth');
const defaultConfig = require(DIR + 'config');
const {
createConfig,
configPath,
} = require(DIR + 'config');
const modulas = require(DIR + 'modulas');
const userMenu = require(DIR + 'user-menu');
const rest = require(DIR + 'rest');
@ -45,7 +49,9 @@ const clean = (a) => a.filter(notEmpty);
module.exports = (params) => {
const p = params || {};
const options = p.config || {};
const config = p.configManager || defaultConfig;
const config = p.configManager || createConfig({
configPath,
});
const {
modules,
@ -90,8 +96,8 @@ module.exports = (params) => {
});
};
module.exports.createConfigManager = defaultConfig.create;
module.exports.configPath = defaultConfig.path;
module.exports.createConfigManager = createConfig;
module.exports.configPath = configPath;
module.exports._getIndexPath = getIndexPath;

View file

@ -29,28 +29,29 @@ const resolve = Promise.resolve.bind(Promise);
const formatMsg = currify((a, b) => CloudFunc.formatMsg(a, b));
const {apiURL} = CloudFunc;
const changeEmitter = new Emitter();
const key = (a) => Object.keys(a).pop();
const ConfigPath = path.join(DIR, 'json/config.json');
const ConfigHome = path.join(HOME, '.cloudcmd.json');
const config = read();
const connection = currify(_connection);
const connectionWraped = wraptile(_connection);
const middle = currify(_middle);
function read(filename = ConfigHome) {
const readjsonSync = (name) => {
return jju.parse(fs.readFileSync(name, 'utf8'), {
mode: 'json',
});
};
const readjsonSync = (name) => {
return jju.parse(fs.readFileSync(name, 'utf8'), {
mode: 'json',
});
};
const rootConfig = readjsonSync(ConfigPath);
const [error, configHome] = tryCatch(readjsonSync, ConfigHome);
const rootConfig = readjsonSync(ConfigPath);
function read(filename) {
if (!filename)
return rootConfig;
const [error, configHome] = tryCatch(readjsonSync, filename);
if (error && error.code !== 'ENOENT')
exit(`cloudcmd --config ${filename}: ${error.message}`);
@ -61,18 +62,8 @@ function read(filename = ConfigHome) {
};
}
module.exports = manage;
module.exports.create = create;
module.exports.middle = middle(manage);
module.exports.subscribe = (fn) => {
changeEmitter.on('change', fn);
};
module.exports.path = ConfigHome;
module.exports.unsubscribe = (fn) => {
changeEmitter.removeListener('change', fn);
};
module.exports.createConfig = createConfig;
module.exports.configPath = ConfigHome;
const manageListen = currify((manage, socket, auth) => {
if (!manage('configDialog'))
@ -83,23 +74,6 @@ const manageListen = currify((manage, socket, auth) => {
return middle;
});
function manage(key, value) {
if (!key)
return;
if (key === '*')
return config;
if (value === undefined)
return config[key];
config[key] = value;
changeEmitter.emit('change', key, value);
return `${key} = ${value}`;
}
function initWrite(filename, configManager) {
if (filename)
return write.bind(null, filename, configManager);
@ -107,15 +81,9 @@ function initWrite(filename, configManager) {
return resolve;
}
function readConfig(filename) {
if (filename)
return read(filename);
return config;
}
function create({filename} = {}) {
function createConfig({configPath} = {}) {
const config = {};
const changeEmitter = new Emitter();
const configManager = (key, value) => {
if (key === '*')
@ -127,26 +95,28 @@ function create({filename} = {}) {
return config[key];
config[key] = value;
changeEmitter.emit('change', key, value);
return `${key} = ${value}`;
};
spread(configManager);
Object.assign(config, readConfig(filename));
Object.assign(config, read(configPath));
configManager.middle = middle(configManager);
configManager.listen = manageListen(configManager);
configManager.write = initWrite(filename, configManager);
configManager.write = initWrite(configPath, configManager);
configManager.subscribe = (fn) => {
changeEmitter.on('change', fn);
};
configManager.unsubscribe = (fn) => {
// replace to off on node v10
changeEmitter.removeListener('change', fn);
};
return configManager;
}
function spread(store) {
const entries = Object.entries(config);
for (const [name, value] of entries) {
store(name, value);
}
}
const write = async (filename, config) => {
return writejson(filename, config('*'), {mode: 0o600});
};

View file

@ -6,11 +6,11 @@ const stub = require('@cloudcmd/stub');
const root = '../';
const configPath = './config';
const config = require(configPath);
const {
createConfig,
_cryptoPass,
create,
} = config;
} = require(configPath);
const config = createConfig();
const {apiURL} = require(root + 'common/cloudfunc');
@ -24,14 +24,16 @@ test('config: manage', (t) => {
test('config: manage: get', async (t) => {
const editor = 'deepword';
const configManager = createConfig();
const {done} = await connect({
config: {editor},
configManager,
});
done();
t.equal(config('editor'), editor, 'should get config');
t.equal(configManager('editor'), editor, 'should get config');
t.end();
});
@ -63,7 +65,7 @@ test('config: cryptoPass: no password', (t) => {
hello: 'world',
};
const config = create();
const config = createConfig();
const result = _cryptoPass(config, json);
t.deepEqual(result, [config, json], 'should not change json');
@ -81,7 +83,7 @@ test('config: cryptoPass', (t) => {
password,
};
const config = create();
const config = createConfig();
const result = _cryptoPass(config, json);
t.deepEqual(result, [config, expected], 'should crypt password');

View file

@ -4,7 +4,7 @@ const test = require('supertape');
const io = require('socket.io-client');
const {connect} = require('../../test/before');
const config = require('../config');
const config = require('../config').createConfig();
test('distribute: export', async (t) => {
const defaultConfig = {
@ -17,6 +17,7 @@ test('distribute: export', async (t) => {
const {port, done} = await connect({
config: defaultConfig,
configManager: config,
});
const url = `http://localhost:${port}/distribute?port=${1111}`;

View file

@ -50,7 +50,9 @@ test('distribute: import: received: no error', async (t) => {
});
test('distribute: import: received', async (t) => {
const configManager = createConfigManager();
const {done, port} = await connect({
configManager,
config: {
name: 'bill',
import: true,
@ -62,10 +64,9 @@ test('distribute: import: received', async (t) => {
},
});
const config = createConfigManager();
config('importUrl', `http://localhost:${port}`);
configManager('importUrl', `http://localhost:${port}`);
const {status} = await distribute.import(config);
const {status} = await distribute.import(configManager);
await done();
t.equal(status, 'received','should equal');
@ -73,7 +74,9 @@ test('distribute: import: received', async (t) => {
});
test('distribute: import: received: auth: reject', async (t) => {
const configManager = createConfigManager();
const {done, port} = await connect({
configManager,
config: {
name: 'bill',
import: true,
@ -85,10 +88,9 @@ test('distribute: import: received: auth: reject', async (t) => {
},
});
const config = createConfigManager();
config('importUrl', `http://localhost:${port}`);
configManager('importUrl', `http://localhost:${port}`);
const {status} = await distribute.import(config);
const {status} = await distribute.import(configManager);
await done();
t.equal(status, 'reject', 'should equal');
@ -96,7 +98,9 @@ test('distribute: import: received: auth: reject', async (t) => {
});
test('distribute: import: received: auth: accept', async (t) => {
const configManager = createConfigManager();
const {done, port} = await connect({
configManager,
config: {
name: 'bill',
import: true,
@ -108,10 +112,9 @@ test('distribute: import: received: auth: accept', async (t) => {
},
});
const config = createConfigManager();
config('importUrl', `http://localhost:${port}`);
configManager('importUrl', `http://localhost:${port}`);
const {status} = await distribute.import(config);
const {status} = await distribute.import(configManager);
await done();
t.equal(status, 'received','should equal');
@ -119,7 +122,9 @@ test('distribute: import: received: auth: accept', async (t) => {
});
test('distribute: import: received: no name', async (t) => {
const configManager = createConfigManager();
const {done, port} = await connect({
configManager,
config: {
name: '',
import: true,
@ -129,10 +134,9 @@ test('distribute: import: received: no name', async (t) => {
},
});
const config = createConfigManager();
config('importUrl', `http://localhost:${port}`);
configManager('importUrl', `http://localhost:${port}`);
const {status} = await distribute.import(config);
const {status} = await distribute.import(configManager);
await done();
t.equal(status, 'received','should equal');
@ -140,7 +144,9 @@ test('distribute: import: received: no name', async (t) => {
});
test('distribute: import: error', async (t) => {
const configManager = createConfigManager();
const {done} = await connect({
configManager,
config: {
import: true,
export: false,
@ -149,10 +155,9 @@ test('distribute: import: error', async (t) => {
},
});
const config = createConfigManager();
config('importUrl', `http://localhost:0`);
configManager('importUrl', `http://localhost:0`);
const {status} = await distribute.import(config, {
const {status} = await distribute.import(configManager, {
reconnection: false,
});
@ -163,7 +168,9 @@ test('distribute: import: error', async (t) => {
});
test('distribute: import: config:change: no export', async (t) => {
const configManager = createConfigManager();
const {done} = await connect({
configManager,
config: {
import: true,
export: false,
@ -172,9 +179,7 @@ test('distribute: import: config:change: no export', async (t) => {
},
});
const config = createConfigManager();
const {status} = await distribute.import(config, {
const {status} = await distribute.import(configManager, {
reconnection: false,
});

View file

@ -2,7 +2,7 @@
const test = require('supertape');
const log = require('./log');
const config = require('../config');
const {createConfig} = require('../config');
test('distribute: log: getMessage', (t) => {
const e = 'hello';
@ -23,7 +23,9 @@ test('distribute: log: getMessage: message', (t) => {
});
test('distribute: log: config', (t) => {
const config = createConfig();
const logOriginal = config('log');
config('log', true);
log('log', 'test message');
config('log', logOriginal);

View file

@ -10,18 +10,15 @@ const flop = require('flop');
const ponse = require('ponse');
const rendy = require('rendy');
const format = require('format-io');
const squad = require('squad');
const apart = require('apart');
const currify = require('currify');
const tryToCatch = require('try-to-catch');
const once = require('once');
const config = require(DIR_SERVER + 'config');
const root = require(DIR_SERVER + 'root');
const prefixer = require(DIR_SERVER + 'prefixer');
const CloudFunc = require(DIR_COMMON + 'cloudfunc');
const prefix = squad(prefixer, apart(config, 'prefix'));
const getPrefix = (config) => prefixer(config('prefix'));
const onceRequire = once(require);
@ -172,7 +169,7 @@ function indexProcessing(config, options) {
name,
}),
fm: left + right,
prefix: prefix(),
prefix: getPrefix(config),
config: JSON.stringify(config('*')),
columns: Columns[config('columns')],
});
@ -183,7 +180,7 @@ function indexProcessing(config, options) {
function buildIndex(config, html, json) {
const panel = CloudFunc.buildFromJSON({
data: json,
prefix: prefix(),
prefix: getPrefix(config),
template: Template,
});

View file

@ -321,7 +321,10 @@ test('cloudcmd: route: sendIndex: encode', async (t) => {
reRequire(routePath);
const cloudcmd = reRequire(cloudcmdPath);
const {request} = serveOnce(cloudcmd);
const {request} = serveOnce(cloudcmd, {
configManager: createConfigManager(),
});
const {body} = await request.get('/');
mockRequire.stop('flop');
@ -411,6 +414,7 @@ test('cloudcmd: route: no termianl: /fs', async (t) => {
const options = {
config,
configManager: createConfigManager(),
};
const {request} = serveOnce(cloudcmd);

View file

@ -10,8 +10,6 @@ const squad = require('squad');
const tryToCatch = require('try-to-catch');
const wraptile = require('wraptile');
const config = require(DIR_SERVER + 'config');
const two = currify((f, a, b) => f(a, b));
const exit = require(DIR_SERVER + 'exit');
@ -32,7 +30,7 @@ const io = require('socket.io');
const tryRequire = require('tryrequire');
const logger = tryRequire('morgan');
module.exports = async (options) => {
module.exports = async (options, config) => {
const prefix = config('prefix');
const port = process.env.PORT || /* c9 */
config('port');
@ -57,9 +55,7 @@ module.exports = async (options) => {
app.use(prefix, cloudcmd({
config: options,
socket: socketServer,
configManager: cloudcmd.createConfigManager({
filename: cloudcmd.configPath,
}),
configManager: config,
}));
if (port < 0 || port > 65535)

View file

@ -24,6 +24,7 @@ function before(options, fn = options) {
config,
plugins,
modules,
configManager,
} = options;
const app = express();
@ -41,6 +42,7 @@ function before(options, fn = options) {
socket,
plugins,
config: assign(defaultConfig(), config),
configManager,
modules,
}));

View file

@ -21,13 +21,15 @@ const fixture = {
const defaultOptions = {
config: {
auth: false,
root: join(__dirname, '..'),
},
};
const cloudcmd = require(cloudcmdPath);
const serveOnce = require('serve-once');
const {request} = serveOnce(cloudcmd);
const {request} = serveOnce(cloudcmd, defaultOptions);
const once = promisify((name, extract, fn) => {
extract.once(name, (header, stream) => {
@ -76,7 +78,6 @@ test('cloudcmd: rest: pack: tar: put: file', async (t) => {
const name = String(Math.random()) + '.tar.gz';
const cloudcmd = reRequire(cloudcmdPath);
const {request} = serveOnce(cloudcmd, defaultOptions);
await request.put(`/api/v1/pack`, {

View file

@ -7,7 +7,7 @@ const io = require('socket.io-client');
const configPath = path.join(__dirname, '../..', 'server', 'config');
const {connect} = require('../before');
const configFn = require(configPath);
const configFn = require(configPath).createConfig();
test('cloudcmd: console: enabled', async (t) => {
const config = {

View file

@ -4,7 +4,7 @@ const test = require('supertape');
const criton = require('criton');
const cloudcmd = require('..');
const configFn = require('../server/config');
const configFn = cloudcmd.createConfigManager();
const config = {
auth: false,