UNPKG

bit-bin

Version:

<a href="https://opensource.org/licenses/Apache-2.0"><img alt="apache" src="https://img.shields.io/badge/License-Apache%202.0-blue.svg"></a> <a href="https://github.com/teambit/bit/blob/master/CONTRIBUTING.md"><img alt="prs" src="https://img.shields.io/b

782 lines (609 loc) 24.2 kB
"use strict"; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; function _bluebird() { const data = require("bluebird"); _bluebird = function () { return data; }; return data; } function _defineProperty2() { const data = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); _defineProperty2 = function () { return data; }; return data; } function semver() { const data = _interopRequireWildcard(require("semver")); semver = function () { return data; }; return data; } function _ramda() { const data = require("ramda"); _ramda = function () { return data; }; return data; } function _objects() { const data = require("../objects"); _objects = function () { return data; }; return data; } function _scopeMeta() { const data = _interopRequireDefault(require("./scopeMeta")); _scopeMeta = function () { return data; }; return data; } function _exceptions() { const data = require("../exceptions"); _exceptions = function () { return data; }; return data; } function _utils() { const data = require("../../utils"); _utils = function () { return data; }; return data; } function _constants() { const data = require("../../constants"); _constants = function () { return data; }; return data; } function _bitId() { const data = _interopRequireDefault(require("../../bit-id/bit-id")); _bitId = function () { return data; }; return data; } function _component() { const data = _interopRequireDefault(require("../../consumer/component")); _component = function () { return data; }; return data; } function _componentVersion() { const data = _interopRequireDefault(require("../component-version")); _componentVersion = function () { return data; }; return data; } function _sources() { const data = require("../../consumer/component/sources"); _sources = function () { return data; }; return data; } function _componentObjects() { const data = _interopRequireDefault(require("../component-objects")); _componentObjects = function () { return data; }; return data; } function _specsResults() { const data = _interopRequireDefault(require("../../consumer/specs-results")); _specsResults = function () { return data; }; return data; } function _logger() { const data = _interopRequireDefault(require("../../logger/logger")); _logger = function () { return data; }; return data; } function _generalError() { const data = _interopRequireDefault(require("../../error/general-error")); _generalError = function () { return data; }; return data; } function _versionParser() { const data = _interopRequireDefault(require("../../version/version-parser")); _versionParser = function () { return data; }; return data; } function _componentOverrides() { const data = _interopRequireDefault(require("../../consumer/config/component-overrides")); _componentOverrides = function () { return data; }; return data; } function _envFactory() { const data = require("../../legacy-extensions/env-factory"); _envFactory = function () { return data; }; return data; } function _showDoctorError() { const data = _interopRequireDefault(require("../../error/show-doctor-error")); _showDoctorError = function () { return data; }; return data; } function _validationError() { const data = _interopRequireDefault(require("../../error/validation-error")); _validationError = function () { return data; }; return data; } function _artifact() { const data = require("../../consumer/component/sources/artifact"); _artifact = function () { return data; }; return data; } const VERSION_ZERO = '0.0.0'; /** * we can't rename the class as ModelComponent because old components are already saved in the model * with 'Component' in their headers. see object-registrar.types() */ // TODO: FIX me .parser // @ts-ignore class Component extends _objects().BitObject { constructor(props) { super(); (0, _defineProperty2().default)(this, "scope", void 0); (0, _defineProperty2().default)(this, "name", void 0); (0, _defineProperty2().default)(this, "versions", void 0); (0, _defineProperty2().default)(this, "lang", void 0); (0, _defineProperty2().default)(this, "deprecated", void 0); (0, _defineProperty2().default)(this, "bindingPrefix", void 0); (0, _defineProperty2().default)(this, "local", void 0); (0, _defineProperty2().default)(this, "state", void 0); (0, _defineProperty2().default)(this, "scopesList", void 0); 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().DEFAULT_LANGUAGE; this.deprecated = props.deprecated || false; this.bindingPrefix = props.bindingPrefix || _constants().DEFAULT_BINDINGS_PREFIX; this.local = props.local; this.state = props.state || {}; this.scopesList = props.scopesList || []; } // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! get versionArray() { return Object.values(this.versions); } listVersions(sort) { const versions = Object.keys(this.versions); if (!sort) return versions; if (sort === 'ASC') { return versions.sort(semver().compare); } return versions.sort(semver().compare).reverse(); } hasVersion(version) { return Boolean(this.versions[version]); } /** * add a new remote if it is not there already */ addScopeListItem(scopeListItem) { if (!scopeListItem.name || !scopeListItem.url || !scopeListItem.date) { throw new TypeError(`model-component.addRemote get an invalid remote. name: ${scopeListItem.name}, url: ${scopeListItem.url}, date: ${scopeListItem.date}`); } if (!this.scopesList.find(r => r.url === scopeListItem.url)) { this.scopesList.push(scopeListItem); } } /** * 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. */ _getComparableVersionsObjects(otherComponent, // in case of merging, the otherComponent is the existing component, and "this" is the incoming component local) { const otherLocalVersion = otherComponent.getLocalVersions(); const otherComponentVersions = (0, _utils().filterObject)(otherComponent.versions, (val, key) => Object.keys(this.versions).includes(key) && (!local || otherLocalVersion.includes(key))); const thisComponentVersions = (0, _utils().filterObject)(this.versions, (val, key) => Object.keys(otherComponentVersions).includes(key) && (!local || otherLocalVersion.includes(key))); return { thisComponentVersions, otherComponentVersions }; } compatibleWith(component, local) { const { thisComponentVersions, otherComponentVersions } = this._getComparableVersionsObjects(component, local); return (0, _ramda().equals)(thisComponentVersions, otherComponentVersions); } diffWith(component, local) { const { thisComponentVersions, otherComponentVersions } = this._getComparableVersionsObjects(component, local); return Object.keys(thisComponentVersions).filter(version => thisComponentVersions[version].hash !== otherComponentVersions[version].hash); } latest() { if ((0, _utils().empty)(this.versions)) return VERSION_ZERO; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return semver().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 */ latestExisting(repository) { if ((0, _utils().empty)(this.versions)) return VERSION_ZERO; const versions = this.listVersions('ASC'); let version = null; let versionStr = null; while (!version && versions && versions.length) { // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! versionStr = versions.pop(); // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! version = this.loadVersionSync(versionStr, repository, false); } return versionStr || VERSION_ZERO; } collectLogs(repo) { var _this = this; return (0, _bluebird().coroutine)(function* () { // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! const versions = yield repo.findMany(_this.versionArray); const logValues = versions.map(version => version ? version.log : { message: '<no-data-available>' }); const indexedLogs = (0, _ramda().fromPairs)((0, _ramda().zip)((0, _ramda().keys)(_this.versions), logValues)); return indexedLogs; })(); } /** * when bitMap is passed, it got called from the consumer and as such it strips the sharedDir */ collectVersions(repo) { return Promise.all(this.listVersions().map(versionNum => { // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! return this.toConsumerComponent(versionNum, this.scope, repo); })); } /** * if exactVersion is defined, add exact version instead of using the semver mechanism */ getVersionToAdd(releaseType = _constants().DEFAULT_BIT_RELEASE_TYPE, exactVersion) { if (exactVersion && this.versions[exactVersion]) { throw new (_exceptions().VersionAlreadyExists)(exactVersion, this.id()); } return exactVersion || this.version(releaseType); } addVersion(version, versionToAdd) { this.versions[versionToAdd] = version.hash(); this.markVersionAsLocal(versionToAdd); return versionToAdd; } version(releaseType = _constants().DEFAULT_BIT_RELEASE_TYPE) { const latest = this.latest(); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (latest) return semver().inc(latest, releaseType); return _constants().DEFAULT_BIT_VERSION; } id() { return this.scope ? [this.scope, this.name].join('/') : this.name; } toBitId() { return new (_bitId().default)({ scope: this.scope, name: this.name }); } toBitIdWithLatestVersion() { return new (_bitId().default)({ scope: this.scope, name: this.name, version: this.latest() }); } toBitIdWithLatestVersionAllowNull() { const id = this.toBitIdWithLatestVersion(); return id.version === VERSION_ZERO ? id.changeVersion(undefined) : id; } toObject() { function versions(vers) { const obj = {}; (0, _utils().forEach)(vers, (ref, version) => { obj[version] = ref.toString(); }); return obj; } const componentObject = { name: this.name, scope: this.scope, versions: versions(this.versions), lang: this.lang, deprecated: this.deprecated, bindingPrefix: this.bindingPrefix, remotes: this.scopesList }; // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! if (this.local) componentObject.local = this.local; // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! if (!(0, _ramda().isEmpty)(this.state)) componentObject.state = this.state; return componentObject; } loadVersion(version, repository) { var _this2 = this; return (0, _bluebird().coroutine)(function* () { const versionRef = _this2.versions[version]; if (!versionRef) throw new (_exceptions().VersionNotFound)(version); // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! return versionRef.load(repository); })(); } loadVersionSync(version, repository, throws = true) { const versionRef = this.versions[version]; if (!versionRef) throw new (_exceptions().VersionNotFound)(version); // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! return versionRef.loadSync(repository, throws); } collectVersionsObjects(repo, versions) { var _this3 = this; return (0, _bluebird().coroutine)(function* () { const collectRefs = /*#__PURE__*/function () { var _ref = (0, _bluebird().coroutine)(function* () { const refsCollection = []; function addRefs(_x) { return _addRefs.apply(this, arguments); } function _addRefs() { _addRefs = (0, _bluebird().coroutine)(function* (object) { const refs = object.refs(); const objs = yield Promise.all(refs.map(ref => ref.load(repo, true))); refsCollection.push(...refs); yield Promise.all(objs.map(obj => addRefs(obj))); }); return _addRefs.apply(this, arguments); } const versionsRefs = versions.map(version => _this3.versions[version]); refsCollection.push(...versionsRefs); const versionsObjects = yield Promise.all(versions.map(version => _this3.versions[version].load(repo))); yield Promise.all(versionsObjects.map(versionObject => addRefs(versionObject))); return refsCollection; }); return function collectRefs() { return _ref.apply(this, arguments); }; }(); const refs = yield collectRefs(); return Promise.all(refs.map(ref => ref.loadRaw(repo))); })(); } collectObjects(repo) { return Promise.all([this.asRaw(repo), this.collectRaw(repo)]).then(([rawComponent, objects]) => new (_componentObjects().default)(rawComponent, objects)).catch(err => { if (err.code === 'ENOENT') { throw new Error(`fatal: an object of "${this.id()}" was not found at ${err.path}\nplease try to re-import the component`); } throw err; }); } /** * to delete a version from a component, don't call this method directly. Instead, use sources.removeVersion() */ removeVersion(version) { const objectRef = this.versions[version]; delete this.versions[version]; if (this.state.versions && this.state.versions[version]) delete this.state.versions[version]; return objectRef; } toComponentVersion(versionStr) { const versionNum = (0, _versionParser().default)(versionStr).resolve(this.listVersions()); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (!this.versions[versionNum]) { throw new (_showDoctorError().default)(`the version ${versionNum} does not exist in ${this.listVersions().join('\n')}, versions array`); } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return new (_componentVersion().default)(this, versionNum); } /** * convert a ModelComponent of a specific version to ConsumerComponent * when it's being called from the Consumer, some manipulation are done on the component, such * as stripping the originallySharedDir and adding wrapDir. * when it's being called from the Scope, no manipulations are done. * * @see sources.consumerComponentToVersion() for the opposite action. */ toConsumerComponent(versionStr, scopeName, repository, manipulateDirData) { var _this4 = this; return (0, _bluebird().coroutine)(function* () { _logger().default.debug(`model-component, converting ${_this4.id()}, version: ${versionStr} to ConsumerComponent`); const componentVersion = _this4.toComponentVersion(versionStr); const version = yield componentVersion.getVersion(repository); const loadFileInstance = ClassName => /*#__PURE__*/function () { var _ref2 = (0, _bluebird().coroutine)(function* (file) { const loadP = file.file.load(repository); const content = yield loadP; if (!content) throw new (_showDoctorError().default)(`failed loading file ${file.relativePath} from the model`); return new ClassName({ base: '.', path: file.relativePath, contents: content.contents, test: file.test }); }); return function (_x2) { return _ref2.apply(this, arguments); }; }(); const filesP = version.files ? Promise.all(version.files.map(loadFileInstance(_sources().SourceFile))) : null; const distsP = version.dists ? Promise.all(version.dists.map(loadFileInstance(_sources().Dist))) : null; const scopeMetaP = scopeName ? _scopeMeta().default.fromScopeName(scopeName).load(repository) : Promise.resolve(); const log = version.log || null; // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! const compilerP = (0, _envFactory().makeEnvFromModel)(_constants().COMPILER_ENV_TYPE, version.compiler, repository); // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! const testerP = (0, _envFactory().makeEnvFromModel)(_constants().TESTER_ENV_TYPE, version.tester, repository); // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! const [files, dists, scopeMeta, compiler, tester] = yield Promise.all([filesP, distsP, scopeMetaP, compilerP, testerP]); const extensions = version.extensions.clone(); yield Promise.all(extensions.map( /*#__PURE__*/function () { var _ref3 = (0, _bluebird().coroutine)(function* (extension) { extension.artifacts = yield Promise.all(extension.artifacts.map(loadFileInstance(_artifact().Artifact))); }); return function (_x3) { return _ref3.apply(this, arguments); }; }())); const bindingPrefix = _this4.bindingPrefix === 'bit' ? '@bit' : _this4.bindingPrefix; // when generating a new ConsumerComponent out of Version, it is critical to make sure that // all objects are cloned and not copied by reference. Otherwise, every time the // ConsumerComponent instance is changed, the Version will be changed as well, and since // the Version instance is saved in the Repository._cache, the next time a Version instance // is retrieved, it'll be different than the first time. // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! const consumerComponent = new (_component().default)({ name: _this4.name, version: componentVersion.version, scope: _this4.scope, lang: _this4.lang, bindingPrefix, // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! mainFile: version.mainFile || null, compiler, tester, dependencies: version.dependencies.getClone(), devDependencies: version.devDependencies.getClone(), flattenedDependencies: version.flattenedDependencies.clone(), flattenedDevDependencies: version.flattenedDevDependencies.clone(), packageDependencies: (0, _ramda().clone)(version.packageDependencies), devPackageDependencies: (0, _ramda().clone)(version.devPackageDependencies), peerPackageDependencies: (0, _ramda().clone)(version.peerPackageDependencies), compilerPackageDependencies: (0, _ramda().clone)(version.compilerPackageDependencies), testerPackageDependencies: (0, _ramda().clone)(version.testerPackageDependencies), files, dists, mainDistFile: version.mainDistFile, docs: version.docs, license: scopeMeta ? _sources().License.deserialize(scopeMeta.license) : undefined, // todo: make sure we have license in case of local scope // @ts-ignore specsResults: version.specsResults ? version.specsResults.map(res => _specsResults().default.deserialize(res)) : null, log, customResolvedPaths: (0, _ramda().clone)(version.customResolvedPaths), overrides: _componentOverrides().default.loadFromScope(version.overrides), packageJsonChangedProps: (0, _ramda().clone)(version.packageJsonChangedProps), deprecated: _this4.deprecated, scopesList: (0, _ramda().clone)(_this4.scopesList), extensions }); if (manipulateDirData) { consumerComponent.stripOriginallySharedDir(manipulateDirData); consumerComponent.addWrapperDir(manipulateDirData); } return consumerComponent; })(); } refs() { return Object.values(this.versions); } replaceRef(oldRef, newRef) { const replace = (value, key) => { if (value === oldRef.hash) { // @ts-ignore this.versions[key] = newRef.hash; } }; (0, _ramda().forEachObjIndexed)(replace, this.versions); } validateBeforePersisting(componentStr) { _logger().default.silly(`validating component object: ${this.hash().hash} ${this.id()}`); const component = Component.parse(componentStr); component.validate(); } toBuffer(pretty) { const args = (0, _utils().getStringifyArgs)(pretty); const obj = this.toObject(); const str = JSON.stringify(obj, ...args); if (this.validateBeforePersist) this.validateBeforePersisting(str); return Buffer.from(str); } /** * Clear data that is relevant only for the local scope and should not be moved to the remote scope */ clearStateData() { this.local = false; // backward compatibility for components created before 0.12.6 this.state = {}; } markVersionAsLocal(version) { if (!this.state.versions) this.state = { versions: {} }; // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! if (!this.state.versions[version]) this.state.versions[version] = {}; // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! this.state.versions[version].local = true; } getLocalVersions() { if ((0, _ramda().isEmpty)(this.state) || (0, _ramda().isEmpty)(this.state.versions)) return []; // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! return Object.keys(this.state.versions).filter(version => this.state.versions[version].local); } isLocallyChanged() { if (this.local) return true; // backward compatibility for components created before 0.12.6 if ((0, _ramda().isEmpty)(this.state) || (0, _ramda().isEmpty)(this.state.versions)) return false; const localVersions = this.getLocalVersions(); return localVersions.length > 0; } static parse(contents) { const rawComponent = JSON.parse(contents); return Component.from({ name: rawComponent.box ? `${rawComponent.box}/${rawComponent.name}` : rawComponent.name, scope: rawComponent.scope, versions: (0, _utils().mapObject)(rawComponent.versions, val => _objects().Ref.from(val)), lang: rawComponent.lang, deprecated: rawComponent.deprecated, bindingPrefix: rawComponent.bindingPrefix, local: rawComponent.local, state: rawComponent.state, scopesList: rawComponent.remotes }); } static from(props) { return new Component(props); } static fromBitId(bitId) { if (bitId.box) throw new Error('component.fromBitId, bitId should not have the "box" property populated'); // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! return new Component({ name: bitId.name, scope: bitId.scope }); } validate() { const message = `unable to save Component object "${this.id()}"`; if (!this.name) throw new (_generalError().default)(`${message} the name is missing`); if (this.state && this.state.versions) { Object.keys(this.state.versions).forEach(version => { if (!this.versions[version]) { throw new (_validationError().default)(`${message}, the version ${version} is marked as staged but is not available`); } }); } } } exports.default = Component;