'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _regenerator;

function _load_regenerator() {
  return _regenerator = _interopRequireDefault(require('babel-runtime/regenerator'));
}

var _bluebird;

function _load_bluebird() {
  return _bluebird = require('bluebird');
}

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _ssh;

function _load_ssh() {
  return _ssh = _interopRequireDefault(require('ssh2'));
}

var _ramda;

function _load_ramda() {
  return _ramda = _interopRequireDefault(require('ramda'));
}

var _os;

function _load_os() {
  return _os = _interopRequireWildcard(require('os'));
}

var _lodash;

function _load_lodash() {
  return _lodash = _interopRequireDefault(require('lodash.merge'));
}

var _prompts;

function _load_prompts() {
  return _prompts = require('../../../prompts');
}

var _keyGetter;

function _load_keyGetter() {
  return _keyGetter = _interopRequireDefault(require('./key-getter'));
}

var _componentObjects;

function _load_componentObjects() {
  return _componentObjects = _interopRequireDefault(require('../../component-objects'));
}

var _exceptions;

function _load_exceptions() {
  return _exceptions = require('../exceptions');
}

var _bitId;

function _load_bitId() {
  return _bitId = require('../../../bit-id');
}

var _utils;

function _load_utils() {
  return _utils = require('../../../utils');
}

var _componentNotFound;

function _load_componentNotFound() {
  return _componentNotFound = _interopRequireDefault(require('../../../scope/exceptions/component-not-found'));
}

var _component;

function _load_component() {
  return _component = _interopRequireDefault(require('../../../consumer/component'));
}

var _checkVersionCompatibility;

function _load_checkVersionCompatibility() {
  return _checkVersionCompatibility = _interopRequireDefault(require('../check-version-compatibility'));
}

var _logger;

function _load_logger() {
  return _logger = _interopRequireDefault(require('../../../logger/logger'));
}

var _constants;

function _load_constants() {
  return _constants = require('../../../constants');
}

var _removedComponents;

function _load_removedComponents() {
  return _removedComponents = require('../../removed-components');
}

var _mergeConflictOnRemote;

function _load_mergeConflictOnRemote() {
  return _mergeConflictOnRemote = _interopRequireDefault(require('../../exceptions/merge-conflict-on-remote'));
}

var _analytics;

function _load_analytics() {
  return _analytics = require('../../../analytics/analytics');
}

var _globalConfig;

function _load_globalConfig() {
  return _globalConfig = require('../../../api/consumer/lib/global-config');
}

var _generalError;

function _load_generalError() {
  return _generalError = _interopRequireDefault(require('../../../error/general-error'));
}

var _customError;

function _load_customError() {
  return _customError = _interopRequireDefault(require('../../../error/custom-error'));
}

var _remoteResolverError;

function _load_remoteResolverError() {
  return _remoteResolverError = _interopRequireDefault(require('../exceptions/remote-resolver-error'));
}

var _exportAnotherOwnerPrivate;

function _load_exportAnotherOwnerPrivate() {
  return _exportAnotherOwnerPrivate = _interopRequireDefault(require('../exceptions/export-another-owner-private'));
}

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _extendableBuiltin(cls) {
  function ExtendableBuiltin() {
    var instance = Reflect.construct(cls, Array.from(arguments));
    Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
    return instance;
  }

  ExtendableBuiltin.prototype = Object.create(cls.prototype, {
    constructor: {
      value: cls,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });

  if (Object.setPrototypeOf) {
    Object.setPrototypeOf(ExtendableBuiltin, cls);
  } else {
    ExtendableBuiltin.__proto__ = cls;
  }

  return ExtendableBuiltin;
}

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var checkVersionCompatibility = (_ramda || _load_ramda()).default.once((_checkVersionCompatibility || _load_checkVersionCompatibility()).default);
var PASSPHRASE_MESSAGE = 'Encrypted private key detected, but no passphrase given';
var AUTH_FAILED_MESSAGE = 'All configured authentication methods failed';
var PASSPHRASE_POSSIBLY_MISSING_MESSAGE = 'Cannot parse privateKey: Unsupported key format';

var cachedPassphrase = null;

function absolutePath(path) {
  if (!path.startsWith('/')) return `~/${path}`;
  return path;
}

function clean(str) {
  return str.replace('\n', '');
}

var SSH = function () {
  // Username entered by the user on the prompt user/pass process

  function SSH(_ref) {
    var path = _ref.path,
        username = _ref.username,
        port = _ref.port,
        host = _ref.host;

    _classCallCheck(this, SSH);

    this.path = path;
    this.username = username;
    this.port = port;
    this.host = host || '';
  }

  /**
   * strategies:
   * 1) token (generated by bit-login command)
   * 2) ssh-agent (public-key should be saved on bitsrc, user needs to enable ssh-agent in its os. the agent saves the passphrase, so no need to enter)
   * 3) ssh-key. (user can specify location by `bit config`, if not, the default one is used. doesn't support passphrase)
   * 4) prompt of user/password
   */


  _createClass(SSH, [{
    key: 'connect',
    value: function () {
      var _ref2 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee() {
        var strategies, strategiesNames, strategiesFailures, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, strategyName, strategyFunc, strategyResult;

        return (_regenerator || _load_regenerator()).default.wrap(function _callee$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                strategies = {
                  token: this._tokenAuthentication,
                  'ssh-agent': this._sshAgentAuthentication,
                  'ssh-key': this._sshKeyAuthentication,
                  'user-password': this._userPassAuthentication
                };
                strategiesNames = Object.keys(strategies);
                strategiesFailures = [];
                _iteratorNormalCompletion = true;
                _didIteratorError = false;
                _iteratorError = undefined;
                _context.prev = 6;
                _iterator = strategiesNames[Symbol.iterator]();

              case 8:
                if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
                  _context.next = 31;
                  break;
                }

                strategyName = _step.value;

                (_logger || _load_logger()).default.debug(`ssh, trying to connect using ${strategyName}`);
                strategyFunc = strategies[strategyName].bind(this);
                _context.prev = 12;
                _context.next = 15;
                return strategyFunc();

              case 15:
                strategyResult = _context.sent;

                if (!strategyResult) {
                  _context.next = 18;
                  break;
                }

                return _context.abrupt('return', strategyResult);

              case 18:
                _context.next = 28;
                break;

              case 20:
                _context.prev = 20;
                _context.t0 = _context['catch'](12);

                (_logger || _load_logger()).default.debug(`ssh, failed to connect using ${strategyName}. ${_context.t0.message}`);

                if (!(_context.t0 instanceof AuthenticationStrategyFailed)) {
                  _context.next = 27;
                  break;
                }

                strategiesFailures.push(_context.t0.message);
                _context.next = 28;
                break;

              case 27:
                throw _context.t0;

              case 28:
                _iteratorNormalCompletion = true;
                _context.next = 8;
                break;

              case 31:
                _context.next = 37;
                break;

              case 33:
                _context.prev = 33;
                _context.t1 = _context['catch'](6);
                _didIteratorError = true;
                _iteratorError = _context.t1;

              case 37:
                _context.prev = 37;
                _context.prev = 38;

                if (!_iteratorNormalCompletion && _iterator.return) {
                  _iterator.return();
                }

              case 40:
                _context.prev = 40;

                if (!_didIteratorError) {
                  _context.next = 43;
                  break;
                }

                throw _iteratorError;

              case 43:
                return _context.finish(40);

              case 44:
                return _context.finish(37);

              case 45:
                (_logger || _load_logger()).default.errorAndAddBreadCrumb('ssh', 'all connection strategies have been failed!');
                strategiesFailures.unshift('The following strategies were failed');
                throw new (_exceptions || _load_exceptions()).AuthenticationFailed(strategiesFailures.join('\n[-] '));

              case 48:
              case 'end':
                return _context.stop();
            }
          }
        }, _callee, this, [[6, 33, 37, 45], [12, 20], [38,, 40, 44]]);
      }));

      function connect() {
        return _ref2.apply(this, arguments);
      }

      return connect;
    }()
  }, {
    key: '_tokenAuthentication',
    value: function () {
      var _ref3 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee2() {
        var sshConfig, authFailedMsg;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee2$(_context2) {
          while (1) {
            switch (_context2.prev = _context2.next) {
              case 0:
                sshConfig = this._composeTokenAuthObject();

                if (sshConfig) {
                  _context2.next = 3;
                  break;
                }

                throw new AuthenticationStrategyFailed('user token not defined in bit-config. please run `bit login` to authenticate.');

              case 3:
                authFailedMsg = 'failed to authenticate with user token. generate a new token by running `bit logout && bit login`.';
                return _context2.abrupt('return', this._connectWithConfig(sshConfig, 'token', authFailedMsg));

              case 5:
              case 'end':
                return _context2.stop();
            }
          }
        }, _callee2, this);
      }));

      function _tokenAuthentication() {
        return _ref3.apply(this, arguments);
      }

      return _tokenAuthentication;
    }()
  }, {
    key: '_sshAgentAuthentication',
    value: function () {
      var _ref4 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee3() {
        var sshConfig, authFailedMsg;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee3$(_context3) {
          while (1) {
            switch (_context3.prev = _context3.next) {
              case 0:
                if (this._hasAgentSocket()) {
                  _context3.next = 2;
                  break;
                }

                throw new AuthenticationStrategyFailed('unable to get SSH keys from ssh-agent to. perhaps service is down or disabled.');

              case 2:
                sshConfig = (0, (_lodash || _load_lodash()).default)(this._composeBaseObject(), { agent: process.env.SSH_AUTH_SOCK });
                authFailedMsg = 'no matching private key found in ssh-agent to authenticate to remote server.';
                return _context3.abrupt('return', this._connectWithConfig(sshConfig, 'ssh-agent', authFailedMsg));

              case 5:
              case 'end':
                return _context3.stop();
            }
          }
        }, _callee3, this);
      }));

      function _sshAgentAuthentication() {
        return _ref4.apply(this, arguments);
      }

      return _sshAgentAuthentication;
    }()
  }, {
    key: '_sshKeyAuthentication',
    value: function () {
      var _ref5 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee4() {
        var keyBuffer, sshConfig, authFailedMsg;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee4$(_context4) {
          while (1) {
            switch (_context4.prev = _context4.next) {
              case 0:
                _context4.next = 2;
                return (0, (_keyGetter || _load_keyGetter()).default)();

              case 2:
                keyBuffer = _context4.sent;

                if (keyBuffer) {
                  _context4.next = 5;
                  break;
                }

                throw new AuthenticationStrategyFailed('SSH key not found in `~/.ssh/id_rsa` or `ssh_key_file` config in `bit config` either not configured or refers to wrong path.');

              case 5:
                sshConfig = (0, (_lodash || _load_lodash()).default)(this._composeBaseObject(), { privateKey: keyBuffer });
                authFailedMsg = 'failed connecting to remote server using `~/.ssh/id_rsa` or `ssh_key_file` in `bit config`.';
                return _context4.abrupt('return', this._connectWithConfig(sshConfig, 'ssh-key', authFailedMsg));

              case 8:
              case 'end':
                return _context4.stop();
            }
          }
        }, _callee4, this);
      }));

      function _sshKeyAuthentication() {
        return _ref5.apply(this, arguments);
      }

      return _sshKeyAuthentication;
    }()
  }, {
    key: '_userPassAuthentication',
    value: function () {
      var _ref6 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee5() {
        var sshConfig, authFailedMsg;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee5$(_context5) {
          while (1) {
            switch (_context5.prev = _context5.next) {
              case 0:
                _context5.next = 2;
                return this._composeUserPassObject();

              case 2:
                sshConfig = _context5.sent;
                authFailedMsg = 'unable to connect using provided username and password combination.';
                return _context5.abrupt('return', this._connectWithConfig(sshConfig, 'user-password', authFailedMsg));

              case 5:
              case 'end':
                return _context5.stop();
            }
          }
        }, _callee5, this);
      }));

      function _userPassAuthentication() {
        return _ref6.apply(this, arguments);
      }

      return _userPassAuthentication;
    }()
  }, {
    key: 'close',
    value: function close() {
      this.connection.end();
      return this;
    }
  }, {
    key: '_composeBaseObject',
    value: function _composeBaseObject(passphrase) {
      return {
        username: this.username,
        host: this.host,
        port: this.port,
        passphrase,
        readyTimeout: (_constants || _load_constants()).DEFAULT_SSH_READY_TIMEOUT
      };
    }
  }, {
    key: '_composeTokenAuthObject',
    value: function _composeTokenAuthObject() {
      var token = (0, (_globalConfig || _load_globalConfig()).getSync)((_constants || _load_constants()).CFG_USER_TOKEN_KEY);
      if (token) {
        this._sshUsername = 'token';
        return (0, (_lodash || _load_lodash()).default)(this._composeBaseObject(), { username: 'token', password: token });
      }
      return null;
    }
  }, {
    key: '_composeUserPassObject',
    value: function _composeUserPassObject() {
      var _this = this;

      return (0, (_prompts || _load_prompts()).userpass)().then(function (_ref7) {
        var username = _ref7.username,
            password = _ref7.password;

        (_analytics || _load_analytics()).Analytics.setExtraData('authentication_method', 'user_password');
        _this._sshUsername = username;
        return (0, (_lodash || _load_lodash()).default)(_this._composeBaseObject(), { username, password });
      });
    }
  }, {
    key: '_hasAgentSocket',
    value: function _hasAgentSocket() {
      return !!process.env.SSH_AUTH_SOCK;
    }
  }, {
    key: '_connectWithConfig',
    value: function () {
      var _ref8 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee6(sshConfig, authenticationType, authFailedMsg) {
        var connectWithConfigP, macMojaveOs, passphrasePossiblyMissing;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee6$(_context6) {
          while (1) {
            switch (_context6.prev = _context6.next) {
              case 0:
                connectWithConfigP = function connectWithConfigP() {
                  var conn = new (_ssh || _load_ssh()).default();
                  return new Promise(function (resolve, reject) {
                    conn.on('error', function (err) {
                      reject(err);
                    }).on('ready', function () {
                      resolve(conn);
                    }).connect(sshConfig);
                  });
                };

                _context6.prev = 1;
                _context6.next = 4;
                return connectWithConfigP();

              case 4:
                this.connection = _context6.sent;

                (_analytics || _load_analytics()).Analytics.setExtraData('authentication_method', authenticationType);
                (_logger || _load_logger()).default.debug(`ssh, authenticated successfully using ${authenticationType}`);
                return _context6.abrupt('return', this);

              case 10:
                _context6.prev = 10;
                _context6.t0 = _context6['catch'](1);

                if (!(_context6.t0.message === AUTH_FAILED_MESSAGE)) {
                  _context6.next = 14;
                  break;
                }

                throw new AuthenticationStrategyFailed(authFailedMsg);

              case 14:
                (_logger || _load_logger()).default.error(_context6.t0);

                if (!(_context6.t0.code === 'ENOTFOUND')) {
                  _context6.next = 17;
                  break;
                }

                throw new (_generalError || _load_generalError()).default(`unable to find the SSH server. host: ${_context6.t0.host}, port: ${_context6.t0.port}. Original error message: ${_context6.t0.message}`);

              case 17:
                if (!(_context6.t0.message === PASSPHRASE_POSSIBLY_MISSING_MESSAGE)) {
                  _context6.next = 22;
                  break;
                }

                macMojaveOs = process.platform === 'darwin' && (_os || _load_os()).release() === '18.2.0';
                passphrasePossiblyMissing = 'error connecting with private ssh key. in case passphrase is used, use ssh-agent.';

                if (macMojaveOs) {
                  passphrasePossiblyMissing += ' for macOS Mojave users, use `-m PEM` for `ssh-keygen` command to generate a valid SSH key';
                }
                throw new AuthenticationStrategyFailed(passphrasePossiblyMissing);

              case 22:
                throw new AuthenticationStrategyFailed(`${authFailedMsg} due to an error "${_context6.t0.message}"`);

              case 23:
              case 'end':
                return _context6.stop();
            }
          }
        }, _callee6, this, [[1, 10]]);
      }));

      function _connectWithConfig(_x, _x2, _x3) {
        return _ref8.apply(this, arguments);
      }

      return _connectWithConfig;
    }()
  }, {
    key: 'buildCmd',
    value: function buildCmd(commandName, path, payload, context) {
      return `bit ${commandName} ${(0, (_utils || _load_utils()).toBase64)(path)} ${(0, (_utils || _load_utils()).packCommand)((0, (_utils || _load_utils()).buildCommandMessage)(payload, context))}`;
    }
  }, {
    key: 'exec',
    value: function exec(commandName, payload, context) {
      var _this2 = this;

      (_logger || _load_logger()).default.debug(`ssh: going to run a remote command ${commandName}, path: ${this.path}`);
      // Add the entered username to context
      if (this._sshUsername) {
        context = context || {};
        context.sshUsername = this._sshUsername;
      }
      return new Promise(function (resolve, reject) {
        var res = '';
        var err = void 0;
        // No need to use packCommand on the payload in case of put command
        // because we handle all the base64 stuff in a better way inside the ComponentObjects.manyToString
        // inside pushMany function here
        var cmd = _this2.buildCmd(commandName, absolutePath(_this2.path || ''), commandName === '_put' ? null : payload, context);
        if (!_this2.connection) {
          err = 'ssh connection is not defined';
          (_logger || _load_logger()).default.error(err);
          return reject(err);
        }
        _this2.connection.exec(cmd, function (error, stream) {
          if (error) {
            (_logger || _load_logger()).default.error('ssh, exec returns an error: ', error);
            return reject(error);
          }
          if (commandName === '_put') {
            stream.stdin.write(payload);
            stream.stdin.end();
          }
          stream.on('data', function (response) {
            res += response.toString();
          }).on('exit', function (code) {
            (_logger || _load_logger()).default.debug(`ssh: exit. Exit code: ${code}`);
            var promiseExit = function promiseExit() {
              return code && code !== 0 ? reject(_this2.errorHandler(code, err)) : resolve(clean(res));
            };
            // sometimes the connection 'exit' before 'close' and then it doesn't have the data (err) ready yet.
            // in that case, we prefer to wait until the onClose will terminate the promise.
            // sometimes though, the connection only 'exit' and never 'close' (happened when _put command sent back
            // more than 1MB of data), in that case, the following setTimeout will terminate the promise.
            setTimeout(promiseExit, 2000);
          }).on('close', function (code, signal) {
            if (commandName === '_put') res = res.replace(payload, '');
            (_logger || _load_logger()).default.debug(`ssh: returned with code: ${code}, signal: ${signal}.`);
            // DO NOT CLOSE THE CONNECTION (using this.connection.end()), it causes bugs when there are several open
            // connections. Same bugs occur when running "this.connection.end()" on "end" or "exit" events.
            return code && code !== 0 ? reject(_this2.errorHandler(code, err)) : resolve(clean(res));
          }).stderr.on('data', function (response) {
            err = response.toString();
            (_logger || _load_logger()).default.error(`ssh: got an error, ${err}`);
          });
        });
      });
    }
  }, {
    key: 'errorHandler',
    value: function errorHandler(code, err) {
      var parsedError = void 0;
      try {
        var _unpack2 = this._unpack(err, false),
            headers = _unpack2.headers,
            payload = _unpack2.payload;

        checkVersionCompatibility(headers.version);
        parsedError = payload;
      } catch (e) {
        // be graceful when can't parse error message
        (_logger || _load_logger()).default.error(`ssh: failed parsing error as JSON, error: ${err}`);
      }

      switch (code) {
        default:
          return new (_exceptions || _load_exceptions()).UnexpectedNetworkError(parsedError ? parsedError.message : err);
        case 127:
          return new (_componentNotFound || _load_componentNotFound()).default(parsedError && parsedError.id || err);
        case 128:
          return new (_exceptions || _load_exceptions()).PermissionDenied(`${this.host}:${this.path}`);
        case 129:
          return new (_exceptions || _load_exceptions()).RemoteScopeNotFound(parsedError && parsedError.name || err);
        case 130:
          return new (_exceptions || _load_exceptions()).PermissionDenied(`${this.host}:${this.path}`);
        case 131:
          return new (_mergeConflictOnRemote || _load_mergeConflictOnRemote()).default(parsedError && parsedError.idsAndVersions ? parsedError.idsAndVersions : []);
        case 132:
          return new (_customError || _load_customError()).default(parsedError && parsedError.message ? parsedError.message : err);
        case 133:
          return new (_exceptions || _load_exceptions()).OldClientVersion(parsedError && parsedError.message ? parsedError.message : err);
        case 134:
          {
            var msg = parsedError && parsedError.message ? parsedError.message : err;
            var sourceScope = parsedError && parsedError.sourceScope ? parsedError.sourceScope : 'unknown';
            var destinationScope = parsedError && parsedError.destinationScope ? parsedError.destinationScope : 'unknown';
            return new (_exportAnotherOwnerPrivate || _load_exportAnotherOwnerPrivate()).default(msg, sourceScope, destinationScope);
          }
      }
    }
  }, {
    key: '_unpack',
    value: function _unpack(data) {
      var base64 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;

      try {
        return (0, (_utils || _load_utils()).unpackCommand)(data, base64);
      } catch (err) {
        (_logger || _load_logger()).default.error(`unpackCommand found on error "${err}", while paring the following string: ${data}`);
        throw new (_exceptions || _load_exceptions()).SSHInvalidResponse(data);
      }
    }
  }, {
    key: 'pushMany',
    value: function pushMany(manyComponentObjects, context) {
      var _this3 = this;

      // This ComponentObjects.manyToString will handle all the base64 stuff so we won't send this payload
      // to the pack command (to prevent duplicate base64)
      return this.exec('_put', (_componentObjects || _load_componentObjects()).default.manyToString(manyComponentObjects), context).then(function (data) {
        var _unpack3 = _this3._unpack(data),
            payload = _unpack3.payload,
            headers = _unpack3.headers;

        checkVersionCompatibility(headers.version);
        return payload.ids;
      });
    }
  }, {
    key: 'deleteMany',
    value: function deleteMany(ids, force, context) {
      var _this4 = this;

      return this.exec('_delete', {
        bitIds: ids,
        force
      }, context).then(function (data) {
        var _unpack4 = _this4._unpack(data),
            payload = _unpack4.payload;

        return Promise.resolve((_removedComponents || _load_removedComponents()).RemovedObjects.fromObjects(payload));
      });
    }
  }, {
    key: 'deprecateMany',
    value: function deprecateMany(ids, context) {
      var _this5 = this;

      return this.exec('_deprecate', {
        ids
      }, context).then(function (data) {
        var _unpack5 = _this5._unpack(data),
            payload = _unpack5.payload;

        return Promise.resolve(payload);
      });
    }
  }, {
    key: 'undeprecateMany',
    value: function undeprecateMany(ids, context) {
      var _this6 = this;

      return this.exec('_undeprecate', {
        ids
      }, context).then(function (data) {
        var _unpack6 = _this6._unpack(data),
            payload = _unpack6.payload;

        return Promise.resolve(payload);
      });
    }
  }, {
    key: 'push',
    value: function push(componentObjects) {
      return this.pushMany([componentObjects]);
    }
  }, {
    key: 'describeScope',
    value: function describeScope() {
      var _this7 = this;

      return this.exec('_scope').then(function (data) {
        var _unpack7 = _this7._unpack(data),
            payload = _unpack7.payload,
            headers = _unpack7.headers;

        checkVersionCompatibility(headers.version);
        return payload;
      }).catch(function (err) {
        throw new (_exceptions || _load_exceptions()).RemoteScopeNotFound(_this7.path);
      });
    }
  }, {
    key: 'list',
    value: function () {
      var _ref9 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee8(namespacesUsingWildcards) {
        var _this8 = this;

        return (_regenerator || _load_regenerator()).default.wrap(function _callee8$(_context8) {
          while (1) {
            switch (_context8.prev = _context8.next) {
              case 0:
                return _context8.abrupt('return', this.exec('_list', namespacesUsingWildcards).then(function () {
                  var _ref10 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee7(str) {
                    var _unpack8, payload, headers;

                    return (_regenerator || _load_regenerator()).default.wrap(function _callee7$(_context7) {
                      while (1) {
                        switch (_context7.prev = _context7.next) {
                          case 0:
                            _unpack8 = _this8._unpack(str), payload = _unpack8.payload, headers = _unpack8.headers;

                            checkVersionCompatibility(headers.version);
                            payload.forEach(function (result) {
                              result.id = new (_bitId || _load_bitId()).BitId(result.id);
                            });
                            return _context7.abrupt('return', payload);

                          case 4:
                          case 'end':
                            return _context7.stop();
                        }
                      }
                    }, _callee7, _this8);
                  }));

                  return function (_x6) {
                    return _ref10.apply(this, arguments);
                  };
                }()));

              case 1:
              case 'end':
                return _context8.stop();
            }
          }
        }, _callee8, this);
      }));

      function list(_x5) {
        return _ref9.apply(this, arguments);
      }

      return list;
    }()
  }, {
    key: 'latestVersions',
    value: function latestVersions(componentIds) {
      var _this9 = this;

      var componentIdsStr = componentIds.map(function (componentId) {
        return componentId.toString();
      });
      return this.exec('_latest', componentIdsStr).then(function (str) {
        var _unpack9 = _this9._unpack(str),
            payload = _unpack9.payload,
            headers = _unpack9.headers;

        checkVersionCompatibility(headers.version);
        return payload;
      });
    }
  }, {
    key: 'search',
    value: function search(query, reindex) {
      var _this10 = this;

      return this.exec('_search', { query, reindex: reindex.toString() }).then(function (data) {
        var _unpack10 = _this10._unpack(data),
            payload = _unpack10.payload,
            headers = _unpack10.headers;

        checkVersionCompatibility(headers.version);
        return payload;
      });
    }
  }, {
    key: 'show',
    value: function show(id) {
      var _this11 = this;

      return this.exec('_show', id.toString()).then(function (str) {
        var _unpack11 = _this11._unpack(str),
            payload = _unpack11.payload,
            headers = _unpack11.headers;

        checkVersionCompatibility(headers.version);
        return str ? (_component || _load_component()).default.fromString(payload) : null;
      });
    }
  }, {
    key: 'fetch',
    value: function fetch(ids) {
      var noDeps = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
      var context = arguments[2];

      var options = '';
      var idsStr = ids.serialize();
      if (noDeps) options = '--no-dependencies';
      return this.exec(`_fetch ${options}`, idsStr, context).then(function (str) {
        var parseResponse = function parseResponse() {
          try {
            var results = JSON.parse(str);
            return results;
          } catch (err) {
            throw new (_exceptions || _load_exceptions()).SSHInvalidResponse(str);
          }
        };

        var _parseResponse = parseResponse(),
            payload = _parseResponse.payload,
            headers = _parseResponse.headers;

        checkVersionCompatibility(headers.version);
        var componentObjects = (_componentObjects || _load_componentObjects()).default.manyFromString(payload);
        return componentObjects;
      });
    }
  }]);

  return SSH;
}();

exports.default = SSH;

var AuthenticationStrategyFailed = function (_extendableBuiltin2) {
  _inherits(AuthenticationStrategyFailed, _extendableBuiltin2);

  function AuthenticationStrategyFailed() {
    _classCallCheck(this, AuthenticationStrategyFailed);

    return _possibleConstructorReturn(this, (AuthenticationStrategyFailed.__proto__ || Object.getPrototypeOf(AuthenticationStrategyFailed)).apply(this, arguments));
  }

  return AuthenticationStrategyFailed;
}(_extendableBuiltin(Error));