@jrh/parappa v1.2.0
@jrh/parappa
Wrap any Node.js function with middleware-like behavior.
Installation
npm install @jrh/parappa
The Wrapping Function
Usage
const wrap = require('@jrh/parappa')
Syntax
const wrapped = wrap(original)
Arguments
Name | Type | Description |
---|---|---|
original | Function | A function to wrap. |
Methods
Name | Description | Returns |
---|---|---|
.with(wrapper) | Adds a wrapper function. | Function: Wrapping (Chainable) |
.and(wrapper) | Same as .with . | Function: Wrapping (Chainable) |
Returns
Type | Description |
---|---|
Promise: Function | A promise for the return value of the wrapped function. |
Wrapper Functions
Wrapper functions add middleware-like behavior to the original function.
Example
function original() {
}
function wrapper() {
before() {
}
after() {
}
onError() {
}
}
async function initialize() {
const wrapped = wrap(original).with(wrapper)
await wrapped(1, 2, 3)
}
Methods
Wrapper functions can define any combination of the following methods. All methods can be synchronous or asynchronous.
Name | Description | Arguments |
---|---|---|
.before() | Function to call before the original is executed. | All arguments passed to original . |
.after() | Function to call after the original is executed. | All arguments passed to original . |
.onError() | Function to call if an error occurs. | The caught error , then all arguments passed to original . |
Execution Order
If you have three wrappers attached, this is the expected order of execution:
wrap(original)
.with(wrapperOne)
.and(wrapperTwo)
.and(wrapperThree)
// => wrapperOne (before)
// => wrapperTwo (before)
// => wrapperThree (before)
// => original
// => wrapperOne (after)
// => wrapperTwo (after)
// => wrapperThree (after)
If a .before()
or .after()
function returns a value: Execution will stop and the wrapped function will return that value.
If no .before()
or .after()
function returns a value: The original function's return value will be returned.
Error Handling
When an error is thrown from the original function or any wrapper, each wrapper's .onError()
function will be called in the order that wrappers were applied.
If you have three wrappers attached and the original function throws an error, this is the expected order of execution:
wrap(original).with(wrapperOne).and(wrapperTwo).and(wrapperThree)
// => wrapperOne (before)
// => wrapperTwo (before)
// => wrapperThree (before)
// => original // Throws an error!
// => wrapperOne (onError)
// => wrapperTwo (onError)
// => wrapperThree (onError)
If an .onError()
function returns a value: Execution will stop and the wrapped function will return that value.
If no .onError()
function returns a value: The error will be thrown.
Usage Example
const wrap = require('@jrh/parappa')
function original(meter) {
console.log('I gotta believe!')
console.log(`U Rappin' ${ meter.performance }`)
}
function fleaswallow() {
before(meter) {
console.log(`Just because the rhythm is slow, that don't mean that you can't flow.`)
meter.performance = 'Cool'
}
onError(meter) {
console.log(`Oops!`)
meter.performance = 'Bad'
}
}
function chopchop() {
before(meter) {
console.log(`Kick! Punch! It's all in the mind.`)
}
after(meter) {
console.log(`Don't get cocky, it's gonna get rocky.`)
throw new Error()
}
onError(error, meter) {
console.log(`U Rappin' ${ meter.performance }.`
}
}
// ---------------------------------------------
async function initialize() {
const wrapped = wrap(original).with(fleaswallow).and(chopchop)
await wrapped({ performance: 'Good' })
}
initialize()
// => Just because the rhythm is slow, that don't mean that you can't flow.
// => Kick! Punch! It's all in the mind.
// => I gotta believe!
// => U Rappin' Cool.
// => Don't get cocky, it's gonna get rocky.
// => Oops!
// => U Rappin' Bad.