'use strict';

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

var _regenerator;

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

var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();

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 _semver;

function _load_semver() {
  return _semver = _interopRequireDefault(require('semver'));
}

var _lodash;

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

var _ramda;

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

var _objects;

function _load_objects() {
  return _objects = require('../objects');
}

var _models;

function _load_models() {
  return _models = require('../models');
}

var _exceptions;

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

var _utils;

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

var _version;

function _load_version() {
  return _version = _interopRequireDefault(require('./version'));
}

var _constants;

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

var _bitId;

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

var _version2;

function _load_version2() {
  return _version2 = _interopRequireDefault(require('../../version'));
}

var _component;

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

var _scope;

function _load_scope() {
  return _scope = _interopRequireDefault(require('../scope'));
}

var _repository;

function _load_repository() {
  return _repository = _interopRequireDefault(require('../objects/repository'));
}

var _componentVersion;

function _load_componentVersion() {
  return _componentVersion = _interopRequireDefault(require('../component-version'));
}

var _sources;

function _load_sources() {
  return _sources = require('../../consumer/component/sources');
}

var _componentObjects;

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

var _specsResults;

function _load_specsResults() {
  return _specsResults = _interopRequireDefault(require('../../consumer/specs-results'));
}

var _logger;

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

var _bitId2;

function _load_bitId2() {
  return _bitId2 = require('../../bit-id');
}

var _generalError;

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

var _compilerExtension;

function _load_compilerExtension() {
  return _compilerExtension = _interopRequireDefault(require('../../extensions/compiler-extension'));
}

var _testerExtension;

function _load_testerExtension() {
  return _testerExtension = _interopRequireDefault(require('../../extensions/tester-extension'));
}

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

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

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

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

var Component = function (_BitObject) {
  _inherits(Component, _BitObject);

  function Component(props) {
    _classCallCheck(this, Component);

    var _this = _possibleConstructorReturn(this, (Component.__proto__ || Object.getPrototypeOf(Component)).call(this));

    if (!props.name) throw new TypeError('Model Component constructor expects to get a name parameter');
    _this.scope = props.scope || null;
    _this.name = props.name;
    _this.versions = props.versions || {};
    _this.lang = props.lang || (_constants || _load_constants()).DEFAULT_LANGUAGE;
    _this.deprecated = props.deprecated || false;
    _this.bindingPrefix = props.bindingPrefix || (_constants || _load_constants()).DEFAULT_BINDINGS_PREFIX;
    _this.local = props.local;
    _this.state = props.state || {};
    return _this;
  }

  _createClass(Component, [{
    key: 'listVersions',
    value: function listVersions(sort) {
      var versions = Object.keys(this.versions);
      if (!sort) return versions;
      if (sort === 'ASC') {
        return versions.sort((_semver || _load_semver()).default.compare);
      }

      return versions.sort((_semver || _load_semver()).default.compare).reverse();
    }
  }, {
    key: 'hasVersion',
    value: function hasVersion(version) {
      return !!this.versions[version];
    }

    /**
     * returns only the versions that exist in both components (regardless whether the hash are the same)
     * e.g. this.component = [0.0.1, 0.0.2, 0.0.3], other component = [0.0.3, 0.0.4]. it returns only [0.0.3].
     * also, in case it is coming from 'bit import', the version must be locally changed.
     * otherwise, it doesn't matter whether the hashes are different.
     */

  }, {
    key: '_getComparableVersionsObjects',
    value: function _getComparableVersionsObjects(otherComponent, // in case of merging, the otherComponent is the existing component, and "this" is the incoming component
    local // for 'bit import' the local is true, for 'bit export' the local is false
    ) {
      var _this2 = this;

      var otherLocalVersion = otherComponent.getLocalVersions();
      var otherComponentVersions = (0, (_utils || _load_utils()).filterObject)(otherComponent.versions, function (val, key) {
        return Object.keys(_this2.versions).includes(key) && (!local || otherLocalVersion.includes(key));
      });
      var thisComponentVersions = (0, (_utils || _load_utils()).filterObject)(this.versions, function (val, key) {
        return Object.keys(otherComponentVersions).includes(key) && (!local || otherLocalVersion.includes(key));
      });
      return { thisComponentVersions, otherComponentVersions };
    }
  }, {
    key: 'compatibleWith',
    value: function compatibleWith(component, local) {
      var _getComparableVersion = this._getComparableVersionsObjects(component, local),
          thisComponentVersions = _getComparableVersion.thisComponentVersions,
          otherComponentVersions = _getComparableVersion.otherComponentVersions;

      return (0, (_ramda || _load_ramda()).equals)(thisComponentVersions, otherComponentVersions);
    }
  }, {
    key: 'diffWith',
    value: function diffWith(component, local) {
      var _getComparableVersion2 = this._getComparableVersionsObjects(component, local),
          thisComponentVersions = _getComparableVersion2.thisComponentVersions,
          otherComponentVersions = _getComparableVersion2.otherComponentVersions;

      return Object.keys(thisComponentVersions).filter(function (version) {
        return thisComponentVersions[version].hash !== otherComponentVersions[version].hash;
      });
    }
  }, {
    key: 'latest',
    value: function latest() {
      if ((0, (_utils || _load_utils()).empty)(this.versions)) return '0.0.0';
      return (_semver || _load_semver()).default.maxSatisfying(this.listVersions(), '*');
    }

    /**
     * Return the lateset version which actuall exists in the scope
     * (exists means the object itself exists)
     * This relevant for cases when the component version array has few versions
     * but we don't have all the refs in the object
     *
     * @returns {number}
     * @memberof Component
     */

  }, {
    key: 'latestExisting',
    value: function latestExisting(repository) {
      if ((0, (_utils || _load_utils()).empty)(this.versions)) return '0.0.0';
      var versions = this.listVersions('ASC');
      var version = null;
      var versionStr = null;
      while (!version && versions && versions.length) {
        versionStr = versions.pop();
        version = this.loadVersionSync(versionStr, repository, false);
      }
      return versionStr || '0.0.0';
    }
  }, {
    key: 'collectLogs',
    value: function collectLogs(repo) {
      var _this3 = this;

      return repo.findMany(this.versionArray).then(function (versions) {
        var indexedLogs = (0, (_ramda || _load_ramda()).fromPairs)((0, (_ramda || _load_ramda()).zip)((0, (_ramda || _load_ramda()).keys)(_this3.versions), (0, (_ramda || _load_ramda()).map)((0, (_ramda || _load_ramda()).prop)('log'), versions)));
        return indexedLogs;
      });
    }
  }, {
    key: 'collectVersions',
    value: function collectVersions(repo) {
      var _this4 = this;

      return Promise.all(this.listVersions().map(function (versionNum) {
        return _this4.toConsumerComponent(versionNum, _this4.scope, repo);
      }));
    }
  }, {
    key: 'getVersionToAdd',
    value: function getVersionToAdd() {
      var releaseType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : (_constants || _load_constants()).DEFAULT_BIT_RELEASE_TYPE;
      var exactVersion = arguments[1];

      if (exactVersion && this.versions[exactVersion]) {
        throw new (_exceptions || _load_exceptions()).VersionAlreadyExists(exactVersion, this.id());
      }
      return exactVersion || this.version(releaseType);
    }

    /**
     * if exactVersion is defined, add exact version instead of using the semver mechanism
     */

  }, {
    key: 'addVersion',
    value: function addVersion(version) {
      var releaseType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : (_constants || _load_constants()).DEFAULT_BIT_RELEASE_TYPE;
      var exactVersion = arguments[2];

      var versionToAdd = this.getVersionToAdd(releaseType, exactVersion);
      this.versions[versionToAdd] = version.hash();
      this.markVersionAsLocal(versionToAdd);
      return versionToAdd;
    }
  }, {
    key: 'version',
    value: function version() {
      var releaseType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : (_constants || _load_constants()).DEFAULT_BIT_RELEASE_TYPE;

      var latest = this.latest();
      if (latest) return (_semver || _load_semver()).default.inc(latest, releaseType);
      return (_constants || _load_constants()).DEFAULT_BIT_VERSION;
    }
  }, {
    key: 'id',
    value: function id() {
      return this.scope ? [this.scope, this.name].join('/') : this.name;
    }
  }, {
    key: 'toBitId',
    value: function toBitId() {
      return new (_bitId || _load_bitId()).default({ scope: this.scope, name: this.name });
    }
  }, {
    key: 'toBitIdWithLatestVersion',
    value: function toBitIdWithLatestVersion() {
      return new (_bitId || _load_bitId()).default({ scope: this.scope, name: this.name, version: this.latest() });
    }
  }, {
    key: 'toObject',
    value: function toObject() {
      function versions(vers) {
        var obj = {};
        (0, (_utils || _load_utils()).forEach)(vers, function (ref, version) {
          obj[version] = ref.toString();
        });
        return obj;
      }

      var componentObject = {
        name: this.name,
        scope: this.scope,
        versions: versions(this.versions),
        lang: this.lang,
        deprecated: this.deprecated,
        bindingPrefix: this.bindingPrefix
      };
      if (this.local) componentObject.local = this.local;
      if (!(0, (_ramda || _load_ramda()).isEmpty)(this.state)) componentObject.state = this.state;

      return componentObject;
    }
  }, {
    key: 'loadVersion',
    value: function () {
      var _ref = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee(version, repository) {
        var versionRef;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                versionRef = this.versions[version];

                if (versionRef) {
                  _context.next = 3;
                  break;
                }

                throw new (_exceptions || _load_exceptions()).VersionNotFound(version);

              case 3:
                return _context.abrupt('return', versionRef.load(repository));

              case 4:
              case 'end':
                return _context.stop();
            }
          }
        }, _callee, this);
      }));

      function loadVersion(_x4, _x5) {
        return _ref.apply(this, arguments);
      }

      return loadVersion;
    }()
  }, {
    key: 'loadVersionSync',
    value: function loadVersionSync(version, repository) {
      var throws = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;

      var versionRef = this.versions[version];
      if (!versionRef) throw new (_exceptions || _load_exceptions()).VersionNotFound(version);
      return versionRef.loadSync(repository, throws);
    }
  }, {
    key: 'collectObjects',
    value: function collectObjects(repo) {
      return Promise.all([this.asRaw(repo), this.collectRaw(repo)]).then(function (_ref2) {
        var _ref3 = _slicedToArray(_ref2, 2),
            rawComponent = _ref3[0],
            objects = _ref3[1];

        return new (_componentObjects || _load_componentObjects()).default(rawComponent, objects);
      });
    }

    /**
     * delete all versions objects of the component from the filesystem.
     * if deepRemove is true, it deletes also the refs associated with the deleted versions.
     * finally, it deletes the component object itself
     *
     * @param {Repository} repo
     * @param {boolean} [deepRemove=false] - whether remove all the refs or only the version array
     * @returns {Promise}
     * @memberof Component
     */

  }, {
    key: 'remove',
    value: function remove(repo) {
      var deepRemove = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

      (_logger || _load_logger()).default.debug(`models.component.remove: removing a component ${this.id()} from a local scope`);
      var objectRefs = deepRemove ? this.collectExistingRefs(repo, false).filter(function (x) {
        return x;
      }) : this.versionArray;
      var uniqRefs = (0, (_lodash || _load_lodash()).default)(objectRefs, 'hash');
      return repo.removeMany(uniqRefs.concat([this.hash()]));
    }

    /**
     * to delete a version from a component, don't call this method directly. Instead, use sources.removeVersion()
     */

  }, {
    key: 'removeVersion',
    value: function () {
      var _ref4 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee2(repo, version) {
        var objectRefs;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee2$(_context2) {
          while (1) {
            switch (_context2.prev = _context2.next) {
              case 0:
                objectRefs = this.versions[version];

                delete this.versions[version];
                if (this.state.versions && this.state.versions[version]) delete this.state.versions[version];
                _context2.next = 5;
                return repo.removeMany([objectRefs.hash]);

              case 5:
                return _context2.abrupt('return', this);

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

      function removeVersion(_x8, _x9) {
        return _ref4.apply(this, arguments);
      }

      return removeVersion;
    }()
  }, {
    key: 'toComponentVersion',
    value: function toComponentVersion(versionStr) {
      var versionNum = (_version2 || _load_version2()).default.parse(versionStr).resolve(this.listVersions());

      if (!this.versions[versionNum]) {
        throw new (_generalError || _load_generalError()).default(`the version ${versionNum} does not exist in ${this.listVersions().join('\n')}, versions array`);
      }
      return new (_componentVersion || _load_componentVersion()).default(this, versionNum);
    }
  }, {
    key: 'toConsumerComponent',
    value: function () {
      var _ref5 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee4(versionStr, scopeName, repository) {
        var _this5 = this;

        var componentVersion, version, loadFileInstance, filesP, distsP, scopeMetaP, log, compilerP, testerP, _ref7, _ref8, files, dists, scopeMeta, compiler, tester;

        return (_regenerator || _load_regenerator()).default.wrap(function _callee4$(_context4) {
          while (1) {
            switch (_context4.prev = _context4.next) {
              case 0:
                componentVersion = this.toComponentVersion(versionStr);
                _context4.next = 3;
                return componentVersion.getVersion(repository);

              case 3:
                version = _context4.sent;

                loadFileInstance = function loadFileInstance(ClassName) {
                  return function () {
                    var _ref6 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee3(file) {
                      var loadP, content;
                      return (_regenerator || _load_regenerator()).default.wrap(function _callee3$(_context3) {
                        while (1) {
                          switch (_context3.prev = _context3.next) {
                            case 0:
                              loadP = file.file.load(repository);
                              _context3.next = 3;
                              return loadP;

                            case 3:
                              content = _context3.sent;

                              if (content) {
                                _context3.next = 6;
                                break;
                              }

                              throw new (_generalError || _load_generalError()).default(`failed loading file ${file.relativePath} from the model`);

                            case 6:
                              return _context3.abrupt('return', new ClassName({ base: '.', path: file.relativePath, contents: content.contents, test: file.test }));

                            case 7:
                            case 'end':
                              return _context3.stop();
                          }
                        }
                      }, _callee3, _this5);
                    }));

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

                filesP = version.files ? Promise.all(version.files.map(loadFileInstance((_sources || _load_sources()).SourceFile))) : null;
                distsP = version.dists ? Promise.all(version.dists.map(loadFileInstance((_sources || _load_sources()).Dist))) : null;
                scopeMetaP = scopeName ? (_models || _load_models()).ScopeMeta.fromScopeName(scopeName).load(repository) : Promise.resolve();
                log = version.log || null;
                compilerP = (_compilerExtension || _load_compilerExtension()).default.loadFromModelObject(version.compiler, repository);
                testerP = (_testerExtension || _load_testerExtension()).default.loadFromModelObject(version.tester, repository);
                _context4.next = 13;
                return Promise.all([filesP, distsP, scopeMetaP, compilerP, testerP]);

              case 13:
                _ref7 = _context4.sent;
                _ref8 = _slicedToArray(_ref7, 5);
                files = _ref8[0];
                dists = _ref8[1];
                scopeMeta = _ref8[2];
                compiler = _ref8[3];
                tester = _ref8[4];
                return _context4.abrupt('return', new (_component || _load_component()).default({
                  name: this.name,
                  version: componentVersion.version,
                  scope: this.scope,
                  lang: this.lang,
                  bindingPrefix: this.bindingPrefix,
                  mainFile: version.mainFile || null,
                  compiler,
                  tester,
                  detachedCompiler: version.detachedCompiler,
                  detachedTester: version.detachedTester,
                  dependencies: version.dependencies.getClone(),
                  devDependencies: version.devDependencies.getClone(),
                  compilerDependencies: version.compilerDependencies.getClone(),
                  testerDependencies: version.testerDependencies.getClone(),
                  flattenedDependencies: version.flattenedDependencies.clone(),
                  flattenedDevDependencies: version.flattenedDevDependencies.clone(),
                  flattenedCompilerDependencies: version.flattenedCompilerDependencies.clone(),
                  flattenedTesterDependencies: version.flattenedTesterDependencies.clone(),
                  packageDependencies: (0, (_ramda || _load_ramda()).clone)(version.packageDependencies),
                  devPackageDependencies: (0, (_ramda || _load_ramda()).clone)(version.devPackageDependencies),
                  peerPackageDependencies: (0, (_ramda || _load_ramda()).clone)(version.peerPackageDependencies),
                  compilerPackageDependencies: (0, (_ramda || _load_ramda()).clone)(version.compilerPackageDependencies),
                  testerPackageDependencies: (0, (_ramda || _load_ramda()).clone)(version.testerPackageDependencies),
                  files,
                  dists,
                  docs: version.docs,
                  license: scopeMeta ? (_sources || _load_sources()).License.deserialize(scopeMeta.license) : null, // todo: make sure we have license in case of local scope
                  specsResults: version.specsResults ? version.specsResults.map(function (res) {
                    return (_specsResults || _load_specsResults()).default.deserialize(res);
                  }) : null,
                  log,
                  customResolvedPaths: (0, (_ramda || _load_ramda()).clone)(version.customResolvedPaths),
                  deprecated: this.deprecated
                }));

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

      function toConsumerComponent(_x10, _x11, _x12) {
        return _ref5.apply(this, arguments);
      }

      return toConsumerComponent;
    }()
  }, {
    key: 'refs',
    value: function refs() {
      return (0, (_utils || _load_utils()).values)(this.versions);
    }
  }, {
    key: 'replaceRef',
    value: function replaceRef(oldRef, newRef) {
      var _this6 = this;

      var replace = function replace(value, key) {
        if (value === oldRef.hash) {
          _this6.versions[key] = newRef.hash;
        }
      };
      (0, (_ramda || _load_ramda()).forEachObjIndexed)(replace, this.versions);
    }
  }, {
    key: 'validateBeforePersisting',
    value: function validateBeforePersisting(componentStr) {
      (_logger || _load_logger()).default.debug(`validating component object: ${this.hash().hash} ${this.id()}`);
      var component = Component.parse(componentStr);
      component.validate();
    }
  }, {
    key: 'toBuffer',
    value: function toBuffer(pretty) {
      var args = (0, (_utils || _load_utils()).getStringifyArgs)(pretty);
      var obj = this.toObject();
      var str = JSON.stringify.apply(JSON, [obj].concat(_toConsumableArray(args)));
      if (this.validateBeforePersist) this.validateBeforePersisting(str);
      return Buffer.from(str);
    }
  }, {
    key: 'toVersionDependencies',
    value: function toVersionDependencies(version, scope, source) {
      var versionComp = this.toComponentVersion(version);
      return versionComp.toVersionDependencies(scope, source);
    }

    /**
     * Clear data that is relevant only for the local scope and should not be moved to the remote scope
     */

  }, {
    key: 'clearStateData',
    value: function clearStateData() {
      this.local = false; // backward compatibility for components created before 0.12.6
      this.state = {};
    }
  }, {
    key: 'markVersionAsLocal',
    value: function markVersionAsLocal(version) {
      if (!this.state.versions) this.state = { versions: {} };
      // $FlowFixMe
      if (!this.state.versions[version]) this.state.versions[version] = {};
      // $FlowFixMe
      this.state.versions[version].local = true;
    }
  }, {
    key: 'getLocalVersions',
    value: function getLocalVersions() {
      var _this7 = this;

      if ((0, (_ramda || _load_ramda()).isEmpty)(this.state) || (0, (_ramda || _load_ramda()).isEmpty)(this.state.versions)) return [];
      return Object.keys(this.state.versions).filter(function (version) {
        return _this7.state.versions[version].local;
      });
    }
  }, {
    key: 'isLocallyChanged',
    value: function isLocallyChanged() {
      if (this.local) return true; // backward compatibility for components created before 0.12.6
      if ((0, (_ramda || _load_ramda()).isEmpty)(this.state) || (0, (_ramda || _load_ramda()).isEmpty)(this.state.versions)) return false;
      // $FlowFixMe
      var localVersions = this.getLocalVersions();
      return localVersions.length > 0;
    }
  }, {
    key: 'validate',
    value: function validate() {
      var message = 'unable to save Component object';
      if (!this.name) throw new (_generalError || _load_generalError()).default(`${message} the name is missing`);
    }
  }, {
    key: 'versionArray',
    get: function get() {
      return (0, (_utils || _load_utils()).values)(this.versions);
    }
  }], [{
    key: 'parse',
    value: function parse(contents) {
      var rawComponent = JSON.parse(contents);
      return Component.from({
        name: rawComponent.box ? `${rawComponent.box}/${rawComponent.name}` : rawComponent.name,
        scope: rawComponent.scope,
        versions: (0, (_utils || _load_utils()).mapObject)(rawComponent.versions, function (val) {
          return (_objects || _load_objects()).Ref.from(val);
        }),
        lang: rawComponent.lang,
        deprecated: rawComponent.deprecated,
        bindingPrefix: rawComponent.bindingPrefix,
        local: rawComponent.local,
        state: rawComponent.state
      });
    }
  }, {
    key: 'from',
    value: function from(props) {
      return new Component(props);
    }
  }, {
    key: 'fromBitId',
    value: function fromBitId(bitId) {
      if (bitId.box) throw new Error('component.fromBitId, bitId should not have the "box" property populated');
      return new Component({
        name: bitId.name,
        scope: bitId.scope
      });
    }
  }]);

  return Component;
}((_objects || _load_objects()).BitObject);

exports.default = Component;