index.js
function define () {
  var args = Array.prototype.slice.call(arguments)
  var i, l

  var name = args.shift()
  if (is.array(name)) {
    name = args.shift()
    for (i = 0, l = name.length; i < l; i++) {
      define.apply(this, [name[i]].concat(args))
    }
    return this
  }

  if (!is.string(name)) throw new Error('Method name is not defined')

  var invoke = is.function(args[args.length - 1]) ? wrapFn(args.pop()) : null
  var pre = args.map(wrapFn)

  // define scope method
  this[name] = function () {
    var args = Array.prototype.slice.call(arguments)
    var self = this
    var callback

    if (is.function(args[args.length - 1])) callback = args.pop()

    // init pipeline
    var pipe = []
    var obj = this

    // prototype chain
    while (obj) {
      if (obj.hasOwnProperty('_hooks') && obj._hooks[name]) {
        pipe.unshift(obj._hooks[name])
      }
      obj = Object.getPrototypeOf(obj)
    }
    // pre middlewares
    pipe.unshift(pre)

    // invoke middleware
    if (invoke) pipe.push(invoke)

    pipe = flatten(pipe)

    // context object and next triggerer
    var ctx = new EventEmitter()
    ctx.method = name
    ctx.args = args
    var index = 0
    var size = pipe.length

    function next (err, res) {
      if (err || index === size) {
        var args = Array.prototype.slice.call(arguments)
        // callback when err or end of pipeline
        if (callback) callback.apply(self, args)
        args.unshift('end')
        ctx.emit.apply(ctx, args)
      } else if (index < size) {
        var fn = pipe[index]
        index++
        var val = fn.call(self, ctx, next)
        if (is.promise(val)) {
          val.then(function (res) {
            next(null, res)
          }, function (err) {
            next(err || new Error())
          })
        } else if (fn.length < 2) {
          // args without next() & not promise, sync func
          next(null, val)
        }
      }
    }

    if (callback) {
      next()
    } else {
      // use promise if no callback
      return new Promise(function (resolve, reject) {
        callback = function (err, result) {
          if (err) return reject(err)
          resolve(result)
        }
        next()
      })
    }
  }
  return this
}
function define () {
  var args = Array.prototype.slice.call(arguments)
  var i, l

  var name = args.shift()
  if (is.array(name)) {
    name = args.shift()
    for (i = 0, l = name.length; i < l; i++) {
      define.apply(this, [name[i]].concat(args))
    }
    return this
  }

  if (!is.string(name)) throw new Error('Method name is not defined')

  var invoke = is.function(args[args.length - 1]) ? wrapFn(args.pop()) : null
  var pre = args.map(wrapFn)

  // define scope method
  this[name] = function () {
    var args = Array.prototype.slice.call(arguments)
    var self = this
    var callback

    if (is.function(args[args.length - 1])) callback = args.pop()

    // init pipeline
    var pipe = []
    var obj = this

    // prototype chain
    while (obj) {
      if (obj.hasOwnProperty('_hooks') && obj._hooks[name]) {
        pipe.unshift(obj._hooks[name])
      }
      obj = Object.getPrototypeOf(obj)
    }
    // pre middlewares
    pipe.unshift(pre)

    // invoke middleware
    if (invoke) pipe.push(invoke)

    pipe = flatten(pipe)

    // context object and next triggerer
    var ctx = new EventEmitter()
    ctx.method = name
    ctx.args = args
    var index = 0
    var size = pipe.length

    function next (err, res) {
      if (err || index === size) {
        var args = Array.prototype.slice.call(arguments)
        // callback when err or end of pipeline
        if (callback) callback.apply(self, args)
        args.unshift('end')
        ctx.emit.apply(ctx, args)
      } else if (index < size) {
        var fn = pipe[index]
        index++
        var val = fn.call(self, ctx, next)
        if (is.promise(val)) {
          val.then(function (res) {
            next(null, res)
          }, function (err) {
            next(err || new Error())
          })
        } else if (fn.length < 2) {
          // args without next() & not promise, sync func
          next(null, val)
        }
      }
    }

    if (callback) {
      next()
    } else {
      // use promise if no callback
      return new Promise(function (resolve, reject) {
        callback = function (err, result) {
          if (err) return reject(err)
          resolve(result)
        }
        next()
      })
    }
  }
  return this
}
function define ( ) { var args = Array . prototype . slice . call ( arguments ) var i , l var name = args . shift ( ) if ( is . array ( name ) ) { name = args . shift ( ) for ( i = 0 , l = name . length ; i < l ; i ++ ) { define . apply ( this , [ name [ i ] ] . concat ( args ) ) } return this } if ( ! is . string ( name ) ) throw new Error ( 'Method name is not defined' ) var invoke = is . function ( args [ args . length - 1 ] ) ? wrapFn ( args . pop ( ) ) : null var pre = args . map ( wrapFn ) // define scope method this [ name ] = function ( ) { var args = Array . prototype . slice . call ( arguments ) var self = this var callback if ( is . function ( args [ args . length - 1 ] ) ) callback = args . pop ( ) // init pipeline var pipe = [ ] var obj = this // prototype chain while ( obj ) { if ( obj . hasOwnProperty ( '_hooks' ) && obj . _hooks [ name ] ) { pipe . unshift ( obj . _hooks [ name ] ) } obj = Object . getPrototypeOf ( obj ) } // pre middlewares pipe . unshift ( pre ) // invoke middleware if ( invoke ) pipe . push ( invoke ) pipe = flatten ( pipe ) // context object and next triggerer var ctx = new EventEmitter ( ) ctx . method = name ctx . args = args var index = 0 var size = pipe . length function next ( err , res ) { if ( err || index === size ) { var args = Array . prototype . slice . call ( arguments ) // callback when err or end of pipeline if ( callback ) callback . apply ( self , args ) args . unshift ( 'end' ) ctx . emit . apply ( ctx , args ) } else if ( index < size ) { var fn = pipe [ index ] index ++ var val = fn . call ( self , ctx , next ) if ( is . promise ( val ) ) { val . then ( function ( res ) { next ( null , res ) } , function ( err ) { next ( err || new Error ( ) ) } ) } else if ( fn . length < 2 ) { // args without next() & not promise, sync func next ( null , val ) } } } if ( callback ) { next ( ) } else { // use promise if no callback return new Promise ( function ( resolve , reject ) { callback = function ( err , result ) { if ( err ) return reject ( err ) resolve ( result ) } next ( ) } ) } } return this }
ginga define method
ginga define method