Savage Async Middleware. 🐺
Connect style middleware with promise support.
npm i warewolf --save
Warewolf generates a function that can be called with any number of arguments.
Every function passed will asynchronously wait for a promise to be returned or next
to be called.
import warewolf from 'warewolf';
const handler = warewolf(
(arg1, arg2, next) => {
// middleware
next();
},
(arg1, arg2, next) => {
// middleware
next();
},
(arg1, arg2, done) => {
// after all middleware has been called
done(null, 'success');
}
);
handler(1, 2, console.log);
// prints [null, 'success']
Wrap each step - even pass different args!
import { wareBuilder } from 'warewolf';
const handler = wareBuilder(step => {
return (arg1, arg2, next) => {
console.log('BEFORE');
const result = step(arg1, arg2, next);
console.log('AFTER');
return result;
}
})(
(arg1, arg2, next) => {
// middleware
next();
},
(arg1, arg2, done) => {
// after all middleware has been called
done(null, 'success');
}
);
handler(1, 2, console.log);
// prints 'BEFORE'
// prints 'AFTER'
// prints 'BEFORE'
// prints 'AFTER'
// prints [null, 'success']
Just like connect, we'll stop iteration if next receives a value or if an error is thrown.
import warewolf from 'warewolf';
const handler = warewolf(
(arg1, arg2, next) => {
// middleware
next('error');
},
(arg1, arg2, next) => {
// middleware
next();
},
(arg1, arg2, done) => {
// after all middleware has been called
done('success');
}
);
handler(1, 2, console.log);
// prints 'error'
Also, just like express, if you add a middleware method with an arity + 1 of the main stack call, warewolf treats this method like an error handler.
import warewolf from 'warewolf';
const handler = warewolf(
(arg1, arg2, next) => {
// middleware
next('error');
},
(err, arg1, arg2, next) => {
// error handler!
console.error(err);
next();
},
(arg1, arg2, done) => {
// this is still called
done('success');
}
);
handler(1, 2, console.log);
// prints 'error'
// prints 'success'
import warewolf from 'warewolf';
const ware1 = warewolf(
(arg1, arg2, next) => {
// middleware
next();
},
(arg1, arg2, next) => {
// middleware
next();
}
);
const ware2 = warewolf(
(arg1, arg2, next) => {
// middleware
next();
},
(arg1, arg2, next) => {
// middleware
next();
}
);
const handler = warewolf(ware2, ware1, (arg1, arg2, done) => {
done(null, 'success');
}));
handler(1, 2, console.log);
// prints [null, 'success']
You can also return promises instead of calling next.
import warewolf from 'warewolf';
const handler = warewolf(
(arg1, arg2) => {
// middleware
return new Promise(resolve => setImmediate(resolve));
},
(arg1, arg2) => {
// middleware
return new Promise(resolve => setImmediate(resolve));
},
(arg1, arg2) => {
// after all middleware has been called
return new Promise(resolve => resolve('success'));
}
);
handler(1, 2).then(console.log);
// prints 'success'
Unless you are creating an error handler, whatever you final handler accepts as arguments will be the number of arguments passed to your middleware, so it needs to be uniform!
Getting around this isn't that hard though.
function myShortMiddleware(arg1, next) {
// middleware
next();
}
function myLongMiddleware(arg1, arg2, next) {
}
const handler = warewolf(
myLongMiddleware,
(arg1, arg2, next) => myShortMiddleware(arg1, next),
(arg1, arg2, done) => {
// that was fun
}
);
handler(arg1, arg2, done);
MIT