Source: abstract.js

/*
 * (c) Miva Inc <https://www.miva.com/>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * $Id: abstract.js 72467 2019-01-08 23:00:09Z gidriss $
 */

const util = require('./util');

/** @module Abstract */

/** CATEGORY_SHOW constants. */
/** @ignore */
const REQUEST_SCOPE_STORE = 'store';
/** @ignore */
const REQUEST_SCOPE_DOMAIN = 'domain';

/** Abstract data model */
class Model {
  /**
   * @param {object} data
   * @returns {void}
   */
  constructor(data = {}) {
    if (util.isObject(data)) {
      Object.assign(this, data);
    }
  }

  /**
   * Get a field value.
   * @param {string} field
   * @param {*} defaultValue
   * @returns {*}
   */
  getField(field, defaultValue = null) {
    if (!util.isUndefined(this[field])) {
      return this[field];
    }

    return defaultValue;
  }

  /**
   * Check if a field is defined.
   * @param {string} field
   * @returns {boolean}
   */
  hasField(field) {
    return field in this;
  }

  /**
   * Set a field value.
   * @param {string} field
   * @param {*} value
   * @returns {Model}
   */
  setField(field, value) {
    this[field] = value;
    return this;
  }

  /**
   * Get the data for the request.
   * @return {Object}
   */
  toObject() {
    return this;
  }
}

/** Abstract request all api requests inherit from. */
class Request {
  /**
   * Request Constructor.
   * @param {?Client} client
   * @returns {void}
   */
  constructor(client = null) {
    this.client    = client;
    this.storeCode = null;
    this.scope     = REQUEST_SCOPE_STORE;
  }
  
  /**
   * Constant REQUEST_SCOPE_STORE
   * @returns {string}
   * @const
   * @static
   */
  static get REQUEST_SCOPE_STORE() {
    return REQUEST_SCOPE_STORE;
  }

  /**
   * Constant REQUEST_SCOPE_DOMAIN
   * @returns {string}
   * @const
   * @static
   */
  static get REQUEST_SCOPE_DOMAIN() {
    return REQUEST_SCOPE_DOMAIN;
  }

  /**
   * Get the function of the request.
   * @returns {string}
   */
  getFunction() {
    if (util.isNullOrUndefined(this.function) || !this.function.length) {
      return this.constructor.name;
    }

    return this.function;
  }

  /**
   * Get the store code set for the request.
   * @returns {string}
   */
  getStoreCode() {
    return this.storeCode;
  }

  /**
   * Set the store code for the request.
   * @param {string} storeCode
   * @returns {Request}
   */
  setStoreCode(storeCode) {
    this.storeCode = storeCode;
    return this;
  }

  /**
   * Get the scope of request.
   * @returns {string}
   */
  getScope() {
    return this.scope;
  }

  /**
   * Return the assigned client.
   * @returns {?Client}
   */
  getClient() {
    return this.client;
  }

  /**
   * Set the Client used for the request.
   * @param {?Client} client
   * @returns {Request}
   */
  setClient(client) {
    this.client = client;
    return this;
  }

  /**
   * Reduce the request to a an object.
   * @returns {Object}
   */
  toObject() {
    var ret = {};

    if (this.scope == REQUEST_SCOPE_STORE && !util.isNullOrUndefined(this.storeCode)) {
      ret['Store_Code'] = this.storeCode;
    }

    return ret;
  }

  /**
   * Send this object via the assigned client.
   * @param {Request~sendCallback} callback
   * @returns {void}
   */
  send(callback) {
    if (this.client) {
      return this.client.send(this, callback);
    } else {
      callback(new Error('No client assigned to send request'), null);
    }
  }

  /**
   * The callback signature for Request~send
   * @callback Request~sendCallback
   * @param {?Error} error
   * @param {?Response} response
   */

  /**
   * Queue this request via the assigned client and get a Promise.
   * @returns {Promise}
   * @throws {Error}
   */
  promise() {
    if (this.client) {
      return this.client.promise(this);
    }

    throw new Error('No client assigned to send request');
  }

  /**
   * Override this method to create a response for this request.
   * @abstract
   * @param {Object} data
   * @returns {Response}
   */
  createResponse(data) {
    return new Response(this, data);
  }
}

/** Abstract response all api responses inherit from. */
class Response {
  /**
   * Response constructor.
   * @param {Request} request
   * @param {Object} data
   * @returns void
   */
  constructor(request, data = {}) {
    if (!util.isInstanceOf(request, Request)) {
      throw new Error(util.format('Expected request to be an instance of Request but but got %s',
        typeof request));
    } else if (!util.isObject(data)) {
      throw new Error(util.format('Expected data to be an Object but got %s',
        typeof data));
    }

    this.request = request;
    this.data    = data;
  }

  /**
   * Check is the response was a success.
   * @returns {boolean}
   */
  isSuccess() {
    return !util.isNullOrUndefined(this.data['success']) &&
      (this.data['success'] === true || this.data['success'] === 1);
  }

  /**
   * Check is the response was a error.
   * @returns {boolean}
   */
  isError() {
    return !util.isNullOrUndefined(this.data['success']) &&
      (this.data['success'] === false || this.data['success'] === 0);
  }

  /**
   * Get the error message.
   * @returns {?string}
   */
  getErrorMessage() {
    return !util.isNullOrUndefined(this.data['error_message']) ?
      this.data['error_message'] : null;
  }

  /**
   * Get the error code.
   * @returns {?string}
   */
  getErrorCode() {
      return !util.isNullOrUndefined(this.data['error_code']) ?
          this.data['error_code'] : null;
  }

  /**
   * Get the number of input errors.
   * @returns {number}
   */
  getInputErrorCount() {
    return !util.isNullOrUndefined(this.data['input_errors']) ?
      this.data['input_errors'] : 0;
  }

  /**
   * Get the fields which encountered a validation error.
   * @returns {Array}
   */
  getErrorFields() {
    return !util.isNullOrUndefined(this.data['error_fields']) ?
      this.data['error_fields'] : [];
  }

  /**
   * Get the field which triggered the error.
   * @returns {?string}
   */
  getErrorField() {
    return !util.isNullOrUndefined(this.data['error_field']) ?
      this.data['error_field'] : null;
  }

  /**
   * Get the error message associated with the error field that cause the error.
   * @returns {?string}
   */
  getErrorFieldMessage() {
    return !util.isNullOrUndefined(this.data['error_field_message']) ?
      this.data['error_field_message'] : null;
  }

  /**
   * Check if the error response is a list error.
   * @returns {boolean}
   */
  isListError() {
    return !util.isNullOrUndefined(this.data['list_error']) ?
      this.data['list_error'] : false;
  }

  /**
   * Check if the error response is a validation error.
   * @returns {boolean}
   */
  isValidationError() {
    return !util.isNullOrUndefined(this.data['validation_error']) ?
      this.data['validation_error'] : false;
  }

  /**
   * Check if the error response is a input error.
   * @returns {boolean}
   */
  isInputError() {
    return !util.isNullOrUndefined(this.data['input_errors']) ?
      this.data['input_errors'] : false;
  }

  /**
   * Get the error messages associated with the response.
   * @returns {Array}
   */
  getErrors() {
    return !util.isNullOrUndefined(this.data['errors']) ?
      this.data['errors'] : [];
  }

  /**
   * Get the underlying data object.
   * @returns {Array}
   */
  getData() {
    return this.data;
  }

  /**
   * Get the initiating Request object.
   * @returns {Request}
   */
  getRequest() {
    return this.request;
  }
}

module.exports = {
  Model,
  Request,
  Response
};