help function call bug fix

help function call bug fix

List of SVG elements

    Tags =
     svg: 'a altGlyph altGlyphDef altGlyphItem animate animateColor
      animateMotion animateTransform circle clipPath color-profile cursor
      defs desc ellipse feBlend feColorMatrix feComponentTransfer
      feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap
      feDistantLight feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur
      feImage feMerge feMergeNode feMorphology feOffset fePointLight
      feSpecularLighting feSpotLight feTile feTurbulence
      filter font font-face font-face-format font-face-name font-face-src
      font-face-uri foreignObject g glyph glyphRef hkern image line
      linearGradient marker mask metadata missing-glyph mpath path pattern
      polygon polyline radialGradient rect script set stop style svg symbol
      text textPath title tref tspan use view vkern switch foreignObject'

List of HTML elements

     html: 'a abbr address article aside audio b bdi bdo blockquote body button
      canvas caption cite code colgroup datalist dd del details dfn div dl dt
      em fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header
      hgroup html i iframe ins kbd label legend li main map mark menu meter
      nav noscript object ol optgroup option output p pre progress q rp rt
      ruby s samp script section select small span strong style sub summary
      sup table tbody td textarea tfoot th thead time title tr u ul video'

     htmlVoid: 'area base br col command embed hr img input keygen link meta
      param source track wbr'

Wrapper for browser API

    Api =
     document: @document

Parse id and class string

    parseIdClass = (str) ->
     res =
      id: null
      class: []

     for c, i in str.split "."
      if c.indexOf("#") is 0
       res.id = c.substr 1
      else if c isnt ""
       if not res.class?
        res.class = [c]
       else
        res.class.push c

     return res

    getParameters = (args) ->
     params =
      idClass: null
      text: null
      attrs: null
      func: null

     for arg, i in args
      switch typeof arg
       when 'function' then params.func = arg
       when 'object' then params.attrs = arg
       when 'string'
        if args.length is 1
         params.text = arg
        else
         c = arg.charAt 0

         if i is 0 and (c is '#' or c is '.')
          params.idClass = parseIdClass arg
         else
          params.text = arg

     return params

#Weya DOM

    weyaDomCreate = ->

Weya object to be passed as `this`

     weya =
      _elem: null

Manipulating dom objects

     setStyles = (elem, styles) ->
      for k, v of styles
       if v?
        elem.style.setProperty k, v
       else
        elem.style.removeProperty k

     setEvents = (elem, events) ->
      for k, v of events
       elem.addEventListener k, v, false

     setAttributes = (elem, attrs) ->
      for k, v of attrs
       switch k
        when 'style' then setStyles elem, v
        when 'on' then setEvents elem, v
        else
         if v?
          elem.setAttribute k, v
         else
          elem.removeAttribute k

     setIdClass = (elem, idClass) ->
      if idClass.id?
       elem.id = idClass.id

      if idClass.class?
       if elem.classList?
        for c in idClass.class
         elem.classList.add c
       else #For older browsers; does not work with svgs
        className = ''
        for c in idClass.class
         className += ' ' if className isnt ''
         className += "#{c}"
        elem.className = className

Append a child element

     append = (ns, name, args) ->
      params = getParameters args

Keep a reference to parent element

      pElem = @_elem

Keep a reference of `elem` to return at the end of the function

      if ns?
       elem = @_elem = Api.document.createElementNS ns, name
      else
       elem = @_elem = Api.document.createElement name

      if params.idClass?
       setIdClass elem, params.idClass

      if params.attrs?
       setAttributes elem, params.attrs

      if pElem?
       pElem.appendChild elem

      if params.func?
       params.func.call this
      else if params.text?
       elem.textContent = params.text

      @_elem = pElem
      return elem

Wrap `append`

     wrapAppend = (ns, name) ->
      ->
       append.call this, ns, name, arguments

Initialize

     for name in Tags.svg.split ' '
      weya[name] = wrapAppend "http://www.w3.org/2000/svg", name

     for name in Tags.html.split ' '
      weya[name] = wrapAppend "http://www.w3.org/1999/xhtml", name

     for name in Tags.htmlVoid.split ' '
      weya[name] = wrapAppend null, name

     return weya

#Weya Markup

    weyaMarkupCreate = ->

Weya object to be passed as `this`

     weya =
      _buf: null
      _indent: 0

Render components

     setStyles = (buf, styles) ->
      buf.push " style=\""
      for k, v of styles
       buf.push "#{k}:#{v};"
      buf.push "\""

     setEvents = (buf, events) ->
      for k, v of events
       buf.push " on#{k}=\"#{v}\""

     setAttributes = (buf, attrs) ->
      for k, v of attrs
       switch k
        when 'style' then setStyles buf, v
        when 'on' then setEvents buf, v
        else
         buf.push " #{k}=\"#{v}\""

     setIndent = (buf, indent) ->
      for i in [0...indent]
       buf.push " "

Append a child element

     append = (ns, name, args) ->
      params = getParameters args

      buf = @_buf

      setIndent buf, @_indent

      buf.push "<#{name}"

      if params.idClass?
       if params.idClass.id?
        buf.push " id=\"#{params.idClass.id}\""
       if params.idClass.class?
        buf.push " class=\"#{params.idClass.class}\""

      if params.attrs?
       setAttributes buf, params.attrs

Can close void elements (element that self close) with a `/>`

      buf.push ">\n"
      @_indent++

      if params.func?
       params.func.call this
      else if params.text?
       setIndent buf, @_indent
       buf.push params.text
       buf.push "\n"

      @_indent--
      setIndent buf, @_indent
      buf.push "</#{name}>\n"

Wrap `append`

     wrapAppend = (ns, name) ->
      ->
       append.call this, ns, name, arguments

Initialize

     for name in Tags.svg.split ' '
      weya[name] = wrapAppend "http://www.w3.org/2000/svg", name

     for name in Tags.html.split ' '
      weya[name] = wrapAppend null, name

     for name in Tags.htmlVoid.split ' '
      weya[name] = wrapAppend null, name

     return weya

#Weya API

    weyaDom = weyaDomCreate()
    weyaMarkup = weyaMarkupCreate()

Create and append to `options.elem`. If `options.context` is provied it can be
accessed via `@$`. If `options.elem` is `null`, the element is created but
not appended.

    @Weya = Weya = (options, func) ->
     weya = weyaDom
     pContext = weya.$
     weya.$ = options.context
     pElem = weya._elem
     weya._elem = options.elem
     r = func?.call weya
     weya._elem = pElem
     weya.$ = pContext
     return r

    Weya.markup = (options, func) ->
     weya = weyaMarkup
     pContext = weya.$
     weya.$ = options.context
     added = []
     setFunc = (name, f) ->
      weya[name] = ->
       f.apply weya, arguments
     if options.helpers?
      for name, f of options.helpers
       if not weya[name]?
        added.push name
        setFunc name, f
     pBuf = weya._buf
     weya._buf = []
     r = func?.call weya
     buf = weya._buf
     weya._buf = pBuf
     weya.$ = pContext
     for name in added
      weya[name] = null
     return buf.join ''

    Weya.setApi = (api) ->
     for k, v of api
      Api[k] = v

    if module?
     module.exports = Weya

List of SVG elements

    Tags =
     svg: 'a altGlyph altGlyphDef altGlyphItem animate animateColor
      animateMotion animateTransform circle clipPath color-profile cursor
      defs desc ellipse feBlend feColorMatrix feComponentTransfer
      feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap
      feDistantLight feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur
      feImage feMerge feMergeNode feMorphology feOffset fePointLight
      feSpecularLighting feSpotLight feTile feTurbulence
      filter font font-face font-face-format font-face-name font-face-src
      font-face-uri foreignObject g glyph glyphRef hkern image line
      linearGradient marker mask metadata missing-glyph mpath path pattern
      polygon polyline radialGradient rect script set stop style svg symbol
      text textPath title tref tspan use view vkern switch foreignObject'

List of HTML elements

     html: 'a abbr address article aside audio b bdi bdo blockquote body button
      canvas caption cite code colgroup datalist dd del details dfn div dl dt
      em fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header
      hgroup html i iframe ins kbd label legend li main map mark menu meter
      nav noscript object ol optgroup option output p pre progress q rp rt
      ruby s samp script section select small span strong style sub summary
      sup table tbody td textarea tfoot th thead time title tr u ul video'

     htmlVoid: 'area base br col command embed hr img input keygen link meta
      param source track wbr'

Wrapper for browser API

    Api =
     document: @document

Parse id and class string

    parseIdClass = (str) ->
     res =
      id: null
      class: []

     for c, i in str.split "."
      if c.indexOf("#") is 0
       res.id = c.substr 1
      else if c isnt ""
       if not res.class?
        res.class = [c]
       else
        res.class.push c

     return res

    getParameters = (args) ->
     params =
      idClass: null
      text: null
      attrs: null
      func: null

     for arg, i in args
      switch typeof arg
       when 'function' then params.func = arg
       when 'object' then params.attrs = arg
       when 'string'
        if args.length is 1
         params.text = arg
        else
         c = arg.charAt 0

         if i is 0 and (c is '#' or c is '.')
          params.idClass = parseIdClass arg
         else
          params.text = arg

     return params

#Weya DOM

    weyaDomCreate = ->

Weya object to be passed as `this`

     weya =
      _elem: null

Manipulating dom objects

     setStyles = (elem, styles) ->
      for k, v of styles
       if v?
        elem.style.setProperty k, v
       else
        elem.style.removeProperty k

     setEvents = (elem, events) ->
      for k, v of events
       elem.addEventListener k, v, false

     setAttributes = (elem, attrs) ->
      for k, v of attrs
       switch k
        when 'style' then setStyles elem, v
        when 'on' then setEvents elem, v
        else
         if v?
          elem.setAttribute k, v
         else
          elem.removeAttribute k

     setIdClass = (elem, idClass) ->
      if idClass.id?
       elem.id = idClass.id

      if idClass.class?
       if elem.classList?
        for c in idClass.class
         elem.classList.add c
       else #For older browsers; does not work with svgs
        className = ''
        for c in idClass.class
         className += ' ' if className isnt ''
         className += "#{c}"
        elem.className = className

Append a child element

     append = (ns, name, args) ->
      params = getParameters args

Keep a reference to parent element

      pElem = @_elem

Keep a reference of `elem` to return at the end of the function

      if ns?
       elem = @_elem = Api.document.createElementNS ns, name
      else
       elem = @_elem = Api.document.createElement name

      if params.idClass?
       setIdClass elem, params.idClass

      if params.attrs?
       setAttributes elem, params.attrs

      if pElem?
       pElem.appendChild elem

      if params.func?
       params.func.call this
      else if params.text?
       elem.textContent = params.text

      @_elem = pElem
      return elem

Wrap `append`

     wrapAppend = (ns, name) ->
      ->
       append.call this, ns, name, arguments

Initialize

     for name in Tags.svg.split ' '
      weya[name] = wrapAppend "http://www.w3.org/2000/svg", name

     for name in Tags.html.split ' '
      weya[name] = wrapAppend "http://www.w3.org/1999/xhtml", name

     for name in Tags.htmlVoid.split ' '
      weya[name] = wrapAppend null, name

     return weya

#Weya Markup

    weyaMarkupCreate = ->

Weya object to be passed as `this`

     weya =
      _buf: null
      _indent: 0

Render components

     setStyles = (buf, styles) ->
      buf.push " style=\""
      for k, v of styles
       buf.push "#{k}:#{v};"
      buf.push "\""

     setEvents = (buf, events) ->
      for k, v of events
       buf.push " on#{k}=\"#{v}\""

     setAttributes = (buf, attrs) ->
      for k, v of attrs
       switch k
        when 'style' then setStyles buf, v
        when 'on' then setEvents buf, v
        else
         buf.push " #{k}=\"#{v}\""

     setIndent = (buf, indent) ->
      for i in [0...indent]
       buf.push " "

Append a child element

     append = (ns, name, args) ->
      params = getParameters args

      buf = @_buf

      setIndent buf, @_indent

      buf.push "<#{name}"

      if params.idClass?
       if params.idClass.id?
        buf.push " id=\"#{params.idClass.id}\""
       if params.idClass.class?
        buf.push " class=\"#{params.idClass.class}\""

      if params.attrs?
       setAttributes buf, params.attrs

Can close void elements (element that self close) with a `/>`

      buf.push ">\n"
      @_indent++

      if params.func?
       params.func.call this
      else if params.text?
       setIndent buf, @_indent
       buf.push params.text
       buf.push "\n"

      @_indent--
      setIndent buf, @_indent
      buf.push "</#{name}>\n"

Wrap `append`

     wrapAppend = (ns, name) ->
      ->
       append.call this, ns, name, arguments

Initialize

     for name in Tags.svg.split ' '
      weya[name] = wrapAppend "http://www.w3.org/2000/svg", name

     for name in Tags.html.split ' '
      weya[name] = wrapAppend null, name

     for name in Tags.htmlVoid.split ' '
      weya[name] = wrapAppend null, name

     return weya

#Weya API

    weyaDom = weyaDomCreate()
    weyaMarkup = weyaMarkupCreate()

Create and append to `options.elem`. If `options.context` is provied it can be
accessed via `@$`. If `options.elem` is `null`, the element is created but
not appended.

    @Weya = Weya = (options, func) ->
     weya = weyaDom
     pContext = weya.$
     weya.$ = options.context
     pElem = weya._elem
     weya._elem = options.elem
     r = func?.call weya
     weya._elem = pElem
     weya.$ = pContext
     return r

    Weya.markup = (options, func) ->
     weya = weyaMarkup
     pContext = weya.$
     weya.$ = options.context
     added = []
     if options.helpers?
      for name, f of options.helpers
       if not weya[name]?
        added.push name
        weya[name] = ->
         f.apply weya, arguments
     pBuf = weya._buf
     weya._buf = []
     r = func?.call weya
     buf = weya._buf
     weya._buf = pBuf
     weya.$ = pContext
     for name in added
      weya[name] = null
     return buf.join ''

    Weya.setApi = (api) ->
     for k, v of api
      Api[k] = v

    if module?
     module.exports = Weya


Update crypto.litcoffee

Update crypto.litcoffee

Methods that use the node crypto API

dependencies

    crypto = require('crypto')

@.**add_Random_Chars** size

    String::add_Random_Chars = (size )->
      @ + crypto.randomBytes(size || 10)

@.**add_Random_String** size

    String::add_Random_String = (size )->
      @ + crypto.randomBytes(size || 10).toString('hex').slice(0,size|| 10)

@.**add_Random_Letters** size

    String::add_Random_Letters   = (size )->
      charSet = 'abcdefghijklmnopqrstuvwxyz'
      @ + (charSet[Math.floor(Math.random() * charSet.length)]  for i in [1..size]).join('')

@.**add_5_Random_Letters**

Adds 5 random letters to ```@```

twin methods: add_5_Letters

    String::add_5_Random_Letters = ()->
      @.add_Random_Letters(5)

    String::add_5_Letters = String::add_5_Random_Letters

@.**add_Random_Numbers** size

    String::add_Random_Numbers = (size)->
      charSet = '0123456789'
      @ + (charSet[Math.floor(Math.random() * charSet.length)]  for i in [1..size]).join('')

@.**checksum** [algorithm], [encoding]

Returns a checksum for @

Defaults to ```md5``` algorithm and ```hex``` encoding

    String::checksum = (algorithm, encoding)->
      crypto.createHash(algorithm || 'md5')
            .update(@.toString(), 'utf8')
            .digest(encoding || 'hex')

@.**random_String** ()

Returns a random string of size @ made of ascii chars

    Number::random_String = ->
      "".add_Random_String(@ + 0)

@.**random_Letters** ()

Returns a random string of size @ made of only letters

    Number::random_Letters = ->
      "".add_Random_Letters(@ + 0)

Methods that use the node crypto API

dependencies

    crypto = require('crypto')

@.**add_Random_Chars** size

    String::add_Random_Chars = (size )->
      @ + crypto.randomBytes(size || 10)

@.**add_Random_String** size

    String::add_Random_String = (size )->
      @ + crypto.randomBytes(size || 10).toString('hex').slice(0,size|| 10)

@.**add_Random_Letters** size

    String::add_Random_Letters   = (size )->
      charSet = 'abcdefghijklmnopqrstuvwxyz'
      @ + (charSet[Math.floor(Math.random() * charSet.length)]  for i in [1..size]).join('')

@.**add_5_Random_Letters**

Adds 5 random letters to ```@```

twin methods: add_5_Letters

    String::add_5_Random_Letters = ()->
      @.add_Random_Letters(5)

    String::add_5_Letters = String::add_5_Random_Letters

@.**add_Random_Numbers** size

    String::add_Random_Numbers = (size)->
      charSet = '0123456789'
      @ + (charSet[Math.floor(Math.random() * charSet.length)]  for i in [1..size]).join('')

@.**random_String** ()

Returns a random string of size @ made of ascii chars

    Number::random_String = ->
      "".add_Random_String(@ + 0)

@.**random_Letters** ()

Returns a random string of size @ made of only letters

    Number::random_Letters = ->
      "".add_Random_Letters(@ + 0)


Fixed typos

Fixed typos


feat(document): increase limit for expand

    ObjectID  = require('mongodb').ObjectID

Import event emitter stuff.

    EventEmitter = require('events').EventEmitter
    inherits = require('util').inherits

Import data storage modules.

    mongo   = require '@turbasen/db-mongo'
    redis   = require '@turbasen/db-redis'

    parse   = require '../helper/parse'
    cache   = require '../helper/cache'

    collections = require('../helper/schema').types

---

## Class: Doc

### new Doc(type, id)

* **string** `type` - document type (collection name)
* **string** `id` - document id

---

    module.exports = Doc = (type, id) ->
      throw new Error('Missing Doc type param') if not type

      if typeof id isnt 'string' and id isnt null
        throw new Error('Missing or invalid ID param')

      EventEmitter.call this

### doc.db

MongoDB collection instance where the document is stored.

      @db   = mongo[type]

### doc.id

Unique `ObjectID` for the document. Access through `doc.getId()`.

      @id   = if typeof id is 'string' then new ObjectID(id) else null

### doc.type

Document collection name (object type).

      @type = type

### doc.data

Cached document data from Redis. This gets poppulated automaticly when the
a new document is instanciated.

      @data = {}

### doc.chit

Cache hit indicator. Accessed through `doc.wasCacheHit()`.

      @chit = false

---

      if @id
        redis.hgetall "#{@type}:#{@id.toString()}", (err, data) =>
          return @emit 'error', err if err

          if Object.keys(data).length
            @data = cache.arrayify @type, data
            @chit = true
            return @emit 'ready'

          @db.findOne _id: @id, cache.getFilter(@type), (err, data) =>
            return @emit 'error', err if err

            @data = data or status: 'Slettet'
            redis.hmset "#{@type}:#{@id}", @data, (err) =>
              return @emit 'ready'
      else
        process.nextTick => @emit 'ready'

      return this

    inherits Doc, EventEmitter

### doc.exists()

Check if document exists. Returns `true` if document exists; otherwise `false`.

---

    Doc.prototype.exists = ->
      return @data.status? and @data.status isnt 'Slettet'

### doc.getId()

Get the unique id for current document. Returns an `ObjectID` if the document
exists; otherwise `null`.

---

    Doc.prototype.getId = ->
      @id

### doc.wasCacheHit()

Check if document request was a cache hit. Returns `true` if document request
was a cache hit; otherwise `false`.

---

    Doc.prototype.wasCacheHit = ->
      @chit

### doc.isNotModifiedSince(time)

* **string** `time` - timestamp to check against.

Check if document has not been modified since a given timestamp. Returns `true`
if document has not been modified since given timestamp; otherwise `false`.

---

    Doc.prototype.isModifiedSince = (time) -> @modifiedSince time, false
    Doc.prototype.isNotModifiedSince = (time) -> @modifiedSince time, true

    Doc.prototype.modifiedSince = (time, negate) ->
      return false if not time or not @data.endret

      if not isNaN time
        # Make UNIX timestamp into milliseconds
        time = time + '000' if (time + '').length is 10
        time = parseInt time

      org = new Date(@data.endret)
      chk = new Date(time)

      # HTTP-date's don't have milliseconds
      org.setMilliseconds(0)

      return false if chk.toString() is 'Invalid Date'

      return chk >= org if negate
      return chk <  org

### doc.isMatch(checksum)

* **string** `checksum` - checksum to check against.

Check if checksum, or Etag, matches current document checksum. Returns `true`
if checksum matches the current checksum; otherwise `false`.

---

    Doc.prototype.isMatch = (checksum) ->
      return false if not checksum or not @data.checksum
      return (checksum is "\"#{@data.checksum}\"" or checksum is '*')

### doc.isNoneMatch(checksum)

* **string** `checksum` - checksum to check against.

Check if checksum, or Etag, doesn't match current document checksum. Return
`true` if checksum does not match or document has no checksum; otherwise
`false`.

---

    Doc.prototype.isNoneMatch = (checksum) ->
      return false if not checksum
      return true if not @data.checksum
      return checksum isnt "\"#{@data.checksum}\""

### doc.get([key])

* **string** `key` - get specific object property

Get cached data for the current document. Returns an `object` if `key` is
`undefined`; otherwise `string`. Will return `undefined` if the given key does
not exist.

---

    Doc.prototype.get = (key) ->
      return @data if not key
      return @data[key]

### doc.getFull(filter[, cb])

* **object** `filter` - control which object properties are returned
* **function** `cb` - callback function (**Error** `err`, **object** `data`)

Get the full document data from the database asynchronously. Returns a cursor
stream if `cb` is undefined.

---

    Doc.prototype.getFull = (filter, cb) ->
      if not cb
        throw new Error('Document doesnt exists') if not @exists()
        return @db.find _id: @id, filter, limit: 1
      else
        return cb new Error('Document doesnt exists') if not @exists()
        @db.findOne _id: @id, filter, cb

### doc.getExpanded(opts, cb)

* **object** `opts`
  * **object** `filter` - document & sub-document projection (**default** `{}`)
  * **number** `limit` - sub-document max expanded (**default** `10`)
  * **array** `expand` - sub-document collections to expand (**default** `[]`)
  * **object** `query` - sub-document select query (**default** `{}`)
* **function** `cb` - callback function (**Error** `err`, **object** `data`)

Get the full document with expanded sub-documents from the database
asynchronously. To expand a given collection jsut pass the collection name to
the `expand` parameter and it will be merged with the document data.

---

    Doc.prototype.getExpanded = (opts, cb) ->
      return cb new Error('Document doesnt exists') if not @exists()

      docFields = opts.fields or {}
      subFields = Object.assign {}, docFields

Prevent private fields from being included in sub-documents to prevent
unauthorized information disclosure.

      if Object.keys(subFields).length > 0
        delete subFields.privat

      if Object.keys(subFields).length is 0
        subFields.privat = false

      limit = Math.min opts.limit or 20, 50
      query = opts.query or {}

      count = 0
      mapped = {}

Since `expand` might be a user supplied input parameter we need to limit it to
properties which are expandable (`collections`). We also remove properties which
holds no value for this document.

      expand = (opts.expand or [])
        .filter (v) => @data[v] and v in collections

Next we map the string array into an object array on the following format:
`{ type: String, ids: Array }` where `ids` are ObjectIDs to an document of the
collection `type`.

        .map (v) => type: v, ids: @data[v].slice(0, limit).map (d) -> new ObjectID d

Set up a `final` function which is called when expanded data is ready to be
mapped to the original document.

      final = () =>
        @db.findOne _id: @id, docFields, (err, doc) ->
          cb err, Object.assign doc or {}, mapped

If there are no fields to expand, we just call the `final` function instantly
and no fields will get expanded.

      return final() if expand.length is 0

Set up a `next` function which is called for each expanded data returned from
the database. Expanded data is stored in the `mapped` object which is merged
with the main document in `final`. When all expanded fields are mapped `final`
is called.

      next = (type, _, docs) ->
        mapped[type] = docs or []
        return final() if Object.keys(mapped).length == expand.length

Get the expanded sub-documents from the database.

      expand.forEach (x) ->
        mongo[x.type]

We find the sub-documents using the ObjectIDs in the expanded fields, that is
the easy part. The tricky part is to prevent information leakage of private
documents. This the second part is a `query` limiting the results to public
documents or those owned by the current API user.

          .find Object.assign { _id: $in: x.ids }, query

We reuse the projection fields from the original document, but since we do not
know in advanced who owns a given sub-document we remove the `private` property
to prevent information leakage.

          .project subFields

Bundle all the sub-documents in one array and pass it to the `next` function.

          .toArray next.bind null, x.type

### doc.insert(data, cb)

* **object** `data` - data to insert for document.
* **function** `cb` - callback function (**Error** `err`, **Array** `warn`,
**object** `data`).

Inserts a new document into database.

---

    Doc.prototype.insert = (data, cb) ->
      return cb new Error('Document already exists') if @exists()
      return cb new Error('Document is deleted') if @data.status is 'Slettet'

      parse.docInsert @type, data, (err, warn, data) =>
        return cb err if err

        @db.insertOne data, w: 1, (err) =>
          return cb err if err

          @id   = new ObjectID(data._id)
          @data = cache.filterData @type, data

          redis.hmset "#{@type}:#{@id.toString()}", @data

          cb err, warn, data

### doc.replace(data, cb)

* **object** `data` - replacement data for document.
* **function** `cb` - callback function (**Error** `err`, **Array** `warn`,
**object** `data`).

Replaces all document data in database.

---

    Doc.prototype.replace = (data, cb) ->
      return cb new Error('Document doesnt exists') if not @exists()

      parse.docReplace @type, data, (err, warn, data) =>
        return cb err if err

        @db.replaceOne _id: @id, data, w: 1, (err) =>
          return cb err if err

          @data = cache.filterData @type, data

          redis.del "#{@type}:#{@id.toString()}"
          redis.hmset "#{@type}:#{@id.toString()}", @data

          data._id = @id
          cb err, warn, data

### doc.update(data, cb)

* **object** `data` - replacement object for document.
* **function** `cb` - callback function (**Error** `err`, **Array** `warn`,
**object** `data`).

Partially update the document-data in database. This is some times referred to
as PATCH in a HTTP / REST context.

---

    Doc.prototype.update = (query, cb) ->
      return cb new Error('Document doesnt exists') if not @exists()

      parse.docPatch @type, query, (err, warn, query) =>
        return cb err if err

        @db.updateOne _id: @id, query, w: 1, (err) =>
          return cb err if err

          @getFull {}, (err, doc) =>
            @data = cache.filterData @type, doc

            redis.del "#{@type}:#{@id.toString()}"
            redis.hmset "#{@type}:#{@id.toString()}", @data

            cb err, warn, doc

### doc.delete(cb)

* **function** `cb` - callback function (**Error** `err`).

Delete a document from the database by removing all document properties and
setting the `status` property to `Slettet`.

---

    Doc.prototype.delete = (cb) ->
      return cb new Error('Document doesnt exists') if not @exists()

      @data = status: 'Slettet', endret: new Date()
      @db.replaceOne _id: @id, @data, w: 1, (err) =>
        return cb err if err

        redis.del "#{@type}:#{@id.toString()}"
        redis.hmset "#{@type}:#{@id.toString()}", @data

        cb null

    ObjectID  = require('mongodb').ObjectID

Import event emitter stuff.

    EventEmitter = require('events').EventEmitter
    inherits = require('util').inherits

Import data storage modules.

    mongo   = require '@turbasen/db-mongo'
    redis   = require '@turbasen/db-redis'

    parse   = require '../helper/parse'
    cache   = require '../helper/cache'

    collections = require('../helper/schema').types

---

## Class: Doc

### new Doc(type, id)

* **string** `type` - document type (collection name)
* **string** `id` - document id

---

    module.exports = Doc = (type, id) ->
      throw new Error('Missing Doc type param') if not type

      if typeof id isnt 'string' and id isnt null
        throw new Error('Missing or invalid ID param')

      EventEmitter.call this

### doc.db

MongoDB collection instance where the document is stored.

      @db   = mongo[type]

### doc.id

Unique `ObjectID` for the document. Access through `doc.getId()`.

      @id   = if typeof id is 'string' then new ObjectID(id) else null

### doc.type

Document collection name (object type).

      @type = type

### doc.data

Cached document data from Redis. This gets poppulated automaticly when the
a new document is instanciated.

      @data = {}

### doc.chit

Cache hit indicator. Accessed through `doc.wasCacheHit()`.

      @chit = false

---

      if @id
        redis.hgetall "#{@type}:#{@id.toString()}", (err, data) =>
          return @emit 'error', err if err

          if Object.keys(data).length
            @data = cache.arrayify @type, data
            @chit = true
            return @emit 'ready'

          @db.findOne _id: @id, cache.getFilter(@type), (err, data) =>
            return @emit 'error', err if err

            @data = data or status: 'Slettet'
            redis.hmset "#{@type}:#{@id}", @data, (err) =>
              return @emit 'ready'
      else
        process.nextTick => @emit 'ready'

      return this

    inherits Doc, EventEmitter

### doc.exists()

Check if document exists. Returns `true` if document exists; otherwise `false`.

---

    Doc.prototype.exists = ->
      return @data.status? and @data.status isnt 'Slettet'

### doc.getId()

Get the unique id for current document. Returns an `ObjectID` if the document
exists; otherwise `null`.

---

    Doc.prototype.getId = ->
      @id

### doc.wasCacheHit()

Check if document request was a cache hit. Returns `true` if document request
was a cache hit; otherwise `false`.

---

    Doc.prototype.wasCacheHit = ->
      @chit

### doc.isNotModifiedSince(time)

* **string** `time` - timestamp to check against.

Check if document has not been modified since a given timestamp. Returns `true`
if document has not been modified since given timestamp; otherwise `false`.

---

    Doc.prototype.isModifiedSince = (time) -> @modifiedSince time, false
    Doc.prototype.isNotModifiedSince = (time) -> @modifiedSince time, true

    Doc.prototype.modifiedSince = (time, negate) ->
      return false if not time or not @data.endret

      if not isNaN time
        # Make UNIX timestamp into milliseconds
        time = time + '000' if (time + '').length is 10
        time = parseInt time

      org = new Date(@data.endret)
      chk = new Date(time)

      # HTTP-date's don't have milliseconds
      org.setMilliseconds(0)

      return false if chk.toString() is 'Invalid Date'

      return chk >= org if negate
      return chk <  org

### doc.isMatch(checksum)

* **string** `checksum` - checksum to check against.

Check if checksum, or Etag, matches current document checksum. Returns `true`
if checksum matches the current checksum; otherwise `false`.

---

    Doc.prototype.isMatch = (checksum) ->
      return false if not checksum or not @data.checksum
      return (checksum is "\"#{@data.checksum}\"" or checksum is '*')

### doc.isNoneMatch(checksum)

* **string** `checksum` - checksum to check against.

Check if checksum, or Etag, doesn't match current document checksum. Return
`true` if checksum does not match or document has no checksum; otherwise
`false`.

---

    Doc.prototype.isNoneMatch = (checksum) ->
      return false if not checksum
      return true if not @data.checksum
      return checksum isnt "\"#{@data.checksum}\""

### doc.get([key])

* **string** `key` - get specific object property

Get cached data for the current document. Returns an `object` if `key` is
`undefined`; otherwise `string`. Will return `undefined` if the given key does
not exist.

---

    Doc.prototype.get = (key) ->
      return @data if not key
      return @data[key]

### doc.getFull(filter[, cb])

* **object** `filter` - control which object properties are returned
* **function** `cb` - callback function (**Error** `err`, **object** `data`)

Get the full document data from the database asynchronously. Returns a cursor
stream if `cb` is undefined.

---

    Doc.prototype.getFull = (filter, cb) ->
      if not cb
        throw new Error('Document doesnt exists') if not @exists()
        return @db.find _id: @id, filter, limit: 1
      else
        return cb new Error('Document doesnt exists') if not @exists()
        @db.findOne _id: @id, filter, cb

### doc.getExpanded(opts, cb)

* **object** `opts`
  * **object** `filter` - document & sub-document projection (**default** `{}`)
  * **number** `limit` - sub-document max expanded (**default** `10`)
  * **array** `expand` - sub-document collections to expand (**default** `[]`)
  * **object** `query` - sub-document select query (**default** `{}`)
* **function** `cb` - callback function (**Error** `err`, **object** `data`)

Get the full document with expanded sub-documents from the database
asynchronously. To expand a given collection jsut pass the collection name to
the `expand` parameter and it will be merged with the document data.

---

    Doc.prototype.getExpanded = (opts, cb) ->
      return cb new Error('Document doesnt exists') if not @exists()

      docFields = opts.fields or {}
      subFields = Object.assign {}, docFields

Prevent private fields from being included in sub-documents to prevent
unauthorized information disclosure.

      if Object.keys(subFields).length > 0
        delete subFields.privat

      if Object.keys(subFields).length is 0
        subFields.privat = false

      limit = Math.min opts.limit or 10, 10
      query = opts.query or {}

      count = 0
      mapped = {}

Since `expand` might be a user supplied input parameter we need to limit it to
properties which are expandable (`collections`). We also remove properties which
holds no value for this document.

      expand = (opts.expand or [])
        .filter (v) => @data[v] and v in collections

Next we map the string array into an object array on the following format:
`{ type: String, ids: Array }` where `ids` are ObjectIDs to an document of the
collection `type`.

        .map (v) => type: v, ids: @data[v].slice(0, limit).map (d) -> new ObjectID d

Set up a `final` function which is called when expanded data is ready to be
mapped to the original document.

      final = () =>
        @db.findOne _id: @id, docFields, (err, doc) ->
          cb err, Object.assign doc or {}, mapped

If there are no fields to expand, we just call the `final` function instantly
and no fields will get expanded.

      return final() if expand.length is 0

Set up a `next` function which is called for each expanded data returned from
the database. Expanded data is stored in the `mapped` object which is merged
with the main document in `final`. When all expanded fields are mapped `final`
is called.

      next = (type, _, docs) ->
        mapped[type] = docs or []
        return final() if Object.keys(mapped).length == expand.length

Get the expanded sub-documents from the database.

      expand.forEach (x) ->
        mongo[x.type]

We find the sub-documents using the ObjectIDs in the expanded fields, that is
the easy part. The tricky part is to prevent information leakage of private
documents. This the second part is a `query` limiting the results to public
documents or those owned by the current API user.

          .find Object.assign { _id: $in: x.ids }, query

We reuse the projection fields from the original document, but since we do not
know in advanced who owns a given sub-document we remove the `private` property
to prevent information leakage.

          .project subFields

Bundle all the sub-documents in one array and pass it to the `next` function.

          .toArray next.bind null, x.type

### doc.insert(data, cb)

* **object** `data` - data to insert for document.
* **function** `cb` - callback function (**Error** `err`, **Array** `warn`,
**object** `data`).

Inserts a new document into database.

---

    Doc.prototype.insert = (data, cb) ->
      return cb new Error('Document already exists') if @exists()
      return cb new Error('Document is deleted') if @data.status is 'Slettet'

      parse.docInsert @type, data, (err, warn, data) =>
        return cb err if err

        @db.insertOne data, w: 1, (err) =>
          return cb err if err

          @id   = new ObjectID(data._id)
          @data = cache.filterData @type, data

          redis.hmset "#{@type}:#{@id.toString()}", @data

          cb err, warn, data

### doc.replace(data, cb)

* **object** `data` - replacement data for document.
* **function** `cb` - callback function (**Error** `err`, **Array** `warn`,
**object** `data`).

Replaces all document data in database.

---

    Doc.prototype.replace = (data, cb) ->
      return cb new Error('Document doesnt exists') if not @exists()

      parse.docReplace @type, data, (err, warn, data) =>
        return cb err if err

        @db.replaceOne _id: @id, data, w: 1, (err) =>
          return cb err if err

          @data = cache.filterData @type, data

          redis.del "#{@type}:#{@id.toString()}"
          redis.hmset "#{@type}:#{@id.toString()}", @data

          data._id = @id
          cb err, warn, data

### doc.update(data, cb)

* **object** `data` - replacement object for document.
* **function** `cb` - callback function (**Error** `err`, **Array** `warn`,
**object** `data`).

Partially update the document-data in database. This is some times referred to
as PATCH in a HTTP / REST context.

---

    Doc.prototype.update = (query, cb) ->
      return cb new Error('Document doesnt exists') if not @exists()

      parse.docPatch @type, query, (err, warn, query) =>
        return cb err if err

        @db.updateOne _id: @id, query, w: 1, (err) =>
          return cb err if err

          @getFull {}, (err, doc) =>
            @data = cache.filterData @type, doc

            redis.del "#{@type}:#{@id.toString()}"
            redis.hmset "#{@type}:#{@id.toString()}", @data

            cb err, warn, doc

### doc.delete(cb)

* **function** `cb` - callback function (**Error** `err`).

Delete a document from the database by removing all document properties and
setting the `status` property to `Slettet`.

---

    Doc.prototype.delete = (cb) ->
      return cb new Error('Document doesnt exists') if not @exists()

      @data = status: 'Slettet', endret: new Date()
      @db.replaceOne _id: @id, @data, w: 1, (err) =>
        return cb err if err

        redis.del "#{@type}:#{@id.toString()}"
        redis.hmset "#{@type}:#{@id.toString()}", @data

        cb null


Fix the match sched selection

Fix the match sched selection

Match Schedule
==============

The match schedule, as with the day schedule, is mainly managed within the basic
data module - this module defines only useful utilities.

Constants
---------

We define two constants within this module -- *MATCH_PREROLL*, and
*MATCH_LENGTH*.

*MATCH_PREROLL* is the amount of time, in seconds, before the start
time of a match during which it should be considered active. Its
current value is 180 seconds, which is 30 seconds of swap time and
60 seconds boot period.

    MATCH_PREROLL = 30 + 60

*MATCH_LENGTH* is simply the length of a match in seconds, including
setup and tear-down time - presently 5 minutes.

    MATCH_LENGTH = 60*5

*MATCH_POSTROLL* is the amount of time, in seconds, between the
start time of a match and when it is considered to have ended. It
is defined in terms of *MATCH_PREROLL* and *MATCH_LENGTH*.

    MATCH_POSTROLL = MATCH_LENGTH - MATCH_PREROLL

Match Tracking
--------------

The *firstMatchAfter* function takes as its argument a match schedule,
and a *reference point*, being a JavaScript *Date* object. It finds
the first match in the schedule whose consideration period begins
at or after the reference point. It may also take an optional
*feasibility condition*, to further filter the matches considered.

    firstMatchAfter = (schedule, referencePoint, feasilibilty) ->

If the feasibility condition is unspecified, we use a default
condition which simply accepts all matches.

        unless feasibility?
            feasibility = (match) -> yes

We convert the reference point into a UNIX timestamp for our use.

        referenceUNIX = referencePoint.valueOf() * 0.001

We then use Underscore's *find* function to find the first satisfying
match.

        _.find schedule, (match) ->
            return no unless feasibility(match, referencePoint)
            match.start + MATCH_POSTROLL >= referenceUNIX

Current Match
-------------

We provide the current match (nullable) via the *CurrentMatch*
property. It is a map on the *Data.matchSchedule* property, and the
clock.

First, we define the data source.

    currentMatchSource =
        Bacon.combineTemplate
            schedule: Data.matchSchedule
            clock: Clock

We then define the stream itself, as a map over the input source.

    currentMatch = currentMatchSource.map (data) ->

We find the first match active now, using *firstMatchAfter*. A
feasibility condition is passed to constrain matches to only those
which have not ended.

        firstMatchAfter data.schedule, data.clock, (match, ref) ->
            not (match.start + MAX_POSTROLL > ref)

The public property simply removes the duplicates from that stream.

    window.CurrentMatch = currentMatch.skipDuplicates()

Next Match
----------

We also provide the next match (nullable) via the *NextMatch*
property. It is defined similarly to *CurrentMatch*, except with
the additional feasibility condition of not being the current match.

We first define the data source.

    nextMatchSource =
        Bacon.combineTemplate
            schedule: Data.matchSchedule
            clock: Clock
            currentMatch: CurrentMatch

We then define the stream itself, again as a map over the source.

    nextMatch = nextMatchSource.map (data) ->

As with the current match, we use *firstMatchAfter*, with a feasibility
condition this time specifying that the match is not the current
match.

        firstMatchAfter data.schedule, data.clock, (match) ->
            match.key isnt data.currentMatch?.key

We then publish it by removing duplicates.

    window.NextMatch = nextMatch.skipDuplicates()

Match Schedule
==============

The match schedule, as with the day schedule, is mainly managed within the basic
data module - this module defines only useful utilities.

Constants
---------

We define two constants within this module -- *MATCH_PREROLL*, and
*MATCH_LENGTH*.

*MATCH_PREROLL* is the amount of time, in seconds, before the start
time of a match during which it should be considered active. Its
current value is 180 seconds, which is 30 seconds of swap time and
60 seconds boot period.

    MATCH_PREROLL = 30 + 60

*MATCH_LENGTH* is simply the length of a match in seconds, including
setup and tear-down time - presently 5 minutes.

    MATCH_LENGTH = 60*5

*MATCH_POSTROLL* is the amount of time, in seconds, between the
start time of a match and when it is considered to have ended. It
is defined in terms of *MATCH_PREROLL* and *MATCH_LENGTH*.

    MATCH_POSTROLL = MATCH_LENGTH - MATCH_PREROLL

Match Tracking
--------------

The *firstMatchAfter* function takes as its argument a match schedule,
and a *reference point*, being a JavaScript *Date* object. It finds
the first match in the schedule whose consideration period begins
at or after the reference point. It may also take an optional
*feasibility condition*, to further filter the matches considered.

    firstMatchAfter = (schedule, referencePoint, feasilibilty) ->

If the feasibility condition is unspecified, we use a default
condition which simply accepts all matches.

        unless feasibility?
            feasibility = (match) -> yes

We convert the reference point into a UNIX timestamp for our use.

        referenceUNIX = referencePoint.valueOf() * 0.001

We then use Underscore's *find* function to find the first satisfying
match.

        _.find schedule, (match) ->
            return no unless feasibility(match, referencePoint)
            match.start - MATCH_PREROLL >= referenceUNIX

Current Match
-------------

We provide the current match (nullable) via the *CurrentMatch*
property. It is a map on the *Data.matchSchedule* property, and the
clock.

First, we define the data source.

    currentMatchSource =
        Bacon.combineTemplate
            schedule: Data.matchSchedule
            clock: Clock

We then define the stream itself, as a map over the input source.

    currentMatch = currentMatchSource.map (data) ->

We find the first match active now, using *firstMatchAfter*. A
feasibility condition is passed to constrain matches to only those
which have not ended.

        firstMatchAfter data.schedule, data.clock, (match, ref) ->
            not (match.start + MAX_POSTROLL > ref)

The public property simply removes the duplicates from that stream.

    window.CurrentMatch = currentMatch.skipDuplicates()

Next Match
----------

We also provide the next match (nullable) via the *NextMatch*
property. It is defined similarly to *CurrentMatch*, except with
the additional feasibility condition of not being the current match.

We first define the data source.

    nextMatchSource =
        Bacon.combineTemplate
            schedule: Data.matchSchedule
            clock: Clock
            currentMatch: CurrentMatch

We then define the stream itself, again as a map over the source.

    nextMatch = nextMatchSource.map (data) ->

As with the current match, we use *firstMatchAfter*, with a feasibility
condition this time specifying that the match is not the current
match.

        firstMatchAfter data.schedule, data.clock, (match) ->
            match.key isnt data.currentMatch?.key

We then publish it by removing duplicates.

    window.NextMatch = nextMatch.skipDuplicates()


Fixed utils.stringify on objects with no Object prototype

# Stringifying

    'use strict'

    {isArray} = Array
    hasOwnProp = Object.hasOwnProperty

    module.exports = (utils) ->

## utils.simplify(*Object* object, [*Object* options])

Convert the given object into the most simplified format with no cyclic references and more.

Such object can be easily stringified later using standard *JSON.stringify()*.

Use utils.assemble() function to restore the object into the initial structure.

Second parameter is an config object (all 'false' by default):
  - *properties* - save properties descriptors (getters, config etc.),
  - *protos* - save protos as objects,
  - *constructors* - include constructor functions.

```javascript
var obj = {};
obj.self = obj;
console.log(JSON.stringify(utils.simplify(obj)));
```

If *protos* is *false* and *constructors* is *true*,
object will be recognized as an instance.

```javascript
function Sample(){
  this.fromInstance = 1;
}
Sample.prototype.fromPrototype = 1;

var sample = new Sample;
var parts = utils.simplify(sample, {constructors: true});
var clone = utils.assemble(json);

console.log(clone instanceof Sample)
// it's true because 'protos' option is false and 'constructors' is true
// won't work for json, because functions are not stringified ...
```

        utils.simplify = do ->
            nativeProtos = [Array::, Object::]
            nativeCtors = [Array, Object]

            (obj, opts = {}) ->
                null
                `//<development>`
                unless utils.isObject(obj)
                    throw new Error 'utils.simplify object must be an object'
                unless utils.isPlainObject(opts)
                    throw new Error 'utils.simplify options must be a plain object'
                `//</development>`

                optsProps = opts.properties ?= false
                optsProtos = opts.protos ?= false
                optsCtors = opts.constructors ?= false
                optsInsts = opts.instances = not optsProtos and optsCtors

                # list of objects
                objs = []

                # list of lists of ids per object
                ids = []

                # lists of keys to references per object
                references = {}

                # objects constructors
                if optsCtors then ctors = {}

                # proto destination to proto object
                if optsProtos then protos = {}

                # get cyclic references in the object
                cyclic = (obj) ->

                    len = objs.push obj
                    ids.push objIds = []

                    for key, value of obj when hasOwnProp.call(obj, key)

                        unless value and typeof value is 'object'
                            continue

                        # don't check getters values
                        if optsProps and exports.lookupGetter obj, key
                            objIds.push null
                            continue

                        # check whether obj already exists
                        unless ~(i = objs.indexOf value)
                            i = cyclic value

                        objIds.push i

                    # cycle proto
                    if optsProtos and proto = getPrototypeOf obj

                        # don't save protos for native ones (Array, Object, etc..)
                        if ~(nativeProtos.indexOf proto)
                            i = null

                        # find recursively if it's for first time
                        else unless ~(i = objs.indexOf proto)
                            i = cyclic proto

                        objIds.push i

                    len - 1

                # parse object
                parse = (obj, index) ->

                    r = if isArray obj then [] else {}
                    objIds = ids[index]

                    # Create `references` for each object with keys which are a references to others
                    # Value of each property will be changed to referenced object id
                    obji = 0
                    objReferences = null
                    for key, value of obj when hasOwnProp.call(obj, key)

                        r[key] = value

                        isReference = false

                        # save as reference
                        if value and typeof value is 'object'
                            objReferences ?= []

                            objId = value = objIds[obji++]

                            # with `optsProps` id can be a null when value is an object
                            if value isnt null
                                isReference = true
                                objReferences.push key

                        # save as property description
                        if optsProps
                            desc = getObjOwnPropDesc obj, key
                            desc.value = value if isReference
                            value = desc

                        # override prop value as referenced object id
                        r[key] = value

                    # save reference to proto
                    if optsProtos and getPrototypeOf obj
                        protoObjId = objIds[obji++]
                        if protoObjId isnt null
                            protos[index] = protoObjId

                    # save ctor if needed
                    if optsCtors and ctor = obj.constructor

                        # save for instance or for prototype depend on the flag
                        if optsInsts or hasOwnProp.call(obj, 'constructor')

                            # omits native constructors (Array, Object etc.)
                            unless ~(nativeCtors.indexOf ctor)
                                ctors[index] = ctor

                    # save object references
                    if objReferences then references[index] = objReferences

                    r

                # find cycles
                cyclic obj

                # parse all found objects
                for value, i in objs
                    objs[i] = parse value, i

                # return
                opts: opts
                objects: objs
                references: references
                protos: protos
                constructors: ctors

## utils.assemble(*PlainObject* object)

Backward utils.simplify() operation.

        utils.assemble = do ->
            ctorPropConfig = value: null

            (obj) ->
                null
                `//<development>`
                unless utils.isPlainObject(obj)
                    throw new Error 'utils.assemble object must be a plain object'
                `//</development>`

                {opts, objects, references, protos, constructors} = obj

                optsProps = opts.properties
                optsProtos = opts.protos
                optsCtors = opts.constructors
                optsInsts = opts.instances

                # list of all referenced objects ids
                refsIds = []

                # set references
                if optsProps
                    for objI, refs of references
                        obj = objects[objI]

                        for ref in refs
                            refsIds.push obj[ref].value
                            obj[ref].value = objects[obj[ref].value]
                else
                    for objI, refs of references
                        obj = objects[objI]

                        for ref in refs
                            refsIds.push obj[ref]
                            obj[ref] = objects[obj[ref]]

                # set properties
                if optsProps
                    for obj in objects
                        for key, value of obj when hasOwnProp.call(obj, key)
                            defObjProp obj, key, value

                # set protos
                for objI, refI of protos
                    objects[objI] = utils.setPrototypeOf objects[objI], objects[refI]

                # set objects as instances
                if optsInsts
                    for objI, func of constructors
                        object = objects[objI] = utils.setPrototypeOf objects[objI], func::

                        # call `fromAssebled` if exists
                        func.fromAssembled? object

                # .. or set ctors as properties
                else if optsCtors
                    for objI, func of constructors
                        ctorPropConfig.value = func
                        defObjProp objects[objI], 'constructor', ctorPropConfig

                # update references, because same of them could changed by `setPrototypeOf`
                refId = 0
                for objI, refs of references
                    obj = objects[objI]

                    for ref in refs
                        obj[ref] = objects[refsIds[refId++]]

                objects[0]

# Stringifying

    'use strict'

    {isArray} = Array

    module.exports = (utils) ->

## utils.simplify(*Object* object, [*Object* options])

Convert the given object into the most simplified format with no cyclic references and more.

Such object can be easily stringified later using standard *JSON.stringify()*.

Use utils.assemble() function to restore the object into the initial structure.

Second parameter is an config object (all 'false' by default):
  - *properties* - save properties descriptors (getters, config etc.),
  - *protos* - save protos as objects,
  - *constructors* - include constructor functions.

```javascript
var obj = {};
obj.self = obj;
console.log(JSON.stringify(utils.simplify(obj)));
```

If *protos* is *false* and *constructors* is *true*,
object will be recognized as an instance.

```javascript
function Sample(){
  this.fromInstance = 1;
}
Sample.prototype.fromPrototype = 1;

var sample = new Sample;
var parts = utils.simplify(sample, {constructors: true});
var clone = utils.assemble(json);

console.log(clone instanceof Sample)
// it's true because 'protos' option is false and 'constructors' is true
// won't work for json, because functions are not stringified ...
```

        utils.simplify = do ->
            nativeProtos = [Array::, Object::]
            nativeCtors = [Array, Object]

            (obj, opts = {}) ->
                null
                `//<development>`
                unless utils.isObject(obj)
                    throw new Error 'utils.simplify object must be an object'
                unless utils.isPlainObject(opts)
                    throw new Error 'utils.simplify options must be a plain object'
                `//</development>`

                optsProps = opts.properties ?= false
                optsProtos = opts.protos ?= false
                optsCtors = opts.constructors ?= false
                optsInsts = opts.instances = not optsProtos and optsCtors

                # list of objects
                objs = []

                # list of lists of ids per object
                ids = []

                # lists of keys to references per object
                references = {}

                # objects constructors
                if optsCtors then ctors = {}

                # proto destination to proto object
                if optsProtos then protos = {}

                # get cyclic references in the object
                cyclic = (obj) ->

                    len = objs.push obj
                    ids.push objIds = []

                    for key, value of obj when obj.hasOwnProperty key

                        unless value and typeof value is 'object'
                            continue

                        # don't check getters values
                        if optsProps and exports.lookupGetter obj, key
                            objIds.push null
                            continue

                        # check whether obj already exists
                        unless ~(i = objs.indexOf value)
                            i = cyclic value

                        objIds.push i

                    # cycle proto
                    if optsProtos and proto = getPrototypeOf obj

                        # don't save protos for native ones (Array, Object, etc..)
                        if ~(nativeProtos.indexOf proto)
                            i = null

                        # find recursively if it's for first time
                        else unless ~(i = objs.indexOf proto)
                            i = cyclic proto

                        objIds.push i

                    len - 1

                # parse object
                parse = (obj, index) ->

                    r = if isArray obj then [] else {}
                    objIds = ids[index]

                    # Create `references` for each object with keys which are a references to others
                    # Value of each property will be changed to referenced object id
                    obji = 0
                    objReferences = null
                    for key, value of obj when obj.hasOwnProperty key

                        r[key] = value

                        isReference = false

                        # save as reference
                        if value and typeof value is 'object'
                            objReferences ?= []

                            objId = value = objIds[obji++]

                            # with `optsProps` id can be a null when value is an object
                            if value isnt null
                                isReference = true
                                objReferences.push key

                        # save as property description
                        if optsProps
                            desc = getObjOwnPropDesc obj, key
                            desc.value = value if isReference
                            value = desc

                        # override prop value as referenced object id
                        r[key] = value

                    # save reference to proto
                    if optsProtos and getPrototypeOf obj
                        protoObjId = objIds[obji++]
                        if protoObjId isnt null
                            protos[index] = protoObjId

                    # save ctor if needed
                    if optsCtors and ctor = obj.constructor

                        # save for instance or for prototype depend on the flag
                        if optsInsts or obj.hasOwnProperty('constructor')

                            # omits native constructors (Array, Object etc.)
                            unless ~(nativeCtors.indexOf ctor)
                                ctors[index] = ctor

                    # save object references
                    if objReferences then references[index] = objReferences

                    r

                # find cycles
                cyclic obj

                # parse all found objects
                for value, i in objs
                    objs[i] = parse value, i

                # return
                opts: opts
                objects: objs
                references: references
                protos: protos
                constructors: ctors

## utils.assemble(*PlainObject* object)

Backward utils.simplify() operation.

        utils.assemble = do ->
            ctorPropConfig = value: null

            (obj) ->
                null
                `//<development>`
                unless utils.isPlainObject(obj)
                    throw new Error 'utils.assemble object must be a plain object'
                `//</development>`

                {opts, objects, references, protos, constructors} = obj

                optsProps = opts.properties
                optsProtos = opts.protos
                optsCtors = opts.constructors
                optsInsts = opts.instances

                # list of all referenced objects ids
                refsIds = []

                # set references
                if optsProps
                    for objI, refs of references
                        obj = objects[objI]

                        for ref in refs
                            refsIds.push obj[ref].value
                            obj[ref].value = objects[obj[ref].value]
                else
                    for objI, refs of references
                        obj = objects[objI]

                        for ref in refs
                            refsIds.push obj[ref]
                            obj[ref] = objects[obj[ref]]

                # set properties
                if optsProps
                    for obj in objects
                        for key, value of obj when obj.hasOwnProperty key
                            defObjProp obj, key, value

                # set protos
                for objI, refI of protos
                    objects[objI] = utils.setPrototypeOf objects[objI], objects[refI]

                # set objects as instances
                if optsInsts
                    for objI, func of constructors
                        object = objects[objI] = utils.setPrototypeOf objects[objI], func::

                        # call `fromAssebled` if exists
                        func.fromAssembled? object

                # .. or set ctors as properties
                else if optsCtors
                    for objI, func of constructors
                        ctorPropConfig.value = func
                        defObjProp objects[objI], 'constructor', ctorPropConfig

                # update references, because same of them could changed by `setPrototypeOf`
                refId = 0
                for objI, refs of references
                    obj = objects[objI]

                    for ref in refs
                        obj[ref] = objects[refsIds[refId++]]

                objects[0]