Comparing version 4.9.1 to 4.10.0
4.10.0 / 2018-09-06 | ||
================== | ||
**features** | ||
* [[`9d2f2fc`](http://github.com/eggjs/egg-core/commit/9d2f2fc3655e29aca52ac06a574bf69c1ba4d239)] - feat: impl boot methods (#171) (killa <<killa123@126.com>>) | ||
**others** | ||
* [[`b71074d`](http://github.com/eggjs/egg-core/commit/b71074d7c0d5e5353ab8d3bbf279023184557809)] - fix(config) removes whitespace from both ends of serverEnv (#180) (supperchong <<2267805901@qq.com>>) | ||
* [[`ae38fa4`](http://github.com/eggjs/egg-core/commit/ae38fa4c47c35c32d9ca73e0311f64305573acd4)] - chroe: add more comments for toAsyncFunction and toPromise (Maledong <<maledong_github@outlook.com>>) | ||
* [[`4d4113c`](http://github.com/eggjs/egg-core/commit/4d4113cfd27d1e8ce4ce65d2d19b0035b5291dcc)] - style(core): beautify reg and add .idea to ignore (#179) (Army <<army8735@qq.com>>) | ||
4.9.1 / 2018-07-12 | ||
@@ -3,0 +14,0 @@ ================== |
189
lib/egg.js
@@ -14,12 +14,9 @@ 'use strict'; | ||
const Timing = require('./utils/timing'); | ||
const Lifecycle = require('./lifecycle'); | ||
const DEPRECATE = Symbol('EggCore#deprecate'); | ||
const CLOSESET = Symbol('EggCore#closeSet'); | ||
const ISCLOSE = Symbol('EggCore#isClose'); | ||
const CLOSE_PROMISE = Symbol('EggCore#closePromise'); | ||
const ROUTER = Symbol('EggCore#router'); | ||
const EGG_LOADER = Symbol.for('egg#loader'); | ||
const INIT_READY = Symbol('EggCore#initReady'); | ||
const CLOSE_PROMISE = Symbol('EggCore#closePromise'); | ||
class EggCore extends KoaApplication { | ||
@@ -48,12 +45,5 @@ | ||
// register a close set | ||
this[CLOSESET] = new Set(); | ||
// cache deprecate object by file | ||
this[DEPRECATE] = new Map(); | ||
this[INIT_READY](); | ||
this.timing.start('Application Start'); | ||
this.ready(() => this.timing.end('Application Start')); | ||
/** | ||
@@ -113,2 +103,11 @@ * @member {Object} EggCore#options | ||
this.lifecycle = new Lifecycle({ | ||
baseDir: options.baseDir, | ||
app: this, | ||
logger: this.console, | ||
}); | ||
this.lifecycle.on('error', err => this.emit('error', err)); | ||
this.lifecycle.on('ready_timeout', id => this.emit('ready_timeout', id)); | ||
this.lifecycle.on('ready_stat', data => this.emit('ready_stat', data)); | ||
/** | ||
@@ -213,24 +212,50 @@ * The loader instance, the default class is {@link EggLoader}. | ||
beforeStart(scope) { | ||
if (!is.function(scope)) { | ||
throw new Error('beforeStart only support function'); | ||
} | ||
this.lifecycle.registerBeforeStart(scope); | ||
} | ||
// get filename from stack | ||
const name = utils.getCalleeFromStack(true); | ||
const timingkey = 'Before Start in ' + utils.getResolvedFilename(name, this.options.baseDir); | ||
/** | ||
* register an callback function that will be invoked when application is ready. | ||
* @see https://github.com/node-modules/ready | ||
* @since 1.0.0 | ||
* @param {boolean|Error|Function} flagOrFunction - | ||
* @return {Promise|null} return promise when argument is undefined | ||
* @example | ||
* const app = new Application(...); | ||
* app.ready(err => { | ||
* if (err) throw err; | ||
* console.log('done'); | ||
* }); | ||
*/ | ||
ready(flagOrFunction) { | ||
return this.lifecycle.ready(flagOrFunction); | ||
} | ||
this.timing.start(timingkey); | ||
/** | ||
* If a client starts asynchronously, you can register `readyCallback`, | ||
* then the application will wait for the callback to ready | ||
* | ||
* It will log when the callback is not invoked after 10s | ||
* | ||
* Recommend to use {@link EggCore#beforeStart} | ||
* @since 1.0.0 | ||
* | ||
* @param {String} name - readyCallback task name | ||
* @param {object} opts - | ||
* - {Number} [timeout=10000] - emit `ready_timeout` when it doesn't finish but reach the timeout | ||
* - {Boolean} [isWeakDep=false] - whether it's a weak dependency | ||
* @return {Function} - a callback | ||
* @example | ||
* const done = app.readyCallback('mysql'); | ||
* mysql.ready(done); | ||
*/ | ||
readyCallback(name, opts) { | ||
return this.lifecycle.legacyReadyCallback(name, opts); | ||
} | ||
const done = this.readyCallback(name); | ||
// ensure scope executes after load completed | ||
process.nextTick(() => { | ||
utils.callFn(scope).then(() => { | ||
done(); | ||
this.timing.end(timingkey); | ||
}, err => { | ||
done(err); | ||
this.timing.end(timingkey); | ||
}); | ||
}); | ||
/** | ||
* Register a function that will be called when app close | ||
* @param {Function} fn - the function that can be generator function or async function | ||
*/ | ||
beforeClose(fn) { | ||
this.lifecycle.registerBeforeClose(fn); | ||
} | ||
@@ -249,18 +274,5 @@ | ||
*/ | ||
close() { | ||
async close() { | ||
if (this[CLOSE_PROMISE]) return this[CLOSE_PROMISE]; | ||
const closeFunction = async () => { | ||
// close in reverse order: first created, last closed | ||
const closeFns = Array.from(this[CLOSESET]); | ||
for (const fn of closeFns.reverse()) { | ||
await utils.callFn(fn); | ||
this[CLOSESET].delete(fn); | ||
} | ||
// Be called after other close callbacks | ||
this.emit('close'); | ||
this.removeAllListeners(); | ||
this[ISCLOSE] = true; | ||
}; | ||
this[CLOSE_PROMISE] = closeFunction(); | ||
this[CLOSE_PROMISE] = this.lifecycle.close(); | ||
return this[CLOSE_PROMISE]; | ||
@@ -270,55 +282,2 @@ } | ||
/** | ||
* Register a function that will be called when app close | ||
* @param {Function} fn - the function that can be generator function or async function | ||
*/ | ||
beforeClose(fn) { | ||
assert(is.function(fn), 'argument should be function'); | ||
this[CLOSESET].add(fn); | ||
} | ||
/** | ||
* @member {Function} | ||
* @private | ||
*/ | ||
[INIT_READY]() { | ||
/** | ||
* register an callback function that will be invoked when application is ready. | ||
* @method {Function} EggCore#ready | ||
* @see https://github.com/node-modules/ready | ||
* @since 1.0.0 | ||
* @example | ||
* const app = new Application(...); | ||
* app.ready(err => { | ||
* if (err) throw err; | ||
* console.log('done'); | ||
* }); | ||
*/ | ||
// get app timeout from env or use default timeout 10 second | ||
const eggReadyTimeoutEnv = Number.parseInt(process.env.EGG_READY_TIMEOUT_ENV || 10000); | ||
assert(Number.isInteger(eggReadyTimeoutEnv), `process.env.EGG_READY_TIMEOUT_ENV ${process.env.EGG_READY_TIMEOUT_ENV} should be able to parseInt.`); | ||
/** | ||
* If a client starts asynchronously, you can register `readyCallback`, | ||
* then the application will wait for the callback to ready | ||
* | ||
* It will log when the callback is not invoked after 10s | ||
* | ||
* Recommend to use {@link EggCore#beforeStart} | ||
* @method {Function} EggCore#readyCallback | ||
* @since 1.0.0 | ||
* @example | ||
* const done = app.readyCallback('mysql'); | ||
* mysql.ready(done); | ||
*/ | ||
require('ready-callback')({ timeout: eggReadyTimeoutEnv }).mixin(this); | ||
this.on('ready_stat', data => { | ||
this.console.info('[egg:core:ready_stat] end ready task %s, remain %j', data.id, data.remain); | ||
}).on('ready_timeout', id => { | ||
this.console.warn('[egg:core:ready_timeout] %s seconds later %s was still unable to finish.', eggReadyTimeoutEnv / 1000, id); | ||
}); | ||
} | ||
/** | ||
* get router | ||
@@ -360,5 +319,16 @@ * @member {Router} EggCore#router | ||
/** | ||
* use co to wrap generator function to a function return promise | ||
* @param {GeneratorFunction} fn input function | ||
* @return {AsyncFunction} async function return promise | ||
* 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)); | ||
* ``` | ||
*/ | ||
@@ -374,5 +344,14 @@ toAsyncFunction(fn) { | ||
/** | ||
* use co to wrap array or object to a promise | ||
* @param {Mixed} obj input object | ||
* @return {Promise} promise | ||
* 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)); | ||
* ``` | ||
*/ | ||
@@ -379,0 +358,0 @@ toPromise(obj) { |
@@ -6,3 +6,3 @@ 'use strict'; | ||
const assert = require('assert'); | ||
const isFunction = require('is-type-of').function; | ||
const is = require('is-type-of'); | ||
const debug = require('debug')('egg-core'); | ||
@@ -37,2 +37,3 @@ const homedir = require('node-homedir'); | ||
this.app = this.options.app; | ||
this.lifecycle = this.app.lifecycle; | ||
this.timing = this.app.timing || new Timing(); | ||
@@ -99,2 +100,6 @@ this[REQUIRE_COUNT] = 0; | ||
get bootFileName() { | ||
return this.app.type === 'application' ? 'app' : 'agent'; | ||
} | ||
/** | ||
@@ -127,2 +132,4 @@ * Get {@link AppInfo#env} | ||
} | ||
} else { | ||
serverEnv = serverEnv.trim(); | ||
} | ||
@@ -303,3 +310,5 @@ | ||
let ret = this.requireFile(filepath); | ||
ret = isFunction(ret) ? ret(...inject) : ret; | ||
if (is.function(ret) && !is.class(ret)) { | ||
ret = ret(...inject); | ||
} | ||
return ret; | ||
@@ -467,2 +476,3 @@ } | ||
require('./mixin/router'), | ||
require('./mixin/boot'), | ||
]; | ||
@@ -469,0 +479,0 @@ |
@@ -156,3 +156,3 @@ 'use strict'; | ||
// app/service/foo/bar.js => service.foo.bar | ||
const pathName = directory.split(/\/|\\/).slice(-1) + '.' + properties.join('.'); | ||
const pathName = directory.split(/[/\\]/).slice(-1) + '.' + properties.join('.'); | ||
// get exports from the file | ||
@@ -159,0 +159,0 @@ const exports = getExports(fullpath, this.options, pathName); |
@@ -5,3 +5,2 @@ 'use strict'; | ||
module.exports = { | ||
@@ -27,2 +26,3 @@ | ||
this.timing.start('Load app.js'); | ||
this.lifecycle.triggerConfigDidLoad(); | ||
this.getLoadUnits() | ||
@@ -38,2 +38,3 @@ .forEach(unit => this.loadFile(this.resolveModule(path.join(unit.path, 'app')))); | ||
this.timing.start('Load agent.js'); | ||
this.lifecycle.triggerConfigDidLoad(); | ||
this.getLoadUnits() | ||
@@ -43,3 +44,2 @@ .forEach(unit => this.loadFile(this.resolveModule(path.join(unit.path, 'agent')))); | ||
}, | ||
}; |
@@ -43,3 +43,4 @@ 'use strict'; | ||
getCalleeFromStack(withLine) { | ||
getCalleeFromStack(withLine, stackIndex) { | ||
stackIndex = stackIndex === undefined ? 2 : stackIndex; | ||
const limit = Error.stackTraceLimit; | ||
@@ -49,3 +50,3 @@ const prep = Error.prepareStackTrace; | ||
Error.prepareStackTrace = prepareObjectStackTrace; | ||
Error.stackTraceLimit = 4; | ||
Error.stackTraceLimit = 5; | ||
@@ -55,3 +56,3 @@ // capture the stack | ||
Error.captureStackTrace(obj); | ||
let callSite = obj.stack[2]; | ||
let callSite = obj.stack[stackIndex]; | ||
let fileName; | ||
@@ -66,3 +67,3 @@ /* istanbul ignore else */ | ||
// TODO: add test | ||
callSite = obj.stack[3]; | ||
callSite = obj.stack[stackIndex + 1]; | ||
fileName = callSite.getFileName(); | ||
@@ -82,3 +83,3 @@ } | ||
getResolvedFilename(filepath, baseDir) { | ||
const reg = /\\|\//g; | ||
const reg = /[/\\]/g; | ||
return filepath.replace(baseDir + path.sep, '').replace(reg, '/'); | ||
@@ -85,0 +86,0 @@ }, |
{ | ||
"name": "egg-core", | ||
"version": "4.9.1", | ||
"version": "4.10.0", | ||
"description": "A core Pluggable framework based on koa", | ||
@@ -9,4 +9,4 @@ "main": "index.js", | ||
"autod": "autod", | ||
"lint": "eslint lib test *.js", | ||
"test": "npm run lint && egg-bin test", | ||
"lint": "eslint .", | ||
"test": "npm run lint -- --fix && egg-bin test", | ||
"test-local": "egg-bin test", | ||
@@ -39,10 +39,11 @@ "cov": "egg-bin cov", | ||
"autod": "^3.0.1", | ||
"coffee": "^4.1.0", | ||
"egg-bin": "^4.7.0", | ||
"await-event": "^2.1.0", | ||
"coffee": "^4.2.0", | ||
"egg-bin": "^4.8.1", | ||
"egg-ci": "^1.8.0", | ||
"egg-utils": "^2.4.0", | ||
"egg-utils": "^2.4.1", | ||
"eslint": "^4.19.1", | ||
"eslint-config-egg": "^7.0.0", | ||
"js-yaml": "^3.11.0", | ||
"mm": "^2.2.0", | ||
"mm": "^2.4.0", | ||
"mz-modules": "^2.1.0", | ||
@@ -58,14 +59,15 @@ "pedding": "^1.1.0", | ||
"depd": "^1.1.2", | ||
"egg-logger": "^1.6.2", | ||
"egg-logger": "^1.7.1", | ||
"egg-path-matching": "^1.0.1", | ||
"extend2": "^1.0.0", | ||
"get-ready": "^2.0.1", | ||
"globby": "^8.0.1", | ||
"inflection": "^1.12.0", | ||
"is-type-of": "^1.2.0", | ||
"koa": "^2.5.0", | ||
"koa": "^2.5.2", | ||
"koa-convert": "^1.2.0", | ||
"koa-router": "^7.4.0", | ||
"node-homedir": "^1.1.0", | ||
"ready-callback": "^2.0.1", | ||
"utility": "^1.13.1" | ||
"node-homedir": "^1.1.1", | ||
"ready-callback": "^2.1.0", | ||
"utility": "^1.14.0" | ||
}, | ||
@@ -72,0 +74,0 @@ "files": [ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
110373
25
2691
16
15
+ Addedget-ready@^2.0.1
Updatedegg-logger@^1.7.1
Updatedkoa@^2.5.2
Updatednode-homedir@^1.1.1
Updatedready-callback@^2.1.0
Updatedutility@^1.14.0