const assert = require('assert');
|
const fs = require('fs');
|
const KoaApplication = require('koa');
|
const is = require('is-type-of');
|
const co = require('../../utils/co');
|
const BaseContextClass = require('./utils/base_context_class');
|
const utils = require('./utils');
|
const Timing = require('./utils/timing');
|
const EggConsoleLogger = require('egg-logger').EggConsoleLogger;
|
const debug = require('debug')('ee-core:EeCore');
|
const EE_LOADER = Symbol.for('ee#loader');
|
|
class EeCore extends KoaApplication {
|
|
/**
|
* @class
|
* @param {Object} options - options
|
* @since 1.0.0
|
*/
|
constructor(options = {}) {
|
options.type = options.type || 'application';
|
|
assert(typeof options.baseDir === 'string', 'options.baseDir required, and must be a string');
|
// assert(fs.existsSync(options.baseDir), `Directory ${options.baseDir} not exists`);
|
// assert(fs.statSync(options.baseDir).isDirectory(), `Directory ${options.baseDir} is not a directory`);
|
|
super();
|
|
// todo
|
//this.context = null;
|
|
this.timing = new Timing();
|
|
this.console = new EggConsoleLogger({level: 'INFO'});
|
|
/**
|
* @member {Object} EeCore#options
|
* @private
|
* @since 1.0.0
|
*/
|
this._options = this.options = options;
|
|
/**
|
* @member {BaseContextClass} EeCore#BaseContextClass
|
* @since 1.0.0
|
*/
|
this.BaseContextClass = BaseContextClass;
|
|
/**
|
* Base controller to be extended by controller in `app.controller`
|
* @class Controller
|
* @extends BaseContextClass
|
* @example
|
* class UserController extends app.Controller {}
|
*/
|
const Controller = this.BaseContextClass;
|
|
/**
|
* Retrieve base controller
|
* @member {Controller} EeCore#Controller
|
* @since 1.0.0
|
*/
|
this.Controller = Controller;
|
|
/**
|
* Base service to be extended by services in `app.service`
|
* @class Service
|
* @extends BaseContextClass
|
* @example
|
* class UserService extends app.Service {}
|
*/
|
const Service = this.BaseContextClass;
|
|
/**
|
* Retrieve base service
|
* @member {Service} EeCore#Service
|
* @since 1.0.0
|
*/
|
this.Service = Service;
|
|
/**
|
* The loader instance, the default class is {@link EeLoader}.
|
* If you want define
|
* @member {EeLoader} EeCore#loader
|
* @since 1.0.0
|
*/
|
const Loader = this[EE_LOADER];
|
assert(Loader, 'Symbol.for(\'ee#loader\') is required');
|
let loaderOptions = Object.assign({
|
logger: this.console,
|
app:this
|
}, options);
|
this.loader = new Loader(loaderOptions);
|
}
|
|
/**
|
* override koa's app.use, support generator function
|
* @param {Function} fn - middleware
|
* @return {Application} app
|
* @since 1.0.0
|
*/
|
use(fn) {
|
assert(is.function(fn), 'app.use() requires a function');
|
debug('use %s', fn._name || fn.name || '-');
|
this.middleware.push(utils.middleware(fn));
|
return this;
|
}
|
|
/**
|
* The home directory of application
|
* @member {String}
|
* @see {@link AppInfo#homeDir}
|
* @since 1.0.0
|
*/
|
get homeDir() {
|
return this.options.homeDir;
|
}
|
|
/**
|
* The electron current directory of application
|
* @member {String}
|
* @see {@link AppInfo#baseDir}
|
* @since 1.0.0
|
*/
|
get baseDir() {
|
return this.options.baseDir;
|
}
|
|
/**
|
* The ee-core directory of framework
|
* @member {String}
|
* @see {@link AppInfo#EeCoreDir}
|
* @since 1.0.0
|
*/
|
get eeCoreDir() {
|
return this.options.framework;
|
}
|
|
/**
|
* The name of application
|
* @member {String}
|
* @see {@link AppInfo#name}
|
* @since 1.0.0
|
*/
|
get name() {
|
return this.loader ? this.loader.pkg.name : '';
|
}
|
|
/**
|
* The configuration of application
|
* @member {Config}
|
* @since 1.0.0
|
*/
|
get config() {
|
return this.loader ? this.loader.config : {};
|
}
|
|
/**
|
* The addon of application
|
* @member {Addon}
|
* @since 1.0.0
|
*/
|
get addon() {
|
return this.loader ? this.loader.addon : {};
|
}
|
|
get [EE_LOADER]() {
|
return require('./loader/ee_loader');
|
}
|
|
/**
|
* Convert a generator function to a promisable one.
|
*
|
* Notice: for other kinds of functions, it directly returns you what it is.
|
*
|
* @param {Function} fn The inputted function.
|
* @return {AsyncFunction} An async promise-based function.
|
* @example
|
```javascript
|
const fn = function* (arg) {
|
return arg;
|
};
|
const wrapped = app.toAsyncFunction(fn);
|
wrapped(true).then((value) => console.log(value));
|
```
|
*/
|
toAsyncFunction(fn) {
|
if (!is.generatorFunction(fn)) return fn;
|
fn = co.wrap(fn);
|
return async function(...args) {
|
return fn.apply(this, args);
|
};
|
}
|
|
/**
|
* Convert an object with generator functions to a Promisable one.
|
* @param {Mixed} obj The inputted object.
|
* @return {Promise} A Promisable result.
|
* @example
|
```javascript
|
const fn = function* (arg) {
|
return arg;
|
};
|
const arr = [ fn(1), fn(2) ];
|
const promise = app.toPromise(arr);
|
promise.then(res => console.log(res));
|
```
|
*/
|
toPromise(obj) {
|
return co(function* () {
|
return yield obj;
|
});
|
}
|
}
|
|
module.exports = EeCore;
|