docs: function runAfter (args, methodMeta, ret) {
      // return original promise if there are no after extensions
      if (!defined(methodMeta.after)) {
          return ret
      }
      // after original promise resolves then run after methods
      return ret.then(res => {
          // build arguments for after methods
          args = {
              args: defined(args.args) ? args.args : args,
              res: res,
              origRes: defined(args.origRes) ? args.origRes : args.res,
              session: args.session,
          }
          // wait for all extension methods to complete
          return Promise.all(
              // run all after methods in order making sure they return promise
              _.map(methodMeta.after, method => {
                  return (method)(args, methodMeta.signature, 'after')
              })
          )
          // merge returned data into original
          .then(function (results) {
              // either merge or replace result
              _.each(results, result => {
                  // both original res and after result are objects
                  if (typeof res === 'object' && res !== null && typeof result === 'object' && result !== null) {
                      // merge after into original
                      _.merge(res, result)
                  }
                  // one is not an object
                  else if (result !== undefined) {
                      // replace original with after
                      res = result
                  }
              })
              // return final result
              return res
          })
      })
  }