puff v1.1.0
puff
Promisify with proxies
Intro
It's one of those modules that promisify (aka denodeify) things. Promisify means making a node-style function (...args, callback: (err, ...returnValues)) return a Promise instead (...args): Promise<returnValues>.
Using Javascript proxies has the advantage of not modifying the object you pass into it. At least, the operations that you can do with it. All the other operations we're not concerned about will still stay the same as if operating on the original object.
Usage
WARNING: Requires runtime Proxy support! (in case the description didn't give it away)
fn(fnArg, opts)
require('puff/fn')
Promisifies a node-style function.
fnArgThe node-style function.optsmultiArgsWhether to catch multiple arguments in the node-style callback. The arguments will be passed as an array when the returnedPromiseresolves. Otherwise, a single argument is assumed and that is passed as the resolution value of the returnedPromise.
Returns Proxy<Function>: Promise.
obj(objArg, opts)
require('puff/obj')
Promisifies the enumerable properties of an object.
objArgThe object.opts→ fnfilterA function to filter the keys with. Default =defaultFilterbind| Passtrueto bind the returned proxy to the promisified functions. Pass the stringoriginalto bind the original object instead.
Caches all the promisified functions, no hit on property access.
Returns Proxy<Object>.
dynamic(objArg, opts)
require('puff/dynamic')
Promisifies all of the properties of an object.
objArgThe object.opts→ fnfilterA function to filter which keys should be promisified when called. Default =defaultFilterbind| Passtrueto bind the returned proxy to the promisified functions. Pass the stringoriginalto bind the original object instead.
Simplified proxy creation but takes a small hit on property access.
Functions defined on Object.prototype as well as some reserved words such as constructor and prototype are always excluded.
Returns Proxy<Object>.
class(constructorFn, opts)
require('puff/class')
Promisifies the properties of an instance of a class after the instance is created, given the class.
constructorFnThe class (constructor function).opts→ dynamicbindhas no effect here, so it won't be passed on.
Returns Proxy<Function>.
Why use dynamic instead of obj?
This is to support Javascript's multiple inheritance model. Using obj is fine if we will be able to know for sure what keys are defined on an object. It's definitely possible if we enumerate all the keys on the object's prototype chain. But if an object inherits from multiple prototypes, there's no way we can find that out. (If there is, please do let me know.)
auto(objArg, opts)
require('puff') (main module)
Runs the object through obj and possibly fn if it's a function.
objArg|opts→ obj, → fn
defaultFilter(key)
(Internal) The default filter. It filters out strings ending with "Sync".
Chaining modules together
It is recommended that you know the type of the thing you want to promisify.
For plain objects, you can just use obj.
x = require('puff/obj')(x)For hybrid function / function containers, you can use auto.
x = require('puff')(x)But you can also chain calls to fn and obj to achieve the same result:
x = require('puff/fn')(require('puff/obj')(x))The point is that you can mix and match the modules provided to match your needs.
Notes
→ means "also passed to (the right side)"
Special thanks
- Portions of code are derived from
pify. - Thanks to the npm team for support with this package!
License
MIT