rollback but still log error

rollback but still log error

# WebSQL Client

# Top-level SQLitePlugin objects

## root window object:

    root = @

## constant(s):

    READ_ONLY_REGEX = /^\s*(?:drop|delete|insert|update|create)\s/i

## global(s):

    txLocks = {}

## utility functions:

    nextTick = window.setImmediate || (fun) ->
      window.setTimeout(fun, 0)
      return

    ###
      Utility that avoids leaking the arguments object. See
      https://www.npmjs.org/package/argsarray
    ###
    argsArray = (fun) ->
      return ->
        len = arguments.length
        if len
          args = []
          i = -1
          while ++i < len
            args[i] = arguments[i]
          return fun.call this, args
        else
          return fun.call this, []

## SQLitePlugin db-connection

#### SQLitePlugin object

    SQLitePlugin = (openargs, openSuccess, openError, primusAdaptor) ->
      console.log "SQLitePlugin openargs: #{JSON.stringify openargs}"

      if !(openargs and openargs['name'])
        throw new Error("Cannot create a SQLitePlugin" +
                        "instance without a db name")

      dbname = openargs.name

      @primusAdaptor = primusAdaptor
      @openargs = openargs
      @dbname = dbname

      @openSuccess = openSuccess
      @openError = openError

      unless @openSuccess
        @openSuccess = ->
          console.log "DB opened: " + dbname
          return

      unless @openError
        @openError = (e) ->
          console.log e.message
          return

      @open @openSuccess, @openError
      return

    SQLitePlugin::databaseFeatures = isSQLitePluginDatabase: true
    SQLitePlugin::openDBs = {}

    SQLitePlugin::addTransaction = (t) ->

      if !txLocks[@dbname]
        txLocks[@dbname] = {
          queue: []
          inProgress: false
        }
      txLocks[@dbname].queue.push t
      @startNextTransaction()
      return

    SQLitePlugin::transaction = (fn, error, success) ->
      if !@openDBs[@dbname]
        error('database not open')
        return
      @addTransaction new
        SQLitePluginTransaction(this, fn, error, success,
            true, false, @primusAdaptor)
      return

    SQLitePlugin::readTransaction = (fn, error, success) ->
      if !@openDBs[@dbname]
        error('database not open')
        return
      @addTransaction new
        SQLitePluginTransaction(this, fn, error, success,
          true, true, @primusAdaptor)
      return

    SQLitePlugin::startNextTransaction = ->
      self = @

      nextTick () ->
        txLock = txLocks[self.dbname]
        if txLock.queue.length > 0 && !txLock.inProgress
          txLock.inProgress = true
          txLock.queue.shift().start()
        return
      return

    SQLitePlugin::open = (success, error) ->
      onSuccess = () => success this
      unless @dbname of @openDBs
        @openDBs[@dbname] = true
        @primusAdaptor.open onSuccess, error, [ @openargs ]
      else
        ###
        for a re-open run onSuccess async so that the openDatabase return value
        can be used in the success handler as an alternative to the handler's
        db argument
        ###
        nextTick () -> onSuccess();
      return

    SQLitePlugin::close = (success, error) ->
      #console.log "SQLitePlugin.prototype.close"

      if @dbname of @openDBs
        if txLocks[@dbname] && txLocks[@dbname].inProgress
          error(new Error('database cannot be closed ' +
                          'while a transaction is in progress'))
          return

        delete @openDBs[@dbname]

        @primusAdaptor.close success, error, [ { path: @dbname } ]

      return

    SQLitePlugin::executeSql = (statement, params, success, error) ->
      mysuccess = (t, r) -> if !!success then success r
      myerror = (t, e) -> if !!error then error e

      myfn = (tx) ->
        tx.executeSql(statement, params, mysuccess, myerror)
        return

      @addTransaction new SQLitePluginTransaction(this, myfn, null, null,
         false, false, @primusAdaptor)
      return

## SQLitePluginTransaction object for batching:

    ###
    Transaction batching object:
    ###
    SQLitePluginTransaction = (db, fn, error, success,
                              txlock, readOnly, primusAdaptor) ->
      if typeof(fn) != "function"
        ###
        This is consistent with the implementation in Chrome -- it
        throws if you pass anything other than a function. This also
        prevents us from stalling our txQueue if somebody passes a
        false value for fn.
        ###
        throw new Error("transaction expected a function")

      @primusAdaptor = primusAdaptor
      @db = db
      @fn = fn
      @error = error
      @success = success
      @txlock = txlock
      @readOnly = readOnly
      @executes = []

      if txlock
        @executeSql "BEGIN", [], null, (tx, err) ->
          throw new Error("unable to begin transaction: " + err.message)

      return

    SQLitePluginTransaction::start = ->
      try
        @fn this
        @run()
      catch err
        ###
        If "fn" throws, we must report the whole transaction as failed.
        ###
        txLocks[@db.dbname].inProgress = false
        @db.startNextTransaction()
        if @error
          @error err
      return

    SQLitePluginTransaction::executeSql = (sql, values, success, error) ->

      if @readOnly && READ_ONLY_REGEX.test(sql)
        @handleStatementFailure(error,
          {message: 'invalid sql for a read-only transaction'})
        return

      qid = @executes.length

      @executes.push
        success: success
        error: error
        qid: qid

        sql: sql
        params: values || []

      return

    SQLitePluginTransaction::handleStatementSuccess = (handler, response) ->
      if !handler
        return

      rows = response.rows || []
      payload =
        rows:
          item: (i) ->
            rows[i]

          length: rows.length

        rowsAffected: response.rowsAffected or 0
        insertId: response.insertId or undefined

      handler this, payload

      return

    SQLitePluginTransaction::handleStatementFailure = (handler, response) ->
      if !handler
        throw new Error "a statement with no error handler failed: " +
          response.message
      if handler(this, response)
        throw new Error "a statement error callback did not return false"
      return

    SQLitePluginTransaction::run = ->
      txFailure = null

      tropts = []
      batchExecutes = @executes
      waiting = batchExecutes.length
      @executes = []
      tx = this

      handlerFor = (index, didSucceed) ->
        (response) ->
          try
            if didSucceed
              tx.handleStatementSuccess batchExecutes[index].success, response
            else
              tx.handleStatementFailure batchExecutes[index].error, response
          catch err
            txFailure = err  unless txFailure

          if --waiting == 0
            if txFailure
              tx.abort txFailure
            else if tx.executes.length > 0
              ###
              new requests have been issued by the callback
              handlers, so run another batch.
              ###
              tx.run()
            else
              tx.finish()

          return

      i = 0

      mycbmap = {}

      while i < batchExecutes.length
        request = batchExecutes[i]

        qid = request.qid

        mycbmap[qid] =
          success: handlerFor(i, true)
          error: handlerFor(i, false)

        tropts.push
          qid: qid
          sql: request.sql
          params: request.params

        i++

      mycb = (result) ->
        #console.log "mycb result #{JSON.stringify result}"

        for r in result
          type = r.type
          qid = r.qid
          res = r.result

          q = mycbmap[qid]

          if q
            if q[type]
              q[type] res

        return

      errcb = (err) =>
        @error = (err) -> console.warn err
        @abort(new Error(err))

      @primusAdaptor.backgroundExecuteSqlBatch mycb,
        errcb, [{dbargs: {dbname: @db.dbname}, executes: tropts}]

      return

    SQLitePluginTransaction::abort = (txFailure) ->
      if @finalized then return
      tx = @

      succeeded = (tx) ->
        txLocks[tx.db.dbname].inProgress = false
        tx.db.startNextTransaction()
        if tx.error then tx.error txFailure
        return

      failed = (tx, err) ->
        txLocks[tx.db.dbname].inProgress = false
        tx.db.startNextTransaction()
        if tx.error
          tx.error new Error("error while trying to roll back: " + err.message)
        return

      @finalized = true

      if @txlock
        @executeSql "ROLLBACK", [], succeeded, failed
        @run()
      else
        succeeded(tx)

      return

    SQLitePluginTransaction::finish = ->
      if @finalized then return
      tx = @

      succeeded = (tx) ->
        txLocks[tx.db.dbname].inProgress = false
        tx.db.startNextTransaction()
        if tx.success then tx.success()
        return

      failed = (tx, err) ->
        txLocks[tx.db.dbname].inProgress = false
        tx.db.startNextTransaction()
        if tx.error
          tx.error new Error("error while trying to commit: " + err.message)
        return

      @finalized = true

      if @txlock
        @executeSql "COMMIT", [], succeeded, failed
        @run()
      else
        succeeded(tx)

      return

## PrimusAdaptor class

    class PrimusAdaptor
      constructor: ->
        @primus = Primus.connect('http://localhost:8082')
        @id = 0 # command id
        @cblist = []
        self = @
        @primus.on('data', (data) -> return self.onData(data))

      onData: (data) ->
        switch data.command
          when 'openComplete'
            if data.err
              @cblist[data.id].e(data.err, data.databaseID)
            else
              @cblist[data.id].s(data.err, data.databaseID)
            delete @cblist[data.id]
          when 'backgroundExecuteSqlBatchFailed'
            @cblist[data.id].e(data.err, data.databaseID)
          when 'backgroundExecuteSqlBatchComplete'
            @cblist[data.id].s(data.answer)

      open: (onSuccess, onError, args) ->
        @cblist[@id] = {
          s: onSuccess,
          e: onError
        }
        @primus.write({
          command: 'open',
          args: args,
          id: @id++
        })

      close: (onSuccess, onError, args) ->
        @cblist[@id] = {
          s: onSuccess,
          e: onError
        }
        @primus.write({
          command: 'close',
          path: args[0].path,
          args: args,
          id: @id++
        })

      delete: (onSuccess, onError, args) ->
        @cblist[@id] = {
          s: onSuccess,
          e: onError
        }
        @primus.write({
          command: 'delete',
          args: args,
          id: @id++
        })

      backgroundExecuteSqlBatch: (onSuccess, onError, args) ->
        @cblist[@id] = {
          s: onSuccess,
          e: onError
        }
        @primus.write({
          command: 'backgroundExecuteSqlBatch',
          args: args,
          id: @id++
        })

## SQLite plugin object factory:

    dblocations = [ "docs", "libs", "nosync" ]

    SQLiteFactory =
      primusAdaptor: null
      ###
      NOTE: this function should NOT be translated from Javascript
      back to CoffeeScript by js2coffee.
      If this function is edited in Javascript then someone will
      have to translate it back to CoffeeScript by hand.
      ###
      opendb: argsArray (args) ->
        if args.length < 1 then return null

        unless primusAdaptor
          primusAdaptor = new PrimusAdaptor()

        first = args[0]
        openargs = null
        okcb = null
        errorcb = null

        if first.constructor == String
          openargs = {name: first}

          if args.length >= 5
            okcb = args[4]
            if args.length > 5 then errorcb = args[5]

        else
          openargs = first

          if args.length >= 2
            okcb = args[1]
            if args.length > 2 then errorcb = args[2]

        if openargs.location
          dblocation = dblocations[openargs.location]
        openargs.dblocation = dblocation || dblocations[0]

        if !!openargs.createFromLocation and openargs.createFromLocation == 1
          openargs.createFromResource = "1"

        new SQLitePlugin openargs, okcb, errorcb, primusAdaptor

      deleteDb: (first, success, error) ->
        args = {}

        if first.constructor == String
          #console.log "delete db name: #{first}"
          args.path = first
          args.dblocation = dblocations[0]

        else
          #console.log "delete db args: #{JSON.stringify first}"
          if !(first and first['name'])
            throw new Error("Please specify db name")
          args.path = first.name
          if first.location
            dblocation = dblocations[first.location]
          args.dblocation = dblocation || dblocations[0]

        delete SQLitePlugin::openDBs[args.path]
        @primusAdaptor.delete success, error, [ args ]

## Exported API:

    root.sqlitePlugin =
      sqliteFeatures:
        isSQLitePlugin: true

      openDatabase: SQLiteFactory.opendb
      deleteDatabase: SQLiteFactory.deleteDb

# WebSQL Client

# Top-level SQLitePlugin objects

## root window object:

    root = @

## constant(s):

    READ_ONLY_REGEX = /^\s*(?:drop|delete|insert|update|create)\s/i

## global(s):

    txLocks = {}

## utility functions:

    nextTick = window.setImmediate || (fun) ->
      window.setTimeout(fun, 0)
      return

    ###
      Utility that avoids leaking the arguments object. See
      https://www.npmjs.org/package/argsarray
    ###
    argsArray = (fun) ->
      return ->
        len = arguments.length
        if len
          args = []
          i = -1
          while ++i < len
            args[i] = arguments[i]
          return fun.call this, args
        else
          return fun.call this, []

## SQLitePlugin db-connection

#### SQLitePlugin object

    SQLitePlugin = (openargs, openSuccess, openError, primusAdaptor) ->
      console.log "SQLitePlugin openargs: #{JSON.stringify openargs}"

      if !(openargs and openargs['name'])
        throw new Error("Cannot create a SQLitePlugin" +
                        "instance without a db name")

      dbname = openargs.name

      @primusAdaptor = primusAdaptor
      @openargs = openargs
      @dbname = dbname

      @openSuccess = openSuccess
      @openError = openError

      unless @openSuccess
        @openSuccess = ->
          console.log "DB opened: " + dbname
          return

      unless @openError
        @openError = (e) ->
          console.log e.message
          return

      @open @openSuccess, @openError
      return

    SQLitePlugin::databaseFeatures = isSQLitePluginDatabase: true
    SQLitePlugin::openDBs = {}

    SQLitePlugin::addTransaction = (t) ->

      if !txLocks[@dbname]
        txLocks[@dbname] = {
          queue: []
          inProgress: false
        }
      txLocks[@dbname].queue.push t
      @startNextTransaction()
      return

    SQLitePlugin::transaction = (fn, error, success) ->
      if !@openDBs[@dbname]
        error('database not open')
        return
      @addTransaction new
        SQLitePluginTransaction(this, fn, error, success,
            true, false, @primusAdaptor)
      return

    SQLitePlugin::readTransaction = (fn, error, success) ->
      if !@openDBs[@dbname]
        error('database not open')
        return
      @addTransaction new
        SQLitePluginTransaction(this, fn, error, success,
          true, true, @primusAdaptor)
      return

    SQLitePlugin::startNextTransaction = ->
      self = @

      nextTick () ->
        txLock = txLocks[self.dbname]
        if txLock.queue.length > 0 && !txLock.inProgress
          txLock.inProgress = true
          txLock.queue.shift().start()
        return
      return

    SQLitePlugin::open = (success, error) ->
      onSuccess = () => success this
      unless @dbname of @openDBs
        @openDBs[@dbname] = true
        @primusAdaptor.open onSuccess, error, [ @openargs ]
      else
        ###
        for a re-open run onSuccess async so that the openDatabase return value
        can be used in the success handler as an alternative to the handler's
        db argument
        ###
        nextTick () -> onSuccess();
      return

    SQLitePlugin::close = (success, error) ->
      #console.log "SQLitePlugin.prototype.close"

      if @dbname of @openDBs
        if txLocks[@dbname] && txLocks[@dbname].inProgress
          error(new Error('database cannot be closed ' +
                          'while a transaction is in progress'))
          return

        delete @openDBs[@dbname]

        @primusAdaptor.close success, error, [ { path: @dbname } ]

      return

    SQLitePlugin::executeSql = (statement, params, success, error) ->
      mysuccess = (t, r) -> if !!success then success r
      myerror = (t, e) -> if !!error then error e

      myfn = (tx) ->
        tx.executeSql(statement, params, mysuccess, myerror)
        return

      @addTransaction new SQLitePluginTransaction(this, myfn, null, null,
         false, false, @primusAdaptor)
      return

## SQLitePluginTransaction object for batching:

    ###
    Transaction batching object:
    ###
    SQLitePluginTransaction = (db, fn, error, success,
                              txlock, readOnly, primusAdaptor) ->
      if typeof(fn) != "function"
        ###
        This is consistent with the implementation in Chrome -- it
        throws if you pass anything other than a function. This also
        prevents us from stalling our txQueue if somebody passes a
        false value for fn.
        ###
        throw new Error("transaction expected a function")

      @primusAdaptor = primusAdaptor
      @db = db
      @fn = fn
      @error = error
      @success = success
      @txlock = txlock
      @readOnly = readOnly
      @executes = []

      if txlock
        @executeSql "BEGIN", [], null, (tx, err) ->
          throw new Error("unable to begin transaction: " + err.message)

      return

    SQLitePluginTransaction::start = ->
      try
        @fn this
        @run()
      catch err
        ###
        If "fn" throws, we must report the whole transaction as failed.
        ###
        txLocks[@db.dbname].inProgress = false
        @db.startNextTransaction()
        if @error
          @error err
      return

    SQLitePluginTransaction::executeSql = (sql, values, success, error) ->

      if @readOnly && READ_ONLY_REGEX.test(sql)
        @handleStatementFailure(error,
          {message: 'invalid sql for a read-only transaction'})
        return

      qid = @executes.length

      @executes.push
        success: success
        error: error
        qid: qid

        sql: sql
        params: values || []

      return

    SQLitePluginTransaction::handleStatementSuccess = (handler, response) ->
      if !handler
        return

      rows = response.rows || []
      payload =
        rows:
          item: (i) ->
            rows[i]

          length: rows.length

        rowsAffected: response.rowsAffected or 0
        insertId: response.insertId or undefined

      handler this, payload

      return

    SQLitePluginTransaction::handleStatementFailure = (handler, response) ->
      if !handler
        throw new Error "a statement with no error handler failed: " +
          response.message
      if handler(this, response)
        throw new Error "a statement error callback did not return false"
      return

    SQLitePluginTransaction::run = ->
      txFailure = null

      tropts = []
      batchExecutes = @executes
      waiting = batchExecutes.length
      @executes = []
      tx = this

      handlerFor = (index, didSucceed) ->
        (response) ->
          try
            if didSucceed
              tx.handleStatementSuccess batchExecutes[index].success, response
            else
              tx.handleStatementFailure batchExecutes[index].error, response
          catch err
            txFailure = err  unless txFailure

          if --waiting == 0
            if txFailure
              tx.abort txFailure
            else if tx.executes.length > 0
              ###
              new requests have been issued by the callback
              handlers, so run another batch.
              ###
              tx.run()
            else
              tx.finish()

          return

      i = 0

      mycbmap = {}

      while i < batchExecutes.length
        request = batchExecutes[i]

        qid = request.qid

        mycbmap[qid] =
          success: handlerFor(i, true)
          error: handlerFor(i, false)

        tropts.push
          qid: qid
          sql: request.sql
          params: request.params

        i++

      mycb = (result) ->
        #console.log "mycb result #{JSON.stringify result}"

        for r in result
          type = r.type
          qid = r.qid
          res = r.result

          q = mycbmap[qid]

          if q
            if q[type]
              q[type] res

        return

      errcb = (err) ->
        throw new Error(err)

      @primusAdaptor.backgroundExecuteSqlBatch mycb,
        errcb, [{dbargs: {dbname: @db.dbname}, executes: tropts}]

      return

    SQLitePluginTransaction::abort = (txFailure) ->
      if @finalized then return
      tx = @

      succeeded = (tx) ->
        txLocks[tx.db.dbname].inProgress = false
        tx.db.startNextTransaction()
        if tx.error then tx.error txFailure
        return

      failed = (tx, err) ->
        txLocks[tx.db.dbname].inProgress = false
        tx.db.startNextTransaction()
        if tx.error
          tx.error new Error("error while trying to roll back: " + err.message)
        return

      @finalized = true

      if @txlock
        @executeSql "ROLLBACK", [], succeeded, failed
        @run()
      else
        succeeded(tx)

      return

    SQLitePluginTransaction::finish = ->
      if @finalized then return
      tx = @

      succeeded = (tx) ->
        txLocks[tx.db.dbname].inProgress = false
        tx.db.startNextTransaction()
        if tx.success then tx.success()
        return

      failed = (tx, err) ->
        txLocks[tx.db.dbname].inProgress = false
        tx.db.startNextTransaction()
        if tx.error
          tx.error new Error("error while trying to commit: " + err.message)
        return

      @finalized = true

      if @txlock
        @executeSql "COMMIT", [], succeeded, failed
        @run()
      else
        succeeded(tx)

      return

## PrimusAdaptor class

    class PrimusAdaptor
      constructor: ->
        @primus = Primus.connect('http://localhost:8082')
        @id = 0 # command id
        @cblist = []
        self = @
        @primus.on('data', (data) -> return self.onData(data))

      onData: (data) ->
        switch data.command
          when 'openComplete'
            if data.err
              @cblist[data.id].e(data.err, data.databaseID)
            else
              @cblist[data.id].s(data.err, data.databaseID)
            delete @cblist[data.id]
          when 'backgroundExecuteSqlBatchFailed'
            @cblist[data.id].e(data.err, data.databaseID)
          when 'backgroundExecuteSqlBatchComplete'
            @cblist[data.id].s(data.answer)

      open: (onSuccess, onError, args) ->
        @cblist[@id] = {
          s: onSuccess,
          e: onError
        }
        @primus.write({
          command: 'open',
          args: args,
          id: @id++
        })

      close: (onSuccess, onError, args) ->
        @cblist[@id] = {
          s: onSuccess,
          e: onError
        }
        @primus.write({
          command: 'close',
          path: args[0].path,
          args: args,
          id: @id++
        })

      delete: (onSuccess, onError, args) ->
        @cblist[@id] = {
          s: onSuccess,
          e: onError
        }
        @primus.write({
          command: 'delete',
          args: args,
          id: @id++
        })

      backgroundExecuteSqlBatch: (onSuccess, onError, args) ->
        @cblist[@id] = {
          s: onSuccess,
          e: onError
        }
        @primus.write({
          command: 'backgroundExecuteSqlBatch',
          args: args,
          id: @id++
        })

## SQLite plugin object factory:

    dblocations = [ "docs", "libs", "nosync" ]

    SQLiteFactory =
      primusAdaptor: null
      ###
      NOTE: this function should NOT be translated from Javascript
      back to CoffeeScript by js2coffee.
      If this function is edited in Javascript then someone will
      have to translate it back to CoffeeScript by hand.
      ###
      opendb: argsArray (args) ->
        if args.length < 1 then return null

        unless primusAdaptor
          primusAdaptor = new PrimusAdaptor()

        first = args[0]
        openargs = null
        okcb = null
        errorcb = null

        if first.constructor == String
          openargs = {name: first}

          if args.length >= 5
            okcb = args[4]
            if args.length > 5 then errorcb = args[5]

        else
          openargs = first

          if args.length >= 2
            okcb = args[1]
            if args.length > 2 then errorcb = args[2]

        if openargs.location
          dblocation = dblocations[openargs.location]
        openargs.dblocation = dblocation || dblocations[0]

        if !!openargs.createFromLocation and openargs.createFromLocation == 1
          openargs.createFromResource = "1"

        new SQLitePlugin openargs, okcb, errorcb, primusAdaptor

      deleteDb: (first, success, error) ->
        args = {}

        if first.constructor == String
          #console.log "delete db name: #{first}"
          args.path = first
          args.dblocation = dblocations[0]

        else
          #console.log "delete db args: #{JSON.stringify first}"
          if !(first and first['name'])
            throw new Error("Please specify db name")
          args.path = first.name
          if first.location
            dblocation = dblocations[first.location]
          args.dblocation = dblocation || dblocations[0]

        delete SQLitePlugin::openDBs[args.path]
        @primusAdaptor.delete success, error, [ args ]

## Exported API:

    root.sqlitePlugin =
      sqliteFeatures:
        isSQLitePlugin: true

      openDatabase: SQLiteFactory.opendb
      deleteDatabase: SQLiteFactory.deleteDb


Let's make it a bit more markdowney

Let's make it a bit more markdowney

Kickstart File
--------------
This file is responsible for starting up the entire server.

Lets start by initializing our basic express stuff.

    express = require 'express'
    app = express()

We need to set a default "views" directory. `/views` makes sense.

    app.set 'views', __dirname + '/views'

Right now, jade templates are the default.

    app.set 'view engine', 'jade'

Let's set the `/public` directory to be the only public directory for assets

    app.use(express.static(__dirname + '/public'))

This is our route-mapper, which is responsible for acting as "glue" between the routes and the controllers.

    require('./guts/routing')(app)

We will listen on the port `3000`.

    app.listen(3000)

Kickstart File
--------------
This file is responsible for starting up the entire server.

Lets start by initializing our basic express stuff.

    express = require 'express'
    app = express()

We need to set a default "views" directory. "/views" makes sense.

    app.set 'views', __dirname + '/views'

Right now, jade templates are the default.

    app.set 'view engine', 'jade'

Let's set the /public directory to be the only public directory for assets

    app.use(express.static(__dirname + '/public'))

This is our route-mapper

    require('./guts/routing')(app)

We will listen on the port 3000.

    app.listen(3000)


collapse menu on click link

collapse menu on click link

# Header helpers

    Template.header.events
      'click #at-nav-link': (event) ->
        if Meteor.user() then AccountsTemplates.logout()
      'click .logout': (event) ->
        AccountsTemplates.logout()
      'click a': (event) ->
        $('.navbar-toggle').click()


Move some descriptions around

Move some descriptions around

# React Maybe Matchers for Jasmine

Tests using the React test utilities directly are both difficult to read
and inconvenient to type. These matchers are intended to to make it
easier to write tests and to understand what they are doing later.

One of the biggest problems with writing Jasmine matchers for React is that
you often have to search through Reacts tree to find the things you want
to test.  In Rspec (in Ruby) you can often chain matchers together to create
complex and readable tests.  Alas, this is not possible for Jasmine.

To compensate for this we will make a [Maybe monad](monad.md#what-is-a-monad)
which will allow us to chain a series of filters.  People often get flustered
about monads, but their use is very straight forward.

## DSL for React tests

These matchers will allow us to write tests like:

```coffee
  expect(component).toBeAComponent (it) ->
    it.contains.tags("div")
      .with.cssClass("my-class")
      .and.text("contents")
      .exactly(2).times
      .result()
```

**Note:** text() is not implemented yet.

In the example above, `toBeAComponent` accepts a callback, which it will call,
funishing a monad called `it`.  We can then chain a series of tests.

The chain in this example means that I am expecting my component to contain a DOM `div`
with the class `my-css-class`.  This `div` should contain the text, `contents`.
There should be exactly 2 such `divs` in my tree.  The `result()` at the
end simply means, "I'm done with my testing, please calculate the results".

The Maybe monad is a special kind of monad that only processes when
the data is valid.  In this case, if there are no `div` elements, then it
wont bother trying to figure out the cssClass, etc.  It will ignore
everything until it gets to the `result`.  Its a useful technique when
you dont want to constantly check return values for errors.

## Requirements

The matchers need to pluralize strings, so we need to load
[a string pluralizer method](pluralize.litcoffee)

    require("./pluralize.litcoffee")

The [ComponentQuery](./ComponentQuery.litcoffee) is a
[JasmineMonad](./JasmineMonad.litcoffee)
that allows you to take a single React component and make queries
of it, often generating a [ComponentFilter](./ComponentFilter.litcoffee).

    ComponentQuery = require("./ComponentQuery.litcoffee")

### Main matcher interface

We actually only require one main method in our matchers interface because
all of our matchers are actually implemented as methods on our monads.

    ReactMatchers =

      toBeAComponent: (util, testers) ->
        compare: (component, func) ->
          filter = new ComponentQuery(component, util, testers)
          func(filter)

Export our matchers from this file.

    module.exports = ReactMatchers

# React Maybe Matchers for Jasmine

Tests using the React test utilities directly are both difficult to read
and inconvenient to type. These matchers are intended to to make it
easier to write tests and to understand what they are doing later.

## DSL for React tests

These matchers will allow us to write tests like:

```coffee
  expect(component).toBeAComponent (it) ->
    it.contains.tags("div")
      .with.cssClass("my-class")
      .and.text("contents")
      .exactly(2).times
      .result()
```

**Note:** text() is not implemented yet.

One of the biggest problems with writing Jasmine matchers for React is that
you often have to search through Reacts tree to find the things you want
to test.  In Rspec (in Ruby) you can often chain matchers together to create
complex and readable tests.  Alas, this is not possible for Jasmine.

To compensate for this we will make a [Maybe monad](monad.md#what-is-a-monad)
which will allow us to chain a series of filters.  People often get flustered
about monads, but their use is very straight forward.

In the example above, `toBeAComponent` accepts a callback, which it will call,
funishing a monad called `it`.  We can then chain a series of tests.

The chain in this example means that I am expecting my component to contain a DOM `div`
with the class `my-css-class`.  This `div` should contain the text, `contents`.
There should be exactly 2 such `divs` in my tree.  The `result()` at the
end simply means, "I'm done with my testing, please calculate the results".

The Maybe monad is a special kind of monad that only processes when
the data is valid.  In this case, if there are no `div` elements, then it
wont bother trying to figure out the cssClass, etc.  It will ignore
everything until it gets to the `result`.  Its a useful technique when
you dont want to constantly check return values for errors.

## Requirements

The matchers need to pluralize strings, so we need to load
[a string pluralizer method](pluralize.litcoffee)

    require("./pluralize.litcoffee")

The [ComponentQuery](./ComponentQuery.litcoffee) is a
[JasmineMonad](./JasmineMonad.litcoffee)
that allows you to take a single React component and make queries
of it, often generating a [ComponentFilter](./ComponentFilter.litcoffee).

    ComponentQuery = require("./ComponentQuery.litcoffee")

### Main matcher interface

We actually only require one main method in our matchers interface because
all of our matchers are actually implemented as methods on our monads.

    ReactMatchers =

      toBeAComponent: (util, testers) ->
        compare: (component, func) ->
          filter = new ComponentQuery(component, util, testers)
          func(filter)

Export our matchers from this file.

    module.exports = ReactMatchers


Fix another no-TLA failure

Fix another no-TLA failure

Next Match Manager
==================

We first set everything in a callback, so that it is invoked only
after the loading of the DOM.

    $ ->

Input
-----

We need both the next match and the list of teams as our inputs.

        inputStream = Bacon.combineTemplate
            teams: Data.teams
            next: NextMatch

List Management
---------------

We use D3 to set the data within the list.

        inputStream.onValue (state) ->
            return unless state.next?

            nodeHTML = (entry) ->
                name = state.teams[entry]?.name ? entry
                "<li>#{name}</li>"

            DisplayInformation '.next-match-teams',
                               state.next.teams ? [],
                               'li', nodeHTML

Time Display
------------

We use the next match alone for the display of its start time.

    NextMatch.onValue (match) ->
        if match?
            $('.next-match-time').text(FormatTime(FromUNIX(match.start),
                                                        false))
        else
            $('.next-match-time').text('-')

Next Match Manager
==================

We first set everything in a callback, so that it is invoked only
after the loading of the DOM.

    $ ->

Input
-----

We need both the next match and the list of teams as our inputs.

        inputStream = Bacon.combineTemplate
            teams: Data.teams
            next: NextMatch

List Management
---------------

We use D3 to set the data within the list.

        inputStream.onValue (state) ->
            return unless state.next?

            nodeHTML = (entry) ->
                "<li>#{state.teams[entry].name}</li>"

            DisplayInformation '.next-match-teams',
                               state.next.teams ? [],
                               'li', nodeHTML

Time Display
------------

We use the next match alone for the display of its start time.

    NextMatch.onValue (match) ->
        if match?
            $('.next-match-time').text(FormatTime(FromUNIX(match.start),
                                                        false))
        else
            $('.next-match-time').text('-')


modified:   addressExample.litcoffee

modified:   addressExample.litcoffee

Example for simple-schema
===

      @Address = (city, state) ->
        this.city = city
        this.state = state

      @Address:: =
        constructor: Address

        toString: () ->
          @city + ',' + @state

        clone: () ->
          new Address @city, @state

        equals: (other) ->
          if not (other instanceof Address) then return false

        typeName: () ->
          "Address"

        toJSONValue: () ->
          return {
            @city
            @state
          }

      EJSON.addType "Address", (value)->
        console.log value
        new Address value.city, value.state

      @personA =
        name: "Chris Mather"

        createdAt: new Date()

        file: new Uint8Array([104, 101, 108, 108, 111])

        address: new Address("San Francisco", "CA")

      @personB =
        name: "Chuck Short"

        createdAt: new Date()

        file: new Uint8Array([104, 101, 108, 108, 111])

        address: new Address("Columbia", "SC")

      @People = new Meteor.Collection "people"

      @People2 = new Meteor.Collection2 "people2", {
        schema:
          name:
            type: String
            label: "name"
            max: 200
          address:
            type: Object
            label: "address"
        }

      if (Meteor.isClient)
        Meteor.subscribe "people"
        Meteor.subscribe "people2"
        Meteor.startup ()->
          People.insert personB
          People2.insert personB

      if (Meteor.isServer)
        Meteor.publish "people", ()->
          @added "people", Meteor.uuid(), personA
          @ready()
        Meteor.publish "people2", ()->
          @added "people2", Meteor.uuid(), personA
          @ready()

Example for simple-schema
===

      @Address = (city, state) ->
        this.city = city
        this.state = state

      @Address:: =
        constructor: Address

        toString: () ->
          @city + ',' + @state

        clone: () ->
          new Address @city, @state

        equals: (other) ->
          if not (other instanceof Address) then return false

        typeName: () ->
          "Address"

        toJSONValue: () ->
          return {
            @city
            @state
          }

      EJSON.addType "Address", (value)->
        console.log value
        new Address value.city, value.state

      @person =
        name: "Chris Mather"

        createdAt: new Date()

        file: new Uint8Array([104, 101, 108, 108, 111])

        address: new Address("San Francisco", "CA")

      @person2 =
        name: "Chuck Short"

        createdAt: new Date()

        file: new Uint8Array([104, 101, 108, 108, 111])

        address: new Address("Columbia", "SC")

      @People = new Meteor.Collection "people"

      @People2 = new Meteor.Collection2 "people2", {
        schema:
          name:
            type: String
            label: "name"
            max: 200
          address:
            type: Object
            label: "address"
        }

      if (Meteor.isClient)
        Meteor.subscribe "people"
        Meteor.subscribe "people2"
        Meteor.startup ()->
          People.insert person2
          People2.insert person2

      if (Meteor.isServer)
        Meteor.publish "people", ()->
          @added "people", Meteor.uuid(), person
          @ready()
        Meteor.publish "people2", ()->
          @added "people2", Meteor.uuid(), person
          @ready()


Added more test coverage

Added more test coverage

### Users Controller Test

Unit tests for the `users` controller. Any new methods added to `/server/controllers/users` should have matching tests here.

	fs = require 'fs'
	path = require 'path'
	colors = require 'colors'
	moment = require 'moment'
	chai = require 'chai'
	chai.should()
	testConfig = require '../config.json'

Create mock server objects to pass through the tests

	req = {
		params: {}
		body: {}
	}
	res = {}
	app = {
		dialog: (str) -> console.log str.green if testConfig.console
		log: (str) -> console.log str.cyan if testConfig.console
		error: (str) -> throw new Error str.red if testConfig.console
		warn: (str) -> console.warn "[Warning]".yellow, str.yellow if testConfig.console
		models: {}
		data_config: {}
	}

Assign the controller

	controller = require("../../factory/server/controllers/users")(app)

Begin tests.

	describe 'controllers.users', () ->

#### [create_new_user](https://github.com/merciba/ecrit/blob/master/factory/server/controllers/users.litcoffee#create_new_user)

		it 'create_new_user', (done) ->

__Scenario:__ `req.body.user` matches [User model](https://github.com/merciba/ecrit/blob/master/factory/server/models/User.litcoffee)
__Should:__ Call `app.models.users.create` with identical query.

			scenario_one = () ->

				req.body.user = {
					id: 'id'
					first_name: 'Test'
				}
				app.models.users = {
					create: (query, next) ->
						query.id.should.equal 'id'
						query.first_name.should.equal 'Test'
						next null, query

					attributes: require('../../factory/server/models/User').attributes
				}

				controller.create_new_user req, res, done

			scenario_one()

### Users Controller Test

Unit tests for the `users` controller. Any new methods added to `/server/controllers/users` should have matching tests here.

	fs = require 'fs'
	path = require 'path'
	colors = require 'colors'
	moment = require 'moment'
	chai = require 'chai'
	chai.should()
	testConfig = require '../config.json'

Create mock server objects to pass through the tests

	req = {
		params: {}
		body: {}
	}
	res = {}
	app = {
		dialog: (str) -> console.log str.green if testConfig.console
		log: (str) -> console.log str.cyan if testConfig.console
		error: (str) -> throw new Error str.red if testConfig.console
		warn: (str) -> console.warn "[Warning]".yellow, str.yellow if testConfig.console
		models: {}
		data_config: {}
	}

Assign the controller

	controller = require("../../factory/server/controllers/users")(app)

Begin tests.

	describe 'controllers.users', () ->

#### [create_new_user](https://github.com/merciba/ecrit/blob/master/factory/server/controllers/users.litcoffee#create_new_user)

		it 'create_new_user', (done) ->

__Scenario:__ `req.body.user` matches [User model](https://github.com/merciba/ecrit/blob/master/factory/server/models/User.litcoffee)
__Should:__ Display the time, method and original URL if `ecrit test` is invoked with the `--console` flag.

			scenario_one = () ->

				req.body.user = {
					id: 'id'
				}
				app.models.users = {
					create: (query, next) ->
						query.should.have.property 'id'
						next null, query
					attributes: require('../../factory/server/models/User').attributes
				}

				controller.create_new_user req, res, done

			scenario_one()


No longer need this method (thank god)

No longer need this method (thank god)

    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()

      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: (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