gcl
Version:
码农村nodejs类库,完成解决回调陷阱,配置框架,IOC框架,统一多DB访问框架,可扩展日志框架和io/db/net/thread/pool 克隆表达式,加解密算法等等一系列基础类库和算法的实现
422 lines (414 loc) • 16 kB
JavaScript
import V from '../common/tool';
import F from 'fs';
import I from './tool';
import P from 'path';
/**
* todo
* Config基础存储类 拥有getValue(k),setValue(k,v),merge(config)等方法
* @param
*/
export const Config = class {
constructor() {
let _ = this;
_.data = {};
}
getValue(key) {
return this.data[key];
}
setValue(key, value) {
this.data[key] = value;
}
merge(config) {
this.data = V.merge(this.data, config.data);
}
};
/**
* ConfigConvert的基础类模型说明 基本上只有接口定义 未实现任何功能
*
*/
export const ConfigConvert = class {
constructor() {
this.needConfig = false;
}
toConfig() { return null }
toStrings(config) {
return "";
}
};
/**
* ConfigConvert的基本定义负责将一个KeyValueMap转换成真实的config
*/
export const AppSettingsConfigConvert = class extends ConfigConvert {
constructor() {
super();
}
toConfig(val) {
let config = new Config();
val = V.getValue(val, {});
for (let k in val) {
let v = val[k];
config.data[k] = v;
}
return config;
}
};
export const AppSettings = (cm, key) => cm.getConfigValue('AppSettings', key);
/**
* Config的代理,用于调用configmanger完成config的获取与赋值操作,保护ConfigManager的调用完整逻辑
*/
export const ProxyConfig = class extends Config {
constructor(config, confkey) {
super();
const { _, __ } = pri(this, { config: config, confkey: confkey });
}
getValue(key) {
const { _, __ } = pri(this);
return __.config.getConfigValue(__.confkey, key);
}
setValue(key, value) {
const { _, __ } = pri(this);
return __.config.setConfigValue(__.confkey, key, value);
}
merge(config) {
V.shoeException("不支持的功能merge")
}
};
/**
* ConfigManager Config类库的核心类,负责完成链式连接,提供统一的接口供ConfigManager 获取值,并监控配置的变更
*/
export const ConfigManager = class extends Config {
constructor(parent, resource) {
super();
const { _, __ } = pri(this, { dic: {}, data: {}, hasUpdate: false, parent, resource });
if (!parent) {
__.dic['ConfigConverts'] = new ___.ConfigConvert();
}
_.adapter = ___.getConfigAdapter();
_.adapter.fill(_, __.dic, __.resource);
}
getConfig(key) {
const { _, __ } = pri(this);
__.data[key] = __.data[key] || new ProxyConfig(_, key);
return __.data[key];
}
getConfigValue(config, key) {
const { _, __ } = pri(this);
if (!__.dic[config]) return ___.getValue(__.parent, config, key);
else {
return __.dic[config].getValue(key);
}
}
setConfigValue(config, key, value) {
const { _, __ } = pri(this);
__.hasUpdate = true;
if (!__.dic[config])
___.setValue(__.parent, config, key, value);
else
__.dic[config].setValue(key, value);
}
update() {
const { _, __ } = pri(this);
if (__.hasUpdate) _.adapter.update(_, __.dic, __.resource);
}
refill() {
const { _, __ } = pri(this);
__.dic = {};
_.adapter.fill(_, __.dic, __.resource);
}
};
export const ConfigAdapter = class {
constructor() {}
fill(cm, dic, resource) {
resource = resource.load();
if (typeof(resource) == 'string') {
//拿到配置的JSON数据 比JSON不要求严格格式
resource = eval('(' + resource + ')');
}
for (var i in resource) {
if (i == 'base') continue; //放置base属性被误读
var convert = cm.getConfigValue('ConfigConverts', i);
if (!convert) {
V.showException('ConfigConverts 没有找到对应的解析器' + i);
} else {
var val = convert.toConfig(resource[i], convert.needConfig ? cm : null);
if (!val) {
console.log('ConfigConverts 解析失败' + i + ':');
console.log(resource[i]);
} else {
if (dic[i]) {
dic[i].merge(val);
} else {
dic[i] = val;
}
}
}
}
}
update(cm, dic, resource) {
var data = {};
for (var i in dic) {
var convert = cm.getConfigValue('ConfigConverts', i);
if (!convert) {
V.showException('ConfigConverts 没有找到对应的解析器' + i);
} else {
var val = convert.toString(dic[i]);
if (!val) {
console.log('ConfigConverts 解析失败' + i + ':');
console.log(dic[i]);
} else {
data[i] = val;
}
}
}
resource.save(V.toJsonString(data));
}
};
export const getConfigManagerFromObj = function(cm, obj) {
if (!obj) return cm;
return new ConfigManager(cm, (function() {
return new class {
constructor() {
const { __ } = pri(this);
if (typeof(obj) === 'string') {
obj = eval('(' + obj + ')');
}
}
load() { return obj; }
save() { V.showException('getConfigManagerFromObj不支持此方式'); }
};
})());
};
export const getConfigManagerFromJS = function(cm, path) {
if (!path) return cm;
return new ConfigManager(cm, (function() {
return new class {
constructor() {
if (typeof(path) === 'string') {
path = V.include(path);
}
}
load() { return path; }
save() { V.showException('getConfigManagerFromJS不支持此方式'); }
};
})());
};
/**
* 异步获取配置文件
* @param {*} cm
* @param {*} path
*/
export const getConfigManagerFromFile = async function(cm, path) {
if (!path) return cm;
let config = {};
let cm2 = null;
let fill = async() => {
var paths = V.isArray(path) ? path : path.split(';');
await V.each(paths, async v => {
try {
const _v = v;
if (!(v.startWith('/') || v.startWith('\\')))
v = (I.execDir() + V.environment.splitChar + v.trim('/').trim('\\'));
else
v = I.formatPath(v);
let cont = (await V.callback(F.readFile, F, v) || '{}');
cont = eval('(' + cont.toString('utf-8').replace(/(\s+\/\/[^\r\n]*[\r\n]*)+|[\r\n\s]+/g, ' ') + ')');
V.merge(config, cont, true);
F.watchFile(_v, fill);
return false;
} catch (e) {
console.log(`读取文件${v}错误:` + e.message);
throw new Error(`读取文件${path + '\\' + v}错误:` + e.message);
}
}, true).then(() => {
if (cm2) cm2.refill();
else cm2 = new ConfigManager(cm, new class {
load() { return config; };
save() { V.showException('getConfigManagerFromFile不支持此方式'); }
});
});
return cm2;
};
await fill();
return cm2;
};
/**
* 同步获取配置文件
* @param {*} cm
* @param {*} path
*/
export const getConfigManagerFromFileSync = function(cm, path) {
if (!path) return cm;
let config = {};
let cm2 = null;
let fill = () => {
let paths = V.isArray(path) ? path : path.split(';');
paths.forEach(v => {
try {
const _v = v;
if (!(v.startWith('/') || v.startWith('\\')))
v = (I.execDir() + V.environment.splitChar + v.trim('/').trim('\\'));
else
v = I.formatPath(v);
let cont = F.readFileSync(v) || '{}';
cont = eval('(' + cont.toString('utf-8').replace(/(\s+\/\/[^\r\n]*[\r\n]*)+|[\r\n\s]+/g, ' ') + ')');
V.merge(config, cont, true);
F.watchFile(_v, fill);
return;
} catch (e) {
console.log(`读取文件${v}错误:` + e.message);
throw new Error(`读取文件${path + '\\' + v}错误:` + e.message);
}
});
if (cm2) cm2.refill();
else cm2 = new ConfigManager(cm, new class {
load() { return config; };
save() { V.showException('getConfigManagerFromFileSync不支持此方式'); }
});
return cm2;
};
fill();
return cm2;
};
export const getConfigManagerFromDir = async function(cm, path, regex = '^\\S+\\.npcf$') {
if (!path) return cm;
if (path.startWith('/') || path.startWith('\\'))
path = (P.parse(P.resolve(P.normalize(process.mainModule.filename))).dir + V.environment.splitChar + path.trim('/').trim('\\'));
else
path = I.formatPath(path);
let config = {};
let cm2 = null;
let fill = async() => {
var data = await V.callback(F.readdir, F, path) || [];
const reg = new RegExp(regex);
await V.each(data, async v => {
try {
if (!reg.test(v)) return false;
let cont = (await V.callback(F.readFile, F, path + V.environment.splitChar + v) || '{}');
cont = eval('(' + cont.toString('utf-8').replace(/(\s+\/\/[^\r\n]*[\r\n]*)+|[\r\n\s]+/g, ' ') + ')');
V.merge(config, cont, true);
return false;
} catch (e) {
console.log(`读取文件${path + V.environment.splitChar + v}错误:` + e.message);
throw new Error(`读取文件${path + V.environment.splitChar + v}错误:` + e.message);
}
}, true).then(() => {
if (cm2) cm2.refill();
else cm2 = new ConfigManager(cm, new class {
load() { return config; };
save() { V.showException('getConfigManagerFromFileSync不支持此方式'); }
});
});
return cm2;
};
F.watchFile(path, fill);
await fill();
return cm2;
};
export const getConfigManagerFromDirSync = function(cm, path, regex = '^\\S+\\.npcf$') {
if (!path) return cm;
if (path.startWith('/') || path.startWith('\\'))
path = (P.parse(P.resolve(P.normalize(process.mainModule.filename))).dir + V.environment.splitChar + path.trim('/').trim('\\'));
else
path = I.formatPath(path);
let config = {};
let cm2 = null;
let fill = () => {
let data = F.readdirSync(path) || [];
const reg = new RegExp(regex);
data.forEach(v => {
try {
if (!reg.test(v)) return;
let cont = F.readFileSync(path + V.environment.splitChar + v) || '{}';
cont = eval('(' + cont.toString('utf-8').replace(/(\s+\/\/[^\r\n]*[\r\n]*)+|[\r\n\s]+/g, ' ') + ')');
V.merge(config, cont, true);
return;
} catch (e) {
console.log(`读取文件${path + V.environment.splitChar + v}错误:` + e.message);
throw new Error(`读取文件${path + '\\' + v}错误:` + e.message);
}
});
if (cm2) cm2.refill();
else cm2 = new ConfigManager(cm, new class {
load() { return config; };
save() { V.showException('getConfigManagerFromFileSync不支持此方式'); }
});
return cm2;
};
F.watchFile(path, fill);
fill();
return cm2;
};
export const getBaseConfigManager = async() => {
if (___.baseConfig) {} else ___.baseConfig = await getConfigManagerFromFile(null, 'base.npcf');
return ___.baseConfig;
};
export const getApplicationConfigManager = async() => {
if (___.appConfig) {} else ___.appConfig = await getApplicationConfigManagerFromFile(P.parse(process.mainModule.filename).name + '.npcf');
return ___.appConfig;
};
export const getApplicationConfigManagerFromJS = async path => getConfigManagerFromJS(await getBaseConfigManager(), path);
export const getApplicationConfigManagerFromObj = async obj => getConfigManagerFromObj(await getBaseConfigManager(), obj);
export const getApplicationConfigManagerFromFile = async path => getConfigManagerFromFile(await getBaseConfigManager(), path);
export const getApplicationConfigManagerFromDir = async path => getConfigManagerFromDir(await getBaseConfigManager(), path);
export const getBaseConfigManagerSync = () => {
if (___.baseConfig) {} else ___.baseConfig = getConfigManagerFromFileSync(null, 'base.npcf');
return ___.baseConfig;
};
export const getApplicationConfigManagerSync = () => {
if (___.appConfig) {} else ___.appConfig = getApplicationConfigManagerFromFileSync(P.parse(process.mainModule.filename).name + '.npcf');
return ___.appConfig;
};
export const getApplicationConfigManagerFromFileSync = path => getConfigManagerFromFileSync(getBaseConfigManagerSync(), path);
export const getApplicationConfigManagerFromDirSync = path => getConfigManagerFromDirSync(getBaseConfigManagerSync(), path);
const ___ = {
Configs: {
ConfigConverts: {
AppSettings: { type: 'AppSettingsConfigConvert', path: '/com/coooders/io/config' }
}
},
getValue: (parent, config, key) => parent ? parent.getConfigValue(config, key) : null,
setValue: (parent, config, key, value) => parent ? parent.setConfigValue(config, key, value) : null,
ConfigConvert: class extends Config {
constructor() {
super();
this.data['ConfigConverts'] = this;
}
toConfig(val) {
return new class extends Config {
constructor() {
super();
let _ = this;
for (var i in val) {
if (i == 'base') {
_.basepath = val.base ? val.base : null;
___.Configs.base = _.basepath;
continue;
}
_.data[i] = (function() {
const conf = val[i];
//create要求是类定义 不能是 类名!!
//require 如何获取全局的参数或者npm后的参数 全文件地址可以不带盘符 或者相对路径查找文件
//注意使用了地址的类方法
const cls = V.include(conf.path, _.basepath);
if (conf.type && cls[conf.type])
return V.create2(cls[conf.type], []);
else return V.create2(cls, []);
})();
}
}
};
}
toStrings(config) {
V.showException('基础解析器不支持此功能');
}
},
getConfigAdapter: function() {
if (!ConfigAdapter.instance) {
ConfigAdapter.instance = new ConfigAdapter();
}
return ConfigAdapter.instance;
}
};
export const Configs = ___.Configs;
export default { Configs, Config, ConfigConvert, AppSettingsConfigConvert, ProxyConfig, AppSettings, ConfigManager, ConfigAdapter, getConfigManagerFromJS, getConfigManagerFromObj, getConfigManagerFromFile, getConfigManagerFromDir, getBaseConfigManager, getApplicationConfigManager, getApplicationConfigManagerFromDir, getApplicationConfigManagerFromFile, getApplicationConfigManagerFromJS, getApplicationConfigManagerFromObj, getBaseConfigManagerSync, getApplicationConfigManagerSync, getConfigManagerFromFileSync, getConfigManagerFromDirSync };
const pri = V.pris();