"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.exists = exists;
exports.mkdirSftp = mkdirSftp;
exports.normalizeConfig = normalizeConfig;
exports.normalizePutFilesOptions = normalizePutFilesOptions;
exports.normalizePutDirectoryOptions = normalizePutDirectoryOptions;
exports.generateCallback = generateCallback;
exports.readdir = exports.stat = void 0;

var _fs = _interopRequireDefault(require("fs"));

var _path = _interopRequireDefault(require("path"));

var _sbPromisify = _interopRequireDefault(require("sb-promisify"));

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); }); }; }

const CODE_REGEXP = /Error: (E[\S]+): /;
const DEFAULT_CONCURRENCY = 5;
const readFile = (0, _sbPromisify.default)(_fs.default.readFile);
const stat = (0, _sbPromisify.default)(_fs.default.stat);
exports.stat = stat;
const readdir = (0, _sbPromisify.default)(_fs.default.readdir);
exports.readdir = readdir;

function transformError(givenError) {
  const code = CODE_REGEXP.exec(givenError);

  if (code) {
    // eslint-disable-next-line no-param-reassign,prefer-destructuring
    givenError.code = code[1];
  }

  return givenError;
}

function exists(filePath) {
  return new Promise(function (resolve) {
    _fs.default.access(filePath, _fs.default.R_OK, function (error) {
      resolve(!error);
    });
  });
}

function mkdirSftp(_x, _x2) {
  return _mkdirSftp.apply(this, arguments);
}

function _mkdirSftp() {
  _mkdirSftp = _asyncToGenerator(function* (path, sftp) {
    let stats;

    try {
      stats = yield (0, _sbPromisify.default)(sftp.stat).call(sftp, path);
    } catch (_) {
      /* No Op */
    }

    if (stats) {
      if (stats.isDirectory()) {
        // Already exists, nothing to worry about
        return;
      }

      throw new Error('mkdir() failed, target already exists and is not a directory');
    }

    try {
      yield (0, _sbPromisify.default)(sftp.mkdir).call(sftp, path);
    } catch (error) {
      throw transformError(error);
    }
  });
  return _mkdirSftp.apply(this, arguments);
}

function normalizeConfig(_x3) {
  return _normalizeConfig.apply(this, arguments);
}

function _normalizeConfig() {
  _normalizeConfig = _asyncToGenerator(function* (givenConfig) {
    const config = Object.assign({}, givenConfig);

    if (config.username && typeof config.username !== 'string') {
      throw new Error('config.username must be a valid string');
    }

    if (typeof config.host !== 'undefined') {
      if (typeof config.host !== 'string' || !config.host) {
        throw new Error('config.host must be a valid string');
      }
    } else if (typeof config.sock !== 'undefined') {
      if (!config.sock || typeof config.sock !== 'object') {
        throw new Error('config.sock must be a valid object');
      }
    } else {
      throw new Error('config.host or config.sock must be provided');
    }

    if (config.privateKey) {
      const privateKey = config.privateKey;

      if (typeof privateKey !== 'string') {
        throw new Error('config.privateKey must be a string');
      }

      if (!(privateKey.includes('BEGIN') && privateKey.includes('KEY'))) {
        try {
          config.privateKey = yield readFile(privateKey, 'utf8');
        } catch (error) {
          if (error.code === 'ENOENT') {
            throw new Error(`config.privateKey does not exist at given fs path`);
          }

          throw error;
        }
      }
    } else if (config.password) {
      const password = config.password;

      if (typeof password !== 'string') {
        throw new Error('config.password must be a string');
      }
    }

    config.tryKeyboard = !!config.tryKeyboard;

    if (config.tryKeyboard === true) {
      if (typeof config.onKeyboardInteractive !== 'function') {
        config.onKeyboardInteractive = (name, instructions, instructionsLang, prompts, finish) => {
          if (prompts.length > 0 && prompts[0].prompt.toLowerCase().includes('password')) {
            finish([config.password]);
          }
        };
      }
    } else {
      config.onKeyboardInteractive = null;
    }

    return config;
  });
  return _normalizeConfig.apply(this, arguments);
}

function normalizePutFilesOptions(givenConfig) {
  const config = {};

  if (givenConfig.sftpOptions && typeof givenConfig.sftpOptions === 'object') {
    config.sftpOptions = givenConfig.sftpOptions;
  } else config.sftpOptions = {};

  if (typeof givenConfig.concurrency === 'number') {
    config.concurrency = givenConfig.concurrency;
  } else config.concurrency = DEFAULT_CONCURRENCY;

  if (typeof givenConfig.sftp === 'object') {
    config.sftp = givenConfig.sftp;
  } else config.sftp = null;

  return config;
}

function normalizePutDirectoryOptions(givenConfig) {
  const config = normalizePutFilesOptions(givenConfig);

  if (givenConfig.tick) {
    if (typeof givenConfig.tick !== 'function') {
      throw new Error('config.tick must be a function');
    }

    config.tick = givenConfig.tick;
  } else {
    config.tick = function () {};
  }

  if (givenConfig.validate) {
    if (typeof givenConfig.validate !== 'function') {
      throw new Error('config.validate must be a function');
    }

    config.validate = givenConfig.validate;
  } else {
    config.validate = function (path) {
      return _path.default.basename(path).substr(0, 1) !== '.';
    };
  }

  config.recursive = {}.hasOwnProperty.call(givenConfig, 'recursive') ? !!givenConfig.recursive : true;
  return config;
}

function generateCallback(resolve, reject) {
  return function (error, result) {
    if (error) {
      reject(error);
    } else {
      resolve(result);
    }
  };
}