@tableau/taco-toolkit
Version:
Tableau Connector Toolkit
297 lines • 24.6 kB
JavaScript
;
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAppLogOption = exports.parseFeatureFlags = exports.parseStaticServerPort = exports.parseMainPort = exports.parsePortRange = exports.parseArgs = exports.handleLoggerSetup = void 0;
var commander_1 = require("commander");
var node_os_1 = __importDefault(require("node:os"));
var node_path_1 = __importDefault(require("node:path"));
var uuid_1 = require("uuid");
var caller_type_1 = require("../../../../shared/enums/caller-type");
var error_codes_1 = require("../../../../shared/errors/error-codes");
var error_source_1 = require("../../../../shared/errors/error-source");
var status_code_1 = require("../../../../shared/errors/status-code");
var log_level_1 = require("../../../../shared/logger/log-level");
var eps_logger_1 = require("../../../logging/eps-logger");
var app_init_1 = require("./app-init");
var EPS_INSTANCE_ID = (0, uuid_1.v4)();
var epsTempDirRoot = node_path_1.default.join(node_os_1.default.tmpdir(), 'tableau-eps-temp');
var epsTempDir = node_path_1.default.join(epsTempDirRoot, EPS_INSTANCE_ID);
// TODO: the default folder should not have Tableau dependency...
// verify there's nothing replying on this, and point to cwd/log
var DEFAULT_LOG_DIR = node_path_1.default.join(node_os_1.default.homedir(), 'Documents', 'My Tableau Repository', 'Logs');
var DEFAULT_LOG_LEVEL = log_level_1.LogLevel.DEBUG;
var DEFAULT_STATIC_SERVER_UI_DIR = node_path_1.default.join(epsTempDir, 'static-server', 'app');
var DEFAULT_STATIC_SERVER_HANDLERS_DIR = node_path_1.default.join(epsTempDir, 'static-server', 'handlers');
var DEFAULT_LANGUAGE = 'en_US';
var DEFAULT_LOCALE = 'en_US';
/**
* A command line value for log level option to disable a log writer.
* Note: it should be only used in the command line layer.
*/
var LOG_OFF_LEVEL = 'off';
var logLevelChoices = __spreadArray(__spreadArray([], __read(log_level_1.logLevelValues), false), [LOG_OFF_LEVEL], false);
function handleLoggerSetup(args) {
var program = new commander_1.Command();
// throw for error cases, so that it can log errors and fall back
addLoggerOptions(program).allowUnknownOption().exitOverride();
try {
program.parse(args);
}
catch (error) {
// if logger configs are incorrect, init logger with fallback settings
eps_logger_1.Logger.init(EPS_INSTANCE_ID, {
filename: eps_logger_1.EPS_LOG_FILE_NAME,
fileLogDirPath: DEFAULT_LOG_DIR,
fileLogLevel: log_level_1.LogLevel.INFO,
sourceName: 'EPS',
consoleLogLevel: log_level_1.LogLevel.WARNING,
});
eps_logger_1.Logger.error("Invalid logging options: ".concat(error, "."));
eps_logger_1.Logger.warn('Initializing logger with fallback settings.');
return;
}
var _a = program.opts(), logDir = _a.logDir, logLevel = _a.logLevel, consoleLogLevel = _a.consoleLogLevel;
var appLogOption = getAppLogOption({ logDir: logDir, logLevel: logLevel, consoleLogLevel: consoleLogLevel });
var loggerConfig = (0, eps_logger_1.createLoggerConfig)('EPS', appLogOption);
eps_logger_1.Logger.init(EPS_INSTANCE_ID, loggerConfig);
}
exports.handleLoggerSetup = handleLoggerSetup;
function addLoggerOptions(program) {
return program
.option('--log-dir <log_dir>', 'Log Directory', DEFAULT_LOG_DIR)
.addOption(new commander_1.Option('--log-level <log_level>', "Log level for file-based logs. Choices: ".concat(logLevelChoices))
.argParser(parseLogLevel)
.default(DEFAULT_LOG_LEVEL))
.addOption(new commander_1.Option('--console-log-level <log_level>', "Log level for console logs. Choices: ".concat(logLevelChoices))
.argParser(parseLogLevel)
.default(LOG_OFF_LEVEL));
}
function parseLogLevel(value) {
var lowerCaseValue = value.toLowerCase();
if (!logLevelChoices.includes(lowerCaseValue)) {
throw new commander_1.InvalidArgumentError("Allowed choices are: ".concat(logLevelChoices));
}
return lowerCaseValue;
}
function parseArgs(args) {
var program = new commander_1.Command();
addLoggerOptions(program)
.requiredOption('--caller-pid <caller_pid>', 'Caller Process Id', parsePid)
.requiredOption('--caller-id <caller_id>', 'Caller Id')
.requiredOption('--port-file <port_file>', 'Port file path')
.addOption(new commander_1.Option('--caller-type <caller_type>', 'Valid values: desktop, prep, vizqlserver, etc.')
.choices(Object.values(caller_type_1.CallerType))
.default(caller_type_1.CallerType.desktop))
.addOption(new commander_1.Option('--mode <mode>', "Valid values: ".concat(Object.values(app_init_1.ServerMode)))
.choices(Object.values(app_init_1.ServerMode))
.default(app_init_1.ServerMode.prod))
.option('--feature-flags <feature_flags>', 'EPS feature flags as defined in monolith')
.option('--port-range <port_range>', 'Port range for all EPS services. Format: start-end', parsePortRange, [9089, 9999])
.option('--static-server-ui-dir <log_dir>', 'Connector app root directory', DEFAULT_STATIC_SERVER_UI_DIR)
.option('--static-server-handlers-dir <log_dir>', 'Connector handlers root directory', DEFAULT_STATIC_SERVER_HANDLERS_DIR)
.option('--static-server-port <port>', 'Static Server port to use, for vizqlserver only')
.option('--main-port <port>', 'Main API port to use, for vizqlserver only')
.option('--grpc-server-port <port>', 'grpc Server port to use', parsePort)
.option('--language <language>', 'Runtime user choice for language', DEFAULT_LANGUAGE)
.option('--locale <locale>', 'Runtime user choice for locale', DEFAULT_LOCALE)
.option('--eps-temp-dir-path <dir_path>', 'Root for temporary file storage', epsTempDirRoot)
.addHelpCommand()
.allowUnknownOption()
.configureOutput({
writeOut: function (str) { return eps_logger_1.Logger.info("".concat(str)); },
writeErr: function (str) {
return eps_logger_1.Logger.logEPSError(status_code_1.StatusCode.InvalidArgument, error_source_1.ErrorSources.Content, error_codes_1.ErrorCodes.ORP420NN, "Error with command line options. ".concat(str));
},
});
program.parse(args);
var options = program.opts();
eps_logger_1.Logger.debug("Command arguments: ".concat(JSON.stringify(options, undefined, 2)));
return __assign(__assign({}, options), {
// addtional parsing for certain properties
mainPort: parseMainPort(options), staticServerPort: parseStaticServerPort(options), featureFlags: parseFeatureFlags(options.featureFlags), epsInstanceId: EPS_INSTANCE_ID });
}
exports.parseArgs = parseArgs;
function parsePortRange(portRange) {
var parts = portRange.split('-');
if (parts.length !== 2) {
throw new commander_1.InvalidArgumentError("Port range must be formatted in 'start-end'");
}
var start = parseInt(parts[0], 10);
var end = parseInt(parts[1], 10);
if (!isValidPort(start) || !isValidPort(end)) {
throw new commander_1.InvalidArgumentError("Invalid port number in the port range: ".concat(portRange));
}
if (end - start < 5) {
throw new commander_1.InvalidArgumentError('EPS requires at least 5 ports');
}
return [start, end];
}
exports.parsePortRange = parsePortRange;
function parsePort(portString) {
var port = parseInt(portString, 10);
if (!isValidPort(port)) {
throw new commander_1.InvalidArgumentError("Invalid port number: ".concat(portString));
}
return port;
}
function isValidPort(port) {
return Number.isInteger(port) && port > 0 && port <= 65535;
}
function parsePid(pidString) {
var pid = parseInt(pidString, 10);
if (isNaN(pid) || pid < 0) {
throw new commander_1.InvalidArgumentError("Invalid pid number: ".concat(pidString));
}
return pid;
}
function parseMainPort(options) {
var callerType = options.callerType, mainPort = options.mainPort;
if (mainPort === undefined) {
if (callerType === caller_type_1.CallerType.vizQLServer || callerType === caller_type_1.CallerType.dcf) {
throw new Error("--main-port must be provided when --caller-type is ".concat(callerType, "."));
}
return;
}
if (callerType !== caller_type_1.CallerType.vizQLServer && callerType !== caller_type_1.CallerType.dcf) {
throw new Error("--main-port can be only used when --caller-type is ".concat(caller_type_1.CallerType.vizQLServer, " or ").concat(caller_type_1.CallerType.dcf, ". The current caller type is '").concat(callerType, "'."));
}
return parsePort(mainPort);
}
exports.parseMainPort = parseMainPort;
function parseStaticServerPort(options) {
var callerType = options.callerType, staticServerPort = options.staticServerPort;
if (staticServerPort === undefined) {
if (callerType === caller_type_1.CallerType.vizQLServer) {
throw new Error("--static-server-port must be provided when --caller-type is ".concat(callerType, "."));
}
return;
}
if (callerType !== caller_type_1.CallerType.vizQLServer) {
throw new Error("--static-server-port can be only used when --caller-type is ".concat(caller_type_1.CallerType.vizQLServer, ". The current caller type is '").concat(callerType, "'."));
}
return parsePort(staticServerPort);
}
exports.parseStaticServerPort = parseStaticServerPort;
/**
* The configuration for feature flags from monolith.
* This config does not include all feature flags passed from monolith,
* but only the flags that EPS needs to handle.
*/
var FEATURE_FLAGS_CONFIG = {
EPSSupportgRPC: {
falseValue: 'off',
defaultValue: true,
},
EPSStaticTacoUnpack: {
falseValue: 'off',
defaultValue: true,
},
};
function parseFeatureFlags(input) {
var e_1, _a;
var flagsString = input !== null && input !== void 0 ? input : '';
var args = flagsString
.split(',')
.filter(Boolean)
.map(function (arg) {
var _a = __read(arg.split(':'), 2), key = _a[0], value = _a[1];
return [key.trim(), value === null || value === void 0 ? void 0 : value.trim()];
});
var flags = Object.fromEntries(args);
var result = {};
try {
for (var _b = __values(Object.entries(FEATURE_FLAGS_CONFIG)), _c = _b.next(); !_c.done; _c = _b.next()) {
var _d = __read(_c.value, 2), key = _d[0], config = _d[1];
var flagName = key;
eps_logger_1.Logger.info("IN FF PARSING LOOP: ".concat(flagName));
var defaultValue = config.defaultValue, falseValue = config.falseValue;
var value = flags[flagName];
if (value === falseValue) {
result[flagName] = false;
}
else {
result[flagName] = defaultValue;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
return result;
}
exports.parseFeatureFlags = parseFeatureFlags;
/**
* Get app log options from command line values
*/
function getAppLogOption(options) {
var logLevel = options.logLevel, consoleLogLevel = options.consoleLogLevel, logDir = options.logDir;
if (logLevel === LOG_OFF_LEVEL) {
return {
// if file-based log has been explicitly disabled, force to enable console log
consoleLogLevel: consoleLogLevel === LOG_OFF_LEVEL ? log_level_1.LogLevel.INFO : consoleLogLevel,
logDir: undefined,
logLevel: undefined,
};
}
var logOption = {
logDir: logDir,
logLevel: logLevel,
consoleLogLevel: consoleLogLevel === LOG_OFF_LEVEL ? undefined : consoleLogLevel,
};
return logOption;
}
exports.getAppLogOption = getAppLogOption;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbWFuZC1saW5lLXBhcnNlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9lcHMvbWFpbi9jb3JlL2FwcC11dGlscy9jb21tYW5kLWxpbmUtcGFyc2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsdUNBQStFO0FBQy9FLG9EQUF3QjtBQUN4Qix3REFBNEI7QUFDNUIsNkJBQW1DO0FBRW5DLG9FQUFpRTtBQUNqRSxxRUFBa0U7QUFDbEUsdUVBQXFFO0FBQ3JFLHFFQUFrRTtBQUNsRSxpRUFBOEU7QUFDOUUsMERBQTJGO0FBRzNGLHVDQUF1RDtBQUV2RCxJQUFNLGVBQWUsR0FBRyxJQUFBLFNBQU0sR0FBRSxDQUFBO0FBQ2hDLElBQU0sY0FBYyxHQUFHLG1CQUFJLENBQUMsSUFBSSxDQUFDLGlCQUFFLENBQUMsTUFBTSxFQUFFLEVBQUUsa0JBQWtCLENBQUMsQ0FBQTtBQUNqRSxJQUFNLFVBQVUsR0FBRyxtQkFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsZUFBZSxDQUFDLENBQUE7QUFFN0QsaUVBQWlFO0FBQ2pFLGdFQUFnRTtBQUNoRSxJQUFNLGVBQWUsR0FBRyxtQkFBSSxDQUFDLElBQUksQ0FBQyxpQkFBRSxDQUFDLE9BQU8sRUFBRSxFQUFFLFdBQVcsRUFBRSx1QkFBdUIsRUFBRSxNQUFNLENBQUMsQ0FBQTtBQUM3RixJQUFNLGlCQUFpQixHQUFHLG9CQUFRLENBQUMsS0FBSyxDQUFBO0FBQ3hDLElBQU0sNEJBQTRCLEdBQUcsbUJBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLGVBQWUsRUFBRSxLQUFLLENBQUMsQ0FBQTtBQUNsRixJQUFNLGtDQUFrQyxHQUFHLG1CQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxlQUFlLEVBQUUsVUFBVSxDQUFDLENBQUE7QUFDN0YsSUFBTSxnQkFB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