sdg
Version:
pomelo ts
407 lines • 26.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const fs_1 = tslib_1.__importDefault(require("fs"));
const path_1 = tslib_1.__importDefault(require("path"));
const lodash_1 = tslib_1.__importDefault(require("lodash"));
const events_1 = require("events");
const base_1 = tslib_1.__importDefault(require("./base"));
const Constants = tslib_1.__importStar(require("./util/constants"));
const appUtil_1 = require("./util/appUtil");
const events_2 = tslib_1.__importDefault(require("./util/events"));
class Application extends base_1.default {
constructor(opts) {
super();
this.usedPlugins = [];
this.opts = opts;
this.loaded = [];
// @ts-ignore
this.components = {};
this.settings = {};
this.serverInfo = opts.serverInfo;
this.logger = opts.logger || console;
// @ts-ignore
const base = opts.base || path_1.default.dirname(require.main.filename);
this.set(Constants.RESERVED.BASE, base, true);
this.initEvent();
this.restore();
this.initCurServerInfo();
this.loadMaster();
}
initCurServerInfo() {
this.serverId = this.getServerId();
this.serverType = this.getServerType();
}
getCurServer() {
return this.serverInfo;
}
initEvent() {
this.event = new events_1.EventEmitter();
this.event.on(Constants.COMMAND.KILL, () => { });
}
restore() {
this.servers = {};
this.serverTypeMaps = {};
}
async start() {
this.startTime = Date.now();
appUtil_1.loadDefaultComponents(this);
await appUtil_1.optComponents(this.loaded, Constants.RESERVED.START);
await this.afterStart();
}
async afterStart() {
await appUtil_1.optComponents(this.loaded, Constants.RESERVED.AFTER_START);
this.logger.info(`[${this.serverId}] startup in ${Date.now() - this.startTime} ms`);
}
/**
* server管理器,这里只管理serverInfo,具体逻辑交给proxy
* @param servers
*/
addServers(servers) {
if (!servers || !servers.length)
return;
for (const server of servers) {
if (server.id === this.serverId)
continue;
this.servers[server.id] = server;
const serverType = this.getServerType(server);
let maps = this.serverTypeMaps[serverType];
if (!maps)
this.serverTypeMaps[serverType] = maps = [];
this.replaceServer(maps, server);
}
// 通知proxy更新对应server代理
this.event.emit(events_2.default.ADD_SERVERS, servers);
}
removeServers(ids) {
for (const id of ids) {
const server = this.servers[id];
if (!server)
continue;
delete this.servers[id];
lodash_1.default.remove(this.getServersByType(server.type), { id });
}
this.event.emit(events_2.default.REMOVE_SERVERS, ids);
}
replaceServers(servers) {
if (!servers)
return;
this.servers = servers;
const serverArray = [];
this.serverTypeMaps = {};
lodash_1.default.forOwn(servers, (server) => {
const serverType = this.getServerType(server);
if (!this.serverTypeMaps[serverType])
this.serverTypeMaps[serverType] = [];
this.serverTypeMaps[serverType].push(server);
});
this.event.emit(events_2.default.REPLACE_SERVERS, serverArray);
}
/**
* 更新serverInfo的配置信息
* @param serverInfo
*/
updateServerInfo(serverInfo) {
const serverId = serverInfo.id;
if (serverId === this.serverId) {
this.serverInfo = serverInfo;
this.initCurServerInfo();
}
if (this.servers[serverId]) {
this.servers[serverId] = serverInfo;
const serverTypes = this.getServersByType(serverInfo.type);
const idx = lodash_1.default.findIndex(serverTypes, { id: serverId });
if (idx !== -1)
serverTypes[idx] = serverInfo;
}
}
set(setting, val, attach) {
this.settings[setting] = val;
if (attach)
this[setting] = val;
return this;
}
get(setting) {
return this.settings[setting];
}
/**
* Set the route function for the specified server type.
*
* Examples:
*
* app.route('area', routeFunc);
*
* let routeFunc = function(session, msg, app, cb) {
* // all request to area would be route to the first area server
* let areas = app.getServersByType('area');
* cb(null, areas[0].id);
* };
*
* @param {String} serverType server type string
* @param {Function} routeFunc route function. routeFunc(session, msg, app, cb)
* @return {Object} current application instance for chain invoking
* @memberOf Application
*/
route(routeFunc, serverType) {
if (!routeFunc)
throw 'routeFunction must provide';
let routes = this.get(Constants.KEYWORDS.ROUTE);
if (!routes) {
routes = {};
this.set(Constants.KEYWORDS.ROUTE, routes);
}
if (serverType) {
routes[serverType] = routeFunc;
}
else {
routes.default = routeFunc;
}
return this;
}
configure(env, type, fn) {
let cb = fn;
if (typeof env === 'function') {
cb = env;
env = Constants.RESERVED.ALL;
}
if (typeof type === 'function') {
cb = type;
type = Constants.RESERVED.ALL;
}
if (env === Constants.RESERVED.ALL || this.contains(this.settings.env, env)) {
if (type === Constants.RESERVED.ALL || this.contains(this.settings.serverType, type)) {
cb.call(this).then();
}
}
return this;
}
registerAdmin(moduleId, module, opts) {
let modules = this.get(Constants.KEYWORDS.MODULE);
if (!modules) {
modules = {};
this.set(Constants.KEYWORDS.MODULE, modules);
}
if (typeof moduleId !== 'string') {
opts = module;
module = moduleId;
if (module) {
moduleId = (module.moduleId);
if (!moduleId)
moduleId = module.constructor.name;
}
}
if (!moduleId)
return;
modules[moduleId] = {
moduleId,
module,
opts
};
}
/**
* Check if `setting` is enabled.
*
* @param {String} setting application setting
* @return {Boolean}
* @memberOf Application
*/
enabled(setting) {
return !!this.get(setting);
}
/**
* Check if `setting` is disabled.
*
* @param {String} setting application setting
* @return {Boolean}
* @memberOf Application
*/
disabled(setting) {
return !this.get(setting);
}
get serverTypes() {
return lodash_1.default.keys(this.serverTypeMaps);
}
getBase() {
return this.get(Constants.RESERVED.BASE);
}
getServerIds() {
return Object.keys(this.servers);
}
getServers() {
return this.servers;
}
getServerType(serverInfo) {
return (serverInfo || this.serverInfo).type;
}
getServerId(serverInfo) {
return (serverInfo || this.serverInfo).id;
}
getServerById(id) {
return this.servers[id];
}
getServersByType(type) {
return this.serverTypeMaps[type] || [];
}
isFrontend(server) {
server = server || this.getCurServer();
return server && !!server.frontend;
}
/**
* 加载配置 config目录下
* @param key
* @param val
* @param reload
*/
loadConfigBaseApp(key, val, reload = false) {
const filename = path_1.default.resolve(this.getBase(), val);
if (!fs_1.default.existsSync(filename))
throw filename + ' not exists';
this.set(key, require(filename));
if (reload) {
// TODO reload
}
}
/**
* Use plugin.
* @param {Object} plugin plugin instance
* @param {[type]} opts (optional) construct parameters for the factory function
* @memberOf Application
*/
use(plugin, opts) {
opts = opts || {};
if (!plugin)
throw new Error(`plugin is null!`);
if (this.usedPlugins.includes(plugin))
throw new Error(`plugin[${plugin.name} was used already!]`);
if (plugin.components) {
for (let componentCtor of plugin.components) {
this.load(componentCtor, opts);
}
}
if (plugin.events) {
for (let eventCtor of plugin.events) {
this.loadEvent(eventCtor, opts);
}
}
this.usedPlugins.push(plugin);
this.logger.warn(`used Plugin: ${plugin.name}`);
}
/**
* add a filter to before and after filter
*/
filter(filter) {
this.before(filter);
this.after(filter);
}
/**
* Add before filter.
* @param {Object|Function} bf before filter, bf(msg, session, next)
* @memberOf Application
*/
before(bf) {
this.addFilter(Constants.KEYWORDS.BEFORE_FILTER, bf);
}
/**
* Add after filter.
* @param {Object|Function} af after filter, `af(err, msg, session, resp, next)`
* @memberOf Application
*/
after(af) {
this.addFilter(Constants.KEYWORDS.AFTER_FILTER, af);
}
/**
* add a global filter to before and after global filter
*/
globalFilter(filter) {
if (filter.before)
this.globalBefore(filter);
if (filter.after)
this.globalAfter(filter);
}
/**
* Add global before filter.
*
* @param {Object|Function} bf before filter, bf(msg, session, next)
* @memberOf Application
*/
globalBefore(bf) {
this.addFilter(Constants.KEYWORDS.GLOBAL_BEFORE_FILTER, bf);
}
/**
* Add global after filter.
*/
globalAfter(af) {
this.addFilter(Constants.KEYWORDS.GLOBAL_AFTER_FILTER, af);
}
load(name, component, opts) {
if (typeof name !== 'string') {
opts = component;
component = name;
name = '';
}
if (typeof component === 'function') {
component = new component(this, opts || {});
}
if (!component)
throw 'component dose not exist';
if (!name && typeof component.name === 'string') {
name = component.name;
}
if (name && this.components[name]) {
// ignore duplicate component
this.logger.warn(`ignore duplicate component: ${name}`);
return component;
}
this.loaded.push(component);
if (name) {
this.components[name] = component;
}
return component;
}
replaceServer(serverLists, server) {
lodash_1.default.remove(serverLists, s => s.id === server.id);
serverLists.push(server);
}
addFilter(type, filter) {
let filters = this.get(type);
if (!filters) {
filters = [];
this.set(type, filters);
}
filters.push(filter);
}
;
/**
* 加载master服务器配置
*/
loadMaster() {
this.loadConfigBaseApp(Constants.RESERVED.MASTER, Constants.FILEPATH.MASTER);
}
/**
* 加载一个事件侦听
* @param Event
* @param opts
*/
loadEvent(Event, opts) {
let eventInstance = new Event(this, opts);
for (let evt in events_2.default) {
let name = events_2.default[evt];
let method = eventInstance[name];
if (method) {
this.event.on(name, method.bind(eventInstance));
}
}
}
contains(str, settings) {
if (!settings)
return false;
const ts = settings.split('|');
for (const s of ts) {
if (str === s)
return true;
}
return false;
}
}
exports.default = Application;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwbGljYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvYXBwbGljYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsb0RBQW9CO0FBQ3BCLHdEQUF3QjtBQUN4Qiw0REFBdUI7QUFDdkIsbUNBQXFDO0FBR3JDLDBEQUEwQjtBQUMxQixvRUFBOEM7QUFDOUMsNENBQXNFO0FBT3RFLG1FQUFzQztBQWlDdEMsTUFBcUIsV0FBWSxTQUFRLGNBQUk7SUEwQjNDLFlBQVksSUFBc0I7UUFDaEMsS0FBSyxFQUFFLENBQUM7UUFYSCxnQkFBVyxHQUFjLEVBQUUsQ0FBQztRQVlqQyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNqQixJQUFJLENBQUMsTUFBTSxHQUFHLEVBQUUsQ0FBQztRQUNqQixhQUFhO1FBQ2IsSUFBSSxDQUFDLFVBQVUsR0FBRyxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7UUFDbkIsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDO1FBQ2xDLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sSUFBSSxPQUFPLENBQUM7UUFDckMsYUFBYTtRQUNiLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLElBQUksY0FBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzlELElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBRTlDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNqQixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDZixJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUN6QixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDcEIsQ0FBQztJQUVPLGlCQUFp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