Research
Security News
Threat Actor Exposes Playbook for Exploiting npm to Build Blockchain-Powered Botnets
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
An Eventuals implementation that:
righto
takes a task to run, and arguments to pass to the task. If you pass any eventual arguments (rightos or promises), they will be resolved before running the dependant task.
righto
'd tasks are resolved once and the result is cached. If a task is in flight when it's results are asked for, the results will be passed when the task resolves.
righto(cps-function, ...args) -> fn(err-back)
where:
a cps-function has signature: cps-function(...args, err-back) -> void
an err-back has signature: err-back(error, ...results) -> void
Simple Example: read some files
var fs = require('fs');
function concatStrings(a, b, callback){
callback(null, a + b);
};
var myFile = righto(fs.readFile, 'utf8' 'myFile.txt');
var mySecondFile = righto(fs.readFile, 'utf8', 'mySecondFile.txt');
var concattedFiles = righto(concatStrings, myFile, mySecondFile);
concattedFiles(function(error, result){
console.log(error); // null
console.log(result); // the two concatted files.
});
A more involved example: return a document for a user while checking permissions.
// Make a task from an err-back function
var document = righto(db.Documents.get, documentId);
var user = righto(db.Users.get, userId);
// Resolve an object with eventual properties to pass to a function.
var account = righto(db.Accounts.get, righto.resolve({
userId: user.get('id')
}));
// Reject the flow if a business rule is not met
function isOwner(document, account){
if(document.ownerId !== account.id){
return righto.fail({ message: 'Account does not own document', code: 403 });
}
}
// Make a task from a synchronous function
// Depend on `document` and `account` in parallel, automatically.
var hasPermission = righto.sync(isOwner, document, account);
// Take results from a task only after another task is complete
var allowedDocument = righto.mate(document, righto.after(hasPermission));
// Use the results.
allowedDocument(function(eror, document){
// Respond with the error or the document.
});
Used in the backend of https://7tennis.com.au/, which handled 800k concurrent users for the early 2017 season.
The inventor of JavaScript said it was cool in a tweet once: https://twitter.com/BrendanEich/status/1059210746163130368
var eventual = righto(task, any...);
righto suports passing error-first CPS functions by default as tasks:
function getFoo(callback){
setTimeout(function(){
callback(null, 'foo');
});
}
var eventuallyFoo = righto(getFoo);
eventuallyFoo(function(error, result){
result === 'foo';
});
righto supports passing Promises as a dependency:
var somePromise = new Promise(function(resolve, reject){
setTimeout(function(){
resolve('foo');
});
});
var someRighto = righto(function(somePromiseResult, done){
done(null, somePromiseResult);
}, somePromise);
someRighto(function(error, result){
result === 'foo';
});
And supports easily integrating back to promises:
var someRighto = righto(function(done){
setTimeout(function(){
done(null, 'foo');
});
});
var somePromise = new Promise(righto.fork(someRighto));
somePromise.then(function(result){
result === 'foo';
});
Righto can't help you once you pass control back to promises :)
righto supports running a generator (or any next
able iterator):
var generated = righto.iterate(function*(a, b, c){
var x = yield righto(function(done){
setTimeout(function(){
done(null, 'x');
});
});
var y = yield righto(function(done){
setTimeout(function(){
done(null, 'y');
});
});
return x + y + a + b + c;
});
var result = generated('a', 'b', 'c');
result(function(error, result){
result === 'xyabc';
});
Errors bubble up through tasks, so if a dependency errors, the task errors.
// Task that errors
function foo(callback){
setTimeout(function(){
callback(new Error('IT BORKED!'));
}, 1000);
}
var getFoo = righto(foo);
function bar(a, callback){
callback(null, 'hello ' + a);
}
var getBar = righto(bar, getFoo);
getBar(function(error, result){
// ...about 1 second later...
error -> IT BORKED!;
});
You can force a righto task for run at any time without dealing with the results (or error) by calling it with no arguments:
// Lazily resolve (won't run untill called)
var something = righto(getSomething);
// Force something to start resolving *now*
something();
// later ...
something(function(error, result){
// handle error or use result.
});
Also, since righto tasks return themselves when called, you can do this a little more shorthand, like so:
// Immediately force the righto to begin resolving.
var something = righto(getSomething)(); // <= note the call with no arguments.
// later ...
something(function(error, result){
// handle error or use result.
});
By default, dependent tasks are passed only the first result of a dependency righto
. eg:
function foo(callback){
setTimeout(function(){
callback(null, 'first', 'second', 'third');
}, 1000);
}
var getFoo = righto(foo);
function bar(a, callback){
callback(null, a);
}
var getBar = righto(bar, getFoo);
getBar(function(error, result){
// ...1 second later...
result -> 'first';
});
But you can pick and choose what results are used from a dependency like so:
// foo() and bar() as defined above...
var getBar = righto(bar, righto.take(getFoo, 0, 2)); // Take result 0, and result 2, from getFoo
getBar(function(error, result){
// ...1 second later...
result -> 'first third';
});
righto.reduce takes an Array of values (an an eventual that resolves to an array) as the first argument, resolves them from left-to-right, optionally passing the result of the last, and the next task to a reducer.
If no reducer is passed, the tasks will be resolved in series, and the final tasks result will be passed as the result from reduce.
If a reducer is used, a seed can optionally be passed as the third parameter.
If no tasks are passed, the final result will be undefined
.
No reducer passed:
function a(callback){
aCalled = true;
t.pass('a called');
callback(null, 1);
}
function b(callback){
t.ok(aCalled, 'b called after a');
callback(null, 2);
}
var result = righto.reduce([righto(a), righto(b)]);
result(function(error, finalResult){
// finalResult === 2
});
With a custom reducer, and seed.
function a(last, callback){
aCalled = true;
t.pass('a called');
callback(null, last);
}
function b(last, callback){
t.ok(aCalled, 'b called after a');
callback(null, last + 2);
}
// Passes previous eventual result to next reducer call.
var result = righto.reduce(
[a, b],
function(result, next){ // Reducer
return righto(next, result);
},
5 // Seed
);
result(function(error, finalResult){
// finalResult === 7
});
Sometimes you need a task to run after another has succeeded, but you don't need its results, righto.after(task1, task2, taskN...) can be used to achieve this:
function foo(callback){
setTimeout(function(){
callback(null, 'first result');
}, 1000);
}
var getFoo = righto(foo);
function bar(callback){
callback(null, 'second result');
}
var getBar = righto(bar, righto.after(getFoo)); // wait for foo before running bar.
getBar(function(error, result){
result -> 'second result';
});
righto.all takes N tasks, or an Array of tasks as the first argument, resolves them all in parallel, and results in an Array of results.
var task1 = righto(function(done){
setTimeout(function(){
done(null, 'a');
}, 1000);
});
var task2 = righto(function(done){
setTimeout(function(){
done(null, 'b');
}, 1000);
});
var task3 = righto(function(done){
setTimeout(function(){
done(null, 'c');
}, 1000);
});
var all = righto.all([task1, task2, task3]);
all(function(error, results){
results; // -> ['a','b','c']
});
Synchronous functions can be used to create righto tasks using righto.sync:
var someNumber = righto(function(done){
setTimeout(function(){
done(null, 5);
}, 1000);
}
function addFive(value){
return value + 5;
}
var syncTask = righto.sync(addFive, someNumber);
syncTask(function(error, result){
result; // -> 10
});
Eventuals can also be returned from inside righto.sync, which will be resolved within the flow.
righto.sync(createARighto, args...); // Calls createARighto with args..., and then returns a new righto that resolves the result
righto.sync(createAPromise, args...); // Calls createAPromise with args..., and then returns a new righto that resolves the results
Anything can be converted to a righto with righto.from(anything);
righto.from(someRighto); // Returns someRighto
righto.from(somePromise); // Returns a new righto that resolves the promise
righto.from(5); // Returns a new righto that resolves 5
Sometimes it may be required to pass a resolvable (a righto, or promise) as an argument
rather than passing the resolved value of the resolvable. you can do this using righto.value(resolvable)
var righto1 = righto(function(done){
done(null, 5);
});
var rightoValue = righto.value(righto1);
var righto2 = righto(function(value, done){
// value === righto1
value(function(error, x){
// x === 5;
});
}, rightoValue);
righto2();
You can create a new righto
that resolves the key/runs a function on a result like so:
var user = righto(getUser);
var userName = user.get('name');
// OR: Use a function
var userName = user.get(user => user.name);
userName(function(error, name){
// error or userName.
});
And keys can be righto
's as well:
var user = righto(getUser);
var userKey = righto(getKey);
var userName = user.get(userKey);
userName(function(error, something){
// error or something.
});
You can resolve a task to an array containing either
the error or results from a righto with righto.surely
,
which resolves to an array in the form of [error?, results...?]
.
var errorOrX = righto.surely(function(done){
done(new Error('borked'));
});
var errorOrY = righto.surely(function(done){
done(null, 'y');
});
var z = righto(function([xError, x], [yError, y]){
xError; // -> Error 'borked'
x; // -> undefined
yError; // -> null
y; // -> 'y'
}, errorOrX, errorOrY);
z();
Wrap a righto task with a handler that either forwards the successful result, or sends the rejected error through a handler to resolve the task.
function mightFail(callback){
if(Math.random() > 0.5){
callback('borked');
}else{
callback(null, 'result');
}
};
function defaultString(error, callback){
callback(null, '');
}
var maybeAString = righto(mightFail),
aString = righto.handle(maybeAString, defaultString);
aString(function(error, result){
typeof result === 'string';
});
This can also be used to pass custom error results:
function nullOnNoent(error, callback){
if(error.code === 'ENOENT'){
return callback();
}
return callback(error);
}
var aFile = righto(fs.readFile, 'someFilePath.txt', 'utf8'),
aFileOrNull = righto.handle(aFile, nullOnNoent);
aFile(function(error, result){
// If the file isnt found, error && result will be null
});
Resolves an object to a new object where any righto values are resolved:
var foo = righto(function(callback){
asyncify(function(){
callback(null, 'foo');
});
});
// recursively resolve child objects
// V
var bar = righto.resolve({foo: {bar: foo}}, true);
bar(function(error, bar){
bar; // -> {foo: {bar: 'foo'}}
});
Occasionally you might want to mate a number of tasks into one task.
For this, you can use righto.mate.
function getStuff(callback){
// eventually...
callback(null, 3);
}
var stuff = righto(getStuff);
function getOtherStuff(callback){
// eventually...
callback(null, 7);
}
var otherStuff = righto(getOtherStuff);
var stuffAndOtherStuff = righto.mate(stuff, otherStuff);
stuffAndOtherStuff(function(error, stuff, otherStuff){
error -> null
stuff -> 3
otherStuff -> 7
});
A shorthand way to provide a failed result.
This is handy for rejecting in .get methods.
var something = someRighto.get(function(value){
if(!value){
return righto.fail('was falsey');
}
return value;
});
If you are using righto in an environment that supports proxies, you can use the proxy API:
var righto = require('righto').proxy;
var foo = righto(function(done){
setTimeout(function(){
done(null, {foo: 'bar'});
});
});
foo.bar(function(error, bar){
bar === 'bar'
});
The proxied api always returns the proxied version, meaning you can dot-access arbitrarily:
var righto = require('righto').proxy;
var foo = righto(function(done){
setTimeout(function(){
done(null, {
foo: {
bar: {
baz: 'hello'
}
}
});
});
});
foo.bar.baz(function(error, baz){
baz === 'hello'
});
Use these methods to check if something is a righto, a thenable, or resolvable (either righto or thenable);
var rigthoA = righto(function(done){
done(null, 1);
});
var promiseB = new Promise(function(resolve, reject){
resolve(null, 2);
});
righto.isRighto(rigthoA); -> true
righto.isRighto(promiseB); -> false
righto.isThenable(rigthoA); -> false
righto.isThenable(promiseB); -> true
righto.isResolvable(rigthoA); -> true
righto.isResolvable(promiseB); -> true
You can get a trace of where a righto went to resolve its dependencies by setting:
righto._debug = true;
which will tell any following calls to righto
to store a stack trace against it.
You can then retrieve the trace with:
var x = righto(something, ...);
x._trace(); ->
something (.../index.js:1034:13)
- argument "b" from taskB (.../index.js:1022:13)
- argument "a" from taskA (.../index.js:1016:13)
- argument "c" from taskC (.../index.js:1028:13)
- argument "a" from taskA (.../index.js:1016:13)
- argument "b" from taskB (.../index.js:1022:13)
- argument "a" from taskA (.../index.js:1016:13)
You can also tell righto to print a graph trace, highlighting the offending task, when a graph rejects.
Either per-righto:
var task = righto(fn, dep, dep, dep...);
task._traceOnError = true;
task();
// Logs...
Or globally:
righto._autotraceOnError = true;
Which print handy traces like this one:
Only rightos that were instantiated after setting the debug flag will support tracing.
The take/ignore syntax that used a single righto within an array has been deprecated due to it having been a bad idea that I should never have implemented to begin with.
This syntax was deprecated a few v1 versions ago, so you can get a console.warn for potential usages of the syntax by turning on _debug mode and _warnOnUnsupported:
righto._debug = true;
righto._warnOnUnsupported = true;
// ... code ...
var getFoo = righto(foo, [getBar]); // <- the unsupported syntax
getFoo( ... ); // -> console.warn()'s the line number where it was used.
FAQs
Wana do some async stuff? Righto..
The npm package righto receives a total of 98 weekly downloads. As such, righto popularity was classified as not popular.
We found that righto 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
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.