Pass proto to ensure consistency

Pass proto to ensure consistency

    q     = require 'q'
    fs    = require 'fs'
    async = require 'async'
    uuid  = require 'uuid-1345'

    microtime = require 'microtime'

    EventEmitter2 = require('eventemitter2').EventEmitter2
    emitter       = new EventEmitter2 wildcard: true

    available   = { }
    initialized = { }
    listeners   = { }

    code_root = process.env.SEARCH_ROOT || 'dist'

    underscore = (value) -> value.replace /\W+/g, '_'
    strip      = (name)  -> name.toLowerCase().replace /\W+/g, ''

    SEARCH_ROOTS  = { }
    WRAPPED       = { }
    _INITIALIZERS = { }
    HYDRATED      = { }

    HYRDATION_LISTENERS = { }

    INITIALIZERS = (cls, method) ->
      _INITIALIZERS[cls] = [ ] unless _INITIALIZERS[cls]?

      _INITIALIZERS[cls].push fn: method, called: false

    WRAP = (cls, method) ->
      unless WRAPPED[cls]?
        WRAPPED[cls] = [
          'constructor'
          'initialize'
          'details'
        ]

      WRAPPED[cls].indexOf(method) < 0

    class Madul

      details: =>
        name  = @.__proto__.constructor.name
        props = for own key, val of @.__proto__
          if key != 'constructor' &&
             key != 'details'     &&
             key != 'initialize'  && ((
               key[0]            == '_' &&
               @.__proto__[key]? == false
             ) || key[0] != '_')

            if typeof val == 'function'
              value = val.constructor.name
            else if Array.isArray val
              value = for v in val
                if typeof v == 'function'
                  v.constructor.name
                else if typeof v == 'object'
                  v.constructor.name
                else
                  v
              value = value.join ','
            else if typeof val == 'object'
              value = val.constructor.name
            else
              value = val

            "#{key} => #{value}"

        "\n  #{name}\n    #{props.filter((e) -> e?).join '\n    '}"

      @LISTEN: (event, callback) => emitter.on event, callback

      @FIRE: (event, args) => emitter.emit event, args

      @SEARCH_ROOT: (mod, path) =>
        Madul.FIRE '$.Madul.search_root.register', "#{mod}": path

        SEARCH_ROOTS[mod] = path.substring 0, path.lastIndexOf '/'

      listen: (event, callback) ->
        Madul.LISTEN "*.#{@constructor.name}.#{event}", callback

      fire: (event, args) ->
        Madul.FIRE "@.#{@constructor.name}.#{event}", args

      warn: (event, details) ->
        Madul.FIRE "!.#{@constructor.name}.#{event}", details

      _report: (name, method, state, id, args) =>
        Madul.FIRE "@.#{name}.#{method}.#{state}",
          uuid:      id
          args:      args
          timestamp: microtime.now()

      _respond: (proto, method, id, deferred) =>
        (state, data) =>
          process.nextTick =>
            deferred[state] data

            proto._report proto.constructor.name, method, state, id, data

      _prep_invocation: (proto, method, input, def) =>
        id  = uuid.v4fast()
        res = proto._respond proto, method, id, def

        if Array.isArray input
          input.push (out) => res 'resolve', out
          input.push (err) => res 'reject',  err
          input.push (out) => res 'notify',  out
        else if typeof input == 'object'
          input.done   = (out) => res 'resolve', out
          input.fail   = (err) => res 'reject',  err
          input.update = (out) => res 'notify',  out

          input = [ input ]
        else
          msg = "input to #{proto.constructor.name}.#{method} must be an Array of Object"
          @warn 'input.invalid', msg
          throw new Error msg

        proto._report proto.constructor.name, method, 'invoke', id, input

        input

      _do_wrap: (proto, method) =>
        if method != 'fire' && method != 'warn' && method != 'listen'
          Madul.FIRE "$.#{proto.constructor.name}.#{method}.wrap"

          if typeof proto[method] == 'function'
            proto["_#{method}"] = proto[method]

            proto[method] = =>
              def  = q.defer()
              args = if arguments[0]? then Array.prototype.slice.call arguments else [ ]

              proto["_#{method}"].apply @, proto._prep_invocation proto, method, args, def

              def.promise
          else if typeof proto[method] == 'object'

            if Array.isArray proto[method].validate
              args_format = 'ARRAY'
              decs        = for val in proto[method].validate
                @_parse_handle(val).ref

              proto[method].validate = decs
            else if typeof proto[method].validate == 'object'
              args_format = 'OBJECT'
              decs        = for own key, val of proto[method].validate
                { ref } = @_parse_handle val
                proto[method].validate[key] = ref
                ref
            else if typeof proto[method].validate == 'string'
              args_format = 'ARRAY'
              decs        = [ @_parse_handle(proto[method].validate).ref ]
            else if typeof proto[method].validate != 'undefined'
              @warn 'meta.invalid', validate: 'must be a String, Object, or Array'
              return
            else
              args_format = 'ARRAY'
              decs        = [ ]

            decs = decs.concat(proto[method].before.map (b, i) =>
              { ref } = @_parse_handle b
              proto[method].before[i] = ref
              ref
            ) if proto[method].before?

            decs = decs.concat(proto[method].after.map (a, i) =>
              { ref } = @_parse_handle a
              proto[method].after[i] = ref
              ref
            ) if proto[method].after?

            Madul.FIRE '$.Madul.decorators.hydrate', decs

            @_do_hydrate proto, decs, =>
              proto["_#{method}"] = proto[method]

              proto[method] = =>
                def = q.defer()
                me  = proto["_#{method}"]

                if args_format == 'ARRAY'
                  args = Array.prototype.slice.call arguments

                  if me.validate?
                    validators = for val, i in me.validate
                      { ref } = @_parse_handle val
                      Madul.FIRE '$.Madul.validator.execute', "#{ref}": args[i]
                      proto[ref].EXECUTE args[i]
                else if args_format == 'OBJECT'
                  args = arguments[0]

                  if me.validate?
                    validators = for own key, val of me.validate
                      { ref } = @_parse_handle val
                      Madul.FIRE '$.Madul.validator.execute', "#{ref}": args[key]
                      proto[ref].EXECUTE args[key]
                else
                  @warn 'cannot-continue', 'No arg format specified'

                  return def.reject 'No arg format specified'

                me.before = [ ] unless me.before?
                me.after  = [ ] unless me.after?

                q.all validators
                .then =>
                  q.all me.before.map (b) =>
                    Madul.FIRE '$.Madul.before_filter.execute', "#{b}": args
                    proto[b].before args
                .then =>
                  me.behavior.apply @, @_prep_invocation proto, method, args, def
                .then (result) =>
                  if me.after.length > 0
                    q.all me.after.map (b) =>
                      Madul.FIRE '$.Madul.after_filter.execute', "#{b}": result
                      b.after result
                  else
                    d = q.defer()

                    process.nextTick => d.resolve result

                    d.promise
                .then  (out) => def.resolve out
                .catch (err) => def.reject  err

                def.promise
          else
            @warn 'cannot-wrap', method

          WRAPPED[proto.constructor.name].push method

      _wrap_methods: (proto, callback) =>
        name    = proto.constructor.name
        to_wrap = [ ]

        while proto? && Object.keys(proto).length > 0 && WRAPPED[name]? == false
          to_wrap.push { proto, name, methods: [ ] }

          for own prop, body of proto
            if prop[0]                  != '_'         &&
               typeof proto["_#{prop}"] == 'undefined' &&
               WRAP(name, prop)         == true

              continue if proto.deps? && proto.deps.indexOf(prop.replace(/_/g, '-')) > -1

              if typeof body == 'function' || typeof body?.behavior == 'function'
                to_wrap[to_wrap.length - 1].methods.push prop

          proto = proto.__proto__
          name  = proto.constructor.name

        async.each to_wrap.reverse(), (wrap, completed) =>
          async.each wrap.methods, (method, next) =>
            wrap.proto._do_wrap wrap.proto, method

            INITIALIZERS wrap.name, method if method[0] == '$'

            next()
          , => @_call_initializers_for wrap.proto, wrap.name, completed
        , callback

      _make_available: (name, mod) =>
        Madul.FIRE "$.#{name}.available"

        available[strip name] = mod

      _hydrate_deps: (proto, done) =>
        protos = [ proto ]

        if proto.__proto__?
          while proto.__proto__? && Object.keys(proto.__proto__).length > 0
            protos.push proto = proto.__proto__

        async.each protos.reverse(), (p, next) =>
          name = p.constructor.name

          if p.hasOwnProperty 'deps'
            if HYDRATED[name] == undefined
              HYDRATED[name]            = false
              HYRDATION_LISTENERS[name] = [ next ]

              p._do_hydrate p, p.deps, =>
                HYDRATED[name] = true

                for listener in HYRDATION_LISTENERS[name]
                  listener()
            else if HYDRATED[name] == false
              HYRDATION_LISTENERS[name].push next
            else if HYDRATED[name] == true
              next()
          else
            next()
        , done

      _init_if_madul: (path, callback) =>
        mod      = require path
        proto    = mod
        is_madul = false

        while proto
          is_madul = true if proto.name == 'Madul'
          if is_madul                            == false      &&
             proto.constructor.name              != 'Object'   &&
             typeof proto                        == 'function' &&
             typeof proto.__super__?.constructor == 'function'
            proto = proto.__super__.constructor
          else
            proto = undefined

        if is_madul
          new mod()
            .initialize()
            .then callback
        else
          callback mod

      _load: (me, name, path, loaded) =>
        me._init_if_madul path, (mod) =>
          me._make_available name, mod
          loaded mod

      _check: (me, path, dep, ref, finished) =>
        fs.readdir path, (err, files) =>
          if err?
            me.warn 'file-not-found', err

            done type: 'ERROR', info: err
          else
            async.each files, (f, next) =>
              depth = "#{path}/#{f}"

              fs.stat depth, (e, s) =>
                if s.isDirectory() && f[0] != '.'
                  me._check me, depth, dep, ref, next
                else if s.isFile() && f.substring(0, f.length - 3) == dep
                  me._load me, ref, depth, (mod) => me._do_add me, mod, ref, next
                else
                  next()
            , finished

      _do_add: (me, mod, ref, next) =>
        Madul.FIRE "$.#{me.constructor.name}.dependency.register", ref

        me[underscore ref] = mod

        next()

      _add: (me, ref, path, next) =>
        me._init_if_madul path, (mod) =>
          me._make_available ref, mod
          me._do_add me, mod, ref, next

      _parse_handle: (value) =>
        tokens = value.split '='

        if tokens.length == 2
          initer = tokens[1].trim()
          t      = tokens[0].split '->'

          if t[0].indexOf('#') > -1
            r = t[0].split '#'

            root = SEARCH_ROOTS[r[0].trim()]
            t[0] = r[1]

          if t.length == 2
            name  = t[0].trim()
            alias = t[1].trim()
          else if t.length == 1
            name = alias = t[0].trim()
          else
            return next @warn 'alias.invalid', tokens[1]

          toks = initer.split ':'

          if toks.length == 2
            initer = toks[0].trim()
            pres   = toks[1].split(',').map (p) => p.trim()
          else if toks.length == 1
            initer = toks[0].trim()
          else
            return next @warn 'dependency-initializer.invalid', tokens[1]

        else if tokens.length == 1
          t = tokens[0].split '->'

          if t[0].indexOf('#') > -1
            r = t[0].split '#'

            root = SEARCH_ROOTS[r[0].trim()]
            t[0] = r[1]

          if t.length == 2
            name  = t[0].trim()
            alias = t[1].trim()
          else if t.length == 1
            name = alias = t[0].trim()
          else
            return next @warn 'alias.invalid', tokens[1]

        else
          return next @warn 'dependency.invalid', d

        { ref: alias || name, alias, name, root, initer, pres }

      _do_hydrate: (proto, deps, hydration_complete) =>
        initers = [ ]

        async.each deps, (d, next) =>
          { ref, alias, name, root, initer, pres } = @_parse_handle d

          if pres?
            insert_at = for p in pres
              index_for = (sibling) => sibling.alias == p.alias

              initers.find index_for

            insert_at.sort()

            insert_at = if insert_at.length == 0 then 0 else insert_at[insert_at.length - 1]

            initers.splice insert_at, 0, alias: alias, execute: initer

          if proto[underscore ref]? == false
            if available[strip ref]? == true
              proto._do_add proto, available[strip ref], ref, next
            else
              try
                proto._add proto, ref, name, next
              catch e
                if root?
                  Madul.FIRE '$.Madul.search_root.load', { name, alias, root }

                  proto._check proto, root, name, ref, next
                else
                  cwd = process.cwd()
                  pkg = "#{cwd}/node_modules/#{name}/package.json"

                  fs.stat pkg, (err, stat) =>
                    if stat?.isFile()
                      fs.readFile pkg, 'utf8', (err, data) =>
                        json = JSON.parse data
                        main = json.main || json._main || 'index.js'
                        path = "#{cwd}/node_modules/#{name}/#{main}"

                        proto._add proto, ref, path, next
                    else
                      proto._check proto, "#{cwd}/#{code_root}", name, ref, next
          else
            next()
        , =>
          async.eachSeries initers, (initer, next) =>
            proto[initer.execute].apply(@).then next
          , hydration_complete

      _finish_up: (proto, args) =>
        name = proto.constructor.name

        if listeners[name]?
          async.each listeners[name], (listener, next) =>
            listener @
            next()
          , => @_register_initialized name
        else
          @_register_initialized name

      _register_initialized: (name) =>
        @_make_available name, @

        initialized[name] = true

        Madul.FIRE "$.#{name}.initialized"

      _call_initializers_for: (proto, name, callback) =>
        if _INITIALIZERS[name]?
          async.each _INITIALIZERS[name], (initializer, next) =>
            if initializer.called == false
              proto[initializer.fn].apply @
                .then =>
                  initializer.called = true
                  next()
            else
              next()
          , callback
        else
          callback()

      _invoke_parent_initializers: (callback) =>
        proto = @.__proto__

        if proto.__proto__?
          parents = while proto.__proto__? && Object.keys(proto.__proto__).length > 0
            proto = proto.__proto__

          async.each parents, (parent, next) =>
            @_call_initializers_for parent.constructor.name, next
          , callback
        else
          callback()

      initialize: =>
        deferred = q.defer()
        proto    = @.__proto__
        name     = proto.constructor.name

        Madul.FIRE "$.#{name}.request_instance"

        if initialized[name] == undefined
          Madul.FIRE "$.#{name}.initialize"

          initialized[name] = false
          listeners[name]   = [ deferred.resolve ]

          @_wrap_methods()
          @_hydrate_deps => @_invoke_parent_initializers => @_finish_up proto
        else if initialized[name] == false
          listeners[name].push deferred.resolve
        else if initialized[name] == true
          process.nextTick => deferred.resolve available[strip name]

        deferred.promise

    module.exports = Madul

    q     = require 'q'
    fs    = require 'fs'
    async = require 'async'
    uuid  = require 'uuid-1345'

    microtime = require 'microtime'

    EventEmitter2 = require('eventemitter2').EventEmitter2
    emitter       = new EventEmitter2 wildcard: true

    available   = { }
    initialized = { }
    listeners   = { }

    code_root = process.env.SEARCH_ROOT || 'dist'

    underscore = (value) -> value.replace /\W+/g, '_'
    strip      = (name)  -> name.toLowerCase().replace /\W+/g, ''

    SEARCH_ROOTS  = { }
    WRAPPED       = { }
    _INITIALIZERS = { }
    HYDRATED      = { }

    HYRDATION_LISTENERS = { }

    INITIALIZERS = (cls, method) ->
      _INITIALIZERS[cls] = [ ] unless _INITIALIZERS[cls]?

      _INITIALIZERS[cls].push fn: method, called: false

    WRAP = (cls, method) ->
      unless WRAPPED[cls]?
        WRAPPED[cls] = [
          'constructor'
          'initialize'
          'details'
        ]

      WRAPPED[cls].indexOf(method) < 0

    class Madul

      details: =>
        name  = @.__proto__.constructor.name
        props = for own key, val of @.__proto__
          if key != 'constructor' &&
             key != 'details'     &&
             key != 'initialize'  && ((
               key[0]            == '_' &&
               @.__proto__[key]? == false
             ) || key[0] != '_')

            if typeof val == 'function'
              value = val.constructor.name
            else if Array.isArray val
              value = for v in val
                if typeof v == 'function'
                  v.constructor.name
                else if typeof v == 'object'
                  v.constructor.name
                else
                  v
              value = value.join ','
            else if typeof val == 'object'
              value = val.constructor.name
            else
              value = val

            "#{key} => #{value}"

        "\n  #{name}\n    #{props.filter((e) -> e?).join '\n    '}"

      @LISTEN: (event, callback) => emitter.on event, callback

      @FIRE: (event, args) => emitter.emit event, args

      @SEARCH_ROOT: (mod, path) =>
        Madul.FIRE '$.Madul.search_root.register', "#{mod}": path

        SEARCH_ROOTS[mod] = path.substring 0, path.lastIndexOf '/'

      listen: (event, callback) ->
        Madul.LISTEN "*.#{@constructor.name}.#{event}", callback

      fire: (event, args) ->
        Madul.FIRE "@.#{@constructor.name}.#{event}", args

      warn: (event, details) ->
        Madul.FIRE "!.#{@constructor.name}.#{event}", details

      _report: (name, method, state, id, args) =>
        Madul.FIRE "@.#{name}.#{method}.#{state}",
          uuid:      id
          args:      args
          timestamp: microtime.now()

      _respond: (proto, method, id, deferred) =>
        (state, data) =>
          process.nextTick =>
            deferred[state] data

            proto._report proto.constructor.name, method, state, id, data

      _prep_invocation: (proto, method, input, def) =>
        id  = uuid.v4fast()
        res = proto._respond proto, method, id, def

        if Array.isArray input
          input.push (out) => res 'resolve', out
          input.push (err) => res 'reject',  err
          input.push (out) => res 'notify',  out
        else if typeof input == 'object'
          input.done   = (out) => res 'resolve', out
          input.fail   = (err) => res 'reject',  err
          input.update = (out) => res 'notify',  out

          input = [ input ]
        else
          msg = "input to #{proto.constructor.name}.#{method} must be an Array of Object"
          @warn 'input.invalid', msg
          throw new Error msg

        proto._report proto.constructor.name, method, 'invoke', id, input

        input

      _do_wrap: (proto, method) =>
        if method != 'fire' && method != 'warn' && method != 'listen'
          Madul.FIRE "$.#{proto.constructor.name}.#{method}.wrap"

          if typeof proto[method] == 'function'
            proto["_#{method}"] = proto[method]

            proto[method] = =>
              def  = q.defer()
              args = if arguments[0]? then Array.prototype.slice.call arguments else [ ]

              proto["_#{method}"].apply @, proto._prep_invocation proto, method, args, def

              def.promise
          else if typeof proto[method] == 'object'

            if Array.isArray proto[method].validate
              args_format = 'ARRAY'
              decs        = for val in proto[method].validate
                @_parse_handle(val).ref

              proto[method].validate = decs
            else if typeof proto[method].validate == 'object'
              args_format = 'OBJECT'
              decs        = for own key, val of proto[method].validate
                { ref } = @_parse_handle val
                proto[method].validate[key] = ref
                ref
            else if typeof proto[method].validate == 'string'
              args_format = 'ARRAY'
              decs        = [ @_parse_handle(proto[method].validate).ref ]
            else if typeof proto[method].validate != 'undefined'
              @warn 'meta.invalid', validate: 'must be a String, Object, or Array'
              return
            else
              args_format = 'ARRAY'
              decs        = [ ]

            decs = decs.concat(proto[method].before.map (b, i) =>
              { ref } = @_parse_handle b
              proto[method].before[i] = ref
              ref
            ) if proto[method].before?

            decs = decs.concat(proto[method].after.map (a, i) =>
              { ref } = @_parse_handle a
              proto[method].after[i] = ref
              ref
            ) if proto[method].after?

            Madul.FIRE '$.Madul.decorators.hydrate', decs

            @_do_hydrate proto, decs, =>
              proto["_#{method}"] = proto[method]

              proto[method] = =>
                def = q.defer()
                me  = proto["_#{method}"]

                if args_format == 'ARRAY'
                  args = Array.prototype.slice.call arguments

                  if me.validate?
                    validators = for val, i in me.validate
                      { ref } = @_parse_handle val
                      Madul.FIRE '$.Madul.validator.execute', "#{ref}": args[i]
                      proto[ref].EXECUTE args[i]
                else if args_format == 'OBJECT'
                  args = arguments[0]

                  if me.validate?
                    validators = for own key, val of me.validate
                      { ref } = @_parse_handle val
                      Madul.FIRE '$.Madul.validator.execute', "#{ref}": args[key]
                      proto[ref].EXECUTE args[key]
                else
                  @warn 'cannot-continue', 'No arg format specified'

                  return def.reject 'No arg format specified'

                me.before = [ ] unless me.before?
                me.after  = [ ] unless me.after?

                q.all validators
                .then =>
                  q.all me.before.map (b) =>
                    Madul.FIRE '$.Madul.before_filter.execute', "#{b}": args
                    proto[b].before args
                .then =>
                  me.behavior.apply @, @_prep_invocation proto, method, args, def
                .then (result) =>
                  if me.after.length > 0
                    q.all me.after.map (b) =>
                      Madul.FIRE '$.Madul.after_filter.execute', "#{b}": result
                      b.after result
                  else
                    d = q.defer()

                    process.nextTick => d.resolve result

                    d.promise
                .then  (out) => def.resolve out
                .catch (err) => def.reject  err

                def.promise
          else
            @warn 'cannot-wrap', method

          WRAPPED[proto.constructor.name].push method

      _wrap_methods: (proto, callback) =>
        name    = proto.constructor.name
        to_wrap = [ ]

        while proto? && Object.keys(proto).length > 0 && WRAPPED[name]? == false
          to_wrap.push { proto, name, methods: [ ] }

          for own prop, body of proto
            if prop[0]                  != '_'         &&
               typeof proto["_#{prop}"] == 'undefined' &&
               WRAP(name, prop)         == true

              continue if proto.deps? && proto.deps.indexOf(prop.replace(/_/g, '-')) > -1

              if typeof body == 'function' || typeof body?.behavior == 'function'
                to_wrap[to_wrap.length - 1].methods.push prop

          proto = proto.__proto__
          name  = proto.constructor.name

        async.each to_wrap.reverse(), (wrap, completed) =>
          async.each wrap.methods, (method, next) =>
            wrap.proto._do_wrap wrap.proto, method

            INITIALIZERS wrap.name, method if method[0] == '$'

            next()
          , => @_call_initializers_for wrap.proto, wrap.name, completed
        , callback

      _make_available: (name, mod) =>
        Madul.FIRE "$.#{name}.available"

        available[strip name] = mod

      _hydrate_deps: (done) =>
        proto  = @.__proto__
        protos = [ proto ]

        if proto.__proto__?
          while proto.__proto__? && Object.keys(proto.__proto__).length > 0
            protos.push proto = proto.__proto__

        async.each protos.reverse(), (p, next) =>
          name = p.constructor.name

          if p.hasOwnProperty 'deps'
            if HYDRATED[name] == undefined
              HYDRATED[name]            = false
              HYRDATION_LISTENERS[name] = [ next ]

              p._do_hydrate p, p.deps, =>
                HYDRATED[name] = true

                for listener in HYRDATION_LISTENERS[name]
                  listener()
            else if HYDRATED[name] == false
              HYRDATION_LISTENERS[name].push next
            else if HYDRATED[name] == true
              next()
          else
            next()
        , done

      _init_if_madul: (path, callback) =>
        mod      = require path
        proto    = mod
        is_madul = false

        while proto
          is_madul = true if proto.name == 'Madul'
          if is_madul                            == false      &&
             proto.constructor.name              != 'Object'   &&
             typeof proto                        == 'function' &&
             typeof proto.__super__?.constructor == 'function'
            proto = proto.__super__.constructor
          else
            proto = undefined

        if is_madul
          new mod()
            .initialize()
            .then callback
        else
          callback mod

      _load: (me, name, path, loaded) =>
        me._init_if_madul path, (mod) =>
          me._make_available name, mod
          loaded mod

      _check: (me, path, dep, ref, finished) =>
        fs.readdir path, (err, files) =>
          if err?
            me.warn 'file-not-found', err

            done type: 'ERROR', info: err
          else
            async.each files, (f, next) =>
              depth = "#{path}/#{f}"

              fs.stat depth, (e, s) =>
                if s.isDirectory() && f[0] != '.'
                  me._check me, depth, dep, ref, next
                else if s.isFile() && f.substring(0, f.length - 3) == dep
                  me._load me, ref, depth, (mod) => me._do_add me, mod, ref, next
                else
                  next()
            , finished

      _do_add: (me, mod, ref, next) =>
        Madul.FIRE "$.#{me.constructor.name}.dependency.register", ref

        me[underscore ref] = mod

        next()

      _add: (me, ref, path, next) =>
        me._init_if_madul path, (mod) =>
          me._make_available ref, mod
          me._do_add me, mod, ref, next

      _parse_handle: (value) =>
        tokens = value.split '='

        if tokens.length == 2
          initer = tokens[1].trim()
          t      = tokens[0].split '->'

          if t[0].indexOf('#') > -1
            r = t[0].split '#'

            root = SEARCH_ROOTS[r[0].trim()]
            t[0] = r[1]

          if t.length == 2
            name  = t[0].trim()
            alias = t[1].trim()
          else if t.length == 1
            name = alias = t[0].trim()
          else
            return next @warn 'alias.invalid', tokens[1]

          toks = initer.split ':'

          if toks.length == 2
            initer = toks[0].trim()
            pres   = toks[1].split(',').map (p) => p.trim()
          else if toks.length == 1
            initer = toks[0].trim()
          else
            return next @warn 'dependency-initializer.invalid', tokens[1]

        else if tokens.length == 1
          t = tokens[0].split '->'

          if t[0].indexOf('#') > -1
            r = t[0].split '#'

            root = SEARCH_ROOTS[r[0].trim()]
            t[0] = r[1]

          if t.length == 2
            name  = t[0].trim()
            alias = t[1].trim()
          else if t.length == 1
            name = alias = t[0].trim()
          else
            return next @warn 'alias.invalid', tokens[1]

        else
          return next @warn 'dependency.invalid', d

        { ref: alias || name, alias, name, root, initer, pres }

      _do_hydrate: (proto, deps, hydration_complete) =>
        initers = [ ]

        async.each deps, (d, next) =>
          { ref, alias, name, root, initer, pres } = @_parse_handle d

          if pres?
            insert_at = for p in pres
              index_for = (sibling) => sibling.alias == p.alias

              initers.find index_for

            insert_at.sort()

            insert_at = if insert_at.length == 0 then 0 else insert_at[insert_at.length - 1]

            initers.splice insert_at, 0, alias: alias, execute: initer

          if proto[underscore ref]? == false
            if available[strip ref]? == true
              proto._do_add proto, available[strip ref], ref, next
            else
              try
                proto._add proto, ref, name, next
              catch e
                if root?
                  Madul.FIRE '$.Madul.search_root.load', { name, alias, root }

                  proto._check proto, root, name, ref, next
                else
                  cwd = process.cwd()
                  pkg = "#{cwd}/node_modules/#{name}/package.json"

                  fs.stat pkg, (err, stat) =>
                    if stat?.isFile()
                      fs.readFile pkg, 'utf8', (err, data) =>
                        json = JSON.parse data
                        main = json.main || json._main || 'index.js'
                        path = "#{cwd}/node_modules/#{name}/#{main}"

                        proto._add proto, ref, path, next
                    else
                      proto._check proto, "#{cwd}/#{code_root}", name, ref, next
          else
            next()
        , =>
          async.eachSeries initers, (initer, next) =>
            proto[initer.execute].apply(@).then next
          , hydration_complete

      _finish_up: (proto, args) =>
        name = proto.constructor.name

        if listeners[name]?
          async.each listeners[name], (listener, next) =>
            listener @
            next()
          , => @_register_initialized name
        else
          @_register_initialized name

      _register_initialized: (name) =>
        @_make_available name, @

        initialized[name] = true

        Madul.FIRE "$.#{name}.initialized"

      _call_initializers_for: (name, callback) =>
        if _INITIALIZERS[name]?
          async.each _INITIALIZERS[name], (initializer, next) =>
            if initializer.called == false
              proto[initializer.fn].apply @
                .then =>
                  initializer.called = true
                  next()
            else
              next()
          , callback
        else
          callback()

      _invoke_parent_initializers: (callback) =>
        proto = @.__proto__

        if proto.__proto__?
          parents = while proto.__proto__? && Object.keys(proto.__proto__).length > 0
            proto = proto.__proto__

          async.each parents, (parent, next) =>
            @_call_initializers_for parent.constructor.name, next
          , callback
        else
          callback()

      initialize: =>
        deferred = q.defer()
        proto    = @.__proto__
        name     = proto.constructor.name

        Madul.FIRE "$.#{name}.request_instance"

        if initialized[name] == undefined
          Madul.FIRE "$.#{name}.initialize"

          initialized[name] = false
          listeners[name]   = [ deferred.resolve ]

          @_wrap_methods()
          @_hydrate_deps => @_invoke_parent_initializers => @_finish_up proto
        else if initialized[name] == false
          listeners[name].push deferred.resolve
        else if initialized[name] == true
          process.nextTick => deferred.resolve available[strip name]

        deferred.promise

    module.exports = Madul


Ensure we don't add the same dependencies twice

    Module = require './module'
    Carver = require './carver'
    q      = require 'q'

    class Skyll extends Module
      deps: [ 'q' ]
      pub:  [ 'craft' ]

      render_pipeline: [ ]
      starting_row:    0

      grid: undefined

      cell:
        width:  0
        height: 0

      pathfinder: (neighbors) ->
        o = [ ]

        for n in [1..(neighbors.length / 1)]
          c = 1 / neighbors.length

          if neighbors[n - 1] == 'RIGHT'
            o.push "#{neighbors[n - 1]}": ((c * n) * ((2 / c) * 0.5)) * c
          else
            o.push "#{neighbors[n - 1]}": ((c * n) * (0.5 / c)) * c

        chance = Math.random()

        for option in o
          neighbor = Object.keys(option)[0]

          return neighbor if option[neighbor] > chance

      initialize: (params) =>
        deferred = q.defer()

        @grid = params.grid
        @cell = params.cell

        @ctor_params = { }

        @starting_row = params.starting_row

        for p in params.pipeline
          @ctor_params[p] =
            width:  params.cell.width  * params.grid[0].length
            height: params.cell.height * params.grid.length
            cell:   params.cell

          @deps.push p unless @deps.includes p

        super().then =>
          for p in params.pipeline
            render_pipeline.push @[p]

          deferred.resolve @

        deferred.promise

      craft: (level) =>
        new Carver()
          .initialize @grid, @starting_row, @pathfinder
          .then (mod)  => mod.carve_path()
          .then (path) => @q.all @render_pipeline.map (p) => p.render level, path
          .then        => @done()

    module.exports = Skyll

    Module = require './module'
    Carver = require './carver'
    q      = require 'q'

    class Skyll extends Module
      deps: [ 'q' ]
      pub:  [ 'craft' ]

      render_pipeline: [ ]
      starting_row:    0

      grid: undefined

      cell:
        width:  0
        height: 0

      pathfinder: (neighbors) ->
        o = [ ]

        for n in [1..(neighbors.length / 1)]
          c = 1 / neighbors.length

          if neighbors[n - 1] == 'RIGHT'
            o.push "#{neighbors[n - 1]}": ((c * n) * ((2 / c) * 0.5)) * c
          else
            o.push "#{neighbors[n - 1]}": ((c * n) * (0.5 / c)) * c

        chance = Math.random()

        for option in o
          neighbor = Object.keys(option)[0]

          return neighbor if option[neighbor] > chance

      initialize: (params) =>
        deferred = q.defer()

        @grid = params.grid
        @cell = params.cell

        @ctor_params = { }

        @starting_row = params.starting_row

        for p in params.pipeline
          @ctor_params[p] =
            width:  params.cell.width  * params.grid[0].length
            height: params.cell.height * params.grid.length
            cell:   params.cell

          @deps.push p

        super().then =>
          for p in params.pipeline
            render_pipeline.push @[p]

          deferred.resolve @

        deferred.promise

      craft: (level) =>
        new Carver()
          .initialize @grid, @starting_row, @pathfinder
          .then (mod)  => mod.carve_path()
          .then (path) => @q.all @render_pipeline.map (p) => p.render level, path
          .then        => @done()

    module.exports = Skyll


Elegance

Elegance

This is where shrub's package system meets Angular's module system. Packages'
implementations of controllers, services, filters, providers, and directives
are gathered and registered into Angular.

    angular.module('shrub.packages', [
      'shrub.require'
      'shrub.pkgman'
    ])

      .config([
        '$compileProvider', '$controllerProvider', '$filterProvider'
        '$injector', '$provide', 'shrub-pkgmanProvider'
        'shrub-requireProvider'
        (
          $compileProvider, $controllerProvider, $filterProvider
          $injector, $provide, pkgman, {require}
        ) ->

          config = require 'config'
          debug = require('debug') 'shrub:angular'

Set an injector so that Angular injection can occur out of band.

          angular_ = require 'angular'
          angular_.setInjector $injector

Invoke hook `controller`.
Allows packages to define Angular controllers. Implementations should return an
[annotated function](http://docs.angularjs.org/guide/di#dependency-annotation).

          debug 'Registering controllers...'

          for path, injected of pkgman.invoke 'controller'
            controllerName = pkgman.normalizePath path
            debug controllerName
            $controllerProvider.register controllerName, injected

          debug 'Controllers registered.'

          debug 'Registering directives...'

Normalize, augment, and register a directive.

          prepareDirective = (name, path, injected) -> ($injector) ->

Normalize the directive to object form.

            directive = $injector.invoke injected
            directive = link: directive if angular.isFunction directive

Ensure a compilation function exists for the directive which by default
returns the `link` function.

            directive.compile ?= -> directive.link

Proxy any defined link function, firing any attached any controllers' `link`
method, as well as passing execution on to the original `link` function.

            link = directive.link
            directive.link = (scope, element, attrs, controllers) ->
              if controllers?
                controllers = [controllers] unless angular.isArray controllers
                controller.link? arguments... for controller in controllers

              link? arguments...

Ensure the directive has a name. Defaults to the normalized path of the
implementing package.

            directive.name ?= name

If controller binding is specified, the controller defaults to the directive
name. In other words, if you define a directive and a controller in the same
package, and specify `directive.bindToController = true`, your directive will
include the controller automatically.

            if directive.bindToController
              directive.controller ?= directive.name

Handle a bunch of internal Angular normalization.

            directive.require ?= directive.controller and directive.name
            directive.priority ?= 0
            directive.restrict ?= 'EA'

            if angular.isObject directive.scope
              directive.$$isolateBindings = isolateBindingsFor directive

Invoke hook `augmentDirective`.
Allows packages to augment the directives defined by packages. One example is
the automatic relinking functionality implemented by
[shrub-skin](../packages/shrub-skin/client/index.coffee#L12).

            for injectedDirective in pkgman.invokeFlat(
              'augmentDirective', directive, path
            )
              $injector.invoke injectedDirective

Haven't gone deep enough into Angular to understand why this has to be, but it
does.

            directive.index = 0
            return [directive]

Internal Angular state that we have to reset.

          isolateBindingsFor = (directive) ->

            LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/

            bindings = {}

            for scopeName, definition of directive.scope
              match = definition.match LOCAL_REGEXP

              throw angular.$$minErr('$compile')(
                'iscp'
                "
                  Invalid isolate scope definition for directive '{0}'.
                  Definition: {... {1}: '{2}' ...}
                "
                directive.name, scopeName, definition
              ) unless match

              bindings[scopeName] =
                mode: match[1][0]
                collection: match[2] is '*'
                optional: match[3] is '?'
                attrName: match[4] or scopeName

            return bindings

Invoke hook `directive`.
Allows packages to define Angular directives. Implementations should return an
[annotated function](http://docs.angularjs.org/guide/di#dependency-annotation).

          for path, injected of pkgman.invoke 'directive'
            do (path, injected) ->
              directiveName = pkgman.normalizePath path
              debug directiveName

First, register it through Angular's normal registration mechanism. This sets
a bunch of internal state we don't have access to.

              $compileProvider.directive directiveName, injected

Follow that by normalizing, augmenting, and registering the directive again.
It will run over the previous definition, ensuring everything works nicely.

              $provide.factory "#{directiveName}Directive", [
                '$injector', prepareDirective directiveName, path, injected
              ]

          debug 'Directives registered.'

          debug 'Registering filters...'

Invoke hook `filter`.
Allows packages to define Angular filters. Implementations should return a
function.

          for path, injected of pkgman.invoke 'filter'
            filterName = pkgman.normalizePath path
            debug filterName
            $filterProvider.register filterName, injected

          debug 'Filters registered.'

Invoke hook `provider`.
Allows packages to define Angular providers. Implementations should return an
[annotated function](http://docs.angularjs.org/guide/di#dependency-annotation).

          debug 'Registering providers...'

          for path, provider of pkgman.invoke 'provider'
            debug path
            $provide.provider path, provider

          debug 'Providers registered.'

Invoke hook `service`.
Allows packages to define Angular services. Implementations should return an
[annotated function](http://docs.angularjs.org/guide/di#dependency-annotation).

          debug 'Registering services...'

          for path, injected of pkgman.invoke 'service'
            debug path
            $provide.service path, injected

          debug 'Services registered.'

      ])

The module that provides Angular with access to Shrub's package manager.

    angular.module('shrub.pkgman', [
      'shrub.require'
    ])

      .provider 'shrub-pkgman', [
        '$provide', 'shrub-requireProvider'
        ($provide, {require}) ->

          config = require 'config'
          debug = require('debug') 'shrub:pkgman'
          pkgman = require 'pkgman'

          debug 'Loading packages...'

Load the package list from configuration.

          pkgman.registerPackageList config.get 'packageList'

          debug 'Packages loaded.'

Simply pass along pkgman as the 'service'.

          pkgman.$get = -> pkgman

          return pkgman
      ]

This is where shrub's package system meets Angular's module system. Packages'
implementations of controllers, services, filters, providers, and directives
are gathered and registered into Angular.

    angular.module('shrub.packages', [
      'shrub.require'
      'shrub.pkgman'
    ])

      .config([
        '$compileProvider', '$controllerProvider', '$filterProvider'
        '$injector', '$provide', 'shrub-pkgmanProvider'
        'shrub-requireProvider'
        (
          $compileProvider, $controllerProvider, $filterProvider
          $injector, $provide, pkgman, {require}
        ) ->

          config = require 'config'
          debug = require('debug') 'shrub:angular'

Set an injector so that Angular injection can occur out of band.

          angular_ = require 'angular'
          angular_.setInjector $injector

Invoke hook `controller`.
Allows packages to define Angular controllers. Implementations should return an
[annotated function](http://docs.angularjs.org/guide/di#dependency-annotation).

          debug 'Registering controllers...'

          for path, injected of pkgman.invoke 'controller'
            controllerName = pkgman.normalizePath path
            debug controllerName
            $controllerProvider.register controllerName, injected

          debug 'Controllers registered.'

          debug 'Registering directives...'

Normalize, augment, and register a directive.

          prepareDirective = (name, path, injected) -> ($injector) ->
            directive = $injector.invoke injected

Ensure a compilation function exists for the directive, and ensure that by
default it returns the `link` function.

            if angular.isFunction directive
              directive = link: directive
              directive.compile = -> directive.link
            else if not directive.compile
              directive.compile = -> directive.link

Proxy any defined link function, firing any attached any controllers' `link`
method, as well as passing execution on to the original `link` function.

            link = directive.link
            directive.link = (scope, element, attrs, controllers) ->
              if controllers?
                controllers = [controllers] unless angular.isArray controllers
                controller.link? arguments... for controller in controllers

              link? arguments...

Ensure the directive has a name. Defaults to the normalized path of the
implementing package.

            directive.name ?= name

If controller binding is specified, the controller defaults to the directive
name. In other words, if you define a directive and a controller in the same
package, and specify `directive.bindToController = true`, your directive will
include the controller automatically.

            if directive.bindToController
              directive.controller ?= directive.name

Handle a bunch of internal Angular normalization.

            directive.require ?= directive.controller and directive.name
            directive.priority ?= 0
            directive.restrict ?= 'EA'

            if angular.isObject directive.scope
              directive.$$isolateBindings = isolateBindingsFor directive

Invoke hook `augmentDirective`.
Allows packages to augment the directives defined by packages. One example is
the automatic relinking functionality implemented by
[shrub-skin](../packages/shrub-skin/client/index.coffee#L12).

            for injectedDirective in pkgman.invokeFlat(
              'augmentDirective', directive, path
            )
              $injector.invoke injectedDirective

Haven't gone deep enough into Angular to understand why this has to be, but it
does.

            directive.index = 0
            return [directive]

Internal Angular state that we have to reset.

          isolateBindingsFor = (directive) ->

            LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/

            bindings = {}

            for scopeName, definition of directive.scope
              match = definition.match LOCAL_REGEXP

              throw angular.$$minErr('$compile')(
                'iscp'
                "
                  Invalid isolate scope definition for directive '{0}'.
                  Definition: {... {1}: '{2}' ...}
                "
                directive.name, scopeName, definition
              ) unless match

              bindings[scopeName] =
                mode: match[1][0]
                collection: match[2] is '*'
                optional: match[3] is '?'
                attrName: match[4] or scopeName

            return bindings

Invoke hook `directive`.
Allows packages to define Angular directives. Implementations should return an
[annotated function](http://docs.angularjs.org/guide/di#dependency-annotation).

          for path, injected of pkgman.invoke 'directive'
            do (path, injected) ->
              directiveName = pkgman.normalizePath path
              debug directiveName

First, register it through Angular's normal registration mechanism. This sets
a bunch of internal state we don't have access to.

              $compileProvider.directive directiveName, injected

Follow that by normalizing, augmenting, and registering the directive again.
It will run over the previous definition, ensuring everything works nicely.

              $provide.factory "#{directiveName}Directive", [
                '$injector', prepareDirective directiveName, path, injected
              ]

          debug 'Directives registered.'

          debug 'Registering filters...'

Invoke hook `filter`.
Allows packages to define Angular filters. Implementations should return a
function.

          for path, injected of pkgman.invoke 'filter'
            filterName = pkgman.normalizePath path
            debug filterName
            $filterProvider.register filterName, injected

          debug 'Filters registered.'

Invoke hook `provider`.
Allows packages to define Angular providers. Implementations should return an
[annotated function](http://docs.angularjs.org/guide/di#dependency-annotation).

          debug 'Registering providers...'

          for path, provider of pkgman.invoke 'provider'
            debug path
            $provide.provider path, provider

          debug 'Providers registered.'

Invoke hook `service`.
Allows packages to define Angular services. Implementations should return an
[annotated function](http://docs.angularjs.org/guide/di#dependency-annotation).

          debug 'Registering services...'

          for path, injected of pkgman.invoke 'service'
            debug path
            $provide.service path, injected

          debug 'Services registered.'

      ])

The module that provides Angular with access to Shrub's package manager.

    angular.module('shrub.pkgman', [
      'shrub.require'
    ])

      .provider 'shrub-pkgman', [
        '$provide', 'shrub-requireProvider'
        ($provide, {require}) ->

          config = require 'config'
          debug = require('debug') 'shrub:pkgman'
          pkgman = require 'pkgman'

          debug 'Loading packages...'

Load the package list from configuration.

          pkgman.registerPackageList config.get 'packageList'

          debug 'Packages loaded.'

Simply pass along pkgman as the 'service'.

          pkgman.$get = -> pkgman

          return pkgman
      ]


add docs for View#source

add docs for View#source

# Batman.View

For a general explanation of `Batman.View` and how it works, see [the guide](/docs/views.html).

## ::constructor(options = {})

A `View` is a `Batman.Object`, so any options you pass are mixed in. Use this
to set `html`, `node`, `superview`, `parentNode` and/or your custom data.

    test 'constructor mixes in options', ->
      view = new Batman.View(animal: 'cat')
      equal 'cat', view.get('animal')

    test 'constructor automatically adds to the superview if supplied', ->
      superview = new Batman.View()
      view = new Batman.View(superview: superview)
      equal 1, superview.subviews.length

## ::lookupKeypath(keypath) : Object

Traverses up the view tree searching for the specified keypath, and returns the
result. This is equivalent to performing a `Batman.get` for each view above
`this` in the tree, until a defined result is returned. The path it takes is as
follows:

current view → chain of superviews → layout view → active controller → app →
window

If there is no match, `undefined` is returned. However, if used in an accessor
or binding, the entire path to the root will be registered as a potential
source of data. Consequently, if the keypath is later set on any part of the
chain, the data will be correctly bound.

`lookupKeypath` is the function invoked to locate data when evaluating a
binding.

    test 'lookupKeypath returns the value if defined on the view', ->
      view = new Batman.View(animal: 'cat')
      equal 'cat', view.lookupKeypath('animal')

    test 'lookupKeypath returns the value if defined on an ancestor', ->
      superview = new Batman.View(animal: 'cat')
      subview = new Batman.View(superview: superview)
      equal 'cat', subview.lookupKeypath('animal')

## ::setKeypath(keypath, value) : Object

Traverses the View tree searching for the specified keypath, and sets the value
on the nearest ancestor which defines it. If no ancestor view defines the given
keypath, it will be set on the nearest ancestor which is not a
backing view.

`setKeypath` is the function invoked to set data when using an input binding.

    test 'setKeypath sets the value if defined on the view', ->
      view = new Batman.View(animal: 'dog')

      view.setKeypath('animal', 'cat')
      equal 'cat', view.get('animal')

    test 'setKeypath sets the value if defined on an ancestor', ->
      superview = new Batman.View(animal: 'dog')
      subview = new Batman.View(superview: superview)

      subview.setKeypath('animal', 'cat')
      equal 'cat', superview.get('animal')

    test 'setKeypath sets the value on the nearest non-backing view when not defined anywhere', ->
      superview = new Batman.View()
      view = new Batman.View(superview: superview)
      backingView = new Batman.BackingView(superview: view)

      backingView.setKeypath('animal', 'cat')
      equal 'cat', view.get('animal')

## ::%node : Node

A reference to the DOM node that this view encapsulates. The entire tree
beneath this node is also the responsibility of this view and/or its subviews.

Accessing `node` will load and parse the template on demand if it isn't already
loaded.

    test 'node parses the template', ->
      view = new Batman.View(html: '
cat
')

      node = view.get('node')
      equal 'cat', node.firstChild.innerHTML

You can also access a view's `node` in its methods, for example, activating jQuery plugins:

```
class App.SearchBarView extends Batman.View
  viewDidAppear: ->
    $node = $(@get('node'))
    $node.typeahead() # <= whatever jQuery plugin you want!
```
## ::%source : String

This string will be used to fetch a view's HTML, relative to [`Batman.config.pathToHTML`](/docs/configuration.html).
You don't need to add `.html` to this string -- it will be added automatically.

Inside a controller action, batman.js provides a default source based on the
contoller's [`routingKey`](/docs/api/batman.controller.html#routingkey_and_minification) and the [controller action](/docs/api/batman.controller.html#actions).

You can set `source` in the class definition:

```
class App.HeaderNavigationView extends Batman.View
  source: 'layout/_header'
```

Or when calling `@render()` inside a controller action:

```
class App.PostsController extends Batman.Controller
  show: ->
    @set('post', new App.Post)
    if @get('post.isAlternative')
      @render(source: "posts/alternative_new")
    else
      @render() # defaults to 'posts/new'
```

## ::%html : String

The HTML source for the view's template. Setting this will parse the template
and build bindings automatically, but it will not be inserted into the DOM
until the view is added to a superview. You can specify a view's HTML when you define the class:

```
class App.SearchBarView extends Batman.View
  html: "<input type='text' placeholder='Enter a search term' />"
```

If you don't explicitly set `html` but you do set `source`, then getting `html`
will automatically fetch the template source from the local template store.

    test 'setting a source loads the correct template', ->
      Batman.View.store.set('/animals', '
cat
')
      view = new Batman.View(source: '/animals')

      node = view.get('node')
      equal 'cat', node.firstChild.innerHTML

## ::.superview : Batman.View

A reference to the current superview (the direct ancestor in the tree). This is
used for traversing the tree when searching for data, as in
`View::lookupKeypath`.

## ::.subviews : Batman.Set

The set of direct children of a `View`. To manipulate the view tree, you should
operate directly on this set — batman.js will automatically keep the DOM in
sync with the logical tree.

## ::subviews.add(view)

Adding to a view's subview set will automatically update the tree, and parse
the template and bindings. If the superview is already in the DOM, this will
insert the current view's node into the DOM.

    test 'adding to a superview parses bindings', ->
      superview = new Batman.View()
      view = new Batman.View(html: '

', animal: 'cat')

      superview.subviews.add(view)
      equal 'cat', view.get('node').firstChild.innerHTML

## ::subviews.remove(view)

Removing from a view's subview set will automatically remove the subview from
the DOM.

    test 'removing from the current superview removes the node from the DOM', ->
      superview = new Batman.View(html: '', parentNode: document.body)
      superview.get('node')
      view = new Batman.View(html: '', superview: superview)

      ok Batman.DOM.containsNode(superview.get('node'), view.get('node'))

      superview.subviews.remove(view)
      ok not Batman.DOM.containsNode(superview.get('node'), view.get('node'))

## ::removeFromSuperview()

Removes this view from its parent, without killing it.

    test 'removing from the current superview removes the node from the DOM', ->
      superview = new Batman.View()
      view = new Batman.View(superview: superview)

      view.removeFromSuperview()
      ok not superview.subviews.has(view)

## ::die()

Kills this view, which renders it to forever unusable. This has the
following implications:

- The view is removed from its superview
- The view's node is removed from the DOM
- The view's bindings are destroyed
- The view's current subviews are killed

    test 'die kills the view', ->
      superview = new Batman.View()
      view = new Batman.View(superview: superview)

      view.die()
      equal true, view.isDead
      equal 0, superview.subviews.length

## ::.isDead : boolean

True if the view has been killed, false otherwise.

## ::destroySubviews()

Kills every subview of this view.

    test 'destroySubviews kills all subviews', ->
      superview = new Batman.View()
      one = new Batman.View(superview: superview)
      two = new Batman.View(superview: superview)

      superview.destroySubviews()
      ok one.isDead
      ok two.isDead

## ::propagateToSubviews(eventOrKey : string, value : Object)

If `value` is defined, set `eventOrKey` to `value` on the entire subtree.
Otherwise, fire `eventOrKey` on the entire subtree.

    test 'propagateToSubviews propagates events', ->
      superview = new Batman.View()
      one = new Batman.View(superview: superview)
      two = new Batman.View(superview: one)

      superview.on 'eventName', superSpy = createSpy()
      one.on 'eventName', oneSpy = createSpy()
      two.on 'eventName', twoSpy = createSpy()

      superview.propagateToSubviews('eventName')

      equal 1, superSpy.callCount
      equal 1, oneSpy.callCount
      equal 1, twoSpy.callCount

    test 'propagateToSubviews propagates keys', ->
      superview = new Batman.View()
      one = new Batman.View(superview: superview)
      two = new Batman.View(superview: one)

      superview.propagateToSubviews('key', 'value')

      equal superview.get('key'), 'value'
      equal one.get('key'), 'value'
      equal two.get('key'), 'value'

## @viewForNode(node, climbTree = true) : Batman.View

Finds the view acting as the current context for a node — i.e. perform the
reverse mapping of the view tree to the DOM. If you pass `false` for
`climbTree`, it won't traverse up the DOM, and will return `undefined` unless
the node is the view's root.

## ::filter(label : string, filter : function)

Defines a filter on the `View` class for use within the `View` during rendering.

# Batman.View

For a general explanation of `Batman.View` and how it works, see [the guide](/docs/views.html).

## ::constructor(options = {})

A `View` is a `Batman.Object`, so any options you pass are mixed in. Use this
to set `html`, `node`, `superview`, `parentNode` and/or your custom data.

    test 'constructor mixes in options', ->
      view = new Batman.View(animal: 'cat')
      equal 'cat', view.get('animal')

    test 'constructor automatically adds to the superview if supplied', ->
      superview = new Batman.View()
      view = new Batman.View(superview: superview)
      equal 1, superview.subviews.length

## ::lookupKeypath(keypath) : Object

Traverses up the view tree searching for the specified keypath, and returns the
result. This is equivalent to performing a `Batman.get` for each view above
`this` in the tree, until a defined result is returned. The path it takes is as
follows:

current view → chain of superviews → layout view → active controller → app →
window

If there is no match, `undefined` is returned. However, if used in an accessor
or binding, the entire path to the root will be registered as a potential
source of data. Consequently, if the keypath is later set on any part of the
chain, the data will be correctly bound.

`lookupKeypath` is the function invoked to locate data when evaluating a
binding.

    test 'lookupKeypath returns the value if defined on the view', ->
      view = new Batman.View(animal: 'cat')
      equal 'cat', view.lookupKeypath('animal')

    test 'lookupKeypath returns the value if defined on an ancestor', ->
      superview = new Batman.View(animal: 'cat')
      subview = new Batman.View(superview: superview)
      equal 'cat', subview.lookupKeypath('animal')

## ::setKeypath(keypath, value) : Object

Traverses the View tree searching for the specified keypath, and sets the value
on the nearest ancestor which defines it. If no ancestor view defines the given
keypath, it will be set on the nearest ancestor which is not a
backing view.

`setKeypath` is the function invoked to set data when using an input binding.

    test 'setKeypath sets the value if defined on the view', ->
      view = new Batman.View(animal: 'dog')

      view.setKeypath('animal', 'cat')
      equal 'cat', view.get('animal')

    test 'setKeypath sets the value if defined on an ancestor', ->
      superview = new Batman.View(animal: 'dog')
      subview = new Batman.View(superview: superview)

      subview.setKeypath('animal', 'cat')
      equal 'cat', superview.get('animal')

    test 'setKeypath sets the value on the nearest non-backing view when not defined anywhere', ->
      superview = new Batman.View()
      view = new Batman.View(superview: superview)
      backingView = new Batman.BackingView(superview: view)

      backingView.setKeypath('animal', 'cat')
      equal 'cat', view.get('animal')

## ::%node : Node

A reference to the DOM node that this view encapsulates. The entire tree
beneath this node is also the responsibility of this view and/or its subviews.

Accessing `node` will load and parse the template on demand if it isn't already
loaded.

    test 'node parses the template', ->
      view = new Batman.View(html: '
cat
')

      node = view.get('node')
      equal 'cat', node.firstChild.innerHTML

You can also access a view's `node` in its methods, for example, activating jQuery plugins:

```
class App.SearchBarView extends Batman.View
  viewDidAppear: ->
    $node = $(@get('node'))
    $node.typeahead() # <= whatever jQuery plugin you want!
```

## ::%html : String

The HTML source for the view's template. Setting this will parse the template
and build bindings automatically, but it will not be inserted into the DOM
until the view is added to a superview. You can specify a view's HTML when you define the class:

```
class App.SearchBarView extends Batman.View
  html: "<input type='text' placeholder='Enter a search term' />"
```

If you don't explicitly set `html` but you do set `source`, then getting `html`
will automatically fetch the template source from the local template store.

    test 'setting a source loads the correct template', ->
      Batman.View.store.set('/animals', '
cat
')
      view = new Batman.View(source: '/animals')

      node = view.get('node')
      equal 'cat', node.firstChild.innerHTML

## ::.superview : Batman.View

A reference to the current superview (the direct ancestor in the tree). This is
used for traversing the tree when searching for data, as in
`View::lookupKeypath`.

## ::.subviews : Batman.Set

The set of direct children of a `View`. To manipulate the view tree, you should
operate directly on this set — batman.js will automatically keep the DOM in
sync with the logical tree.

## ::subviews.add(view)

Adding to a view's subview set will automatically update the tree, and parse
the template and bindings. If the superview is already in the DOM, this will
insert the current view's node into the DOM.

    test 'adding to a superview parses bindings', ->
      superview = new Batman.View()
      view = new Batman.View(html: '

', animal: 'cat')

      superview.subviews.add(view)
      equal 'cat', view.get('node').firstChild.innerHTML

## ::subviews.remove(view)

Removing from a view's subview set will automatically remove the subview from
the DOM.

    test 'removing from the current superview removes the node from the DOM', ->
      superview = new Batman.View(html: '', parentNode: document.body)
      superview.get('node')
      view = new Batman.View(html: '', superview: superview)

      ok Batman.DOM.containsNode(superview.get('node'), view.get('node'))

      superview.subviews.remove(view)
      ok not Batman.DOM.containsNode(superview.get('node'), view.get('node'))

## ::removeFromSuperview()

Removes this view from its parent, without killing it.

    test 'removing from the current superview removes the node from the DOM', ->
      superview = new Batman.View()
      view = new Batman.View(superview: superview)

      view.removeFromSuperview()
      ok not superview.subviews.has(view)

## ::die()

Kills this view, which renders it to forever unusable. This has the
following implications:

- The view is removed from its superview
- The view's node is removed from the DOM
- The view's bindings are destroyed
- The view's current subviews are killed

    test 'die kills the view', ->
      superview = new Batman.View()
      view = new Batman.View(superview: superview)

      view.die()
      equal true, view.isDead
      equal 0, superview.subviews.length

## ::.isDead : boolean

True if the view has been killed, false otherwise.

## ::destroySubviews()

Kills every subview of this view.

    test 'destroySubviews kills all subviews', ->
      superview = new Batman.View()
      one = new Batman.View(superview: superview)
      two = new Batman.View(superview: superview)

      superview.destroySubviews()
      ok one.isDead
      ok two.isDead

## ::propagateToSubviews(eventOrKey : string, value : Object)

If `value` is defined, set `eventOrKey` to `value` on the entire subtree.
Otherwise, fire `eventOrKey` on the entire subtree.

    test 'propagateToSubviews propagates events', ->
      superview = new Batman.View()
      one = new Batman.View(superview: superview)
      two = new Batman.View(superview: one)

      superview.on 'eventName', superSpy = createSpy()
      one.on 'eventName', oneSpy = createSpy()
      two.on 'eventName', twoSpy = createSpy()

      superview.propagateToSubviews('eventName')

      equal 1, superSpy.callCount
      equal 1, oneSpy.callCount
      equal 1, twoSpy.callCount

    test 'propagateToSubviews propagates keys', ->
      superview = new Batman.View()
      one = new Batman.View(superview: superview)
      two = new Batman.View(superview: one)

      superview.propagateToSubviews('key', 'value')

      equal superview.get('key'), 'value'
      equal one.get('key'), 'value'
      equal two.get('key'), 'value'

## @viewForNode(node, climbTree = true) : Batman.View

Finds the view acting as the current context for a node — i.e. perform the
reverse mapping of the view tree to the DOM. If you pass `false` for
`climbTree`, it won't traverse up the DOM, and will return `undefined` unless
the node is the view's root.

## ::filter(label : string, filter : function)

Defines a filter on the `View` class for use within the `View` during rendering.


Correctly handle function attributes and Date objects during client-side model instantiation

# Object-relational mapping

*This is mostly stubbed for the browser. I can't justify sending a 400k ORM
library to the client, even though it would be awesome.*

    Promise = require 'bluebird'

    pkgman = require 'pkgman'

    collections = {}

    exports.pkgmanRegister = (registrar) ->

#### Implements hook `shrubAngularService`.

      registrar.registerHook 'shrubAngularService', -> [
        '$http'
        ($http) ->

          service = {}

          exports.initialize()

## orm.collection

* (String) `identity` - Collection identity. e.g. `'shrub-user'`

*Get a collection by identity.*

          service.collection = (identity) -> collections[identity]

## orm.collections

*Get all collections.*

          service.collections = -> collections

          service

      ]

    exports.initialize = ->

#### Invoke hook `shrubOrmCollections`.

      collections_ = {}
      for collectionList in pkgman.invokeFlat 'shrubOrmCollections'
        for identity, collection of collectionList

Collection defaults.

          collection.identity ?= identity
          collections_[collection.identity] = collection

Instantiate a model with defaults supplied.

          collection.instantiate = (values = {}) ->
            model = JSON.parse JSON.stringify values

            for key, value of @attributes

Set functions.

              model[key] = value if 'function' is typeof value

Set any model defaults.

              if value.defaultsTo?

                model[key] ?= if 'function' is typeof value.defaultsTo
                  value.defaultsTo.call model
                else
                  JSON.parse JSON.stringify value.defaultsTo

Handle dates.

              if model[key]? and 'date' is value or 'date' is value.type
                model[key] = new Date model[key]

            model

#### Invoke hook `shrubOrmCollectionsAlter`.

      pkgman.invoke 'shrubOrmCollectionsAlter', collections_

      collections = collections_

# Object-relational mapping

*This is mostly stubbed for the browser. I can't justify sending a 400k ORM
library to the client, even though it would be awesome.*

    Promise = require 'bluebird'

    pkgman = require 'pkgman'

    collections = {}

    exports.pkgmanRegister = (registrar) ->

#### Implements hook `shrubAngularService`.

      registrar.registerHook 'shrubAngularService', -> [
        '$http'
        ($http) ->

          service = {}

          exports.initialize()

## orm.collection

* (String) `identity` - Collection identity. e.g. `'shrub-user'`

*Get a collection by identity.*

          service.collection = (identity) -> collections[identity]

## orm.collections

*Get all collections.*

          service.collections = -> collections

          service

      ]

    exports.initialize = ->

#### Invoke hook `shrubOrmCollections`.

      collections_ = {}
      for collectionList in pkgman.invokeFlat 'shrubOrmCollections'
        for identity, collection of collectionList

Collection defaults.

          collection.identity ?= identity
          collections_[collection.identity] = collection

Instantiate a model with defaults supplied.

          collection.instantiate = (values = {}) ->
            model = JSON.parse JSON.stringify values

            for key, value of @attributes
              continue unless value.defaultsTo?

Set any model defaults.

              model[key] ?= if 'function' is typeof value.defaultsTo
                value.defaultsTo.call model
              else
                JSON.parse JSON.stringify value.defaultsTo

            model

#### Invoke hook `shrubOrmCollectionsAlter`.

      pkgman.invoke 'shrubOrmCollectionsAlter', collections_

      collections = collections_


Allow restarting by sending a special message.

nodePush Pushserver
===================

Copyright Information
---------------------

	"@author	Tim Düsterhus"
	"@copyright	2012-2013 Tim Düsterhus"
	"@license	BSD 3-Clause License <http://opensource.org/licenses/BSD-3-Clause>"
	"@package	be.bastelstu.wcf.nodePush"

Setup
-----

First we import the required packages and make them available in a global variable.

	express = require 'express'
	http = require 'http'
	io = require 'socket.io'
	net = require 'net'
	fs = require 'fs'

Next we try to load the configuration file "config.js".

	try
		config = require '../config.js'
	catch e
		config = { }

In case not every configuration property is set we initialize it with a default property.

	config.outbound ?= { }
	config.outbound.useTCP ?= true
	config.outbound.port ?= 9001
	config.outbound.host ?= '0.0.0.0'
	config.outbound.socket ?= __dirname + "/../outbound.sock"
	config.inbound ?= { }
	config.inbound.useTCP ?= false
	config.inbound.port ?= 9002
	config.inbound.host ?= '127.0.0.1'
	config.inbound.socket ?= __dirname + "/../inbound.sock"
	config.user ?= 'nobody'
	config.group ?= 'nogroup'

We continue with creating some helper functions.

	log = (message) ->
		console.log "[be.bastelstu.wcf.nodePush] #{message}"

	thousandsSeparator = (number) ->
		String(number).replace /(^-?\d{1,3}|\d{3})(?=(?:\d{3})+(?:$|\.))/g, '$1,'

	fs.open "#{__dirname}/../tmp/nodePush.child.pid", "w", 0o600, (err, fd) ->
		fs.writeSync fd, process.pid

	# Ensure our namespace is present
	be = be ? {}
	be.bastelstu ?= {}
	be.bastelstu.wcf ?= {}

be.bastelstu.wcf.nodePush
=========================

	class be.bastelstu.wcf.nodePush

Attributes
----------

`app` will become an instance of `express`.

		app: null

`server` willbecome an instance of `http`.

		server: null

`io` will become an instance of `socket.io`.

		io: null

`stats` is an object with the different statistics recorded. Statistics will be shown on the status page.

		stats:
			status: 0
			outbound:
				total: 0
				current: 0
			inbound: 0
			messages: { }
			bootTime: new Date()

Methods
-------
**constructor()**
The constructor is executed when the class is initialized. It prints some helpful information,
such as the PID and the used sockets and continues with initializing everything.

		constructor: ->
			log "nodePush running (pid:#{process.pid})"

First we display the used inbound and outbound sockets.

			if config.inbound.useTCP
				log "Inbound: #{config.inbound.host}:#{config.inbound.port}"
			else
				log "Inbound: #{config.inbound.socket}"
			if config.outbound.useTCP
				log "Outbound: #{config.outbound.host}:#{config.outbound.port}"
			else
				log "Outbound: #{config.outbound.socket}"

			@stats.bootTime = new Date()

Afterwards we initialize the inbound and outbound connection.

			@initInbound()
			@initOutbound()

In order to do a proper cleanup on shutdown we bind the `shutdown` method to the needed events and signals.

			process.on 'exit', =>
				@shutdown()
			process.on 'uncaughtException', (message) =>
				@shutdown message, 1
			process.on 'SIGINT', =>
				@shutdown()
			process.on 'SIGTERM', =>
				@shutdown()
			process.on 'SIGHUP', =>
				@shutdown null, 2

At the end we set a nice title for `ps`.

			process.title = 'nodePush'

**initOutbound()**
`initOutbound` initializes the connection to the browser. That includes starting the HTTP server and preparing
socket.io.

		initOutbound: ->
			log 'Initializing outbound socket'

First we start the express based HTTP server.

			@app = express()
			@server = http.createServer @app
			@io = io.listen @server

Afterwards we set socket.io configuration for the default environment. Files will be minified and logging reduced to a minimum.

			@io.set 'log level', 1
			@io.set 'browser client etag', true
			@io.set 'browser client minification', true
			@io.set 'browser client gzip', true

In case `env` is set to development we show some more debug output.

			@io.configure 'development', =>
				@io.set 'log level', 3
				@io.set 'browser client etag', false
				@io.set 'browser client minification', false

Next we listen on the socket.io `connection` event to record statistics.

			@io.sockets.on 'connection', (socket) =>
				@stats.outbound.total++ if @app.get('env') is 'development'
				@stats.outbound.current++

				socket.on 'disconnect', =>
					@stats.outbound.current--

We continue with creating a callback for the `listen` call.

			listenCallback = =>

In case we are running as root we try to shed root privilegies. If this is not possible we exit, as a service
running as root is dangerous.

				if process.getuid? and (process.getuid() is 0 or process.getgid() is 0)
					try
						log 'Trying to shed root privilegies'
						process.setgid config.group
						process.setuid config.user
						log "New User ID: #{process.getuid()}, New Group ID: #{process.getgid()}"
					catch e
						log 'Cowardly refusing to keep the process alive as root.'
						process.exit 1

After the the HTTP server is listening and we are no longer running as root we start some intervals for the builtin tick events.

				setInterval =>
					@sendMessage 'be.bastelstu.wcf.nodePush.tick15'
				, 15e3
				setInterval =>
					@sendMessage 'be.bastelstu.wcf.nodePush.tick30'
				, 30e3
				setInterval =>
					@sendMessage 'be.bastelstu.wcf.nodePush.tick60'
				, 60e3
				setInterval =>
					@sendMessage 'be.bastelstu.wcf.nodePush.tick90'
				, 90e3
				setInterval =>
					@sendMessage 'be.bastelstu.wcf.nodePush.tick120'
				, 120e3

				log "Done"

Start listening on the configured outbound socket.

			if config.outbound.useTCP
				@server.listen config.outbound.port, config.outbound.host, null, listenCallback
			else
				@server.listen config.outbound.socket, listenCallback
				fs.chmod config.outbound.socket, '777'

Show the status page when '/' is requested.

			@app.get '/', (req, res) =>
				res.charset = 'utf-8';
				res.type 'txt'

Show detailed information when environment is `development`.

				if @app.get('env') is 'development'
					@stats.status++
					reply = """
					Up since: #{@stats.bootTime}
					Status page: #{thousandsSeparator @stats.status} Requests
					Outbound: #{thousandsSeparator @stats.outbound.current} now - #{thousandsSeparator @stats.outbound.total} Total
					Inbound: #{thousandsSeparator @stats.inbound}
					Messages:
					"""
					for message, amount of @stats.messages
						reply += "\n	#{message}: #{thousandsSeparator amount}"
				else
					reply = """
					Up since: #{@stats.bootTime}
					Outbound: #{thousandsSeparator @stats.outbound.current} now
					"""

				res.send reply

**sendMessage(name)**
Sends a message with the given name.

		sendMessage: (name) ->
			return unless /^[a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+(\.[a-zA-Z0-9-_]+)+$/.test name

			if name is 'be.bastelstu.wcf.nodePush._restart'
				process.kill process.pid, 'SIGHUP'

			if @app.get('env') is 'development'
				@stats.messages[name] ?= 0
				@stats.messages[name]++

			@io.sockets.send name

**initInbound()**
`initInbound` initializes the PHP side socket.

		initInbound: ->
			log 'Initializing inbound socket'

We start by creating a server.

			socket = net.createServer (c) =>
				@stats.inbound++ if @app.get('env') is 'development'

In case data is written to the server we pass it to the connected browsers and close the connection afterwards.

				c.on 'data', (data) =>
					setTimeout =>
						@sendMessage data.toString().trim()
					, 20
					c.end()

				c.on 'end', ->
					c.end()

In case nothing happens within 5 seconds we close the connection in order to save resources.

				c.setTimeout 5e3, ->
					c.end()

After all callbacks are bound we start listening.

			if config.inbound.useTCP
				socket.listen config.inbound.port, config.inbound.host
			else
				socket.listen config.inbound.socket
				fs.chmod config.inbound.socket, '777'

**shutdown()**
`shutdown` performs a clean shutdown of nodePush. It cleans up the unix socket files.

		shutdown: (message = null, code = 0) ->
			if message?
				log "Shutting down: #{message}"
			else
				log 'Shutting down'

			fs.unlinkSync config.inbound.socket if not config.inbound.useTCP and fs.existsSync config.inbound.socket
			fs.unlinkSync config.outbound.socket if not config.outbound.useTCP and fs.existsSync config.outbound.socket

			process.removeAllListeners()
			process.exit code

In the end we finally initialize the class with starts all the services.

	new be.bastelstu.wcf.nodePush()

nodePush Pushserver
===================

Copyright Information
---------------------

	"@author	Tim Düsterhus"
	"@copyright	2012-2013 Tim Düsterhus"
	"@license	BSD 3-Clause License <http://opensource.org/licenses/BSD-3-Clause>"
	"@package	be.bastelstu.wcf.nodePush"

Setup
-----

First we import the required packages and make them available in a global variable.

	express = require 'express'
	http = require 'http'
	io = require 'socket.io'
	net = require 'net'
	fs = require 'fs'

Next we try to load the configuration file "config.js".

	try
		config = require '../config.js'
	catch e
		config = { }

In case not every configuration property is set we initialize it with a default property.

	config.outbound ?= { }
	config.outbound.useTCP ?= true
	config.outbound.port ?= 9001
	config.outbound.host ?= '0.0.0.0'
	config.outbound.socket ?= __dirname + "/../outbound.sock"
	config.inbound ?= { }
	config.inbound.useTCP ?= false
	config.inbound.port ?= 9002
	config.inbound.host ?= '127.0.0.1'
	config.inbound.socket ?= __dirname + "/../inbound.sock"
	config.user ?= 'nobody'
	config.group ?= 'nogroup'

We continue with creating some helper functions.

	log = (message) ->
		console.log "[be.bastelstu.wcf.nodePush] #{message}"

	thousandsSeparator = (number) ->
		String(number).replace /(^-?\d{1,3}|\d{3})(?=(?:\d{3})+(?:$|\.))/g, '$1,'

	fs.open "#{__dirname}/../tmp/nodePush.child.pid", "w", 0o600, (err, fd) ->
		fs.writeSync fd, process.pid

	# Ensure our namespace is present
	be = be ? {}
	be.bastelstu ?= {}
	be.bastelstu.wcf ?= {}

be.bastelstu.wcf.nodePush
=========================

	class be.bastelstu.wcf.nodePush

Attributes
----------

`app` will become an instance of `express`.

		app: null

`server` willbecome an instance of `http`.

		server: null

`io` will become an instance of `socket.io`.

		io: null

`stats` is an object with the different statistics recorded. Statistics will be shown on the status page.

		stats:
			status: 0
			outbound:
				total: 0
				current: 0
			inbound: 0
			messages: { }
			bootTime: new Date()

Methods
-------
**constructor()**
The constructor is executed when the class is initialized. It prints some helpful information,
such as the PID and the used sockets and continues with initializing everything.

		constructor: ->
			log "nodePush running (pid:#{process.pid})"

First we display the used inbound and outbound sockets.

			if config.inbound.useTCP
				log "Inbound: #{config.inbound.host}:#{config.inbound.port}"
			else
				log "Inbound: #{config.inbound.socket}"
			if config.outbound.useTCP
				log "Outbound: #{config.outbound.host}:#{config.outbound.port}"
			else
				log "Outbound: #{config.outbound.socket}"

			@stats.bootTime = new Date()

Afterwards we initialize the inbound and outbound connection.

			@initInbound()
			@initOutbound()

In order to do a proper cleanup on shutdown we bind the `shutdown` method to the needed events and signals.

			process.on 'exit', =>
				@shutdown()
			process.on 'uncaughtException', (message) =>
				@shutdown message, 1
			process.on 'SIGINT', =>
				@shutdown()
			process.on 'SIGTERM', =>
				@shutdown()
			process.on 'SIGHUP', =>
				@shutdown null, 2

At the end we set a nice title for `ps`.

			process.title = 'nodePush'

**initOutbound()**
`initOutbound` initializes the connection to the browser. That includes starting the HTTP server and preparing
socket.io.

		initOutbound: ->
			log 'Initializing outbound socket'

First we start the express based HTTP server.

			@app = express()
			@server = http.createServer @app
			@io = io.listen @server

Afterwards we set socket.io configuration for the default environment. Files will be minified and logging reduced to a minimum.

			@io.set 'log level', 1
			@io.set 'browser client etag', true
			@io.set 'browser client minification', true
			@io.set 'browser client gzip', true

In case `env` is set to development we show some more debug output.

			@io.configure 'development', =>
				@io.set 'log level', 3
				@io.set 'browser client etag', false
				@io.set 'browser client minification', false

Next we listen on the socket.io `connection` event to record statistics.

			@io.sockets.on 'connection', (socket) =>
				@stats.outbound.total++ if @app.get('env') is 'development'
				@stats.outbound.current++

				socket.on 'disconnect', =>
					@stats.outbound.current--

We continue with creating a callback for the `listen` call.

			listenCallback = =>

In case we are running as root we try to shed root privilegies. If this is not possible we exit, as a service
running as root is dangerous.

				if process.getuid? and (process.getuid() is 0 or process.getgid() is 0)
					try
						log 'Trying to shed root privilegies'
						process.setgid config.group
						process.setuid config.user
						log "New User ID: #{process.getuid()}, New Group ID: #{process.getgid()}"
					catch e
						log 'Cowardly refusing to keep the process alive as root.'
						process.exit 1

After the the HTTP server is listening and we are no longer running as root we start some intervals for the builtin tick events.

				setInterval =>
					@sendMessage 'be.bastelstu.wcf.nodePush.tick15'
				, 15e3
				setInterval =>
					@sendMessage 'be.bastelstu.wcf.nodePush.tick30'
				, 30e3
				setInterval =>
					@sendMessage 'be.bastelstu.wcf.nodePush.tick60'
				, 60e3
				setInterval =>
					@sendMessage 'be.bastelstu.wcf.nodePush.tick90'
				, 90e3
				setInterval =>
					@sendMessage 'be.bastelstu.wcf.nodePush.tick120'
				, 120e3

				log "Done"

Start listening on the configured outbound socket.

			if config.outbound.useTCP
				@server.listen config.outbound.port, config.outbound.host, null, listenCallback
			else
				@server.listen config.outbound.socket, listenCallback
				fs.chmod config.outbound.socket, '777'

Show the status page when '/' is requested.

			@app.get '/', (req, res) =>
				res.charset = 'utf-8';
				res.type 'txt'

Show detailed information when environment is `development`.

				if @app.get('env') is 'development'
					@stats.status++
					reply = """
					Up since: #{@stats.bootTime}
					Status page: #{thousandsSeparator @stats.status} Requests
					Outbound: #{thousandsSeparator @stats.outbound.current} now - #{thousandsSeparator @stats.outbound.total} Total
					Inbound: #{thousandsSeparator @stats.inbound}
					Messages:
					"""
					for message, amount of @stats.messages
						reply += "\n	#{message}: #{thousandsSeparator amount}"
				else
					reply = """
					Up since: #{@stats.bootTime}
					Outbound: #{thousandsSeparator @stats.outbound.current} now
					"""

				res.send reply

**sendMessage(name)**
Sends a message with the given name.

		sendMessage: (name) ->
			return unless /^[a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+(\.[a-zA-Z0-9-_]+)+$/.test name

			if @app.get('env') is 'development'
				@stats.messages[name] ?= 0
				@stats.messages[name]++

			@io.sockets.send name

**initInbound()**
`initInbound` initializes the PHP side socket.

		initInbound: ->
			log 'Initializing inbound socket'

We start by creating a server.

			socket = net.createServer (c) =>
				@stats.inbound++ if @app.get('env') is 'development'

In case data is written to the server we pass it to the connected browsers and close the connection afterwards.

				c.on 'data', (data) =>
					setTimeout =>
						@sendMessage data.toString().trim()
					, 20
					c.end()

				c.on 'end', ->
					c.end()

In case nothing happens within 5 seconds we close the connection in order to save resources.

				c.setTimeout 5e3, ->
					c.end()

After all callbacks are bound we start listening.

			if config.inbound.useTCP
				socket.listen config.inbound.port, config.inbound.host
			else
				socket.listen config.inbound.socket
				fs.chmod config.inbound.socket, '777'

**shutdown()**
`shutdown` performs a clean shutdown of nodePush. It cleans up the unix socket files.

		shutdown: (message = null, code = 0) ->
			if message?
				log "Shutting down: #{message}"
			else
				log 'Shutting down'

			fs.unlinkSync config.inbound.socket if not config.inbound.useTCP and fs.existsSync config.inbound.socket
			fs.unlinkSync config.outbound.socket if not config.outbound.useTCP and fs.existsSync config.outbound.socket

			process.removeAllListeners()
			process.exit code

In the end we finally initialize the class with starts all the services.

	new be.bastelstu.wcf.nodePush()