UNPKG

@testcomplete/usermanager

Version:

A library that pick a credentials group session from a catalogue for a testing execution

689 lines (589 loc) 20.4 kB
require('nativejs-proto-extensions'); let ifopt = { // @TODO: Make arg validation of functions /** * @var {Boolean} colorize Indicating to not use color in log ouputs. */ colorize: true, /** * @var {Object} colors Default Color of ifopt. */ colors: { Restore: "[xlb]", Reset: "\x1b[0m", Bright: "\x1b[1m", Dim: "\x1b[2m", Underscore: "\x1b[4m", Blink: "\x1b[5m", Reverse: "\x1b[7m", Hidden: "\x1b[8m", fg: { Black: "\x1b[30m", Red: "\x1b[31m", Green: "\x1b[32m", Yellow: "\x1b[33m", Blue: "\x1b[34m", Magenta: "\x1b[35m", Cyan: "\x1b[36m", White: "\x1b[37m", Crimson: "\x1b[38m", Success: "\x1b[32m", Error: "\x1b[31m", Info: "\x1b[36m", Warning: "\x1b[33m", Debug: "\x1b[38;5;208m" }, bg: { Black: "\x1b[40m", Red: "\x1b[41m", Green: "\x1b[42m", Yellow: "\x1b[43m", Blue: "\x1b[44m", Magenta: "\x1b[45m", Cyan: "\x1b[46m", White: "\x1b[47m", Crimson: "\x1b[48m", Success: "\x1b[42m", Error: "\x1b[41m", Info: "\x1b[46m", Warning: "\x1b[43m", Debug: "\x1b[38;5;208m" } }, /** * @var {String} separator Default separator for arguments. */ separator: ",", /** * @var {String} shortopt Memorized short options. */ shortopt: "", /** * @var {Array} longopt Memorized list of long options. */ longopt: [], /** * @var {Array} implicits Memorized list of property name of implicit * arguments. */ implicits: [], /** * @var {Object} implicitRefs Memorized of object reference to bridge * value of implicit arguments. */ implicitRefs: null, /** * @var {Object} levels Logging levels */ levels: { }, /** * @var {Object} smartLogging Log level rule to manage display. */ smartLogging: { }, /** * @var {boolean} selfDebug To display debug message of ifopt. */ selfDebug: false, /** * Set options to parse without parsing them. * * @param {String} sopt Short Options * @param {Array} lopt Long Options * @param {Array} implicitNames (Optional) Name of property as implicit * argument * @param {Object} implicitRefs (Optional) Object reference to brigde with * caller * * @return {boolean} */ setOpts: function ( sopt, lopt, implicitNames = [], implicitRefs = {} ) { ifopt.setShortOpt(sopt); ifopt.setLongOpt(lopt); ifopt.setImplicitOpt(implicitNames, implicitRefs); return true; }, /** * Set the short options for the instance. * * @param {String} sopt Provided short options string. * * @return {boolean} */ setShortOpt: function (sopt) { ifopt.shortopt = sopt; return true; }, /** * Set the long options for the instance. * * @param {Array} lopt Provided long options list. * * @return {boolean} */ setLongOpt: function (lopt) { ifopt.longopt = lopt; return true; }, /** * Set the implicit argument of the program (name and ref object). * * @param {Array} implicitNames Name of properties of ref object. * @param {Object} implicitRefs Object Reference. * * @return {boolean} */ setImplicitOpt: function (implicitNames, implicitRefs) { ifopt.implicits = implicitNames; ifopt.implicitRefs = implicitRefs; return true; }, /** * Set the separator to split an option. * * @param {String} sep The separator char. * * @return {boolean} */ setSeparator: function (sep) { ifopt.separator = sep; return true; }, /** * Get the current color object configuration. * * @return {Object|{fg: {Red: string, Cyan: string, White: string, Yellow: string, Blue: string, Magenta: string, Black: string, Crimson: string, Green: string}, Reverse: string, bg: {Red: string, Cyan: string, White: string, Yellow: string, Blue: string, Magenta: string, Black: string, Crimson: string, Green: string}, Blink: string, Dim: string, Hidden: string, Underscore: string, Reset: string, Bright: string}} */ getColors: function () { return ifopt.colors; }, /** * Return the color string for specified path * * @param colorPty Path of the color in property ifopt.colors. * * @return {*} */ getColor: function (colorPty) { return ifopt.colors.getValueForPath(colorPty); }, /** * Set the new object colors configuration. * Use getColors first, perform modification and update with this method. * * @param {Object|{fg: {Red: string, Cyan: string, White: string, Yellow: string, Blue: string, Magenta: string, Black: string, Crimson: string, Green: string}, Reverse: string, bg: {Red: string, Cyan: string, White: string, Yellow: string, Blue: string, Magenta: string, Black: string, Crimson: string, Green: string}, Blink: string, Dim: string, Hidden: string, Underscore: string, Reset: string, Bright: string}} colors */ setColors: function (colors) { ifopt.colors = colors; }, /** * Set/Update a color specifying its property path * * @param {String} colorPty The object property path (fg.Yellow) * @param {String} color Bash Color Instruction * * @return {boolean} */ setColor: function (colorPty, color) { let newColor = ifopt.colors; let newColorRef = newColor; colorPty = colorPty.split("."); for (let i = 0; i < colorPty.length; i++) { let pty = colorPty[i]; if (i === (colorPty.length - 1)) { newColorRef[pty] = color; } else{ if (!newColorRef[pty]) { newColorRef[pty] = {}; } newColorRef = newColorRef[pty]; } } Object.assign(ifopt.colors, newColor); return true; }, /** * Neutralize colors controls to blank. * If called without parameter, the defined colors for ifopt * instance are neutralize. You can passe your colors object definition * (copy from ifopt one using getColors()). * * @param {Object} colors Colors object definition (optional) * * @return {*} */ removeColor: function (colors = ifopt.colors) { let removed = Object.assign({}, colors); for (let pty in removed) { if (removed.hasOwnProperty(pty)) { if (typeof removed[pty] === 'string') { removed[pty] = ''; } if (removed[pty] instanceof Object) { removed[pty] = ifopt.removeColor(removed[pty]); } } } return removed; }, /** * Set log message will not use colors. * * @return {boolean} */ noColor: function () { ifopt.colorize = false; return true; }, /** * Set if log message use colors. * If called without parameters, meaning true, use colors. * * @param {boolean} usage Use color (or not (false)) * * @return {boolean} */ useColor: function (usage = true) { ifopt.colorize = (usage); return true; }, /** * Traiter les arguments passé au programme * * @param shortopt Définition des options courtes. * @param longopt Définition des options longues. * @param implicits Définition des paramètre implicite. * @param implicitRefs Objet de référence pour passer les valeurs. * * @returns {{}} Options parsées. */ getopt: function (shortopt, longopt, implicits, implicitRefs) { shortopt = shortopt || ifopt.shortopt; longopt = longopt || ifopt.longopt; implicits = implicits || ifopt.implicits; implicitRefs = implicitRefs || ifopt.implicitRefs; ifopt.shortopt = shortopt; ifopt.longopt = longopt; ifopt.implicits = implicits; ifopt.implicitRefs = implicitRefs; ifopt.checkShortopt(shortopt); let processedArg = 0; let implicitArg = 1; let procOptions = {}; // .optarg, .opt, .optval let runWithoutError = true; process.argv.forEach(function(arg) { processedArg++; // Skip Interpreter (node.exe) and it self (mdmerge.js) if (processedArg < 3) return; // Check if it is a explicit argument (longopt). if (/^--/.test(arg)) { let splitOpt = arg.match(/^--([a-zA-Z0-9._-]+)=?(.*)/); if (!splitOpt) return; let opt = splitOpt[1]; let optVal = splitOpt[2]; for(let i = 0; i < longopt.length; i++) { let lgOpt = longopt[i].match(/([a-zA-Z0-9._-]+)(:*)/); let lgOptName = lgOpt[1]; let lgOptConfig = lgOpt[2]; if (opt === lgOptName) { if (lgOptConfig === ':' && !optVal) { ifopt.log(`Option %s require a value`, 1, [opt]); runWithoutError = false; } if (procOptions[opt]) { procOptions = ifopt.appendOption(procOptions, arg, opt, optVal); } else { procOptions[opt] = ifopt.createOption(arg, opt, optVal); } } } } // Check if it is a explicit argument (shortopt). else if (/^-/.test(arg)) { let opt = arg.substr(1, 1); let optIdx = shortopt.indexOf(opt); let optVal = arg.match(/^-(.+)=(.*)/); if (optVal) optVal = optVal[2]; if (optIdx < 0 ) return; let nextOptChar1 = shortopt.substr(optIdx +1, 1); let nextOptChar2 = shortopt.substr(optIdx +2, 1); if (nextOptChar1 === ':' && nextOptChar2 !== ':' && !optVal) { ifopt.log(`Option %s require a value`, 1, [opt]); runWithoutError = false; } if (procOptions[opt]) { procOptions = ifopt.appendOption(procOptions, arg, opt, optVal); } else { procOptions[opt] = ifopt.createOption(arg, opt, optVal); } } // This is an implicit argument. else { // Check if there is an implicit argument if (implicits[implicitArg - 1]) { let implicitPty = implicits[implicitArg - 1]; implicitRefs[implicitPty] = arg; } implicitArg++; } }); if (runWithoutError) { return procOptions; } else { process.exit(); } }, // @TODO validation de la chaine shortopt pour limiter les doublons checkShortopt: function() { }, /** * Créer une option parsée pour utilisation ultérieure. * * @param optarg Option d'origine passée en argument. * @param opt Option isolée. * @param optval Valeur de l'option. * * @returns {{optarg: *, opt: *, optval: *}} */ createOption: function (optarg, opt, optval) { return { "arg": optarg, "opt": opt, "val": optval }; }, /** * Afficher un message dans le stream. * * @param message Message à afficher. * @param level Niveau de message. 0=OK,1=KO,2=WARN. * @param args Arguments which will replace placeholder in message. * @param ignoreSmartLog Ignore smartLog rules. * * @return {number} */ log: function (message = '', level = 0, args = [], ignoreSmartLog = false){ let lvlConf = ifopt.levels[level]; let display = true; let colors = (ifopt.colorize) ? ifopt.colors : ifopt.removeColor(); // Replace Placeholders. let argi = 0; args.map(function (arg) { argi++; arg = colors.fg.Yellow + arg + colors.Reset; arg = arg.split(colors.Restore).join(colors.fg.Yellow); if (/%[1-9]+\$s/.test(message)) { let regexp = new RegExp(`%${argi}\\$s`); message = message.replace(regexp, arg) } else { message = message.replace(/%s/, arg); } }); // Check "smartLogin" for (let group in ifopt.smartLogging) { if (group === 'getValueForPath') continue; let enabled = ifopt.smartLogging[group].enabled; let levels = ifopt.smartLogging[group].levels; if (levels.lastIndexOf(level) >= 0) { display = enabled; break; } } if (display || ignoreSmartLog) { console.log( "[ " + lvlConf.color + lvlConf.name + colors.Reset + " ] : " + message.split(colors.Restore).join(colors.Reset) ); } return lvlConf.return; }, /** * Create logging level for STDx. Will display specified name and color. * * @param {number} level Level number (must be unique) * @param {string} name Display logging name. * @param {string} color Path to the color of ifopt.colors (check ifopt.getColors()) * @param {number} lreturn Return code for the logging level * * @return {boolean} */ createLogLevel: function (level, name, color = 'Reset', lreturn = 0) { // Check if level does not exist. if (ifopt.levels.hasOwnProperty(level)) { let levelName = ifopt.getValueForPath(`levels.${level}.name`); ifopt.log("Log level %s already exist (name: %s). Logging level will be overwrited.", 2, [level, levelName]); } ifopt.levels[level] = { name: name, color: ifopt.colors.getValueForPath(color), return: lreturn }; return true; }, /** * Set display behavior for log() function using group, enabling boolean * for specified levels * * @param groupName Levels groupname to handle them * @param groupEnabled If false, levels will not display when calling log() * @param levels Levels of the group * * @return {boolean} */ setLogLevel: function (groupName, groupEnabled = false, levels = []) { if (!(typeof groupName === 'string')) { ifopt.log( "%s is not string", 1, ["setLogLevel() groupName"] ); return false; } if (ifopt.selfDebug) { ifopt.log("groupName : %s", 4, [groupName]) ifopt.log("groupEnabled '%s'(%s) => %s", 4, [ groupEnabled, typeof groupEnabled, !!(groupEnabled) ]); } groupEnabled = !!(groupEnabled); levels = (typeof levels !== 'object') ? [levels] : levels; if (ifopt.selfDebug) { ifopt.log("levels :", 4); console.log(levels); } if (ifopt.smartLogging[groupName]){ ifopt.smartLogging[groupName].enabled = groupEnabled; if (levels.length > 0) { ifopt.smartLogging[groupName].levels = levels; } } else { ifopt.smartLogging[groupName] = { enabled: groupEnabled, levels: levels }; } if (ifopt.selfDebug) { ifopt.log("smartLogging :", 4); console.dir(ifopt.smartLogging, {depth: null}) } return true; }, /** * Aggregate value under a option when user use multiple times the same options. * * @param {Object} optstack * @param {String} optagr Entered option (short or long) * @param {String} opt Option Name * @param {String} optval Option Value * * @returns {Array} Return aggregated value for the option. */ appendOption: function (optstack, optagr, opt, optval) { if (!(optstack[opt].val instanceof Array)) { optstack[opt].val = [optstack[opt].val]; } optstack[opt].val.push(optval); return optstack; }, /** * Check the option/list of options are provided in the command line. * * @param {String|Array} opts Option/List of options * @param {String} op or|and operator telling if all option are require * or at least one. * @returns {boolean} */ isOption: function (opts, op = "or") { opts = !(opts instanceof Array) ? [].push(opts) : opts; let returnOp = (op.toLowerCase() !== 'or'); let OPTS = ifopt.getopt(); for (let i = 0; i < opts.length; i++) { let opt = opts[i]; if (OPTS[opt]) { if (op.toLowerCase() === 'or') { return true; } } else { if (op.toLowerCase() === 'and') { return false; } } } return returnOp; }, /** * Get all values under a unique list for provided options. * * @param {Array} opts List of options names. * * @returns {Array} List of values. */ getOptsValues: function (opts) { let outputArray = []; for (let i in opts) { let opt = opts[i]; if (ifopt.isOption([opt])) { outputArray = ifopt.optToArray(ifopt.getopt(), opt, outputArray); } } return outputArray; }, /** * Return the value of the first options specified in the array. * * @param {String|Array} opts Options to get value * * @return {[*]|boolean} The returned value or false if not found. */ getOptValue: function (opts) { let options = ifopt.getopt(); if (!(opts instanceof Array)) { opts = [opts] } for (let i = 0; i < opts.length; i++) { if (options[opts[i]]) { return options[opts[i]].val; } } return false; }, /** * Aggregate values of specified options to list of value (merge shortopt and longopt) * * @param {Array} optpool Program options data. * @param {String} name Name of this option (short or long). * @param {Array} outputArray Existing data list to aggregate in. * * @returns {Array} List of values. */ optToArray: function (optpool, name, outputArray) { if (optpool[name]) { if (optpool[name].val instanceof Array) { outputArray = outputArray.concat(optpool[name].val); } else { outputArray = outputArray.concat([optpool[name].val]) } } return outputArray; } }; /** * Initialization */ // Set own logging levels ifopt.createLogLevel(0, 'SUCCESS', 'fg.Success', 0); ifopt.createLogLevel(1, 'ERROR', 'fg.Error', 1); ifopt.createLogLevel(2, 'WARNING', 'fg.Warning', 0); ifopt.createLogLevel(3, 'INFO', 'fg.Info', 0); ifopt.createLogLevel(4, 'DEBUG', 'fg.Debug', 0); module.exports = ifopt;