1.0.0 • Published 1 year ago

@adaptably/wrap v1.0.0

Weekly downloads
-
License
-
Repository
github
Last release
1 year ago

@adaptably/wrap

Wrap any Node.js function with middleware-like behavior.

Installation

npm install @adaptably/wrap

The Wrapping Function

Usage

const wrap = require('@adaptably/wrap')

Syntax

const wrapped = wrap(original)

Arguments

NameTypeDescription
originalFunctionA function to wrap.

Methods

NameDescriptionReturns
.with(wrapper)Adds a wrapper function.Function: Wrapping (Chainable)
.and(wrapper)Same as .with.Function: Wrapping (Chainable)

Returns

TypeDescription
Promise: FunctionA 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() {
  }
}

function initialize() {
  const wrapped = wrap(original).with(wrapper)
  wrapped(arguments)
}

Methods

Wrapper functions can define any combination of the following methods. All methods can be synchronous or asynchronous.

NameDescriptionArguments
.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('@adaptably/wrap')

function original() {
  console.log('Original')
}

function layerOne() {
  before() {
    console.log('Layer One: Before')
  }

  after() {
    console.log('Layer One: After')
  }

  onError() {
    console.log('Layer One: Error!')
  }
}

function layerTwo() {
  before() {
    console.log('Layer Two: Before')
  }

  after() {
    console.log('Layer Two: After')
    throw new Error()
  }

  onError() {
    console.log('Layer Two: Error!')
    return 'Saved'
  }
}

// ---------------------------------------------

async function initialize() {
  const wrapped = wrap(original).with(layerOne).and(layerTwo)
  await wrapped({ message: 'Original' })
}

const result = initialize()
console.log('Result:', result)

// => Layer One: Before
// => Layer Two: Before
// => Original
// => Layer One: After
// => Layer Two: After
// => Layer One: Error!
// => Layer Two: Error!
// => Result: Saved
1.0.0

1 year ago