add docs for App.resources

add docs for App.resources

# Batman.App

`Batman.App` is the central object in any Batman application. It manages the routing table and the current URL parameters, as well as the initial start of the application. It should also be used as a namespace for models and views so that other objects can find them. Batman assumes that there will only ever be one `Batman.App` in use at once.

## Batman.currentApp

A Batman-wide reference to the currently running `Batman.App`.

## @run() : App

`App.run` is the central entry point for a Batman application. `@run` takes these steps to initialize a Batman application:

 1. Instantiate a `Dispatcher`, an internal object for mananging action dispatch to controllers.
 2. Instantiate a `Navigator`, an internal object for managing the URL via pushState or hashbangs.
 3. Instantiate the `layout` view according to the `layout` property on the `App`.
 4. Wait for the layout view to fire it's `ready` event.
 5. Start the first action dispatch by telling the `Navigator` to begin monitoring the URL.

_Note_: `@run` emits the `run` class event on the `App`, but not necessarily as soon as `@run` is called. Because the `layout` View renders asynchronously and may need to fetch other components, the `run` event can and often does fire long after `@run` is called. If you need to execute code as soon as the `App` has started running, add a listener to the `run` event on the `App` class. If you need to execute code as soon as the layout has rendered, you can use the `ready` event on the `App` class.

`@run` can be called before or on the `load` DOMEvent of the window. `@run` will return the App if the commencement was successful and complete, or `false` if the App must wait for the `layout` to render or if the `App` has already run.

#### starting an application with DOMEvents
```coffeescript
window.addEventListener 'load', ->
  MyApp.run()
```

#### starting an application with jQuery
```coffeescript
$ ->
  MyApp.run()
```

## @stop() : App

`@stop` stops the `App` it's called upon. The URL will stop being monitored and no more actions will be dispatched. In usual Batman development you shouldn't have to call this.

## @routes

`@routes` is a class level property referencing the root level `NamedRouteQuery` which allows for binding to routes on objects. See `data-route` bindings for more information.

## @controllers

`@controllers` is a class level property containing the singleton `Batman.Controller` instances for each subclass in the application. This `controllers` directory puts these instances at the lowercase name of the controller. For example, the `TodosController` would be found at `controllers.todos`. `@controllers` ideally should never be bound to, but it is very useful for debugging in the console and other such workarounds.

    test "App.controllers references a directory of controller instances", ->
      class Alfred extends Batman.App
      class Alfred.TodosController extends Batman.Controller
      controller = Alfred.get('controllers.todos')
      equal Batman._functionName(controller.constructor), "TodosController"

    test "Multi-word controller names have a lowercase first letter", ->
      class Alfred extends Batman.App
      class Alfred.ReminderEmailsController extends Batman.Controller
      controller = Alfred.get('controllers.reminderEmails')
      equal Batman._functionName(controller.constructor), "ReminderEmailsController"

## @layout

`@layout` is the base view of the entire view hierarchy. By default, it will parse any data-* attributes in the entire document, excluding any `data-yield`'s, when `App.run()` is called. Use `MyApp.layout = null` to disable the creation of this default view.

## @currentParams

`@currentParams` contains the URL parameters for the current request, including the path relative to the app's base path (`Batman.config.pathToApp`). Some interesting parts to look at: `@currentParams.controller`, `@currentParams.action`.

## @paramsManager
## @paramsPusher

## 'run' class event

The `run` class event is fired once the app has run. This indeterminately but often happens before the app's layout has finished rendering.

## 'ready' class event

The `ready` class event is fired once the app's layout is rendered.

# Batman.App Routing

The `Batman` routing DSL is similar to Rails 3's routing DSL. It is oriented around the notion of a resource:

## @route

`@route` defines a custom route and can be pointed to a controller action directly. For example:

```coffeescript
class window.Example extends Batman.App
  @route 'comments', 'pages#comments'

class Example.PagesController extends Batman.Controller
  comments: ->
```

Would result in `/comments` being added to the routing map, pointed to `PagesController#comments`.

## @resources(resourceName : String[, otherResourceNames... : String][, options : Object][, scopedCallback : Function])

`@resources` is modeled after the Rails routing `resources` method. It automatically defines some routes (and matches them to controller actions) for you. For example,

```coffeescript
class App extends Batman.App
  @resources 'pages'

class App.PagesController extends Batman.Controller
  index: ->
    # ...
  new: ->
    # ...
  show: (params) ->
    App.Page.find params.id, (err, page) ->
      @set('currentPage', page)
  edit: (params) ->
    App.Page.find params.id, (err, page) ->
      @set('currentPage', page)
```

Will set up these routes:

Path | Controller Action | View binding
-- | -- | -- |
/pages | App.PagesController#index | `data-route="routes.pages"`
/pages/new | App.PagesController#new | `data-route="routes.pages.new"`
/pages/:id | App.PagesController#show | `data-route="routes.pages[currentPage]"`
/pages/:id/edit | App.PagesController#edit | `data-route="routes.pages[currentPage].edit"`

Of course, `destroy`, `update`, and `create` are not performed by controller actions in Batman. Instead, call `save` or `destroy` on your records.

### Nested Resources

You may also nest resources, as in Rails:

```coffeescript
class App extends Batman.App
  @resources 'pages', ->
    @resources 'comments'
```

Will set up these routes for `App.Comment`:

Path | Controller Action | View binding
-- | -- | -- |
/pages/:page_id/comments | App.CommentsController#index | `data-route="routes.pages[currentPage].comments"`
/pages/:page_id/comments/new | App.CommentsController#new | `data-route="routes.pages[currentPage].comments.new"`
/pages/:page_id/comments/:id | App.CommentsController#show | `data-route="routes.pages[currentPage].comments[currentComment]"`
/pages/:page_id/comments/:id/edit | App.CommentsController#edit | `data-route="routes.pages[currentPage].comments[currentComment].edit"`

## @member

`@member` defines a routable action you can call on a specific instance of a member of a collection resource. For example, if you have a collection of `Page` resources, and a user can post a comment on a specific page:

```coffeescript
class window.Example extends Batman.App
  @resources 'pages', ->
    @member 'comment'

class Example.PagesController extends Batman.Controller
  comment: (params) ->
```

Would result in `/pages/:id/comment` being added to the routing map, pointed to `PagesController#comment`.

## @collection

`@collection` is similar to `@member` in that it adds routable actions to a `@resources` set of routes. In this case the action would apply to the entire collection. For example, if you have a list of spam comments made across _all_ your `Page` resources:

```coffeescript
class window.Example extends Batman.App
  @resources 'pages', ->
    @collection 'spam_comments'

class Example.PagesController extends Batman.Controller
  comments: ->
```

Would result in `/pages/spam_comments` being added to the routing map, pointed to `PagesController#spam_comments`.

## @root

`@root` defines the root controller and action to be used when visiting the base application URL. For example:

```coffeescript
class window.Example extends Batman.App
  @root 'pages#index'

class Example.PagesController extends Batman.Controller
  index: ->
```

Would result in `/` being pointed to `PagesController#index`.

# Batman.App

`Batman.App` is the central object in any Batman application. It manages the routing table and the current URL parameters, as well as the initial start of the application. It should also be used as a namespace for models and views so that other objects can find them. Batman assumes that there will only ever be one `Batman.App` in use at once.

## Batman.currentApp

A Batman-wide reference to the currently running `Batman.App`.

## @run() : App

`App.run` is the central entry point for a Batman application. `@run` takes these steps to initialize a Batman application:

 1. Instantiate a `Dispatcher`, an internal object for mananging action dispatch to controllers.
 2. Instantiate a `Navigator`, an internal object for managing the URL via pushState or hashbangs.
 3. Instantiate the `layout` view according to the `layout` property on the `App`.
 4. Wait for the layout view to fire it's `ready` event.
 5. Start the first action dispatch by telling the `Navigator` to begin monitoring the URL.

_Note_: `@run` emits the `run` class event on the `App`, but not necessarily as soon as `@run` is called. Because the `layout` View renders asynchronously and may need to fetch other components, the `run` event can and often does fire long after `@run` is called. If you need to execute code as soon as the `App` has started running, add a listener to the `run` event on the `App` class. If you need to execute code as soon as the layout has rendered, you can use the `ready` event on the `App` class.

`@run` can be called before or on the `load` DOMEvent of the window. `@run` will return the App if the commencement was successful and complete, or `false` if the App must wait for the `layout` to render or if the `App` has already run.

#### starting an application with DOMEvents
```coffeescript
window.addEventListener 'load', ->
  MyApp.run()
```

#### starting an application with jQuery
```coffeescript
$ ->
  MyApp.run()
```

## @stop() : App

`@stop` stops the `App` it's called upon. The URL will stop being monitored and no more actions will be dispatched. In usual Batman development you shouldn't have to call this.

## @routes

`@routes` is a class level property referencing the root level `NamedRouteQuery` which allows for binding to routes on objects. See `data-route` bindings for more information.

## @controllers

`@controllers` is a class level property containing the singleton `Batman.Controller` instances for each subclass in the application. This `controllers` directory puts these instances at the lowercase name of the controller. For example, the `TodosController` would be found at `controllers.todos`. `@controllers` ideally should never be bound to, but it is very useful for debugging in the console and other such workarounds.

    test "App.controllers references a directory of controller instances", ->
      class Alfred extends Batman.App
      class Alfred.TodosController extends Batman.Controller
      controller = Alfred.get('controllers.todos')
      equal Batman._functionName(controller.constructor), "TodosController"

    test "Multi-word controller names have a lowercase first letter", ->
      class Alfred extends Batman.App
      class Alfred.ReminderEmailsController extends Batman.Controller
      controller = Alfred.get('controllers.reminderEmails')
      equal Batman._functionName(controller.constructor), "ReminderEmailsController"

## @layout

`@layout` is the base view of the entire view hierarchy. By default, it will parse any data-* attributes in the entire document, excluding any `data-yield`'s, when `App.run()` is called. Use `MyApp.layout = null` to disable the creation of this default view.

## @currentParams

`@currentParams` contains the URL parameters for the current request, including the path relative to the app's base path (`Batman.config.pathToApp`). Some interesting parts to look at: `@currentParams.controller`, `@currentParams.action`.

## @paramsManager
## @paramsPusher

## 'run' class event

The `run` class event is fired once the app has run. This indeterminately but often happens before the app's layout has finished rendering.

## 'ready' class event

The `ready` class event is fired once the app's layout is rendered.

# Batman.App Routing

The `Batman` routing DSL is similar to Rails 3's routing DSL. It is oriented around the notion of a resource:

## @route

`@route` defines a custom route and can be pointed to a controller action directly. For example:

```coffeescript
class window.Example extends Batman.App
  @route 'comments', 'pages#comments'

class Example.PagesController extends Batman.Controller
  comments: ->
```

Would result in `/comments` being added to the routing map, pointed to `PagesController#comments`.

## @resources(resourceName : String[, otherResourceNames... : String][, options : Object][, scopedCallback : Function])

## @member

`@member` defines a routable action you can call on a specific instance of a member of a collection resource. For example, if you have a collection of `Page` resources, and a user can post a comment on a specific page:

```coffeescript
class window.Example extends Batman.App
  @resources 'pages', ->
    @member 'comment'

class Example.PagesController extends Batman.Controller
  comment: (params) ->
```

Would result in `/pages/:id/comment` being added to the routing map, pointed to `PagesController#comment`.

## @collection

`@collection` is similar to `@member` in that it adds routable actions to a `@resources` set of routes. In this case the action would apply to the entire collection. For example, if you have a list of spam comments made across _all_ your `Page` resources:

```coffeescript
class window.Example extends Batman.App
  @resources 'pages', ->
    @collection 'spam_comments'

class Example.PagesController extends Batman.Controller
  comments: ->
```

Would result in `/pages/spam_comments` being added to the routing map, pointed to `PagesController#spam_comments`.

## @root

`@root` defines the root controller and action to be used when visiting the base application URL. For example:

```coffeescript
class window.Example extends Batman.App
  @root 'pages#index'

class Example.PagesController extends Batman.Controller
  index: ->
```

Would result in `/` being pointed to `PagesController#index`.


proceed only for valid event

proceed only for valid event

# CLASS: Element
* Extends: [Evented][Evented]
* Parent: [Index][Parent]

A visual element. Manages **mousemove**, **mousedown** and **mouseup** events.
Manages **regions** and **local event coordinates**.

---

    module.exports = class Element extends require 'ecl/dist/evented'

## CONSTRUCTOR

### new Element(args)

Creates an Element instance.

      constructor: ->
        super

Copy the element origin if it was set from named arguments

        if @origin then @origin = x:(@origin.x or 0), y:(@origin.y or 0)

Register validating listeners for each **type** from the list.

        for type in ['mousemove', 'mousedown', 'mouseup']

Localize the **type** variable.

          do (type) =>

Add capturing listener which will cancel and stop the event
if the event type is not enabled.

            @addListener type:type, capture:yes, listener: (event) ->
              event.cancel().stop() unless @events?[type]

Add normal listener which will cancel and stop the event
if the event type is not enabled.

            @addListener type:type, capture:no, listener: (event) ->
              event.cancel().stop() unless @events?[type]

Register extendable listeners for each **type** from the list.

        for type in ['mousemove', 'mousedown', 'mouseup']

Add capturing extendable listener

          @addListener type, this["#{type}CaptureListener"], yes

Add normal extendable listener

          @addListener type, this["#{type}Listener"], no

#### PARAMETERS
* **args**
    * Type: [Object][Object] - named arguments

* **args.origin**
    * Type: [Object][Object] - origin coordinates

* **args.origin.x**
    * Type: [Number][Number] - x coordinate

* **args.origin.y**
    * Type: [Number][Number] - y coordinate

* **args.regions** - named regions
    * Type: [Object][Object]

* **args.regions.{NAME}**
    * Type: [Array][Array] - [x, y, width, height]

---

## PROPERTIES

### #origin
* Type: [Object][Object] - origin coordinates
* **x**
  * Type: [Number][Number] - x coordinate
* **y**
  * Type: [Number][Number] - y coordinate

---

## METHODS
### #localizeEventCoordinates(event) ->
* Returns: [Element][Element]

Helper method, to localize event coordinates.

      localizeEventCoordinates: (event) ->

Proceed only for valid event

        if event

If event already has localized **x**, use it instead of absolute **x**

          x = (if event.localX? then event.localX else event.x)
          event.localX = x - (@origin?.x or 0)

If event already has localized **y**, use it instead of absolute **y**

          y = (if event.localY? then event.localY else event.y)
          event.localY = y - (@origin?.y or 0)

        return this

---

## LISTENERS
### #mousemoveCaptureListener(event)
* Returns: [Element][Element]

Extendable capturing **mousemove** listener

      mousemoveCaptureListener: (event) ->

Proceed only for valid event

        if event

Store the event in the runtime for later and localize event coordinates

          @___runtime.mousemoveEvent = event
          @localizeEventCoordinates event

        return this

---

### #mousedownCaptureListener(event)
* Returns: [Element][Element]

Extendable capturing **mousedown** listener

      mousedownCaptureListener: (event) ->

Proceed only for valid event

        if event

Store the event in the runtime for later and localize event coordinates

          @___runtime.mousedownEvent = event
          @localizeEventCoordinates event

        return this

---

### #mouseupCaptureListener(event)
* Returns: [Element][Element]

Extendable capturing **mouseup** listener

      mouseupCaptureListener: (event) ->

Proceed only for valid event

        if event

Store the event in the runtime for later and localize event coordinates

          @___runtime.mouseupEvent = event
          @localizeEventCoordinates event

        return this

---

### #mousemoveListener(event)
* Returns: [Element][Element]

Extendable **mousemove** listener

      mousemoveListener: -> this

---

### #mousedownListener(event)
* Returns: [Element][Element]

Extendable **mousemove** listener

      mousedownListener: -> this

---

### #mouseupListener(event)
* Returns: [Element][Element]

Extendable **mousemove** listener

      mouseupListener: -> this

[Element]: ./element

[Parent]: ./index.litcoffee
[Evented]: https://nhzio.github.com/ecl/evented.html
[Number]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number
[Object]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
[Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array

# CLASS: Element
* Extends: [Evented][Evented]
* Parent: [Index][Parent]

A visual element. Manages **mousemove**, **mousedown** and **mouseup** events.
Manages **regions** and **local event coordinates**.

---

    module.exports = class Element extends require 'ecl/dist/evented'

## CONSTRUCTOR

### new Element(args)

Creates an Element instance.

      constructor: ->
        super

Copy the element origin if it was set from named arguments

        if @origin then @origin = x:(@origin.x or 0), y:(@origin.y or 0)

Register validating listeners for each **type** from the list.

        for type in ['mousemove', 'mousedown', 'mouseup']

Localize the **type** variable.

          do (type) =>

Add capturing listener which will cancel and stop the event
if the event type is not enabled.

            @addListener type:type, capture:yes, listener: (event) ->
              event.cancel().stop() unless @events?[type]

Add normal listener which will cancel and stop the event
if the event type is not enabled.

            @addListener type:type, capture:no, listener: (event) ->
              event.cancel().stop() unless @events?[type]

Register extendable listeners for each **type** from the list.

        for type in ['mousemove', 'mousedown', 'mouseup']

Add capturing extendable listener

          @addListener type, this["#{type}CaptureListener"], yes

Add normal extendable listener

          @addListener type, this["#{type}Listener"], no

#### PARAMETERS
* **args**
    * Type: [Object][Object] - named arguments

* **args.origin**
    * Type: [Object][Object] - origin coordinates

* **args.origin.x**
    * Type: [Number][Number] - x coordinate

* **args.origin.y**
    * Type: [Number][Number] - y coordinate

* **args.regions** - named regions
    * Type: [Object][Object]

* **args.regions.{NAME}**
    * Type: [Array][Array] - [x, y, width, height]

---

## PROPERTIES

### #origin
* Type: [Object][Object] - origin coordinates
* **x**
  * Type: [Number][Number] - x coordinate
* **y**
  * Type: [Number][Number] - y coordinate

---

## METHODS
### #localizeEventCoordinates(event) ->
* Returns: [Element][Element]

Helper method, to localize event coordinates.

      localizeEventCoordinates: (event) ->
        if event

If event already has localized **x**, use it instead of absolute **x**

          x = (if event.localX? then event.localX else event.x)
          event.localX = x - (@origin?.x or 0)

If event already has localized **y**, use it instead of absolute **y**

          y = (if event.localY? then event.localY else event.y)
          event.localY = y - (@origin?.y or 0)

        return this

---

## LISTENERS
### #mousemoveCaptureListener(event)
* Returns: [Element][Element]

Extendable capturing **mousemove** listener

      mousemoveCaptureListener: (event) ->

Store the event in the runtime for later and localize event coordinates

        @___runtime.mousemoveEvent = event
        @localizeEventCoordinates event

        return this

---

### #mousedownCaptureListener(event)
* Returns: [Element][Element]

Extendable capturing **mousedown** listener

      mousedownCaptureListener: (event) ->

Store the event in the runtime for later and localize event coordinates

        @___runtime.mousedownEvent = event
        @localizeEventCoordinates event

        return this

---

### #mouseupCaptureListener(event)
* Returns: [Element][Element]

Extendable capturing **mouseup** listener

      mouseupCaptureListener: (event) ->

Store the event in the runtime for later and localize event coordinates

        @___runtime.mouseupEvent = event
        @localizeEventCoordinates event

        return this

---

### #mousemoveListener(event)
* Returns: [Element][Element]

Extendable **mousemove** listener

      mousemoveListener: -> this

---

### #mousedownListener(event)
* Returns: [Element][Element]

Extendable **mousemove** listener

      mousedownListener: -> this

---

### #mouseupListener(event)
* Returns: [Element][Element]

Extendable **mousemove** listener

      mouseupListener: -> this

[Element]: ./element

[Parent]: ./index.litcoffee
[Evented]: https://nhzio.github.com/ecl/evented.html
[Number]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number
[Object]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
[Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array


more tweaks for correctness and documentedness

*This is [Literate Coffeescript](http://coffeescript.org/#literate): code interleaved with Markdown
comments. The Coffeescript compiler will strip the Markdown and compile it like any other file.*

## platform-ng config defaults

This file defines the default configuration options for platform-ng and explains
how can modify the configuration to suit your needs.

When you call `Platform#config()` with your configuration object, this configuration is deep-extended with
yours to produce the working configuration.

### General application configuration

What's the app called (`name`), and what environment is it running in (`env`)? For `env`, anything other
than the string `'production'` is automatically considered `'development'` for debuggability.

	module.exports =
		app:
			name: 'unnamed-app'
			env: 'development'

#### Sessions

For sessions, you can choose to entirely disable them by setting `enabled` to `false`. Otherwise, your
choices for `type` are currently `cookie` or `vanilla`.

The `cookie` type stores all session data in a garbled (not encrypted) client-side cookie, signed using
the `secret`.

The `vanilla` type stores the session in a server-side session store and only transmits a signed session
ID to the client.

`cookie` is default for now, but `vanilla` will replace it in the next major version. The `secure` option
determines whether the cookies are HTTPS-only or not.

			session:
				enabled: true
				type: 'cookie'
				secret: 'change-me'
				secure: false

#### Cookie parser

The cookie parser transforms the `cookie` header into `request.cookies`, `request.signedCookies`, and
`request.secureCookies` objects. You still have to use `response.cookie(...)` and/or
`response.clearCookie(...)` to actually manipulate cookies. The `secret` defined here will be used to
verify signed cookies, and, if you set `{signed: true}` in the third argument to `response.cookie(...)`,
this `secret` will be used to sign the outbound cookies too.

			cookies:
				enabled: true
				secret: 'change-me'

### HTTP server configuration

The `server` sections deals with how platform-ng handles the exchange, parsing, and encoding of HTTP
requests and responses.

		server:
			# Use automatic gzip compression for responses?
			compress: true

			# TCP port to listen on (overriden by PORT environment variable)
			port: 8001

			# Is the app behind a proxy? If so, replace request.ip with X-Forwarded-For, and trust
			# all cookies for HTTPS-only mode.
			behind_proxy: false

			# Enable/disable various body parsers, for performance and security reasons
			parsers:
				urlencoded: true
				json: true
				multipart: false # potential security problem; read http://goo.gl/N4Bci1

			# Allow requests to change HTTP verb using 'X-HTTP-Method-Override' header?
			method_override: false

### Language configuration

This section controls which protolanguages platform-ng will compile, as well as language-specific options
for some of the languages. (The NPM dependencies for these languages are listed in `package.json` as
`optionalDependencies` and can be skipped entirely by calling `npm install --no-optional`.)

		languages:
			coffeescript:
				enabled: true

			stylus:
				enabled: true
				include_css: true	# Whether to inline @include()'d CSS files
				nib: true			# Whether to automatically load the nib library

### Compilation

`compile` controls generic compilation options for all language compilers. The `minify` option will
cause the compiler to munge the output in order to produce the smallest possible code. The `expose_sources`
option will cause the server to serve the original files (e.g. .coffee, .styl, etc) if requested, AND it
will ask the compiler to generate source maps, if supported.

Compilation results are stored in and served from the `.serve/` directory, created and updated at runtime.

		compile:
			minify: true
			expose_sources: true

### Express configuration

platform-ng is powered by Express. You can directly configure Express settings here. The settings are
documented on [this page](http://expressjs.com/3x/api.html#app-settings).

		express:
			'view engine': 'jade'

*This is [Literate Coffeescript](http://coffeescript.org/#literate): code interleaved with Markdown
comments. The Coffeescript compiler will strip the Markdown and compile it like any other file.*

## platform-ng config defaults

This file defines the default configuration options for platform-ng and explains
how can modify the configuration to suit your needs.

When you call `Platform#config()` with your configuration object, this configuration is deep-extended with
yours to produce the working configuration.

### General application configuration

What's the app called (`name`), and what environment is it running in (`env`)? For `env`, anything other
than the string `'production'` is automatically considered `'development'` for debuggability.

	module.exports =
		app:
			name: 'unnamed-app'
			env: 'development'

#### Sessions

For sessions, you can choose to entirely disable them by setting `enabled` to `false`. Otherwise, your
choices for `type` are currently `cookie` or `vanilla`.

The `cookie` type stores all session data in a garbled (not encrypted) client-side cookie, signed using
the `secret`.

The `vanilla` type stores the session in a server-side session store and only transmits a signed session
ID to the client.

`cookie` is default for now, but `vanilla` will replace it in the next major version. The `secure` option
determines whether the cookies are HTTPS-only or not.

			session:
				enabled: true
				type: 'cookie'
				secret: 'change-me'
				secure: false

#### Cookie parser

The cookie parser transforms the `cookie` header into `request.cookies`, `request.signedCookies`, and
`request.secureCookies` objects. You still have to use `response.cookie(...)` and/or
`response.clearCookie(...)` to actually manipulate cookies. The `secret` defined here will be used to
verify signed cookies, and, if you set `{signed: true}` in the third argument to `response.cookie(...)`,
this `secret` will be used to sign the outbound cookies too.

			cookies:
				enabled: true
				secret: 'change-me'

### HTTP server configuration

The `server` sections deals with how platform-ng handles the exchange, parsing, and encoding of HTTP
requests and responses.

		server:
			# Use automatic gzip compression for responses?
			compress: true

			# TCP port to listen on (overriden by PORT environment variable)
			port: 8001

			# Is the app behind a proxy? If so, replace request.ip with X-Forwarded-For, and trust
			# all cookies for HTTPS-only mode.
			behind_proxy: false

			# Enable/disable various body parsers, for performance and security reasons
			parsers:
				urlencoded: true
				json: true
				multipart: false # potential security problem; read http://goo.gl/N4Bci1

			# Allow requests to change HTTP verb using 'X-HTTP-Method-Override' header?
			method_override: false

### Language configuration

This section controls which protolanguages platform-ng will compile, as well as language-specific options
for some of the languages. (The NPM dependencies for these languages are listed in `package.json` as
`optionalDependencies` and can be skipped entirely by calling `npm install --no-optional`.)

		languages:
			coffeescript:
				enabled: true

			stylus:
				enabled: true
				include_css: true	# Whether to inline @include()'d CSS files
				nib: true			# Whether to automatically load the nib library

`compile` controls generic compilation options for all language compilers. The `minify` option will
cause the compiler to munge the output in order to produce the smallest possible code. The `expose_sources`
option will cause the server to serve the original files (e.g. .coffee, .styl, etc) if requested, AND it
will ask the compiler to generate source maps, if supported.

		compile:
			minify: true
			expose_sources: true

platform-ng is powered by Express. You can directly configure Express settings here. The settings are
documented on [this page](http://expressjs.com/3x/api.html#app-settings).

		express:
			'view engine': 'jade'


Added a function to find the navmesh triangle closest to a point.

# navmesh

Navmeshes are stored as "MSN" (MasSplat Navmesh) and are used to define where
entities (including the player) can travel.  By default, they are unable to
leave the surface, "crawling" over it.  Each tile is a 3D triangle.  A light
Any two triangles sharing two vertices are joined and the edge formed may be
crossed from one to the other, otherwise, the edge is treated as a form of wall.

MSN is a binary format.  It is comprised of:

| Type    | Num.              | Description                                                |
| ------- | ----------------- | ---------------------------------------------------------- |
| uint16  | 1                 | The number of vertices defined.                            |
| uint16  | 1                 | The number of triangles defined.                           |
| float32 | 3x num. vertices  | The X, Y and Z of each vertex.                             |
| uint16  | 3x num. triangles | The first, second and third vertex index of each triangle. |

    file = require "./file.litcoffee"
    vector = require "./vector.litcoffee"
    plane = require "./plane.litcoffee"

## load

- filename: The "real" location of the MSN file to load.  (i.e. already
            "require"-d)
- callback: A callback to execute with the array of objects representing the
            loaded objects on success, containing:

+ plane: A plane object for the surface of the triangle itself.
+ vertices: An array of vectors specifying the locations of the vertices which
            make up the triangle.
+ edges: An array of three objects representing the edges of the triangle,
       containing:

* neighbor: When null, there is no other triangle over this edge.  Otherwise
            a reference to the triangle object which can be found over it.
* plane: A plane facing inwards from the edge.  If this edge borders another
         triangle, this will be aligned to both this triangle and the
         neighbor.

    load = (path, callback) ->
        file.arrayBuffer path, (response) ->
            header = new Uint16Array response, 0, 2
            vertexData = new Float32Array response, 4, header[0] * 3
            indices = new Uint16Array response, 4 + header[0] * 4 * 3, header[1] * 3

            vertices = for i in [0...vertexData.length] by 3
                [
                    vertexData[i]
                    vertexData[i + 1]
                    vertexData[i + 2]
                ]

            triangles = for i in [0...indices.length] by 3
                plane: plane.fromTriangle vertices[indices[i]], vertices[indices[i + 1]], vertices[indices[i + 2]]
                indices: [
                    indices[i]
                    indices[i + 1]
                    indices[i + 2]
                ]
                vertices: [
                    vertices[indices[i]]
                    vertices[indices[i + 1]]
                    vertices[indices[i + 2]]
                ]

            for triangle in triangles
                triangle.edges = for edge in [0...3]
                    vertexA = triangle.indices[edge]
                    vertexB = triangle.indices[(edge + 1) % 3]
                    vertexC = []
                    vector.add.vector vertices[vertexA], triangle.plane.normal, vertexC
                    neighbor = null
                    for other in triangles
                        if triangle is other then continue
                        if vertexA not in other.indices then continue
                        if vertexB not in other.indices then continue
                        neighbor = other
                        vector.add.vector vertexC, other.plane.normal, vertexC
                        break
                    neighbor: neighbor
                    plane: plane.fromTriangle vertices[vertexA], vertexC, vertices[vertexB]

            callback triangles
            return
        return

## constrain

- A vector specifying the location moved to.
- A reference to the navmesh triangle which contained the location moved from.
- An optional callback executed when a wall is hit, with arguments:

+ The edge collided with.

Updates the location vector to take into account collision with navmesh triangle
walls and returns the new containing navmesh triangle.

    constrain = (location, triangle, edgeCallback) ->

        for iterations in [0...25]
            distanceA = plane.distance triangle.edges[0].plane, location
            distanceB = plane.distance triangle.edges[1].plane, location
            distanceC = plane.distance triangle.edges[2].plane, location
            if distanceA >= 0 and distanceB >= 0 and distanceC >= 0
                break

            if distanceA < 0 and triangle.edges[0].neighbor
                triangle = triangle.edges[0].neighbor
                continue

            if distanceB < 0 and triangle.edges[1].neighbor
                triangle = triangle.edges[1].neighbor
                continue

            if distanceC < 0 and triangle.edges[2].neighbor
                triangle = triangle.edges[2].neighbor
                continue

            if distanceA < 0 and distanceB < 0
                vector.copy triangle.vertices[1], location
                if edgeCallback
                    edgeCallback triangle.edges[0]
                    edgeCallback triangle.edges[1]
                continue

            if distanceB < 0 and distanceC < 0
                vector.copy triangle.vertices[2], location
                if edgeCallback
                    edgeCallback triangle.edges[1]
                    edgeCallback triangle.edges[2]
                continue

            if distanceC < 0 and distanceA < 0
                vector.copy triangle.vertices[0], location
                if edgeCallback
                    edgeCallback triangle.edges[2]
                    edgeCallback triangle.edges[0]
                continue

            if distanceA < 0
                plane.project triangle.edges[0].plane, location, location
                if edgeCallback then edgeCallback triangle.edges[0]
                continue

            if distanceB < 0
                plane.project triangle.edges[1].plane, location, location
                if edgeCallback then edgeCallback triangle.edges[1]
                continue

            if distanceC < 0
                plane.project triangle.edges[2].plane, location, location
                if edgeCallback then edgeCallback triangle.edges[2]
                continue

        triangle

## findNearest

- A navmesh instance.
- A vector specifying a point in 3D space.

Returns the navmesh triangle which is "best" to start in for that location.

    findNearest = (navmesh, location) ->
        best = null
        bestDistance = -Infinity
        for triangle in navmesh
            distance = plane.distance triangle.plane, location
            if bestDistance >= 0 and distance <= 0 then continue
            bestWallDistance = Infinity
            for edge in triangle.edges
                wallDistance = Math.max 0, plane.distance edge.plane, location
                if wallDistance > bestWallDistance then continue
                bestWallDistance = wallDistance
            behind = distance < 0
            distance = distance * distance + bestWallDistance * bestWallDistance
            if distance >= Math.abs bestDistance then continue
            if behind then distance = -distance
            bestDistance = distance
            best = triangle
        best

    module.exports = { load, constrain, findNearest }

# navmesh

Navmeshes are stored as "MSN" (MasSplat Navmesh) and are used to define where
entities (including the player) can travel.  By default, they are unable to
leave the surface, "crawling" over it.  Each tile is a 3D triangle.  A light
Any two triangles sharing two vertices are joined and the edge formed may be
crossed from one to the other, otherwise, the edge is treated as a form of wall.

MSN is a binary format.  It is comprised of:

| Type    | Num.              | Description                                                |
| ------- | ----------------- | ---------------------------------------------------------- |
| uint16  | 1                 | The number of vertices defined.                            |
| uint16  | 1                 | The number of triangles defined.                           |
| float32 | 3x num. vertices  | The X, Y and Z of each vertex.                             |
| uint16  | 3x num. triangles | The first, second and third vertex index of each triangle. |

    file = require "./file.litcoffee"
    vector = require "./vector.litcoffee"
    plane = require "./plane.litcoffee"

## load

- filename: The "real" location of the MSN file to load.  (i.e. already
            "require"-d)
- callback: A callback to execute with the array of objects representing the
            loaded objects on success, containing:

+ plane: A plane object for the surface of the triangle itself.
+ vertices: An array of vectors specifying the locations of the vertices which
            make up the triangle.
+ edges: An array of three objects representing the edges of the triangle,
       containing:

* neighbor: When null, there is no other triangle over this edge.  Otherwise
            a reference to the triangle object which can be found over it.
* plane: A plane facing inwards from the edge.  If this edge borders another
         triangle, this will be aligned to both this triangle and the
         neighbor.

    load = (path, callback) ->
        file.arrayBuffer path, (response) ->
            header = new Uint16Array response, 0, 2
            vertexData = new Float32Array response, 4, header[0] * 3
            indices = new Uint16Array response, 4 + header[0] * 4 * 3, header[1] * 3

            vertices = for i in [0...vertexData.length] by 3
                [
                    vertexData[i]
                    vertexData[i + 1]
                    vertexData[i + 2]
                ]

            triangles = for i in [0...indices.length] by 3
                plane: plane.fromTriangle vertices[indices[i]], vertices[indices[i + 1]], vertices[indices[i + 2]]
                indices: [
                    indices[i]
                    indices[i + 1]
                    indices[i + 2]
                ]
                vertices: [
                    vertices[indices[i]]
                    vertices[indices[i + 1]]
                    vertices[indices[i + 2]]
                ]

            for triangle in triangles
                triangle.edges = for edge in [0...3]
                    vertexA = triangle.indices[edge]
                    vertexB = triangle.indices[(edge + 1) % 3]
                    vertexC = []
                    vector.add.vector vertices[vertexA], triangle.plane.normal, vertexC
                    neighbor = null
                    for other in triangles
                        if triangle is other then continue
                        if vertexA not in other.indices then continue
                        if vertexB not in other.indices then continue
                        neighbor = other
                        vector.add.vector vertexC, other.plane.normal, vertexC
                        break
                    neighbor: neighbor
                    plane: plane.fromTriangle vertices[vertexA], vertexC, vertices[vertexB]

            callback triangles
            return
        return

## constrain

- A vector specifying the location moved to.
- A reference to the navmesh triangle which contained the location moved from.
- An optional callback executed when a wall is hit, with arguments:

+ The edge collided with.

Updates the location vector to take into account collision with navmesh triangle
walls and returns the new containing navmesh triangle.

    constrain = (location, triangle, edgeCallback) ->

        for iterations in [0...25]
            distanceA = plane.distance triangle.edges[0].plane, location
            distanceB = plane.distance triangle.edges[1].plane, location
            distanceC = plane.distance triangle.edges[2].plane, location
            if distanceA >= 0 and distanceB >= 0 and distanceC >= 0
                break

            if distanceA < 0 and triangle.edges[0].neighbor
                triangle = triangle.edges[0].neighbor
                continue

            if distanceB < 0 and triangle.edges[1].neighbor
                triangle = triangle.edges[1].neighbor
                continue

            if distanceC < 0 and triangle.edges[2].neighbor
                triangle = triangle.edges[2].neighbor
                continue

            if distanceA < 0 and distanceB < 0
                vector.copy triangle.vertices[1], location
                if edgeCallback
                    edgeCallback triangle.edges[0]
                    edgeCallback triangle.edges[1]
                continue

            if distanceB < 0 and distanceC < 0
                vector.copy triangle.vertices[2], location
                if edgeCallback
                    edgeCallback triangle.edges[1]
                    edgeCallback triangle.edges[2]
                continue

            if distanceC < 0 and distanceA < 0
                vector.copy triangle.vertices[0], location
                if edgeCallback
                    edgeCallback triangle.edges[2]
                    edgeCallback triangle.edges[0]
                continue

            if distanceA < 0
                plane.project triangle.edges[0].plane, location, location
                if edgeCallback then edgeCallback triangle.edges[0]
                continue

            if distanceB < 0
                plane.project triangle.edges[1].plane, location, location
                if edgeCallback then edgeCallback triangle.edges[1]
                continue

            if distanceC < 0
                plane.project triangle.edges[2].plane, location, location
                if edgeCallback then edgeCallback triangle.edges[2]
                continue

        triangle

    module.exports = { load, constrain }


Move logging method initialization to constructor

    q  = require 'q'
    fs = require 'fs'

    microtime = require 'microtime'

    logger = require './logger'

    available = { }
    loaded    = { }
    processed = { }

    class Module

      constructor: ->
        @debug = (msg, data) -> logger.debug msg, data
        @info  = (msg, data) -> logger.info  msg, data
        @warn  = (msg, data) -> logger.warn  msg, data
        @error = (msg, data) -> logger.error msg, data

        if arguments.length == 0 || arguments[0] == ''
          @clazz = arguments.callee.caller.name
        else
          @clazz = arguments[0]

        logger.trace "Instantiating #{@clazz}"

      wrap_methods: =>
        @pub?.forEach (method) =>
          callMe   = @[method]
          deferred = q.defer()

          @["_#{method}"] = @[method]

          @[method] = =>
            start    = microtime.now()
            update   = start

            respond = (state, data) =>
              process.nextTick =>
                deferred[state] data

                if state == 'reject'
                  logger.rejected @clazz, method, microtime.now() - start, data

                if process.env.CGAPI_LOG_LEVEL > 4
                  if state == 'resolve'
                    logger.resolved @clazz, method, microtime.now() - start, data
                  else if state == 'notify'
                    logger.notify @clazz, method, microtime.now() - update, data
                    update = microtime.now()

            @done   = (out) => respond 'resolve', out
            @fail   = (err) => respond 'reject',  err
            @update = (out) => respond 'notify',  out

            args = Array.prototype.slice.call arguments

            logger.trace "Invoking #{@clazz}.#{method}()", args

            @["_#{method}"].apply null, args

            deferred.promise

      hydrate_dependencies: =>
        def = q.defer()
        good_to_go = false

        load = (name, path, cb) =>
          if available[name]? == false
            mod = require path

            if typeof mod == 'function'
              new mod()
                .initialize @ctor_params?[name]
                .then (mod) =>
                  available[name] = mod
                  cb()
            else
              available[name] = mod
              cb()
          else
            cb()

        check_directory = (path, dep, cb) =>
          fs.readdir path, (err, files) =>
            if err?
              def.reject type: 'ERROR', info: err
            else
              to_check = files.length
              checked = 0

              files.forEach (f) =>
                depth = "#{path}/#{f}"

                fs.lstat depth, (e, s) =>
                  if s.isDirectory()
                    check_directory depth, dep, =>
                      cb() if ++checked == to_check
                  else if s.isFile()
                    if f == 'index.js' || f.includes '.spec.'
                      cb() if ++checked == to_check
                    else
                      name = f.substring 0, f.length - 3

                      if name == dep
                        load name, depth, => cb() if ++checked == to_check
                      else
                        cb() if ++checked == to_check

        register_dependency = (name, mod) =>
          n = name.replace /\W+/g, '_'
          @[n] = mod

          def.notify type: 'NOTICE', loaded: n

          unless loaded[@clazz]?
            loaded[@clazz] = [ ]

          unless processed[@clazz]?
            processed[@clazz] = 0

          unless loaded[@clazz].indexOf(name) > -1
            loaded[@clazz].push name
            ++processed[@clazz]

          logger.trace 'Registered dependency', "#{@clazz}": "#{n}(file: #{name})"

          if processed[@clazz] >= @deps.length
            if loaded[@clazz].length >= @deps.length
              logger.trace "Loaded all dependencies: #{@clazz}", loaded[@clazz]
              def.resolve @
            else
              not_loaded = [ ]

              @deps.forEach (d) -> not_loaded.push(d) unless loaded[@clazz].indexOf(d) > -1

              logger.error "Failed loading dependencies for: #{@clazz}", not_loaded

              def.reject type: 'ERROR', not_loaded: not_loaded

        @deps?.forEach (d) =>
          if @[d]?
            good_to_go = true
          else
            if available[d]? == true
              register_dependency d, available[d]
            else
              try
                available[d] = require d
                register_dependency d, available[d]
              catch
                check_directory __dirname, d, =>
                  register_dependency d, available[d]

        if good_to_go && loaded[@clazz].length >= @deps.length
          process.nextTick => def.resolve @

        def.promise

      initialize: (wrap = true) =>
        deferred = q.defer()

        if @deps?
          @hydrate_dependencies()
            .then =>
              @wrap_methods() if wrap
              deferred.resolve @
            .fail (reason) => deferred.reject reason
        else
          process.nextTick =>
            @wrap_methods() if wrap
            deferred.resolve @

        deferred.promise

    module.exports = Module

    q  = require 'q'
    fs = require 'fs'

    microtime = require 'microtime'

    logger = require './logger'

    available = { }
    loaded    = { }
    processed = { }

    class Module

      constructor: ->
        if arguments.length == 0 || arguments[0] == ''
          @clazz = arguments.callee.caller.name
        else
          @clazz = arguments[0]

        logger.trace "Instantiating #{@clazz}"

      wrap_methods: =>
        @pub?.forEach (method) =>
          callMe   = @[method]
          deferred = q.defer()

          @["_#{method}"] = @[method]

          @[method] = =>
            start    = microtime.now()
            update   = start

            respond = (state, data) =>
              process.nextTick =>
                deferred[state] data

                if state == 'reject'
                  logger.rejected @clazz, method, microtime.now() - start, data

                if process.env.CGAPI_LOG_LEVEL > 4
                  if state == 'resolve'
                    logger.resolved @clazz, method, microtime.now() - start, data
                  else if state == 'notify'
                    logger.notify @clazz, method, microtime.now() - update, data
                    update = microtime.now()

            @done   = (out) => respond 'resolve', out
            @fail   = (err) => respond 'reject',  err
            @update = (out) => respond 'notify',  out

            args = Array.prototype.slice.call arguments

            logger.trace "Invoking #{@clazz}.#{method}()", args

            @["_#{method}"].apply null, args

            deferred.promise

      hydrate_dependencies: =>
        def = q.defer()
        good_to_go = false

        load = (name, path, cb) =>
          if available[name]? == false
            mod = require path

            if typeof mod == 'function'
              new mod()
                .initialize @ctor_params?[name]
                .then (mod) =>
                  available[name] = mod
                  cb()
            else
              available[name] = mod
              cb()
          else
            cb()

        check_directory = (path, dep, cb) =>
          fs.readdir path, (err, files) =>
            if err?
              def.reject type: 'ERROR', info: err
            else
              to_check = files.length
              checked = 0

              files.forEach (f) =>
                depth = "#{path}/#{f}"

                fs.lstat depth, (e, s) =>
                  if s.isDirectory()
                    check_directory depth, dep, =>
                      cb() if ++checked == to_check
                  else if s.isFile()
                    if f == 'index.js' || f.includes '.spec.'
                      cb() if ++checked == to_check
                    else
                      name = f.substring 0, f.length - 3

                      if name == dep
                        load name, depth, => cb() if ++checked == to_check
                      else
                        cb() if ++checked == to_check

        register_dependency = (name, mod) =>
          n = name.replace /\W+/g, '_'
          @[n] = mod

          def.notify type: 'NOTICE', loaded: n

          unless loaded[@clazz]?
            loaded[@clazz] = [ ]

          unless processed[@clazz]?
            processed[@clazz] = 0

          unless loaded[@clazz].indexOf(name) > -1
            loaded[@clazz].push name
            ++processed[@clazz]

          logger.trace 'Registered dependency', "#{@clazz}": "#{n}(file: #{name})"

          if processed[@clazz] >= @deps.length
            if loaded[@clazz].length >= @deps.length
              logger.trace "Loaded all dependencies: #{@clazz}", loaded[@clazz]
              def.resolve @
            else
              not_loaded = [ ]

              @deps.forEach (d) -> not_loaded.push(d) unless loaded[@clazz].indexOf(d) > -1

              logger.error "Failed loading dependencies for: #{@clazz}", not_loaded

              def.reject type: 'ERROR', not_loaded: not_loaded

        @deps?.forEach (d) =>
          if @[d]?
            good_to_go = true
          else
            if available[d]? == true
              register_dependency d, available[d]
            else
              try
                available[d] = require d
                register_dependency d, available[d]
              catch
                check_directory __dirname, d, =>
                  register_dependency d, available[d]

        if good_to_go && loaded[@clazz].length >= @deps.length
          process.nextTick => def.resolve @

        def.promise

      initialize: (wrap = true) =>
        deferred = q.defer()

        if @deps?
          @hydrate_dependencies()
            .then =>
              @wrap_methods() if wrap
              deferred.resolve @
            .fail (reason) => deferred.reject reason
        else
          process.nextTick =>
            @wrap_methods() if wrap
            deferred.resolve @

        @debug = (msg, data) -> logger.debug msg, data
        @info  = (msg, data) -> logger.info  msg, data
        @warn  = (msg, data) -> logger.warn  msg, data
        @error = (msg, data) -> logger.error msg, data

        deferred.promise

    module.exports = Module


Parse origin header and extract hostname

    url          = require 'url'

    compression  = require 'compression'
    express      = require 'express'
    morgan       = require 'morgan'
    responseTime = require 'response-time'

    multer       = require 'multer'
    async        = require 'async'
    dms2dec      = require 'dms2dec'

    raven        = require 'raven'
    sentry       = require './sentry'

    app = express()
    app.use morgan 'combined'
    app.use compression()
    app.use responseTime()

    Upload = require 's3-uploader'
    s3 = new Upload process.env.AWS_BUCKET_NAME,
      awsBucketUrl: "https://s3-eu-west-1.amazonaws.com/#{process.env.AWS_BUCKET_NAME}/"
      awsBucketPath: process.env.AWS_BUCKET_PATH
      awsBucketAcl: 'public-read'
      awsHttpTimeout: 60000
      returnExif: true

      versions: [{
        original: true
        awsImageAcl: 'private'
      },{
        suffix: '-large'
        quality: 80
        maxHeight: 1040
        maxWidth: 1040
      },{
        suffix: '-medium'
        maxHeight: 780
        maxWidth: 780
      },{
        suffix: '-small'
        maxHeight: 320
        maxWidth: 320
      }]

    origins = process.env.ALLOW_ORIGINS?.split(',') or []

    app.all '/upload', (req, res, next) ->
      res.once 'close', -> sentry.captureResClose res

      origin = url.parse req.get('Origin') or ''

      if origin.hostname not in origins
        error = new Error "Bad Origin Header #{req.get('Origin')}"
        error.status = 403
        return next error

      res.set 'Access-Control-Allow-Origin', req.get('Origin')
      res.set 'Access-Control-Allow-Methods', 'POST'
      res.set 'Access-Control-Allow-Headers', 'X-Requested-With, Content-Type'
      res.set 'Access-Control-Expose-Headers', 'X-Response-Time'
      res.set 'Access-Control-Allow-Max-Age', 0

      return res.send 200 if req.method is 'OPTIONS'
      return next()

    app.post '/upload', multer(dest: require('os').tmpdir()), (req, res, next) ->
      console.log "Recieved #{Object.keys(req.files).length} files"

      async.mapSeries Object.keys(req.files), (key, cb) ->
        if req.files[key].extension not in ['jpg', 'jpeg', 'png', 'gif', 'tiff']
          error = new Error "Invalid Image #{req.files[key].extension}"
          error.status = 422
          return cb error

        s3.upload req.files[key].path, {}, (err, images, meta) ->
          return cb err if err

          if meta.exif['exif:GPSLatitude'] and meta.exif['exif:GPSLongitude']
            meta.geojson =
              type: 'Point'
              coordinates: dms2dec \
                meta.exif['exif:GPSLatitude'], \
                meta.exif['exif:GPSLatitudeRef'], \
                meta.exif['exif:GPSLongitude'], \
                meta.exif['exif:GPSLongitudeRef']
              .reverse()

          return cb null, versions: images.splice(1), meta: meta
      , (err, files) ->
        return next err if err
        sentry.captureHeaderSent req, files if res._headerSent
        return res.status(201).json files

    app.use (req, res, next) ->
      res.status(404).json message: 'Not Found'

    app.use raven.middleware.express sentry
    app.use (err, req, res, next) ->
      if not err.status or err.status >= 500
        sentry.captureError err

        console.error err.message
        console.error err.stack

        res.status(err.status or 500).json message: 'Internal Server Error'
      else
        sentry.captureMessage err.message, level: 'warning', req: req
        res.status(err.status).json message: err.message

    if not module.parent
      app.listen process.env.PORT_WWW
      console.log "Server listening on port #{process.env.PORT_WWW}"
    else
      module.exports = app

    compression  = require 'compression'
    express      = require 'express'
    morgan       = require 'morgan'
    responseTime = require 'response-time'

    multer       = require 'multer'
    async        = require 'async'
    dms2dec      = require 'dms2dec'

    raven        = require 'raven'
    sentry       = require './sentry'

    app = express()
    app.use morgan 'combined'
    app.use compression()
    app.use responseTime()

    Upload = require 's3-uploader'
    s3 = new Upload process.env.AWS_BUCKET_NAME,
      awsBucketUrl: "https://s3-eu-west-1.amazonaws.com/#{process.env.AWS_BUCKET_NAME}/"
      awsBucketPath: process.env.AWS_BUCKET_PATH
      awsBucketAcl: 'public-read'
      awsHttpTimeout: 60000
      returnExif: true

      versions: [{
        original: true
        awsImageAcl: 'private'
      },{
        suffix: '-large'
        quality: 80
        maxHeight: 1040
        maxWidth: 1040
      },{
        suffix: '-medium'
        maxHeight: 780
        maxWidth: 780
      },{
        suffix: '-small'
        maxHeight: 320
        maxWidth: 320
      }]

    origins = process.env.ALLOW_ORIGINS?.split(',') or []

    app.all '/upload', (req, res, next) ->
      res.once 'close', -> sentry.captureResClose res

      if not req.get('Origin') or not (req.get('Origin') in origins)
        error = new Error "Bad Origin Header #{req.get('Origin')}"
        error.status = 403
        return next error

      res.set 'Access-Control-Allow-Origin', req.get('Origin')
      res.set 'Access-Control-Allow-Methods', 'POST'
      res.set 'Access-Control-Allow-Headers', 'X-Requested-With, Content-Type'
      res.set 'Access-Control-Expose-Headers', 'X-Response-Time'
      res.set 'Access-Control-Allow-Max-Age', 0

      return res.send 200 if req.method is 'OPTIONS'
      return next()

    app.post '/upload', multer(dest: require('os').tmpdir()), (req, res, next) ->
      console.log "Recieved #{Object.keys(req.files).length} files"

      async.mapSeries Object.keys(req.files), (key, cb) ->
        if req.files[key].extension not in ['jpg', 'jpeg', 'png', 'gif', 'tiff']
          error = new Error "Invalid Image #{req.files[key].extension}"
          error.status = 422
          return cb error

        s3.upload req.files[key].path, {}, (err, images, meta) ->
          return cb err if err

          if meta.exif['exif:GPSLatitude'] and meta.exif['exif:GPSLongitude']
            meta.geojson =
              type: 'Point'
              coordinates: dms2dec \
                meta.exif['exif:GPSLatitude'], \
                meta.exif['exif:GPSLatitudeRef'], \
                meta.exif['exif:GPSLongitude'], \
                meta.exif['exif:GPSLongitudeRef']
              .reverse()

          return cb null, versions: images.splice(1), meta: meta
      , (err, files) ->
        return next err if err
        sentry.captureHeaderSent req, files if res._headerSent
        return res.status(201).json files

    app.use (req, res, next) ->
      res.status(404).json message: 'Not Found'

    app.use raven.middleware.express sentry
    app.use (err, req, res, next) ->
      if not err.status or err.status >= 500
        sentry.captureError err

        console.error err.message
        console.error err.stack

        res.status(err.status or 500).json message: 'Internal Server Error'
      else
        sentry.captureMessage err.message, level: 'warning', req: req
        res.status(err.status).json message: err.message

    if not module.parent
      app.listen process.env.PORT_WWW
      console.log "Server listening on port #{process.env.PORT_WWW}"
    else
      module.exports = app


fix(document): prevent mixed include/exclude projection error

Mongo.DB does not handle including and excluding fields
simultaneously.

    schema   = require './helper/schema'
    sentry   = require './db/sentry'
    Document = require './model/Document'

    JSONStream = require 'JSONStream'

## param()

    exports.param = (req, res, next, id) ->
      return res.status(400).json message: 'Invalid ObjectId' if not /^[a-f0-9]{24}$/.test id

      req.doc = new Document(req.type, id).once('error', next).once 'ready', ->
        req.isOwner = @exists() and req.user.tilbyder is @get 'tilbyder'

        if not @exists() or (@get('status') isnt 'Offentlig' and not req.isOwner)
          return res.status(404).json message: 'Not Found' if req.method isnt 'HEAD'
          return res.status(404).end()

        next()

## all()

    exports.all = (req, res, next) ->
      res.set 'X-Cache-Hit', req.doc.wasCacheHit()
      res.set 'ETag', "\"#{req.doc.get 'checksum'}\""
      res.set 'Last-Modified', new Date(req.doc.get 'endret').toUTCString()

      if req.method not in ['GET', 'HEAD'] and not req.isOwner
        return res.status(403).json message: 'Request Denied'

      if req.get 'If-Match'
        return res.status(412).end() if req.doc.isNoneMatch req.get 'If-Match'

      else if req.get 'If-None-Match'
        return res.status(304).end() if req.doc.isMatch req.get 'If-None-Match'

      else
        if req.doc.isNotModifiedSince req.get 'If-Modified-Since'
          return res.status(304).end()

        if req.doc.isModifiedSince req.get 'If-Unmodified-Since'
          return res.status(412).end()

      next()

## HEAD and GET

```http
HEAD /{type}/{id}
GET /{type}/{id}
```

    exports.head = exports.get = (req, res, next) ->
      return res.sendStatus 200 if req.method is 'HEAD'

      opts =
        query: $or: [{status: 'Offentlig'}, {tilbyder: req.user.tilbyder}]
        fields: {}

### Fields Projection

```none
&fields=field1[,field2[,..]]
```

Private (`privat.`) fields are hidden unless the current API user is the owner
of the document. This is to prevent unauthorized information disclosure.

      opts.fields.privat = false if not req.isOwner

If you only want some of the document properties returned you can use the
`fields` query parameter to control the projection of document properties.
Multiple fields must be comma separated without any additional spacing.

This projection also applies to expanded sub-documents when using the `&expand=`
query parameter below.

      if req.query?.fields
        opts.fields[field] = true for field in req.query.fields.split ','
        delete opts.fields.privat if not req.isOwner

The list of default fields below will always be returned for compliance reasons.

        opts.fields = Object.assign opts.fields,
          endret: true
          lisens: true
          status: true
          navn  : true
          tilbyder  : true
          navngiving: true

### Sub-document Expansion

```none
&expand=field1[,field2[..]]
```

Sub-document expansion is an easy and convenient way to get connected documents
such as `grupper`, `bilder`, and `områder` as their full objects instead of a
list of `ObjectIDs`. It works by setting the `expand` query parameter to the
fields to expand.

**Rate limit**

Sub-document expansion will decrease your remaining API rate limit with `1` per
collection expanded in addition to the request itself. Thus, if you request a
document (1) with two collection expanded (2) your remaining API rate limit will
be decremented with 3. This is to encurrage resonable expansion of relevant
collections only.

**Order and limit**

Sub-document expansion will return at most 10 first sub-documents for each
collection expanded and out of order. Only sub-documents avaiable to the current
API user will be return as sub-documents my not be published or may have been
deleted.

      if req.query?.expand
        opts.expand = req.query.expand.split ','

### Sub-document Limit

```none
&limit={n}
```

If you wisth to return less sub-documents in order to increase response time and
body size you may do so by using the `limit` query parameter. This will affect
all sub-documents expanded by the `expand` query parameter.

      if req.query?.limit and parseInt req.query.limit, 10
        opts.limit = parseInt req.query.limit, 10

---

      req.doc.getExpanded opts, (err, doc) ->
        return next err if err
        res.json doc

## PUT and PATCH

```http
PUT /{type}/{id}
PATCH /{type}/{id}
```

    exports.patch = exports.put = (req, res, next) ->
      return res.status(400).json message: 'Body is missing' if Object.keys(req.body).length is 0
      return res.status(400).json message: 'Body should be a JSON Hash' if req.body instanceof Array

      req.body.tilbyder = req.user.tilbyder

      method = (if req.method is 'PUT' then 'replace' else 'update')
      req.doc[method] req.body, (err, warn, data) ->
        if err
          return next(err) if err.name isnt 'ValidationError'

          sentry.captureDocumentError req, err

          return res.status(422).json
            document: req.body
            message: 'Validation Failed'
            errors: err.details #TODO(starefossen) document this

        res.set 'ETag', "\"#{data.checksum}\""
        res.set 'Last-Modified', new Date(data.endret).toUTCString()

        return res.status(200).json
          document: data
          message: 'Validation Warnings' if warn.length > 0
          warnings: warn if warn.length > 0

## DELETE

```http
DELETE /{type}/{id}
```

    exports.delete = (req, res, next) ->
      req.doc.delete (err) ->
        return next err if err
        return res.sendStatus 204

    schema   = require './helper/schema'
    sentry   = require './db/sentry'
    Document = require './model/Document'

    JSONStream = require 'JSONStream'

## param()

    exports.param = (req, res, next, id) ->
      return res.status(400).json message: 'Invalid ObjectId' if not /^[a-f0-9]{24}$/.test id

      req.doc = new Document(req.type, id).once('error', next).once 'ready', ->
        req.isOwner = @exists() and req.user.tilbyder is @get 'tilbyder'

        if not @exists() or (@get('status') isnt 'Offentlig' and not req.isOwner)
          return res.status(404).json message: 'Not Found' if req.method isnt 'HEAD'
          return res.status(404).end()

        next()

## all()

    exports.all = (req, res, next) ->
      res.set 'X-Cache-Hit', req.doc.wasCacheHit()
      res.set 'ETag', "\"#{req.doc.get 'checksum'}\""
      res.set 'Last-Modified', new Date(req.doc.get 'endret').toUTCString()

      if req.method not in ['GET', 'HEAD'] and not req.isOwner
        return res.status(403).json message: 'Request Denied'

      if req.get 'If-Match'
        return res.status(412).end() if req.doc.isNoneMatch req.get 'If-Match'

      else if req.get 'If-None-Match'
        return res.status(304).end() if req.doc.isMatch req.get 'If-None-Match'

      else
        if req.doc.isNotModifiedSince req.get 'If-Modified-Since'
          return res.status(304).end()

        if req.doc.isModifiedSince req.get 'If-Unmodified-Since'
          return res.status(412).end()

      next()

## HEAD and GET

```http
HEAD /{type}/{id}
GET /{type}/{id}
```

    exports.head = exports.get = (req, res, next) ->
      return res.sendStatus 200 if req.method is 'HEAD'

      opts =
        query: $or: [{status: 'Offentlig'}, {tilbyder: req.user.tilbyder}]
        fields: {}

### Fields Projection

```none
&fields=field1[,field2[,..]]
```

Private (`privat.`) fields are hidden unless the current API user is the owner
of the document. This is to prevent unauthorized information disclosure.

      opts.fields.privat = false if not req.isOwner

If you only want some of the document properties returned you can use the
`fields` query parameter to control the projection of document properties.
Multiple fields must be comma separated without any additional spacing.

This projection also applies to expanded sub-documents when using the `&expand=`
query parameter below.

      if req.query?.fields
        opts.fields[field] = true for field in req.query.fields.split ','
        opts.fields.privat = false if not req.isOwner

The list of default fields below will always be returned for compliance reasons.

        opts.fields = Object.assign opts.fields,
          endret: true
          lisens: true
          status: true
          navn  : true
          tilbyder  : true
          navngiving: true

### Sub-document Expansion

```none
&expand=field1[,field2[..]]
```

Sub-document expansion is an easy and convenient way to get connected documents
such as `grupper`, `bilder`, and `områder` as their full objects instead of a
list of `ObjectIDs`. It works by setting the `expand` query parameter to the
fields to expand.

**Rate limit**

Sub-document expansion will decrease your remaining API rate limit with `1` per
collection expanded in addition to the request itself. Thus, if you request a
document (1) with two collection expanded (2) your remaining API rate limit will
be decremented with 3. This is to encurrage resonable expansion of relevant
collections only.

**Order and limit**

Sub-document expansion will return at most 10 first sub-documents for each
collection expanded and out of order. Only sub-documents avaiable to the current
API user will be return as sub-documents my not be published or may have been
deleted.

      if req.query?.expand
        opts.expand = req.query.expand.split ','

### Sub-document Limit

```none
&limit={n}
```

If you wisth to return less sub-documents in order to increase response time and
body size you may do so by using the `limit` query parameter. This will affect
all sub-documents expanded by the `expand` query parameter.

      if req.query?.limit and parseInt req.query.limit, 10
        opts.limit = parseInt req.query.limit, 10

---

      req.doc.getExpanded opts, (err, doc) ->
        return next err if err
        res.json doc

## PUT and PATCH

```http
PUT /{type}/{id}
PATCH /{type}/{id}
```

    exports.patch = exports.put = (req, res, next) ->
      return res.status(400).json message: 'Body is missing' if Object.keys(req.body).length is 0
      return res.status(400).json message: 'Body should be a JSON Hash' if req.body instanceof Array

      req.body.tilbyder = req.user.tilbyder

      method = (if req.method is 'PUT' then 'replace' else 'update')
      req.doc[method] req.body, (err, warn, data) ->
        if err
          return next(err) if err.name isnt 'ValidationError'

          sentry.captureDocumentError req, err

          return res.status(422).json
            document: req.body
            message: 'Validation Failed'
            errors: err.details #TODO(starefossen) document this

        res.set 'ETag', "\"#{data.checksum}\""
        res.set 'Last-Modified', new Date(data.endret).toUTCString()

        return res.status(200).json
          document: data
          message: 'Validation Warnings' if warn.length > 0
          warnings: warn if warn.length > 0

## DELETE

```http
DELETE /{type}/{id}
```

    exports.delete = (req, res, next) ->
      req.doc.delete (err) ->
        return next err if err
        return res.sendStatus 204