--- /dev/null
+'use strict'
+
+var wrap = require('./wrap.js')
+
+module.exports = trough
+
+trough.wrap = wrap
+
+var slice = [].slice
+
+// Create new middleware.
+function trough() {
+ var fns = []
+ var middleware = {}
+
+ middleware.run = run
+ middleware.use = use
+
+ return middleware
+
+ // Run `fns`. Last argument must be a completion handler.
+ function run() {
+ var index = -1
+ var input = slice.call(arguments, 0, -1)
+ var done = arguments[arguments.length - 1]
+
+ if (typeof done !== 'function') {
+ throw new Error('Expected function as last argument, not ' + done)
+ }
+
+ next.apply(null, [null].concat(input))
+
+ // Run the next `fn`, if any.
+ function next(err) {
+ var fn = fns[++index]
+ var params = slice.call(arguments, 0)
+ var values = params.slice(1)
+ var length = input.length
+ var pos = -1
+
+ if (err) {
+ done(err)
+ return
+ }
+
+ // Copy non-nully input into values.
+ while (++pos < length) {
+ if (values[pos] === null || values[pos] === undefined) {
+ values[pos] = input[pos]
+ }
+ }
+
+ input = values
+
+ // Next or done.
+ if (fn) {
+ wrap(fn, next).apply(null, input)
+ } else {
+ done.apply(null, [null].concat(input))
+ }
+ }
+ }
+
+ // Add `fn` to the list.
+ function use(fn) {
+ if (typeof fn !== 'function') {
+ throw new Error('Expected `fn` to be a function, not ' + fn)
+ }
+
+ fns.push(fn)
+
+ return middleware
+ }
+}