function compose (middleware) {
    if(!Array.isArray(middleware)) throw TypeError('Middleware stack must be an array!')
    for (const fn of middleware) {
        if(typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')
    }
    let index = -1 //
    
      /**
   * @param {Object} context
   * @return {Promise}
   * @api compose
   */
    return function (context, next) {
        return new Promise((resolve, reject) => {
            function dispatch (i) { //
                if (i <= index) {
                    console.warn('[warn]next() called multiple times')
                    return //reject(new Error('next() called multiple times'))  
                } 
            
                index=i
                let fn=middleware[i]
                if(i===middleware.length) fn=next //
                if(!fn) return resolve()
    
                try {
                    return resolve(fn(context,dispatch.bind(null,i+1)))
                } catch (error) {
                    return reject(error)
                }
    
            }
            dispatch(0)
        })
    }
}