UNPKG

1.27 kBJavaScriptView Raw
1'use strict'
2
3/**
4 * Expose compositor.
5 */
6
7module.exports = compose
8
9function flatten (arr) {
10 return arr.reduce((acc, next) => acc.concat(Array.isArray(next) ? flatten(next) : next), [])
11}
12
13/**
14 * Compose `middleware` returning
15 * a fully valid middleware comprised
16 * of all those which are passed.
17 *
18 * @param {Array} middleware
19 * @return {Function}
20 * @api public
21 */
22
23function compose (middleware) {
24 if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!')
25 middleware = flatten(middleware)
26 for (const fn of middleware) {
27 if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')
28 }
29
30 /**
31 * @param {Object} context
32 * @return {Promise}
33 * @api public
34 */
35
36 return function (context, next) {
37 // last called middleware #
38 let index = -1
39 return dispatch(0)
40 function dispatch (i) {
41 if (i <= index) return Promise.reject(new Error('next() called multiple times'))
42 index = i
43 let fn = middleware[i]
44 if (i === middleware.length) fn = next
45 if (!fn) return Promise.resolve()
46 try {
47 return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
48 } catch (err) {
49 return Promise.reject(err)
50 }
51 }
52 }
53}