all files / oak-tools/lib/ message.js

21.43% Statements 6/28
0% Branches 0/13
16.67% Functions 1/6
21.43% Lines 6/28
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114                                                                                                                                                                                                                        
const _ = require('lodash')
const msgpack = require('msgpack5')()
 
/**
 * Message encapsulation and decapsulation
 */
class Message {
  /**
   * Creates an instance of Message.
   * @constructor
   * @param {Object} [options] options object
   * @param {Function} [options.encode=msgpack5/encode] Encoder function
   * @param {Function} [options.decode=msgpack5/decode] Decoder function
   */
  constructor ({ encode, decode } = msgpack) {
    /**
     * @prop {Function} encoder function
     */
    this.encoder = encode
    /**
     * @prop {Function} decoder function
     */
    this.decoder = decode
    /**
     * @prop {String} Namespace delimiter
     */
    this.delimiter = '.'
  }
 
  static delimiter () {
    return this.delimeter || '.'
  }
 
  /**
   * Pack a message
   * @param {String} namespace namespace of the message
   * @param {any} payload payload of the message
   * @returns {Buffer} Encoded namespace and payload
   */
  pack (namespace, payload) {
    let ret = this.encode(
      [...namespace.split(this.delimiter), payload]
    )
    return ret
  }
  /**
   * @typedef {Object} message
   * @property {String} ns Namespace of the message
   * @property {any} pl Payload of the message
   */
 
  /**
   * Unpack a message
   * @param {Buffer} data
   * @returns {message}
   * @memberof Message
   */
  unpack (data) {
    let _this = this
    let decoded = _this.decode(data)
    // make sure the message decoded and it's an array
    if (decoded && _.isArray(decoded) && decoded.length) {
      // push null to the unpack if there is no payload
      if (decoded.length === 1) {
        decoded.push(null)
      }
      // namespace consists of all array items minus the last
      let namespace = _.join(_.initial(decoded), '.')
      // payload is the last array item
      let payload = _.last(decoded)
      return { ns: namespace, pl: payload }
    }
  }
 
  /**
   * Encode data
   * @param {any} data
   * @returns {Buffer}
   * @memberof Message
   */
  encode (data) {
    if (_.isFunction(this.encoder)) {
      try {
        let enc = this.encoder(data)
        return enc
      } catch (err) {
        return err
      }
    } else {
      return data
    }
  }
 
  /**
   * Decode data
   * @param {Buffer} data
   * @returns {any}
   * @memberof Message
   */
  decode (data) {
    if (_.isFunction(this.decoder)) {
      try {
        return this.decoder(data)
      } catch (err) {
        return err
      }
    } else {
      return data
    }
  }
}
 
module.exports = Message