json-string-packer.js 2.36 KB
// Copyright IBM Corp. 2014,2016. All Rights Reserved.
// Node module: loopback-connector
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

'use strict';

var createPromiseCallback = require('./utils').createPromiseCallback;

module.exports = JSONStringPacker;

var ISO_DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*))(?:Z|(\+|-)([\d|:]*))?$/;

/**
 * Create a new Packer instance that can be used to convert between JavaScript
 * objects and a JsonString representation in a String.
 *
 * @param {String} encoding Buffer encoding refer to https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings
 */
function JSONStringPacker(encoding) {
  this.encoding = encoding || 'base64';
}

/**
 * Encode the provided value to a `JsonString`.
 *
 * @param {*} value Any value (string, number, object)
 * @callback {Function} cb The callback to receive the parsed result.
 * @param {Error} err
 * @param {Buffer} data The encoded value
 * @promise
 */
JSONStringPacker.prototype.encode = function(value, cb) {
  var encoding = this.encoding;

  cb = cb || createPromiseCallback();
  try {
    var data = JSON.stringify(value, function(key, value) {
      if (Buffer.isBuffer(this[key])) {
        return {
          type: 'Buffer',
          data: this[key].toString(encoding),
        };
      } else {
        return value;
      }
    });

    setImmediate(function() {
      cb(null, data);
    });
  } catch (err) {
    setImmediate(function() {
      cb(err);
    });
  }
  return cb.promise;
};

/**
 * Decode the JsonString value back to a JavaScript value.
 * @param {String} jsonString The JsonString input.
 * @callback {Function} cb The callback to receive the composed value.
 * @param {Error} err
 * @param {*} value Decoded value.
 * @promise
 */
JSONStringPacker.prototype.decode = function(jsonString, cb) {
  var encoding = this.encoding;

  cb = cb || createPromiseCallback();
  try {
    var value = JSON.parse(jsonString, function(k, v) {
      if (v && v.type && v.type === 'Buffer') {
        return new Buffer(v.data, encoding);
      }

      if (ISO_DATE_REGEXP.exec(v)) {
        return new Date(v);
      }

      return v;
    });

    setImmediate(function() {
      cb(null, value);
    });
  } catch (err) {
    setImmediate(function() {
      cb(err);
    });
  }
  return cb.promise;
};