// Created on savesnippets.com ยท https://savesnippets.com/AH9O5ZtOZxotMe function createPipeline(...middlewares) { return function run(context) { let index = -1; function dispatch(i) { if (i <= index) return Promise.reject(new Error('next() called multiple times')); index = i; const fn = middlewares[i]; if (!fn) return Promise.resolve(); try { return Promise.resolve(fn(context, () => dispatch(i + 1))); } catch (err) { return Promise.reject(err); } } return dispatch(0); }; } // Usage const pipeline = createPipeline( async (ctx, next) => { ctx.start = Date.now(); await next(); ctx.duration = Date.now() - ctx.start; }, async (ctx, next) => { if (!ctx.user) throw new Error('Unauthenticated'); await next(); }, async (ctx) => { ctx.result = await fetch(`/api/user/${ctx.user}`).then((r) => r.json()); } ); await pipeline({ user: 'alice' });