API.js

"use strict";
/* eslint-disable complexity */
/***************************************************
* Licensed Materials - Property of HCL.
* (c)Copyright HCL America, Inc. 2023-2024
****************************************************/
Object.defineProperty(exports, "__esModule", { value: true });
exports.converter = exports.getActionEventObject = exports.setActionEventObject = exports.getCurrentServiceName = exports.getCurrentServerDatabase = exports.setCurrentServerDatabase = exports.isCurrentServiceTypeIntegration = exports.isCurrentServiceTypeOfflineObjects = exports.isCurrentServiceTypeOnlineObjects = exports.setDefaultServiceTypeAsIntegration = exports.setDefaultServiceTypeAsOfflineObjects = exports.setDefaultServiceTypeAsOnlineObjects = exports.getDefaultServiceType = exports.setServiceTypeAsOnlineObjects = exports.setServiceTypeAsOfflineObjects = exports.getServiceType = exports.rosettajsLogger = exports.generateTernDefsForCustomAPIs = exports.getTernFileNames = exports.deregisterAPIs = exports.registerAPIs = exports.deregisterAPI = exports.registerAPI = exports.isCurrentContextDb = exports.isCurrentContextLocal = exports.isCurrentContextAll = exports.setDefaultContextAsDb = exports.setDefaultContextAsLocal = exports.setDefaultContextAsAll = exports.getDefaultContext = exports.isCurrentFrameworkDRAPI = exports.isCurrentFrameworkJS = exports.isCurrentFrameworkVoltMX = exports.setDefaultFrameworkAsDRAPI = exports.setDefaultFrameworkAsJS = exports.setDefaultFrameworkAsVoltMX = exports.getDefaultFramework = exports.isCurrentAPIOpenFormula = exports.isCurrentAPINotes = exports.setDefaultAPIAsOpenFormula = exports.setDefaultAPIAsNotes = exports.getDefaultAPI = exports._config = exports.build = exports.version = void 0;
const tslib_1 = require("tslib");
/**
 * @file Rosetta API
 * @module rosetta-api
 * @category API
 */
// set the API version as a rosettajs prop
exports.version = require('../../package.json').version;
exports.build = require('../../buildNumber.json').buildNumber;
const api_vmx = tslib_1.__importStar(require("./voltmx/API"));
const converter = tslib_1.__importStar(require("@janus/rosetta-converters"));
exports.converter = converter;
const extenderEvals = tslib_1.__importStar(require("./_extenderEvals"));
exports._config = {
    _notes: "notes",
    _openFormula: "openformula",
    _defaultAPI: "notes",
    framework: {
        _drapi: "drapi",
        _voltmx: "vmx",
        _javascript: "js",
        default: "js"
    },
    context: {
        local: "local",
        db: "db",
        all: "all",
        default: "all"
    }
};
/*------------------------------------------[  API implementation selection  ] */
/**
 * Set getDefaultAPI
 * @returns {string} the default API currently set
*/
const getDefaultAPI = () => { return exports._config._defaultAPI; };
exports.getDefaultAPI = getDefaultAPI;
/**
 * Set default API to Notes when an underlaying Open Formula API function with the same name exists.
 * @returns {string} The default API
 */
function setDefaultAPIAsNotes() {
    exports._config._defaultAPI = exports._config._notes;
    return (0, exports.getDefaultAPI)();
}
exports.setDefaultAPIAsNotes = setDefaultAPIAsNotes;
/**
 * Set default API to Open Formula when an underlaying Notes API function with the same name exists.
 * @returns {string} The default API
 */
function setDefaultAPIAsOpenFormula() {
    exports._config._defaultAPI = exports._config._openFormula;
    return (0, exports.getDefaultAPI)();
}
exports.setDefaultAPIAsOpenFormula = setDefaultAPIAsOpenFormula;
/**
 * Is current API Notes.
 * @returns {boolean} True if the current API is set to Notes;
 *     false otherwise
 */
function isCurrentAPINotes() { return (0, exports.getDefaultAPI)() === exports._config._notes; }
exports.isCurrentAPINotes = isCurrentAPINotes;
/**
 * Is current API Open Formula.
 * @returns {boolean} True if the current API is set to Open Formula
 *     false otherwise
 */
function isCurrentAPIOpenFormula() { return (0, exports.getDefaultAPI)() === exports._config._openFormula; }
exports.isCurrentAPIOpenFormula = isCurrentAPIOpenFormula;
/*------------------------------------------[  FRAMEWORK  ] */
/**
 * Get default framework
 * @returns {string} default framework (JS or VMX)
 */
function getDefaultFramework() {
    return exports._config.framework.default;
}
exports.getDefaultFramework = getDefaultFramework;
/**
 * Set default framework to voltmx
 * @returns {string} The default framework
 */
function setDefaultFrameworkAsVoltMX() {
    exports._config.framework.default = exports._config.framework._voltmx;
    return getDefaultFramework();
}
exports.setDefaultFrameworkAsVoltMX = setDefaultFrameworkAsVoltMX;
/**
 * Set default framework to javascript
 * @returns {string} The default framework
 */
function setDefaultFrameworkAsJS() {
    exports._config.framework.default = exports._config.framework._javascript;
    return getDefaultFramework();
}
exports.setDefaultFrameworkAsJS = setDefaultFrameworkAsJS;
/**
 * Set default framework to drapi
 * @returns {string} The default framework
 */
function setDefaultFrameworkAsDRAPI() {
    exports._config.framework.default = exports._config.framework._drapi;
    return getDefaultFramework();
}
exports.setDefaultFrameworkAsDRAPI = setDefaultFrameworkAsDRAPI;
/**
 * Is current framework Volt MX.
 * @returns {boolean} True if the current framework is set to vmx;
 *     false otherwise
 */
function isCurrentFrameworkVoltMX() { return getDefaultFramework() === exports._config.framework._voltmx; }
exports.isCurrentFrameworkVoltMX = isCurrentFrameworkVoltMX;
/**
 * Is current framework Javascript.
 * @returns {boolean} True if the current framework is set to js;
 *     false otherwise
 */
function isCurrentFrameworkJS() { return getDefaultFramework() === exports._config.framework._javascript; }
exports.isCurrentFrameworkJS = isCurrentFrameworkJS;
/**
 * Is current framework Javascript.
 * @returns {boolean} True if the current framework is set to js;
 *     false otherwise
 */
function isCurrentFrameworkDRAPI() { return getDefaultFramework() === exports._config.framework._drapi; }
exports.isCurrentFrameworkDRAPI = isCurrentFrameworkDRAPI;
/*------------------------------------------[  CONTEXT  ] */
/**
 * Get default context
 * @returns {string} the currently set default context (all|local|db)
 */
function getDefaultContext() {
    return exports._config.context.default;
}
exports.getDefaultContext = getDefaultContext;
/**
 * Set default context to all
 * @returns {string} The default context
 */
function setDefaultContextAsAll() {
    exports._config.context.default = exports._config.context.all;
    return getDefaultContext();
}
exports.setDefaultContextAsAll = setDefaultContextAsAll;
/**
 * Set default context to local
 * @returns {string} The default context
 */
function setDefaultContextAsLocal() {
    exports._config.context.default = exports._config.context.local;
    return getDefaultContext();
}
exports.setDefaultContextAsLocal = setDefaultContextAsLocal;
/**
 * Set default context to db
 * @returns {string} The default context
 */
function setDefaultContextAsDb() {
    exports._config.context.default = exports._config.context.db;
    return getDefaultContext();
}
exports.setDefaultContextAsDb = setDefaultContextAsDb;
/**
 * Is current context all?
 * @returns {boolean} true if the current context is set to all; false otherwise
 */
function isCurrentContextAll() { return getDefaultContext() === exports._config.context.all; }
exports.isCurrentContextAll = isCurrentContextAll;
/**
 * Is current context local?
 * @returns {boolean} true if the current context is set to local; false otherwise
 */
function isCurrentContextLocal() { return getDefaultContext() === exports._config.context.local; }
exports.isCurrentContextLocal = isCurrentContextLocal;
/**
 * Is current context database?
 * @returns {boolean} true if the current context is set to db; false otherwise
 */
function isCurrentContextDb() { return getDefaultContext() === exports._config.context.db; }
exports.isCurrentContextDb = isCurrentContextDb;
/*------------------------------------------[  EXTENSIONS  ] */
/**
 * @private
 * Determines if a string is a Notes formula.
 * @param {string} s The code
 * @returns True if it is a Notes formula, otherwise false.
 */
const isNotes = (s) => converter.isNotes(s);
/**
 * @private
 * Determines if a string is an Open formula.
 * @param {string} s The code
 * @returns True if it is an Open formula, otherwise false.
 */
const isExcel = (s) => converter.isOpenFormula(s);
/**
 * @private
 * Determines if a string is either a Notes formula or open formula.
 * @param {string} s The code
 * @returns True if it is a Notes formula or open formula, false if it is neither.
 */
const isFormula = (s) => isNotes(s) || isExcel(s);
/**
 * @private
 * Capitalizes the first letter of a string
 * @param str The string to capitalizes the first letter
 * @returns A new string with the first letter capitalized.
 */
const capFirstLetter = (str) => str.charAt(0).toUpperCase() + str.slice(1);
/** @private */
const noop = () => { }; // eslint-disable-line @typescript-eslint/no-empty-function
/**
 * @private
 * Parse the name of the custom API. It can optionally contain parameter list.
 *
 * @param name The name of the custom API.
 * @returns {Array} Element 0 will contain the function name+args, element 1 the arguments
 */
const parseName = (name) => name.match(/\b[^()]+\((.*)\)$/) || ['', ''];
/**
 * Parse information from an object defining an extened API.
 * @param {object} data object defining the extended API.
 * @returns {object} Information about the extended API defined by _data_. The following keys will be
 * returned: name, namef, funcArgs, cat, lang, and code. The any optional settings in _data_ will be resolved to values in the returned object.
 * funcArgs will contain any arguments defined for name.
 */
function parseCustomData(data) {
    const rtn = {};
    let { name, namef, cat, lang, code } = data;
    if (typeof name === 'undefined' || !name) {
        throw new Error(`API name was not supplied!`);
    }
    const argsInName = parseName(name);
    if (argsInName && argsInName[0])
        name = argsInName[0].split('(')[0]; // strip args from name arguments since name will be used as the prop in the API object
    if (!name) {
        throw new Error(`API name null after stripping arguments!`);
    }
    rtn.namef = namef || name; // name in formula, default to name if none suppied; note, after stripping args
    rtn.name = name;
    rtn.funcArgs = argsInName[1].replace(/;/g, ',');
    cat = cat || 'Custom';
    rtn.cat = capFirstLetter(cat); // categories always start with capital letter
    // FORMULA LANGUAGE REPRESENTATION:
    // set the formula language object reference prop based on what formula language is being extended, if any
    // normalize open formula or notes, as these we know
    lang = lang || '';
    switch (lang.toLowerCase()) {
        case 'open formula':
            rtn.lang = '_openFormula';
            break;
        case 'notes':
            rtn.lang = '_notes';
            break;
        case '':
            rtn.lang = '';
            break; // no formula language representing the API
        default: rtn.lang = lang.charAt(0) === '_' ? lang : `_${lang}`; // langs start with _ to follow pattern as _notes and _openFormula
    }
    rtn.code = code || noop;
    return rtn;
}
/**
 * @private
 * Create a callback for a custom API
 * @param {object} apiRef rosettajs API object
 * @param {string} name The custom API name
 * @param {string} cat The custom API category
 * @param {*} code The custom API code
 * @param {string} funcArgs arguments that should be defined for the callback
 * @returns A function to be called when the custom API is invoked.
 */
function createCallback(apiRef, name, cat, code, funcArgs) {
    code = code || noop;
    let callback;
    try {
        if (typeof (code) === 'string') { // code supplied is in the form of a string
            if (isFormula(code)) { // code string is a formula; convert it to  string supplied
                // don't treat param as field name
                const paramAsFieldBack = converter.config.getParamAsFieldName();
                converter.config.setParamAsFieldName(false);
                const rosettaJsSrc = converter.getRosettaJSFromFormula(apiRef, code.trim()).converted || '';
                converter.config.setParamAsFieldName(paramAsFieldBack);
                callback = extenderEvals.createFunction(rosettaJsSrc, funcArgs, converter.config.getRosettaJSname());
            }
            else { // assume code is stringified javascript
                callback = extenderEvals.createFunction(code, funcArgs, converter.config.getRosettaJSname());
            }
        }
        else if (typeof (code) === 'function') { // code supplied is an actual Function Object
            callback = code;
        }
        else {
            // default to empty function throwing unimplemented err; same as APIs not yet implemented
            callback = () => { throw new Error(`API ${cat}:${name} is not implemented!`); };
        }
    }
    catch (err) {
        throw new Error(`Error converting code supplied for ${cat}.${name} into a callable method: ${err}`);
    }
    return callback;
}
/**
 * @private
 * Parse parameters from a code function in the custom API definitions.
 * @param {*} code The code who's parameters should be parsed. It can be a function or a string. If it is a string, the following
 * formats are supported:
 * - function (arg) {...}
 * - function (arg = default_value) {...}
 * - function (arg, arg) {...}
 * - function (arg = default_value, arg = default_value) {...}
 * - arg => ...
 * - (arg, arg) => ...
 * - (arg = default_value, arg = default_value) => ...
 * @returns {string[]} An array of the parameter names.
 */
function parseParameters(code) {
    let params = [];
    const funcString = code.toString().trim();
    if (!funcString.startsWith('function') && funcString.indexOf("=>") !== -1) {
        let paramStr = funcString.substring(0, funcString.indexOf("=>")).trim();
        if (paramStr.startsWith("(")) {
            paramStr = paramStr.substring(1, paramStr.indexOf(')'));
            if (paramStr.length > 0) {
                params = paramStr.split(',');
            }
        }
        else {
            params.push(paramStr); // Only a single parameter
        }
    }
    else if (funcString.startsWith('function')) {
        let paramStr = funcString.substring(funcString.indexOf('(') + 1, funcString.indexOf(')')).trim();
        if (paramStr.length > 0) {
            params = paramStr.split(',');
        }
    }
    return params;
}
/**
 * Register an API by adding it as an object to the referential array of APIs
 * Defines/redefines the Rosetta API library by creating/updating a node in the API object
 * The API object may be redefined if when using the existing category, name, language combination
 * If language param is supplied, the API node will also define the method at the formula language level and
 * the main method will point to call the method inside the language object
 *
 * @param {Object} apiRef required. reference to the rosetta API object tree where to register the method.
 * @param {Object} data required. object defining the extended API. object props as follows:
 *   - "name" : <String>  required. the API method name to register under rosetta
 *   - "cat"  : <String>  optional. the category name where the API name will be defined under. default: "Custom"
 *   - "lang" : <String>  optional. the formula language implementation layer to register the method under. default: undefined
 *   - "namef": <String>  optional. the method name to use in the formula lang implementations layer. default: name arg
 *   - "code" : <String|Function>  optional. a string with the formula to convert or a callback function. default: noop: () => {}
 *
 * @example
 * // code as actual js arrow function object, default params for the rest
 * // defines <rosettaObj>.Custom.hello = s => alert(`hello $(s)}`)
 * registerAPI(
 *   apiRef:rosettajs,
 *   {
 *     "name":"hello(s)",
 *     "code": s => alert(`hello $(s)}`)
 *   }
 * );
 *
 * // code as actual js function object,
 * // defines <rosettaObj>.Text.hello(args...) -> .Text._notes.Hello_Test(args...) = function(name) { return "hello " + name; }
 * registerAPI(
 *   apiRef:rosettajs,
 *   {
 *     "name": "hello(name)",
 *     "cat": "Text",
 *     "lang": "notes",
 *     "namef": "Hello_Test",
 *     "code": function(name) { return "hello " + name; }
 *   }
 * );
 *
 * // code as stringified js function body,
 * // defines <rosettaObj>.Text.hellop(args...) -> .Text._notes.HelloPhone_Test(args...) = function(name,phone) { return `hello ${name}. phone is ${phone}` }
 * registerAPI(
 *   apiRef:rosettajs,
 *   {
 *     "name": "hellop(name,phone)",
 *     "cat": "Text",
 *     "lang": "notes",
 *     "namef": "HelloPhone_Test",
 *     "code": "{ return `hello ${name}. phone is ${phone}` }"
 *   }
 *
 * // code as stringified notes formula code (gets auto-converted to rosettajs),
 * // defines <rosettaObj>.Custom.myAbs -> .Custom._notes.myAbs(args...) = n => { return rosettajs.Math.abs(n)+10 }`)
 * registerAPI(
 *   apiRef:rosettajs,
 *   {
 *     "name":"myAbs(n)",
 *     "code": "@Abs(n)+10;"
 *   }
 * );
 *
 * // code as stringified open formula code (gets auto-converted to rosettajs),
 * // defines <rosettaObj>.Custom.myAbs -> .Custom._openFormula.MYABS(args...) = n => { return rosettajs.Math.abs(n)+10 }`)
 * registerAPI(
 *   apiRef:rosettajs,
 *   {
 *     "name":"myAbs(n)",
 *     "namef": "MYABS"
 *     "code": "=ABS(n)+10;"
 *   }
 * );
 *
 * @returns {Object} the return value from registerCustomAPI
 * @throws {String}  Error object string representing registration failure
 */
function registerAPI(apiRef, data) {
    // check and normalize params to expected rosettajs API object schema
    if (!apiRef) {
        throw new Error(`API reference was not supplied!`);
    }
    let { name, namef, funcArgs, cat, lang, code } = parseCustomData(data);
    apiRef[cat] = typeof (apiRef[cat]) === "undefined" ? {} : apiRef[cat]; // if category of API is new, create empty object for it first
    // langRef is the underlying formula language implementations object; example: _notes, _openFormula
    let langRef;
    if (lang) {
        apiRef[cat][lang] = typeof (apiRef[cat][lang]) === "undefined" ? {} : apiRef[cat][lang];
        langRef = apiRef[cat][lang];
    }
    // CREATE A CALLBACK FUNCTION FROM THE CODE SUPPLIED:
    let callback = createCallback(apiRef, name, cat, code, funcArgs);
    // CREATE INTERFACE TO CALLBACK FUNCTION IN FORMULA OR DIRECT
    let ifc;
    if (langRef) {
        ifc = langRef[namef] = callback; // register callback under the language reference object
    }
    else {
        ifc = callback;
    }
    console.debug(`RosettaJS API: Registered new method: <api>.${cat}.${name}${langRef ? '->' + lang + '.' + namef : ''}`);
    // REGISTER API:
    // create a rosetta API method to process args and call the registered method under the language reference obj or the callback directly
    apiRef[cat][name] = (...args) => {
        return ifc(...args);
    };
    return apiRef[cat][name];
}
exports.registerAPI = registerAPI;
/**
 * Deregister an API defined by an extension definition objects.
 * @param {object} apiRef reference to the rosetta api object
 * @param {Array} data a JSON objects representing a custom API that have been registered. See {@link module:rosetta-api~registerAPI registerAPI data parameter} for schema.
 * @throws An error if the deregister failed.
 */
function deregisterAPI(apiRef, data) {
    if (!apiRef) {
        throw new Error(`deregisterAPIs: API reference was not supplied!`);
    }
    let { name, namef, cat, lang } = parseCustomData(data);
    if (apiRef[cat]) {
        if (apiRef[cat][name]) {
            delete apiRef[cat][name];
        }
        else {
            console.warn(`deregisterAPI: API reference does not contain API name ${name}`);
            throw new Error(`API reference does not contain API name ${name}`);
        }
        if (lang.length > 0) {
            if (apiRef[cat][lang]) {
                if (apiRef[cat][lang][namef]) {
                    delete apiRef[cat][lang][namef];
                    if (Object.keys(apiRef[cat][lang]).length === 0) {
                        // No more functions defined in language
                        delete apiRef[cat][lang];
                    }
                }
                else {
                    console.warn(`deregisterAPI: API reference does not contain formula name ${namef} for language ${lang}`);
                    throw new Error(`API reference does not contain formula name ${namef} for language ${lang}`);
                }
            }
            else {
                console.warn(`deregisterAPI: API reference does not contain language ${lang} for category ${cat}`);
                throw new Error(`API reference does not contain language ${lang} for category ${cat}`);
            }
        }
        if (Object.keys(apiRef[cat]).length === 0) {
            // No more functions defined in category
            delete apiRef[cat];
        }
    }
    else {
        console.warn(`deregisterAPI: API reference does not contain category ${cat}`);
        throw new Error(`API reference does not contain category ${cat}`);
    }
}
exports.deregisterAPI = deregisterAPI;
/**
 * Register APIs from an array of JSON API extension definition objects.
 * Each object in the array must adhere to schema required in registerAPI method
 *
 * @param {String} apiRef required. reference to the rosetta api object tree
 * @param {Array} dataArray an array of JSON objects, each representing a custom API to register. See {@link module:rosetta-api~registerAPI registerAPI data parameter} for schema.
 *
 * @example
 * registerAPI(
 *   apiRef:rosettajs,
 *   [
 *     { // defines: <rosettajs>.Custom.simplest = () => { }
 *       "name": "simplest"
 *     },
 *     { // defines: <rosettajs>.Text.simpler = () => { }
 *       "name": "simpler",
 *       "cat": "Text",
 *     },
 *     { // defines: <rosettajs>.Text.simple = function(x) { return x+1; }
 *       "name": "simple(x)",
 *       "cat": "Text",
 *       "code": function(x) { return x+1; }
 *     },
 *     { // defines: <rosettajs>.Text.simple = function(x) { this._notes.simple(): function(x) { return x+1; } }
 *       "name": "simpleNotes(x)",
 *       "cat": "Text",
 *       "lang": "notes",
 *       "code": function(x) { return x+1; }
 *     },
 *     { // defines: <rosettajs>.Text.simple = function(x) { this._notes.ADVanceNOTES123(): function(x) { return x+1; } }
 *       "name": "advancedNotes(x)",
 *       "cat": "Text",
 *       "lang": "notes",
 *       "namef": "ADVanceNOTES123",
 *       "code": function(x) { return x+1; }
 *     },
 *     {
 *       "cat": "Text",
 *       "name": "hello(name)",
 *       "lang": "notes",
 *       "namef": "Hello",
 *       "code": function(name) { return "hello " + name; }
 *     },
 *     {
 *       "name": "goodbye(name)",
 *       "lang": "notes",
 *       "cat": "Text",
 *       "code": function(name) { return "bye bye " + name; }
 *     },
 *     { // defines: <rosettajs>.Custom.weather = function(x) { this._openFormula.WEATHER(): function(zip) { return "Sunny in " + zip; } }
 *       "name": "WEATHER(zip)",
 *       "lang": "open formula",
 *       "cat": "Custom",
 *       "code": function (zip) { return "Sunny in " + zip; }
 *     },
 *     { // defines: <rosettajs>.Custom.absPlusX = function(n,x) { this._notes.absPlusX(): javascript conversion result from "@Abs(n)+x" }
 *       "name": "AbsPlusX(n; x)",
 *       "lang": "notes",
 *       "cat": "Custom",
 *       "code": "@Abs(n)+x;"
 *     }
 *   ]
 * );
 *
 * @returns {Array} Array of callbacks for the API methods registered
 * @throws {String} Error object string representing registration failure
 */
function registerAPIs(apiRef, dataArray = []) {
    if (!apiRef) {
        throw new Error(`API reference was not supplied!`);
    }
    var registeredAPIs = [];
    dataArray.forEach(data => {
        try {
            registeredAPIs.push(registerAPI(apiRef, data));
        }
        catch (err) {
            if ((Object.keys(data).length > 0) && data.name) {
                console.error('Error registering APIs: ', data);
            }
            throw err;
        }
    });
    return registeredAPIs;
}
exports.registerAPIs = registerAPIs;
/**
 * Deregister APIs from an array of JSON API extension definition objects.
 * @param {object} apiRef reference to the rosetta api object
 * @param {Array} dataArray an array of JSON objects, each representing a custom APIs that have been registered. See {@link module:rosetta-api~registerAPI registerAPI data parameter} for schema.
 * @returns {Array} An array of errors indicating any APIs that failed to deregister. An empty array if all were successful.
 */
function deregisterAPIs(apiRef, dataArray = []) {
    if (!apiRef) {
        throw new Error(`deregisterAPIs: API reference was not supplied!`);
    }
    const errors = [];
    dataArray.forEach(data => {
        try {
            deregisterAPI(apiRef, data);
        }
        catch (err) {
            errors.push(err);
        }
    });
    return errors;
}
exports.deregisterAPIs = deregisterAPIs;
/**
 * Get the names for the Tern files generated for the Rosetta API.
 * @returns {Object} The names of the tern file definitions generated for the Rossetta API.
 * Keys are "API" for the Rosetta javascript API, "Notes" for the Notes formula, and "OpenFormula" for OpenFormula.
 */
const getTernFileNames = function () {
    return { API: "rosetta_api_tern.json", Notes: "notes_formula_tern.json", OpenFormula: "open_formula_tern.json" };
};
exports.getTernFileNames = getTernFileNames;
/**
 * Generate Tern definitions for a set of custom APIs. The Tern definitions can be used for intellisense support.
 *
 * @param {Object} apiRef reference to the rosetta API object tree where to register the method.
 * @param {Array} dataArray an array of JSON objects, each representing a custom API to register. See {@link module:rosetta-api~registerAPI registerAPI data parameter} for schema.
 * @param {Object} config contains the name for the api definitions and the name for the formula definitions.
 * @returns {Object} An object containing a property 'API' for the Rosetta API Tern defintions. If the lang parameter is
 * 'notes' or 'open formula' in any of the custom definition objects, then the property 'Formula' will contain the formula Tern definitions.
 */
const generateTernDefsForCustomAPIs = function (apiRef, dataArray, config) {
    let formulaTernDefs;
    const apiTernDefs = {
        "!name": config.apiName,
        "voltmx": { "rosettajs": {} }
    };
    dataArray.forEach(apiDef => {
        var _a;
        let { name, cat, lang, namef, code, doc, docf } = apiDef;
        if (typeof name === 'undefined' || !name) {
            throw new Error('Custom api definition does not have a name: ' + JSON.stringify(apiDef));
        }
        const argsInName = parseName(name); // Parse arguments from name
        const funcArgs = argsInName[1].replace(/;/g, ','); // Notes will use ; as an arg separator
        const apiTernDef = {}; // Tern definiton for the rosetta API implementation
        let formulaTernDef; // Tern defintion for the formula implementation. Only set if a valid formula language specified.
        if (lang && ['notes', 'open formula'].includes(lang.toLowerCase())) {
            formulaTernDef = {};
        }
        if (argsInName && argsInName[0])
            name = argsInName[0].split('(')[0]; // strip args from name arguments since name will be used as the prop in the API object
        if (!name) {
            throw new Error(`API name ${argsInName} null after stripping arguments.`);
        }
        cat = cat || 'Custom';
        let Cat = capFirstLetter(cat); // categories always start with capital letter
        // Determine the function signature from the code.
        code = code || noop;
        let callback = createCallback(apiRef, name, Cat, code, funcArgs);
        let params = parseParameters(callback);
        let type = "fn(";
        let seperator = "";
        params.forEach(param => {
            param = param.trim();
            if (param.indexOf("=") !== -1) {
                // Remove default value setting. This is not supported by Tern
                param = param.substring(0, param.indexOf("=")).trim();
            }
            type += seperator + param + ": ?";
            seperator = ", ";
        });
        type += ")";
        // Set Rosetta API Tern definition
        apiTernDef["!type"] = type;
        if (doc) {
            apiTernDef["!doc"] = doc;
        }
        apiTernDefs[name] = apiTernDef;
        if (cat) {
            // Create a category object in the rosetta api Tern definition 
            const catObj = (_a = apiTernDefs.voltmx.rosettajs[cat]) !== null && _a !== void 0 ? _a : {};
            catObj[name] = name;
            apiTernDefs.voltmx.rosettajs[cat] = catObj;
        }
        // Set formula Tern definition if it is being defined
        if (formulaTernDef) {
            formulaTernDef["!type"] = type;
            const formulaDoc = docf !== null && docf !== void 0 ? docf : doc;
            if (formulaDoc) {
                formulaTernDef["!doc"] = formulaDoc;
            }
            namef = namef || name; // name in formula, default to name if none suppied
            const formulaName = (lang === "open formula" ? "=" : "@") + namef;
            if (!formulaTernDefs) {
                formulaTernDefs = { "!name": config.formulaName };
            }
            formulaTernDefs[formulaName] = formulaTernDef;
            if (cat) {
                // Include the category in the formula tern doc
                const doc = formulaTernDefs[formulaName]["!doc"];
                formulaTernDefs[formulaName]["!doc"] = `@category:${cat}\n${doc !== null && doc !== void 0 ? doc : ""}`;
            }
        }
    });
    return { API: apiTernDefs, Formula: formulaTernDefs };
};
exports.generateTernDefsForCustomAPIs = generateTernDefsForCustomAPIs;
/**
 * Volt MX framework based API: rosettajsLogger;
 * returns the logger object under the VoltMX API layer
 * @returns {*} The rosettajs logger object under the VoltMX API layer
 * @throws {String}  Error object with string representing the failure message
 */
function rosettajsLogger() {
    if (isCurrentFrameworkVoltMX()) {
        return api_vmx.rosettajsLogger();
    }
    throw new Error('rosettajsLogger: voltmx framework only');
}
exports.rosettajsLogger = rosettajsLogger;
/**
 * getServiceType
 * @param {string} serviceName for the Volt MX Object Service
 * @returns {string} the service type for the specified service
 */
function getServiceType(serviceName) {
    if (isCurrentFrameworkVoltMX()) {
        return api_vmx.getServiceType(serviceName);
    }
    throw new Error('getServiceType: voltmx framework only');
}
exports.getServiceType = getServiceType;
/**
 * setServiceTypeAsOfflineObjects(serviceName)
 * @param {string} serviceName for the Volt MX Object Service
 * @returns {string} the service type for the specified service
 */
function setServiceTypeAsOfflineObjects(serviceName) {
    if (isCurrentFrameworkVoltMX()) {
        return api_vmx.setServiceTypeAsOfflineObjects(serviceName);
    }
    throw new Error('setServiceTypeAsOfflineObjects: voltmx framework only');
}
exports.setServiceTypeAsOfflineObjects = setServiceTypeAsOfflineObjects;
/**
 * setServiceTypeAsOnlineObjects(serviceName)
 * @param {string} serviceName for the Volt MX Object Service
 * @returns {string} the service type for the specified service
 */
function setServiceTypeAsOnlineObjects(serviceName) {
    if (isCurrentFrameworkVoltMX()) {
        return api_vmx.setServiceTypeAsOnlineObjects(serviceName);
    }
    throw new Error('setServiceTypeAsOnlineObjects: voltmx framework only');
}
exports.setServiceTypeAsOnlineObjects = setServiceTypeAsOnlineObjects;
/**
 * Volt MX framework based API: getDefaultServiceType;
 * returns the default service type under the VoltMX API layer expressed as a string
 * @returns {String} The default service type under the VoltMX API layer
 * @throws {String}  Error object with string representing the failure message
 */
function getDefaultServiceType() {
    if (isCurrentFrameworkVoltMX()) {
        return api_vmx.getDefaultServiceType();
    }
    throw new Error('getDefaultServiceType: voltmx framework only');
}
exports.getDefaultServiceType = getDefaultServiceType;
/**
 * Volt MX framework based API: setDefaultServiceTypeAsOnlineObjects;
 * Sets the default service type to "object.online", under the VoltMX API layer
 * @returns {String} The default service type
 * @throws {Object} Error object with string representing the failure message
 */
function setDefaultServiceTypeAsOnlineObjects() {
    if (isCurrentFrameworkVoltMX()) {
        return api_vmx.setDefaultServiceTypeAsOnlineObjects();
    }
    throw new Error('setDefaultServiceTypeAsOnlineObjects: voltmx framework only');
}
exports.setDefaultServiceTypeAsOnlineObjects = setDefaultServiceTypeAsOnlineObjects;
/**
 * Volt MX framework based API: setDefaultServiceTypeAsOfflineObjects;
 * Sets the default service type to "object.offline", under the VoltMX API layer
 * @returns {String} The default service type
 * @throws {Object} Error object with string representing the failure message
 */
function setDefaultServiceTypeAsOfflineObjects() {
    if (isCurrentFrameworkVoltMX()) {
        return api_vmx.setDefaultServiceTypeAsOfflineObjects();
    }
    throw new Error('setDefaultServiceTypeAsOfflineObjects: voltmx framework only');
}
exports.setDefaultServiceTypeAsOfflineObjects = setDefaultServiceTypeAsOfflineObjects;
/**
 * Volt MX framework based API: setDefaultServiceTypeAsIntegration;
 * Sets the default service type to "integration", under the VoltMX API layer
 * @returns {String} The default service type
 * @throws {Object} Error object with string representing the failure message
 */
function setDefaultServiceTypeAsIntegration() {
    if (isCurrentFrameworkVoltMX()) {
        return api_vmx.setDefaultServiceTypeAsIntegration();
    }
    throw new Error('setDefaultServiceTypeAsIntegration: voltmx framework only');
}
exports.setDefaultServiceTypeAsIntegration = setDefaultServiceTypeAsIntegration;
/**
 * Volt MX framework based API: isCurrentServiceTypeOnlineObjects;
 * Is current service type "object.online"?
 * @returns {Boolean} true if the current service type is set to object.online
 * @throws {Object} Error object with string representing the failure message
 */
function isCurrentServiceTypeOnlineObjects() {
    if (isCurrentFrameworkVoltMX()) {
        return api_vmx.isCurrentServiceTypeOnlineObjects();
    }
    throw new Error('isCurrentServiceTypeOnlineObjects: voltmx framework only');
}
exports.isCurrentServiceTypeOnlineObjects = isCurrentServiceTypeOnlineObjects;
/**
 * Volt MX framework based API: isCurrentServiceTypeOfflineObjects;
 * Is current service type "object.offline"?
 * @returns {Boolean} true if the current service type is set to object.offline
 * @throws {Object} Error object with string representing the failure message
 */
function isCurrentServiceTypeOfflineObjects() {
    if (isCurrentFrameworkVoltMX()) {
        return api_vmx.isCurrentServiceTypeOfflineObjects();
    }
    throw new Error('isCurrentServiceTypeOfflineObjects: voltmx framework only');
}
exports.isCurrentServiceTypeOfflineObjects = isCurrentServiceTypeOfflineObjects;
/**
 * Volt MX framework based API: isCurrentServiceTypeIntegration;
 * Is current service type "integration"?
 * @returns {Boolean} true if the current service type is set to integration
 * @throws {Object} Error object with string representing the failure message
 */
function isCurrentServiceTypeIntegration() {
    if (isCurrentFrameworkVoltMX()) {
        return api_vmx.isCurrentServiceTypeIntegration();
    }
    throw new Error('isCurrentServiceTypeIntegration: voltmx framework only');
}
exports.isCurrentServiceTypeIntegration = isCurrentServiceTypeIntegration;
/**
 * Volt MX framework based API: setCurrentServerDatabase;
 * Sets the server location and file name to be used under the VoltMX API layer
 * @param {*} serverDatabase The server location and file name of the database.
 * @throws {Object} Error object with string representing the failure message
 */
function setCurrentServerDatabase(serverDatabase) {
    if (isCurrentFrameworkVoltMX()) {
        return api_vmx.setCurrentServerDatabase(serverDatabase);
    }
    throw new Error('setCurrentServerDatabase: voltmx framework only');
}
exports.setCurrentServerDatabase = setCurrentServerDatabase;
/**
 * Volt MX framework based API: getCurrentServerDatabase;
 * Get the server location and file name being used under the VoltMX API layer
 * @returns {String} The server location and file name of the database under the VoltMX API layer
 * @throws {Object} Error object with string representing the failure message
 */
function getCurrentServerDatabase() {
    if (isCurrentFrameworkVoltMX()) {
        return api_vmx.getCurrentServerDatabase();
    }
    throw new Error('getCurrentServerDatabase: voltmx framework only');
}
exports.getCurrentServerDatabase = getCurrentServerDatabase;
/**
 * Volt MX framework based API: getCurrentServiceName;
 * Gets the current service name being used under the VoltMX API layer
 * @returns {String} The current service name under the VoltMX API layer
 * @throws {Object} Error object with string representing the failure message
 */
function getCurrentServiceName() {
    if (isCurrentFrameworkVoltMX()) {
        return api_vmx.getCurrentServiceName();
    }
    throw new Error('getCurrentServiceName: voltmx framework only');
}
exports.getCurrentServiceName = getCurrentServiceName;
/**
 * Volt MX framework based API: setActionEventObject;
 * Sets the Action Event Object
 * @param {*} eventobject The Action Event Object used by Action Widgets.
 * @throws {Object} Error object with string representing the failure message
 */
function setActionEventObject(eventobject) {
    if (isCurrentFrameworkVoltMX()) {
        return api_vmx.setActionEventObject(eventobject);
    }
    throw new Error('setActionEventObject: voltmx framework only');
}
exports.setActionEventObject = setActionEventObject;
/**
 * Volt MX framework based API: getActionEventObject;
 * Gets the Action Event Object
 * @returns {*} The current Action Event Object
 * @throws {Object} Error object with string representing the failure message
 */
function getActionEventObject() {
    if (isCurrentFrameworkVoltMX()) {
        return api_vmx.getActionEventObject();
    }
    throw new Error('getActionEventObject: voltmx framework only');
}
exports.getActionEventObject = getActionEventObject;
//# sourceMappingURL=API.js.map