Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Intelligent event emitter for nodejs - only handle events when they have 'the right stuff'
Clean, conditional event handlers.
eventif simplifies event handling. Instead of doing this:
emitter.on('anevent',function(a,b){
if (a === 1 && b !== 1) {
// do something
} else if (a !== 1 && b === 2) {
// do something else
} else if (a > 5) {
// another thing
} else if (b < 20) {
// and another something
} else {
// default case
}
});
emitter.emit(2,20);
emitter.emit(1,0);
emitter.emit(-1);
Do this:
emitter.on({a: 1, b: 2}, handler1);
emitter.on({a: 0}, handler2);
emitter.on({a: {from: 3, to: 10}, b: -1, _join: 'OR'}, handler3);
Clean, simple, short readable handlers.
Simple:
npm install eventif
Eventif follows the syntax and style of Nodejs Event Emitter.
You follow three simple steps:
You have 2 ways to create an eventif emitter:
You can create a new eventif-compliant emitter by having it inheirt from eventif. As the example in the docs shows, you can use either classical nodejs prototypal inheritance:
const Eventif = require('eventif');
const util = require('util');
function MyEmitter() {
EventEmitter.call(this);
}
util.inherits(MyEmitter, Eventif);
myEmitter = new MyEmitter();
Or, if you prefer, you can use ES6-style syntax:
const EventIf = require('eventif');
class MyEmitter extends EventIf {}
const myEmitter = new MyEmitter();
In both of the above examples, you are creating a new emitter by inheriting from eventif
instead of from events
.
If you already have a standard event emitter class which, somewhere down the line, inherits from events
, you may not be able to change it to inherit from eventif
instead. In that case, instead of creating a new event emitter, you enable the existing one to be eventif capable.
const Eventif = require('eventif');
const EventEmitter = require('events');
const util = require('util');
function MyEmitter() {
EventEmitter.call(this);
}
util.inherits(MyEmitter, Eventif);
Em = Eventif.y(MyEmitter);
// or an alias
Em = Eventif.enable(MyEmitter);
myEmitter = new Em();
If es6 classes make you happier:
const EventIf = require('eventif');
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
Em = Eventif.y(MyEmitter);
// or an alias
Em = Eventif.enable(MyEmitter);
myEmitter = new Em();
NOTE: You only can enable an existing event emitter class if it inherits from EventEmitter
.
Now we have an eventif-capable emitter. Let's use it!
How would you create a normal event handler? With on
!
myEmitter.on('anevent',function(a,b){
// do something
});
How would you create an eventif-capable handler? In exactly the same way!
myEmitter.on('anevent',function(a,b){
// do something
});
Handlers do not need to be changed to support eventif.
However, you now have the option to make those handlers conditional:
myEmitter.on('anevent',{a:1, b:0},function(a,b){
// do something
});
As you can see, handlers really do not need to be changed. Of course, you may want to change them, now that all of that extraneous if-else if-else if-else
or perhaps switch-case-case-case-case-case-default
code can go away!
The signature for emitter functions is as follows:
emitter.on(event,conditions,handler)
emitter.once(event,conditions,handler)
emitter.emit(event,[param1,param2,...,paramN])
See below for details on the correct syntax for conditions and how it matches parameters.
If you call on()
or once()
with no conditions at all, it is handled directly by the original event emitter.
myEmitter.on('anevent',function(a,b){
// do something
});
The above means, "for every event of type 'anevent', always call the handler".
eventif fully supports once()
. The rules for once()
state that "This listener is invoked only the next time event is triggered, after which it is removed."
eventif follows the same logic. The handler is removed after the handler actually is invoked. Thus, if the handler would have been invoked if not for eventif, but the conditions do not match, then the handler remains in place. It is removed only after the actual handler function has been called at least once.
myEmitter.once({a:1},'anevent',function(a,b){
// do something
});
myEmitter.emit('anevent'); // handler is NOT run or removed
myEmitter.emit('anevent',2); // handler is NOT run or removed
myEmitter.emit('anevent',1); // handler IS run and removed
myEmitter.emit('anevent',1); // handler already WAS removed, so it is NOT run
On the other hand, if you used a traditional event emitter, or even eventif without any conditions:
myEmitter.once('anevent',function(a,b){
// do something
});
myEmitter.emit('anevent'); // handler IS run and removed
myEmitter.emit('anevent',2); // handler already WAS removed, so it is NOT run
This is easy. Just emit events like you always do!
myEmitter.emit('anevent');
// or if you want to pass parameters
myEmitter.emit('anevent',1,0,"hello world!");
In order for your conditions to work correctly, you need to specify the correct conditions syntax.
The syntax is the JSQL syntax of searchjs. The condition is what you pass as the (optional) second argument to .on()
or .once()
. The data checked against the condition is constructed of the name of the event and the parameters to your handler.
Let's take that apart.
Here's a simple example:
emitter.on('anevent',/* some condition */,function(a,b){
// do something
});
emitter.emit('anevent',1,"hello");
Your handler expects the first argument to the event to be saved as a
and the second as b
. Thus, the object tested against will be:
{a:1, b:"hello"}
On the other hand, if you created the handler as follows:
emitter.on('anevent',/* some condition */,function(q,f){
// do something
});
emitter.emit('anevent',1,"hello");
Then the data to test the condition against would be:
{q:1, f:"hello"}
In addition, the parameters are saved in order:
{1:1, 2: "hello"}
All that really happens with each event emission is:
{}
{1:1, 2:"hello"}
{1:1, 2:"hello", a:1, b:"hello"}
searchjs.matchObject(data,condition)
, e.g. searchjs.match({1:1, 2:"hello", a:1, b:"hello"}, {1:1})
.matchObject()
returns true
, call the handler, else do not.In each example, we will show if it matches, and thus the handler is called, and why or why not.
emitter.on('anevent',function(){
});
emitter.emit('anevent',1,2,'hello','jim',25,{a:1});
YES: With no condition, the handler always is called.
emitter.on('anevent',{order:1,name:"jim"},function(order,count,message,name){
});
emitter.emit('anevent',1,2,'hello','jim',25,{a:1});
YES:
order
is 1st argument to function, which means 1st parameter to emit()
. In condition, order:1
means it must equal 1. It does, and it matches.name
is 4th argument to function, which means 4th parameter to emit()
. In condition, name:"jim"
means it must equal "jim". It does, and it matches.emitter.on('anevent',{order:1,name:"jill"},function(order,count,message,name){
});
emitter.emit('anevent',1,2,'hello','jim',25,{a:1});
NO:
order
is 1st argument to function, which means 1st parameter to emit()
. In condition, order:1
means it must equal 1. It does, and it matches.name
is 4th argument to function, which means 4th parameter to emit()
. In condition, name:"jill"
means it must equal "jill", but it equals "jim", so it fails.emitter.on('anevent',{3:"jim"},function(){
});
emitter.emit('anevent',1,2,'hello','jim',25,{a:1});
YES:
emitter.on('anevent',{order:1,name:"jill",_join:"OR"},function(order,count,message,name){
});
emitter.emit('anevent',1,2,'hello','jim',25,{a:1});
YES:
Condition says that "order" must equal 1 OR "name" must equal "jill". Since one of them is correct ("order" === 1), it matches.
emitter.on('anevent',{count:{from: 1, to: 50} },function(order,count,message,name){
});
emitter.emit('anevent',1,32,'hello','jim',25,{a:1});
YES:
Condition says that "order" must be from 1 to 50. Since "order" is equal to 32, it is in the range and matches.
FAQs
Intelligent event emitter for nodejs - only handle events when they have 'the right stuff'
The npm package eventif receives a total of 6 weekly downloads. As such, eventif popularity was classified as not popular.
We found that eventif demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.