• Jump To … +
    Client.coffee ClientContainer.coffee ClientModel.coffee index.coffee MemoryInitStore.coffee RedisInitStore.coffee index.coffee JWT.coffee RequestHandler.coffee Server.coffee ServerContainer.coffee ServerModel.coffee SocketHandler.coffee index.coffee parseAcceptHeader.coffee Cache.coffee Mediator.coffee Message.coffee PageMap.coffee Strings.coffee
  • Message.coffee

  • ¶

    NPM dependencies

  • ¶

    shortid
    type-of-is

    ShortId = require('shortid')
    Type = require('type-of-is')
  • ¶

    attribute name used for serializing a model’s type with its data via deflate

    MODEL_KEY = '$model'
  • ¶

    object mapping from model names to constructors that needs to be set via Message.setModels

    models = null
  • ¶

    deflate

  • ¶

    Deflate the passed object so that it can be passed over the wire as json and inflated on the other end into models

    obj : object to deflate

    deflate = (obj)->
      switch Type(obj)
        when Array
          obj.map(deflate)
    
        when Object
          res = {}
          for k,v of obj
            res[k] = deflate(v) 
          res
    
        else
          if (obj and obj.deflate and Type(obj.deflate, Function))
            obj.deflate(
              model_key : MODEL_KEY
            )
          else
            obj
  • ¶

    inflate

  • ¶

    Inflate the passed json object by converting plain json objects into instances of their associated model. Model types are specified via model key defined in Strings

    obj : object to inflate

    inflate = (obj)->
      unless models
        return obj
    
      switch Type(obj)
  • ¶

    map over arrays

        when Array
          obj.map(inflate)
  • ¶

    traverse object and inflate its values

        when Object
          res = {} 
    
          Model = null
  • ¶

    if there is a MODEL_KEY attribute present in the json, use it to lookup the associated model

          if (MODEL_KEY of obj)
            model_name = obj[MODEL_KEY]
            delete obj[MODEL_KEY]
    
            Model = if (model_name of models)
              models[model_name]
            else
              console.error("Can't find Model for #{model_name}")
              null
              
          for k,v of obj
            res[k] = inflate(v)
    
          if Model
            res = new Model(res)
    
          res
  • ¶

    return everything else as is

        else 
          obj
  • ¶

    Message

  • ¶

    A WebSocket message

    class Message
  • ¶

    name for this message

      name  : null
  • ¶

    unique id for this message (shared by its reply)

      id    : null
  • ¶

    jwt auth token

      token : null
  • ¶

    the data for this message

      data  : null
  • ¶

    an error if needed

      error : null
  • ¶

    constructor

  • ¶

    Create a message

    required args

    name : the name for this message

    id : id for this message, otherwise will be generated

    token : jwt token used to identify / authorize the user sending this message

    data : the data / params for this message

    error : used in replies if error occured during processing of message

      constructor : (args)->
        unless args.name
          throw new Error("Message must have name")
    
        @name  = args.name
        @id    = args.id || ShortId.generate()
        @token = args.token
        @data  = if ('data' of args)
          inflate(args.data)
        else
          {}
    
        @error = null
        if args.error
          @error = args.error
          unless Type(@error, Error)
            @error = new Error(@error)
  • ¶

    @setModels

  • ¶

    Set the models to be used by inflate

    _models : models to be used for inflation

      @setModels : (_models)->
        models = _models
  • ¶

    @parse

  • ¶

    Parse and create message from raw josn string

    json : the raw json to parse

      @parse : (json)->
        try 
          message_data = JSON.parse(json)
        catch error
          return @error("JSON.parse failed")
    
        new @(message_data)
  • ¶

    reply

  • ¶

    Create a reply message from this message using its id

    data : data for the reply

    error : error

      reply : (args)->
        args.name = @replyName()
        args.id   = @id
        new @constructor(args)
  • ¶

    replyName

  • ¶

    The name of the reply to this message

      replyName : ()->
        "#{@name}Reply"
  • ¶

    replyEventName

  • ¶

    The event name that gets triggered by this message’s reply This is used in the ClientStore in order to trigger load callback once the data is available

      replyEventName : ()->
        "message:#{@replyName()}:id:#{@id}"
  • ¶

    stringify

  • ¶

    Encode this message into json, deflating its data in the process

      stringify : ()->
        message = {
          name  : @name
          id    : @id
          token : @token
        }
    
        if @error 
          message.error = @error.message
        
        if @data
          message.data = @data
        
        message = deflate(message)
        JSON.stringify(message)
  • ¶

    isError

  • ¶

    Returns true if this message has an error

      isError : ()->
        !!@error
  • ¶

    is

    Convenience method for checking the name of this message

    name : message name to check against

      is : (name)->
        (@name is name)
  • ¶

    in

    Convenience method for checking whether this message’s is one of several possibilities

    names : message names to check against

      in : (names)->
        (@name in names)
    
    module.exports = Message