Comparing version 2.0.1 to 3.0.0
3.0.0 / 2017-01-12 | ||
================== | ||
* feat: [BREAKING_CHANGE] add ready with error and generator listener (#5) | ||
2.0.1 / 2016-03-11 | ||
@@ -3,0 +8,0 @@ ================== |
177
index.js
@@ -1,58 +0,149 @@ | ||
/** | ||
* Copyright(c) dead_horse and other contributors. | ||
* MIT Licensed | ||
* | ||
* Authors: | ||
* dead_horse <dead_horse@qq.com> | ||
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.com) | ||
*/ | ||
'use strict'; | ||
/** | ||
* Module dependencies. | ||
*/ | ||
const co = require('co'); | ||
const util = require('util'); | ||
const is = require('is-type-of'); | ||
const assert = require('assert'); | ||
const EventEmitter = require('events').EventEmitter; | ||
var ready = require('get-ready'); | ||
var EventEmitter = require('events').EventEmitter; | ||
var util = require('util'); | ||
class Base extends EventEmitter { | ||
constructor(options) { | ||
super(); | ||
module.exports = Base; | ||
if (options && options.initMethod) { | ||
assert(is.generatorFunction(this[options.initMethod]), | ||
`[sdk-base] this.${options.initMethod} should be a generator function.`); | ||
function Base() { | ||
EventEmitter.call(this); | ||
this.on('error', this.defaultErrorHandler.bind(this)); | ||
} | ||
co(this[options.initMethod].bind(this)) | ||
.then(() => this.ready(true)) | ||
.catch(err => this.ready(err)); | ||
} | ||
this._ready = false; | ||
this._readyError = null; | ||
this._readyCallbacks = []; | ||
/** | ||
* inherits from EventEmitter | ||
*/ | ||
this.on('error', err => { this._defaultErrorHandler(err); }); | ||
} | ||
util.inherits(Base, EventEmitter); | ||
_wrapListener(eventName, listener) { | ||
if (is.generatorFunction(listener)) { | ||
assert(eventName !== 'error', '[sdk-base] `error` event should not have a generator listener.'); | ||
ready.mixin(Base.prototype); | ||
const newListener = (...args) => { | ||
co(function* () { | ||
yield listener(...args); | ||
}).catch(err => { | ||
err.name = 'EventListenerProcessError'; | ||
this.emit('error', err); | ||
}); | ||
}; | ||
newListener.original = listener; | ||
return newListener; | ||
} | ||
return listener; | ||
} | ||
Base.prototype.defaultErrorHandler = function (err) { | ||
if (this.listeners('error').length > 1) { | ||
// ignore defaultErrorHandler | ||
return; | ||
addListener(eventName, listener) { | ||
return super.addListener(eventName, this._wrapListener(eventName, listener)); | ||
} | ||
console.error('\n[%s][pid: %s][%s][%s] %s: %s \nError Stack:\n %s', | ||
Date(), process.pid, this.constructor.name, __filename, err.name, | ||
err.message, err.stack); | ||
// try to show addition property on the error object | ||
// e.g.: `err.data = {url: '/foo'};` | ||
var additions = []; | ||
for (var key in err) { | ||
if (key === 'name' || key === 'message') { | ||
continue; | ||
on(eventName, listener) { | ||
return super.on(eventName, this._wrapListener(eventName, listener)); | ||
} | ||
once(eventName, listener) { | ||
return super.once(eventName, this._wrapListener(eventName, listener)); | ||
} | ||
prependListener(eventName, listener) { | ||
return super.prependListener(eventName, this._wrapListener(eventName, listener)); | ||
} | ||
prependOnceListener(eventName, listener) { | ||
return super.prependOnceListener(eventName, this._wrapListener(eventName, listener)); | ||
} | ||
removeListener(eventName, listener) { | ||
let target = listener; | ||
if (is.generatorFunction(listener)) { | ||
const listeners = this.listeners(eventName); | ||
for (const fn of listeners) { | ||
if (fn.original === listener) { | ||
target = fn; | ||
break; | ||
} | ||
} | ||
} | ||
return super.removeListener(eventName, target); | ||
} | ||
additions.push(util.format(' %s: %j', key, err[key])); | ||
/** | ||
* set ready state or onready callback | ||
* | ||
* @param {Boolean|Error|Function} flagOrFunction - ready state or callback function | ||
* @return {void|Promise} ready promise | ||
*/ | ||
ready(flagOrFunction) { | ||
if (arguments.length === 0) { | ||
// return a promise | ||
// support `this.ready().then(onready);` and `yield this.ready()`; | ||
return new Promise((resolve, reject) => { | ||
if (this._ready) { | ||
return resolve(); | ||
} else if (this._readyError) { | ||
return reject(this._readyError); | ||
} | ||
this._readyCallbacks.push(err => { | ||
if (err) { | ||
reject(err); | ||
} else { | ||
resolve(); | ||
} | ||
}); | ||
}); | ||
} else if (is.function(flagOrFunction)) { | ||
this._readyCallbacks.push(flagOrFunction); | ||
} else if (flagOrFunction instanceof Error) { | ||
this._ready = false; | ||
this._readyError = flagOrFunction; | ||
this.emit('error', flagOrFunction); | ||
} else { | ||
this._ready = flagOrFunction; | ||
} | ||
if (this._ready || this._readyError) { | ||
this._readyCallbacks.splice(0, Infinity).forEach(callback => { | ||
process.nextTick(() => { | ||
callback(this._readyError); | ||
}); | ||
}); | ||
} | ||
} | ||
if (additions.length) { | ||
console.error('Error Additions:\n%s', additions.join('\n')); | ||
_defaultErrorHandler(err) { | ||
if (this.listeners('error').length > 1) { | ||
// ignore defaultErrorHandler | ||
return; | ||
} | ||
console.error('\n[%s][pid: %s][%s] %s: %s \nError Stack:\n %s', | ||
Date(), process.pid, this.constructor.name, err.name, | ||
err.message, err.stack); | ||
// try to show addition property on the error object | ||
// e.g.: `err.data = {url: '/foo'};` | ||
const additions = []; | ||
for (const key in err) { | ||
if (key === 'name' || key === 'message') { | ||
continue; | ||
} | ||
additions.push(util.format(' %s: %j', key, err[key])); | ||
} | ||
if (additions.length) { | ||
console.error('Error Additions:\n%s', additions.join('\n')); | ||
} | ||
console.error(); | ||
} | ||
console.error(); | ||
}; | ||
} | ||
module.exports = Base; |
{ | ||
"name": "sdk-base", | ||
"version": "2.0.1", | ||
"version": "3.0.0", | ||
"description": "a base class for sdk with default error handler", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "mocha -R spec -t 5000 -r should test/*.test.js", | ||
"test-cov": "istanbul cover _mocha -- -t 5000 -r should test/*.test.js" | ||
"lint": "eslint --ext .js .", | ||
"test": "npm run lint && npm run test-local", | ||
"test-local": "egg-bin test", | ||
"cov": "egg-bin cov", | ||
"ci": "npm run lint && npm run cov" | ||
}, | ||
@@ -28,12 +31,18 @@ "keywords": [ | ||
"dependencies": { | ||
"get-ready": "~1.0.0" | ||
"co": "^4.6.0", | ||
"is-type-of": "^1.0.0" | ||
}, | ||
"devDependencies": { | ||
"istanbul": "*", | ||
"mocha": "*", | ||
"should": "7" | ||
"egg-bin": "^1.10.0", | ||
"egg-ci": "^1.1.0", | ||
"eslint": "^3.13.1", | ||
"eslint-config-egg": "^3.2.0", | ||
"pedding": "^1.1.0" | ||
}, | ||
"engine": { | ||
"node": ">=0.10" | ||
"node": ">= 6.0.0" | ||
}, | ||
"ci": { | ||
"version": "6, 7" | ||
} | ||
} |
@@ -25,3 +25,3 @@ sdk-base | ||
A base class for sdk with default error handler. | ||
A base class for sdk with some common & useful functions. | ||
@@ -36,11 +36,41 @@ ## Installation | ||
Constructor argument: | ||
- {Object} options | ||
- {String} [initMethod] - the async init method name, the method should be a generator function. If set, will execute the function in the constructor. | ||
```js | ||
var Base = require('sdk-base'); | ||
var util = require('util'); | ||
'use strict'; | ||
function Client() { | ||
Base.call(this); | ||
const co = require('co'); | ||
const Base = require('sdk-base'); | ||
class Client extends Base { | ||
constructor() { | ||
super({ | ||
initMethod: 'init', | ||
}); | ||
} | ||
* init() { | ||
// put your async init logic here | ||
} | ||
} | ||
util.inherits(Client, Base); | ||
co(function* () { | ||
const client = new Client(); | ||
// wait client ready, if init failed, client will throw an error. | ||
yield client.ready(); | ||
// support generator event listener | ||
client.on('data', function* (data) { | ||
// put your async process logic here | ||
// | ||
// @example | ||
// ---------- | ||
// yield submit(data); | ||
}); | ||
client.emit('data', { foo: 'bar' }); | ||
}).catch(err => { console.error(err); }); | ||
``` | ||
@@ -50,3 +80,3 @@ | ||
- `.ready(flagOrFunction)` | ||
- `.ready(flagOrFunction)` flagOrFunction is optional, and the argument type can be Boolean, Error or Function. | ||
@@ -56,11 +86,38 @@ ```js | ||
client.ready(true); | ||
// init failed | ||
client.ready(new Error('init failed')); | ||
// listen client ready | ||
client.ready(function() { | ||
client.ready(err => { | ||
if (err) { | ||
console.log('client init failed'); | ||
console.error(err); | ||
return; | ||
} | ||
console.log('client is ready'); | ||
}); | ||
// support promise style call | ||
client.ready() | ||
.then(() => { ... }) | ||
.catch(err => { ... }); | ||
// support generator style call | ||
yield client.ready(); | ||
``` | ||
- `.on(event, listener)` | ||
- `.on(event, listener)` wrap the [EventEmitter.prototype.on(event, listener)](https://nodejs.org/api/events.html#events_emitter_on_eventname_listener), the only difference is to support adding generator listener on events, except 'error' event. | ||
- `once(event, listener)` wrap the [EventEmitter.prototype.once(event, listener)](https://nodejs.org/api/events.html#events_emitter_once_eventname_listener), the only difference is to support adding generator listener on events, except 'error' event. | ||
- `prependListener(event, listener)` wrap the [EventEmitter.prototype.prependListener(event, listener)](https://nodejs.org/api/events.html#events_emitter_prependlistener_eventname_listener), the only difference is to support adding generator listener on events, except 'error' event. | ||
- `prependOnceListener(event, listener)` wrap the [EventEmitter.prototype.prependOnceListener(event, listener)](https://nodejs.org/api/events.html#events_emitter_prependoncelistener_eventname_listener), the only difference is to support adding generator listener on events, except 'error' event. | ||
- `addListener(event, listener)` wrap the [EventEmitter.prototype.addListener(event, listener)](https://nodejs.org/api/events.html#events_emitter_addlistener_eventname_listener), the only difference is to support adding generator listener on events, except 'error' event. | ||
```js | ||
client.on('data', function* (data) { | ||
// your async process logic here | ||
}); | ||
client.once('foo', function* (bar) { | ||
// ... | ||
}); | ||
// listen error event | ||
@@ -67,0 +124,0 @@ client.on('error', function(err) { |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
11226
5
130
128
2
5
1
+ Addedco@^4.6.0
+ Addedis-type-of@^1.0.0
+ Addedco@4.6.0(transitive)
+ Addedcore-util-is@1.0.3(transitive)
+ Addedis-class-hotfix@0.0.6(transitive)
+ Addedis-type-of@1.4.0(transitive)
+ Addedisstream@0.1.2(transitive)
- Removedget-ready@~1.0.0
- Removedget-ready@1.0.0(transitive)