"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.parseErrorMessage = exports.openCommand = exports.executeTelnet = exports.executeAsync = exports.execCLI = exports["default"] = exports.commandExistsSync = exports.commandExists = void 0;



var _path = _interopRequireDefault(require("path"));
var _fs = require("fs");
var _execa = _interopRequireDefault(require("execa"));
var _ora = _interopRequireDefault(require("ora"));
var _client = _interopRequireDefault(require("netcat/client"));
var _config = _interopRequireDefault(require("../configManager/config"));

var _logger = require("./logger");
var _fileutils = require("./fileutils");
var _utils = require("./utils");function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { "default": obj };}function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {try {var info = gen[key](arg);var value = info.value;} catch (error) {reject(error);return;}if (info.done) {resolve(value);} else {Promise.resolve(value).then(_next, _throw);}}function _asyncToGenerator(fn) {return function () {var self = this,args = arguments;return new Promise(function (resolve, reject) {var gen = fn.apply(self, args);function _next(value) {asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);}function _throw(err) {asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);}_next(undefined);});};}function ownKeys(object, enumerableOnly) {var keys = Object.keys(object);if (Object.getOwnPropertySymbols) {var symbols = Object.getOwnPropertySymbols(object);enumerableOnly && (symbols = symbols.filter(function (sym) {return Object.getOwnPropertyDescriptor(object, sym).enumerable;})), keys.push.apply(keys, symbols);}return keys;}function _objectSpread(target) {for (var i = 1; i < arguments.length; i++) {var source = null != arguments[i] ? arguments[i] : {};i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {_defineProperty(target, key, source[key]);}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));});}return target;}function _defineProperty(obj, key, value) {if (key in obj) {Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true });} else {obj[key] = value;}return obj;}

var _require = require('child_process'),exec = _require.exec,execSync = _require.execSync;

/**
 *
 * Also accepts the Node's child_process exec/spawn options
 *
 * @typedef {Object} Opts
 * @property {Object} privateParams - private params that will be masked in the logs
 * @property {Boolean} silent - don't print anything
 * @property {Boolean} ignoreErrors - will print the loader but it will finish with a
 * checkmark regardless of the outcome. Also, it never throws a catch.
 * @property {Boolean} interactive - when you want to execute a command that requires user input
 *
 * Execute commands
 *
 * @param {String} command - command to be executed
 * @param {Opts} [opts={}] - the options for the command
 * @returns {Promise}
 *
 */
var _execute = function _execute(c, command) {var _c$program, _c$program2, _opts$rawCommand, _c$program3, _child, _child$stdout, _child2, _child2$stdout;var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  var defaultOpts = {
    stdio: 'pipe',
    localDir: _path["default"].resolve('./node_modules/.bin'),
    preferLocal: true,
    all: true,
    maxErrorLength: (_c$program = c.program) === null || _c$program === void 0 ? void 0 : _c$program.maxErrorLength,
    mono: (_c$program2 = c.program) === null || _c$program2 === void 0 ? void 0 : _c$program2.mono };


  if (opts.interactive) {
    defaultOpts.silent = true;
    defaultOpts.stdio = 'inherit';
    defaultOpts.shell = true;
  }

  var mergedOpts = _objectSpread(_objectSpread({}, defaultOpts), opts);

  var env = opts.env && c.program.info ? Object.keys(opts.env).map(function (k) {return "".concat(k, "=").concat(opts.env[k]);}).join(' ') : null;

  var cleanCommand = command;
  var interval;
  var intervalTimer = 30000; // 30s
  var timer = intervalTimer;
  var privateMask = '*******';
  var cleanRawCmd = ((_opts$rawCommand = opts.rawCommand) === null || _opts$rawCommand === void 0 ? void 0 : _opts$rawCommand.args) || [];
  if (Array.isArray(command)) cleanCommand = command.join(' ');

  cleanCommand += cleanRawCmd.join(' ');
  var logMessage = cleanCommand;
  var privateParams = mergedOpts.privateParams;
  if (privateParams && Array.isArray(privateParams)) {
    logMessage = (0, _utils.replaceOverridesInString)(
    command,
    privateParams,
    privateMask);

  }

  logMessage = "".concat(env ? "".concat(env, " ") : '').concat(logMessage);
  (0, _logger.logDebug)("_execute: ".concat(logMessage));
  var silent = mergedOpts.silent,mono = mergedOpts.mono,maxErrorLength = mergedOpts.maxErrorLength,ignoreErrors = mergedOpts.ignoreErrors;
  var spinner = !silent && !mono && (0, _ora["default"])({ text: "Executing: ".concat(logMessage) }).start();
  if (opts.interactive) {
    (0, _logger.logRaw)("".concat((0, _logger.chalk)().green('✔'), " Executing: ").concat(logMessage, "\n"));
  }

  if (mono) {
    interval = setInterval(function () {
      (0, _logger.logRaw)("Executing: ".concat(logMessage, " - ").concat(timer / 1000, "s"));
      timer += intervalTimer;
    }, intervalTimer);
  }
  var child;
  if (opts.rawCommand) {
    var args = opts.rawCommand.args;
    child = (0, _execa["default"])(command, args, mergedOpts);
  } else {
    child = _execa["default"].command(cleanCommand, mergedOpts);
  }

  var MAX_OUTPUT_LENGTH = 200;

  var printLastLine = function printLastLine(buffer) {
    var text = Buffer.from(buffer).
    toString().
    trim();
    var lastLine = text.split('\n').pop();
    spinner.text = (0, _utils.replaceOverridesInString)(
    lastLine.substring(0, MAX_OUTPUT_LENGTH),
    privateParams,
    privateMask);

    if (lastLine.length === MAX_OUTPUT_LENGTH) spinner.text += '...\n';
  };

  if ((_c$program3 = c.program) !== null && _c$program3 !== void 0 && _c$program3.info && (_child = child) !== null && _child !== void 0 && (_child$stdout = _child.stdout) !== null && _child$stdout !== void 0 && _child$stdout.pipe) {
    child.stdout.pipe(process.stdout);
  } else if (spinner && (_child2 = child) !== null && _child2 !== void 0 && (_child2$stdout = _child2.stdout) !== null && _child2$stdout !== void 0 && _child2$stdout.on) {
    child.stdout.on('data', printLastLine);
  }

  return child.
  then(function (res) {var _child3, _child3$stdout;
    if ((_child3 = child) !== null && _child3 !== void 0 && (_child3$stdout = _child3.stdout) !== null && _child3$stdout !== void 0 && _child3$stdout.off) {
      spinner && child.stdout.off('data', printLastLine);
    }

    !silent && !mono && spinner.succeed("Executing: ".concat(logMessage));
    (0, _logger.logDebug)(
    (0, _utils.replaceOverridesInString)(res.all, privateParams, privateMask));

    interval && clearInterval(interval);
    // logDebug(res);
    return res.stdout;
  })["catch"](
  function (err) {var _child4, _child4$stdout;
    if ((_child4 = child) !== null && _child4 !== void 0 && (_child4$stdout = _child4.stdout) !== null && _child4$stdout !== void 0 && _child4$stdout.off) {
      spinner && child.stdout.off('data', printLastLine);
    }

    if (!silent && !mono && !ignoreErrors) {spinner.fail("FAILED: ".concat(logMessage));} // parseErrorMessage will return false if nothing is found, default to previous implementation
    (0, _logger.logDebug)(
    (0, _utils.replaceOverridesInString)(err.all, privateParams, privateMask));

    interval && clearInterval(interval);
    // logDebug(err);
    if (ignoreErrors && !silent && !mono) {
      spinner.succeed("Executing: ".concat(logMessage));
      return true;
    }

    var errMessage = parseErrorMessage(err.all, maxErrorLength);

    if (!errMessage) {
      errMessage = '';
    } else {
      errMessage += '\n\n';
    }

    if (err.message) {
      errMessage += "".concat(err.message, "\n\n");
    }

    if (err.stderr) {
      errMessage += "".concat(err.stderr, "\n\n");
    }

    if (err.stack) {
      errMessage += "".concat(err.stack, "\n\n");
    }

    errMessage = (0, _utils.replaceOverridesInString)(
    errMessage,
    privateParams,
    privateMask);


    return Promise.reject("COMMAND: \n\n".concat(
    logMessage, " \n\nFAILED with ERROR: \n\n").concat(errMessage));
    // parseErrorMessage will return false if nothing is found, default to previous implementation
  });
};

/**
 *
 * Execute CLI command
 *
 * @param {Object} c - the trusty old c object
 * @param {String} cli - the cli to be executed
 * @param {String} command - the command to be executed
 * @param {Opts} [opts={}] - the options for the command
 * @returns {Promise}
 *
 */
var execCLI = function execCLI(c, cli, command) {var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
  if (!c.program) {
    return Promise.reject(
    'You need to pass c object as first parameter to execCLI()');

  }
  var p = c.cli[cli];
  if (!(0, _fileutils.fsExistsSync)(p)) {var _c$buildConfig;
    (0, _logger.logDebug)("execCLI error: ".concat(cli, " | ").concat(command), '\nCLI Config:\n', c.cli, '\nSDK Config:\n', (_c$buildConfig = c.buildConfig) === null || _c$buildConfig === void 0 ? void 0 : _c$buildConfig.sdks);
    return Promise.reject("Location of your cli ".concat(
    (0, _logger.chalk)().white(
    p), " does not exists. check your ").concat(
    (0, _logger.chalk)().white(
    c.paths.workspace.config), " file if your ").concat(
    (0, _logger.chalk)().white('sdks'), " paths are correct"));

  }

  return _execute(c, "".concat(p, " ").concat(command), _objectSpread(_objectSpread({}, opts), {}, { shell: true }));
};

/**
 *
 * Execute a plain command
 *
 * @param {String} command - the command to be executed
 * @param {Opts} [opts={}] - the options for the command
 * @returns {Promise}
 *
 */exports.execCLI = execCLI;
var executeAsync = /*#__PURE__*/function () {var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(_c, _cmd, _opts) {var c, cmd, opts, result;return regeneratorRuntime.wrap(function _callee$(_context) {while (1) {switch (_context.prev = _context.next) {case 0:
            // swap values if c is not specified and get it from it's rightful place, config :)
            c = _c;
            cmd = _cmd;
            opts = _opts;
            if (typeof c === 'string') {
              opts = cmd;
              cmd = c;
              c = _config["default"].getConfig();
            }
            opts = opts || {};
            if (cmd.includes('npm') && process.platform === 'win32') {cmd.replace('npm', 'npm.cmd');}
            // let cmdArr;
            // if (typeof cmd === 'string') {
            //     cmdArr = cmd.split('&&');
            // } else {
            //     cmdArr = cmd;
            // }

            // let result;
            // if (cmdArr.length) {
            //     for (let i = 0; i < cmdArr.length; i++) {
            //         // if (cmdArr[i].startsWith('cd ')) {
            //         //     // TODO: flaky. will need to improve
            //         //     const newCwd = path.join(CURRENT_DIR, cmdArr[i].replace('cd ', ''));
            //         //     opts.cwd = newCwd;
            //         // } else {
            //         //     await _execute(c, cmdArr[i], opts);
            //         // }
            //         result = await _execute(c, cmdArr[i], opts);
            //     }
            // }
            _context.next = 8;return _execute(c, cmd, opts);case 8:result = _context.sent;return _context.abrupt("return",

            result);case 10:case "end":return _context.stop();}}}, _callee);}));return function executeAsync(_x, _x2, _x3) {return _ref.apply(this, arguments);};}();


/**
 *
 * Connect to a local telnet server and execute a command
 *
 * @param {Number|String} port - where do you want me to connect to?
 * @param {String} command - the command to be executed once I'm connected
 * @returns {Promise}
 *
 */exports.executeAsync = executeAsync;
var executeTelnet = function executeTelnet(c, port, command) {return new Promise(function (resolve) {
    (0, _logger.logDebug)("execTelnet: ".concat(port, " ").concat(command));
    try {
      var output = '';
      var nc2 = new _client["default"]();
      nc2.addr(c.runtime.localhost).
      port(parseInt(port, 10)).
      connect().
      send("".concat(command, "\n"));
      nc2.on('data', function (data) {
        var resp = Buffer.from(data).toString();
        output += resp;
        if (output.includes('OK')) nc2.close();
      });
      nc2.on('close', function () {return resolve(output);});
    } catch (e) {
      (0, _logger.logError)(e);
      resolve();
    }
  });};

// Legacy error parser
// export const parseErrorMessage = (text, maxErrorLength = 800) => {
//     const errors = [];
//     const toSearch = /(exception|error|fatal|\[!])/i;
//
//     const extractError = (t) => {
//         const errorFound = t ? t.search(toSearch) : -1;
//         if (errorFound === -1) return errors.length ? errors.join(' ') : false; // return the errors or false if we found nothing at all
//         const usefulString = t.substring(errorFound); // dump first part of the string that doesn't contain what we look for
//         let extractedError = usefulString.substring(0, maxErrorLength);
//         if (extractedError.length === maxErrorLength) extractedError += '...'; // add elipsis if string is bigger than maxErrorLength
//         errors.push(extractedError); // save the error
//         const newString = usefulString.substring(100); // dump everything we processed and continue
//         return extractError(newString);
//     };
//
//     return extractError(text);
// };
exports.executeTelnet = executeTelnet;

var parseErrorMessage = function parseErrorMessage(text) {var maxErrorLength = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 800;
  if (!text) return '';
  // Gradle specific
  var gradleFailIndex = text.indexOf('FAILURE: Build failed with an exception.');
  if (gradleFailIndex !== -1) {
    return text.substring(gradleFailIndex);
  }
  // NextJS Specific
  var nextFailIndex = text.indexOf('> Build error occurred');
  if (nextFailIndex !== -1) {
    return text.substring(nextFailIndex);
  }
  var toSearch = /(exception|error|fatal|\[!])/i;
  var arr = text.split('\n');

  var errFound = 0;
  arr = arr.filter(function (v) {
    if (v === '') return false;
    // Cleaner iOS reporting
    if (
    v.includes('-Werror') ||
    v.includes('following modules are linked manually') ||
    v.includes('warn ') ||
    v.includes('note: ') ||
    v.includes('warning: ') ||
    v.includes('Could not find the following native modules') ||
    v.includes('⚠️') ||
    v.includes('/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain'))
    {
      return false;
    }
    // Cleaner Android reporting
    if (
    v.includes('[DEBUG]') ||
    v.includes('[INFO]') ||
    v.includes('[LIFECYCLE]') ||
    v.includes('[WARN]') ||
    v.includes(':+HeapDumpOnOutOfMemoryError') ||
    v.includes('.errors.') ||
    v.includes('-exception-') ||
    v.includes('error_prone_annotations'))
    {
      return false;
    }
    // Special Helper for iOS
    // if (v.endsWith('^')) {
    //     arr[i - 1] = chalk().red(arr[i - 1]);
    // }
    if (v.search(toSearch) !== -1) {
      errFound = 5;
      return true;
    }
    if (errFound > 0) {
      errFound -= 1;
      return true;
    }

    return false;
  });

  arr = arr.map(function (str) {
    var v = str.replace(/\s{2,}/g, ' ');
    var extractedError = v.substring(0, maxErrorLength);
    if (extractedError.length === maxErrorLength) extractedError += '...';
    return extractedError;
  });

  return arr.join('\n');
};exports.parseErrorMessage = parseErrorMessage;

var isUsingWindows = process.platform === 'win32';

var fileNotExists = function fileNotExists(commandName, callback) {
  (0, _fs.access)(commandName, _fs.constants.F_OK, function (err) {
    callback(!err);
  });
};

var fileNotExistsSync = function fileNotExistsSync(commandName) {
  try {
    (0, _fs.accessSync)(commandName, _fs.constants.F_OK);
    return false;
  } catch (e) {
    return true;
  }
};

var localExecutable = function localExecutable(commandName, callback) {
  (0, _fs.access)(commandName, _fs.constants.F_OK | _fs.constants.X_OK, function (err) {
    callback(null, !err);
  });
};

var localExecutableSync = function localExecutableSync(commandName) {
  try {
    (0, _fs.accessSync)(commandName, _fs.constants.F_OK | _fs.constants.X_OK);
    return true;
  } catch (e) {
    return false;
  }
};

var commandExistsUnix = function commandExistsUnix(commandName, cleanedCommandName, callback) {
  fileNotExists(commandName, function (isFile) {
    if (!isFile) {
      exec(
      "command -v ".concat(cleanedCommandName, " 2>/dev/null") + " && { echo >&1 ".concat(
      cleanedCommandName, "; exit 0; }"),
      function (error, stdout) {
        callback(null, !!stdout);
      });

      return;
    }

    localExecutable(commandName, callback);
  });
};

var commandExistsWindows = function commandExistsWindows(commandName, cleanedCommandName, callback) {
  if (/[\x00-\x1f<>:"|?*]/.test(commandName)) {
    callback(null, false);
    return;
  }
  exec("where ".concat(cleanedCommandName), function (error) {
    if (error !== null) {
      callback(null, false);
    } else {
      callback(null, true);
    }
  });
};

var commandExistsUnixSync = function commandExistsUnixSync(commandName, cleanedCommandName) {
  if (fileNotExistsSync(commandName)) {
    try {
      var stdout = execSync(
      "command -v ".concat(cleanedCommandName, " 2>/dev/null") + " && { echo >&1 ".concat(
      cleanedCommandName, "; exit 0; }"));

      return !!stdout;
    } catch (error) {
      return false;
    }
  }
  return localExecutableSync(commandName);
};

var commandExistsWindowsSync = function commandExistsWindowsSync(commandName, cleanedCommandName) {
  if (/[\x00-\x1f<>:"|?*]/.test(commandName)) {
    return false;
  }
  try {
    var stdout = execSync("where ".concat(cleanedCommandName), { stdio: [] });
    return !!stdout;
  } catch (error) {
    return false;
  }
};

var cleanInput = function cleanInput(_s) {
  var s = _s;
  if (/[^A-Za-z0-9_/:=-]/.test(s)) {
    s = "'".concat(s.replace(/'/g, "'\\''"), "'");
    s = s.
    replace(/^(?:'')+/g, '') // unduplicate single-quote at the beginning
    .replace(/\\'''/g, "\\'"); // remove non-escaped single-quote if there are enclosed between 2 escaped
  }
  return s;
};

if (isUsingWindows) {
  cleanInput = function cleanInput(s) {
    var isPathName = /[\\]/.test(s);
    if (isPathName) {
      var dirname = "\"".concat(_path["default"].dirname(s), "\"");
      var basename = "\"".concat(_path["default"].basename(s), "\"");
      return "".concat(dirname, ":").concat(basename);
    }
    return "\"".concat(s, "\"");
  };
}

var commandExists = function commandExists(commandName, callback) {
  var cleanedCommandName = cleanInput(commandName);
  if (!callback && typeof Promise !== 'undefined') {
    return new Promise(function (resolve, reject) {
      commandExists(commandName, function (error, output) {
        if (output) {
          resolve(commandName);
        } else {
          reject(error);
        }
      });
    });
  }
  if (isUsingWindows) {
    commandExistsWindows(commandName, cleanedCommandName, callback);
  } else {
    commandExistsUnix(commandName, cleanedCommandName, callback);
  }
};exports.commandExists = commandExists;

var commandExistsSync = function commandExistsSync(commandName) {
  var cleanedCommandName = cleanInput(commandName);
  if (isUsingWindows) {
    return commandExistsWindowsSync(commandName, cleanedCommandName);
  }
  return commandExistsUnixSync(commandName, cleanedCommandName);
};


// eslint-disable-next-line no-nested-ternary
exports.commandExistsSync = commandExistsSync;var openCommand = process.platform === 'darwin' ?
'open' :
process.platform === 'win32' ?
'start' :
'xdg-open';exports.openCommand = openCommand;var _default =










{
  executeAsync: executeAsync,
  execCLI: execCLI,
  openCommand: openCommand,
  executeTelnet: executeTelnet };exports["default"] = _default;
//# sourceMappingURL=exec.js.map