Viewing File: /usr/local/cpanel/share/libraries/cjt2/src/io/api2-request.js

/*
# cjt/io/api2-request.js                          Copyright(c) 2020 cPanel, L.L.C.
#                                                           All rights reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited
*/

/* --------------------------*/
/* DEFINE GLOBALS FOR LINT
/*--------------------------*/
/* eslint-env amd */
/* --------------------------*/

// -----------------------------------------------------------------------
// DEVELOPER NOTES:
// 1) Unlike UAPI, the API2 does not conform to a strict results layout.
// As development continues we will likely have to add various exceptions
// to the getData() and getError() methods...
// -----------------------------------------------------------------------

// TODO: Add tests for these

/**
 *
 * @module cjt/io/api2-request
 * @example

    require(["lodash","cjt/io/api2-request"], function(_, REQUEST) {
        // TODO:
    });
 */
define(["lodash", "cjt/util/test"], function(_, TEST) {

    "use strict";

    // ------------------------------
    // Module
    // ------------------------------
    var MODULE_NAME = "cjt/io/api2-request"; // requirejs(["cjt/io/api2-request"], function(REQUEST) {}); -> cjt/io/api2-request.js || cjt/io/api2-request.min.js
    var MODULE_DESC = "Contains a helper object used to build API2 call parameters.";
    var MODULE_VERSION = 2.0;

    // ------------------------------
    // Constants
    // ------------------------------
    var DEFAULT_PAGE_SIZE = 10;
    var ASCENDING = 0;
    var DESCENDING = 1;

    /**
     * Creates an empty metadata object
     * @method  _getEmptyRequestMeta
     * @return {Object} Initialized abstract request metadata object
     */
    var _getEmptyRequestMeta = function() {
        return {
            paginate: {
                start_page: 0,
                start_record: 0,
                page_size: DEFAULT_PAGE_SIZE
            },
            filter: [],
            sort: []
        };
    };


    // -----------------------------------------------------------------------------------
    // Api request Api2 calls.
    //
    // @class Api2Request
    //
    // -----------------------------------------------------------------------------------
    var Api2Request = function() {

        /**
         * API version number to use for UAPI.
         *
         * @class  Api2Request
         * @property {Number} version
         */
        this.version = 2;

        /**
         * API module name for UAPI call.  Represents the module in <Module>::<Call>().
         *
         * @class  Api2Request
         * @property {String} module
         */
        this.module = "";

        /**
         * API function name for UAPI call.  Represents the call in <Module>::<Call>().
         *
         * @class  Api2Request
         * @property {String} func
         */
        this.func = "";

        /**
         * Collection of arguments for the API call.
         *
         * @class  WhmV1Request
         * @property {Object} args
         */
        this.args = {};

        /**
         * API call meta data for the UAPI call.  Should be a hash with names for
         * each meta data parameter passed to the UAPI call. This data is used to
         * control properties such as sorting, filters and paging.
         *
         * @class  Api2Request
         * @property {Object} meta
         */
        this.meta = _getEmptyRequestMeta();

        /**
         * Number to add to an auto argument.
         *
         * @class  WhmV1Request
         * @property {Number} auto
         */
        this.auto = 1;
    };

    /**
     *
     * @static
     * @class Api2Request
     * @property {enum} [sort] Contains sorting constants
     */
    Api2Request.sort  = {
        ASCENDING: ASCENDING,
        DESCENDING: DESCENDING
    };

    Api2Request.prototype = {

        /**
         * Initialize the sync data
         *
         * @class  Api2Request
         * @method  initialize
         * @param  {String} module Name of the module where the API function exists.
         * @param  {String} func   Name of the function to call.
         * @param  {Object} data   Data for the function call.
         * @param  {Object} meta   Meta-data such as sorting, filtering, paging and similar data for the api call.
         */
        initialize: function(module, func, data, meta) {
            this.module = module;
            this.func = func;
            this.data = data || {};
            this.meta = meta || {};
            this.auto = 1;

            return this;    // for chaining
        },

        /**
         * Adds an argument
         *
         * @class  WhmV1Request
         * @method  addArgument
         * @param {String} name   Name of the argument
         * @param {Object} value  Value of the argument
         * @param {Boolean} [isAuto] Optional, will add an auto counter to this argument
         */
        addArgument: function(name, value, isAuto) {
            if (!isAuto) {
                this.args[name] = value;
            } else {
                this.args[name + this.auto] = value;
            }
        },

        /**
         * Removes an argument
         *
         * @class  WhmV1Request
         * @method removeArgument
         * @param  {[type]}  name   [description]
         * @param  {Boolean} isAuto [description]
         * @return {[type]}         [description]
         */
        removeArgument: function(name, isAuto) {
            if (!isAuto) {
                this.args[name] = null;
                delete this.args[name];
            } else {
                this.args[name + this.auto] = null;
                delete this.args[name + this.auto];
            }
        },

        /**
         * Make the argument counter increment.
         * @class  WhmV1Request
         * @method  incrementAuto
         * @return {Number} Current value of the increment.
         */
        incrementAuto: function() {
            this.auto++;
            return this.auto;
        },

        /**
         * Clears the arguments
         *
         * @class  WhmV1Request
         * @method  clearArguments
         * @param {String} name   Name of the argument
         * @param {Object} value  Value of the argument
         */
        clearArguments: function() {
            this.args = {};
        },

        /**
         * Adds the paging meta data to the run parameters in UAPI format
         *
         * @class  Api2Request
         * @method  addPaging
         * @param {Number} start   Start page
         * ATTR apiIndex.
         * @param {Number} size    Optional page size, inherits from previous initialization.
         */
        addPaging: function(start, size) {

            // if the size is equal to the "All" page size sentinel value,
            // abort pagination
            if (size === -1 || this.meta.size === -1) {
                return;
            }

            size = size || this.meta.size || 10;

            this.meta.paginate = this.meta.paginate || {};
            this.meta.paginate.start = ((start - 1) * size) + 1;
            this.meta.paginate.size = size;
        },

        /**
         * Clears the paging rules from the meta data.
         *
         * @class  Api2Request
         * @method  clearPaging
         */
        clearPaging: function() {
            delete this.meta.paginate;
        },

        /**
         * Add sorting rules meta data to the run parameters in API2 format.
         *
         * @class  Api2Request
         * @method  addSorting
         * @param {Hash} [options] Optional options passed in from the outside
         * @param {String} field     Name of the field to sort on.
         * @param {String} direction asc or dsc. Defaults to asc.
         * @param {String} type      Sort types supported by the API. Defaults to
         * equality
         */
        addSorting: function(field, direction, type) {
            var sortField = field;
            var sortDir = direction || "asc";
            var sortType = type || "";

            if (sortField) {
                var api2SortRule = (sortDir === "asc" ? "" : "!") + sortField;

                // If we have a type, the we need the complex array format
                if (sortType !== "") {
                    api2SortRule = [api2SortRule, sortType];
                }

                // Store the rule.
                if (this.meta.sort) {
                    this.meta.sort.push(api2SortRule);
                } else {
                    this.meta.sort = [api2SortRule];
                }
            }
        },

        /**
         * Clear the sorting rules meta data.
         *
         * @class Api2Request
         * @method  clearSorting
         */
        clearSorting: function() {
            delete this.meta.sort;
        },


        /**
         * Add filter rules meta data to the run parameters in UAPI format.
         *
         * @class  Api2Request
         * @method  addFilter
         * @param {String|Array} key  Field name or array of three elements [key, operator, value].
         * @param {String} [operator] Comparison operator to use.  Optional if the first parameter is an array.
         * @param {String} [value]    Value to compare the field with. Optional if the first parameter is an array.
         */
        addFilter: function(key, operator, value) {
            var filter;
            if (_.isArray(key)) {
                filter = key;
            } else {
                filter = [key, operator, value];
            }

            // ---------------------------------------------
            // Building a structure that looks like this:
            //
            // [
            //      [ key1 , operator1, value1 ],
            //      [ key2 , operator2, value2 ],
            //      ...
            // ]
            // ---------------------------------------------
            if (filter) {
                if (this.meta.filter) {
                    this.meta.filter.push(filter);
                } else {
                    this.meta.filter = [filter];
                }
            }
        },

        /**
         * Clear the meta data for the filter.
         *
         * @class Api2Request
         * @method  clearFilter
         */
        clearFilter: function() {
            delete this.meta.filter;
        },

        /**
         * Build the API2 call data structure.
         *
         * @class  Api2Request
         * @method getRunArguments
         * @param  {String Array} [fields]  List of fields to extract.
         * @param  {Object }      [context] Context to call callbacks with.
         * @return {Object}       Packages up an api call base on collected information.
         */
        getRunArguments: function(fields, context) {
            return {
                version: this.version,
                module: this.module,
                func: this.func,
                meta: this.meta,
                args: this.args
            };
        }
    };

    // Publish the component
    return {
        MODULE_NAME: MODULE_NAME,
        MODULE_DESC: MODULE_DESC,
        MODULE_VERSION: MODULE_VERSION,
        Class: Api2Request
    };
});
Back to Directory File Manager