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
500 lines (381 loc) • 16.6 kB
JavaScript
"use strict";
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 _ramda() {
const data = _interopRequireDefault(require("ramda"));
_ramda = function () {
return data;
};
return data;
}
function _pMapSeries() {
const data = _interopRequireDefault(require("p-map-series"));
_pMapSeries = function () {
return data;
};
return data;
}
function _enrichContextFromGlobal() {
const data = _interopRequireDefault(require("../../hooks/utils/enrich-context-from-global"));
_enrichContextFromGlobal = function () {
return data;
};
return data;
}
function _bitId() {
const data = require("../../bit-id");
_bitId = function () {
return data;
};
return data;
}
function _versionDependencies() {
const data = _interopRequireDefault(require("../version-dependencies"));
_versionDependencies = function () {
return data;
};
return data;
}
function _logger() {
const data = _interopRequireDefault(require("../../logger/logger"));
_logger = function () {
return data;
};
return data;
}
function _exceptions() {
const data = require("../network/exceptions");
_exceptions = function () {
return data;
};
return data;
}
function _exceptions2() {
const data = require("../exceptions");
_exceptions2 = function () {
return data;
};
return data;
}
function _analytics() {
const data = require("../../analytics/analytics");
_analytics = function () {
return data;
};
return data;
}
function _generalError() {
const data = _interopRequireDefault(require("../../error/general-error"));
_generalError = function () {
return data;
};
return data;
}
function _scopeRemotes() {
const data = require("../scope-remotes");
_scopeRemotes = function () {
return data;
};
return data;
}
function _utils() {
const data = require("../../utils");
_utils = function () {
return data;
};
return data;
}
function _showDoctorError() {
const data = _interopRequireDefault(require("../../error/show-doctor-error"));
_showDoctorError = function () {
return data;
};
return data;
}
const removeNils = _ramda().default.reject(_ramda().default.isNil);
class ScopeComponentsImporter {
constructor(scope) {
(0, _defineProperty2().default)(this, "scope", void 0);
(0, _defineProperty2().default)(this, "sources", void 0);
if (!scope) throw new Error('unable to instantiate ScopeComponentsImporter without Scope');
this.scope = scope;
this.sources = scope.sources;
}
static getInstance(scope) {
return new ScopeComponentsImporter(scope);
}
/**
* 1. Local objects, fetch from local. (done by this.sources.getMany method)
* 2. Fetch flattened dependencies (done by toVersionDependencies method). If they're not locally, fetch from remote
* and save them locally.
* 3. External objects, fetch from a remote and save locally. (done by this.getExternalOnes method).
*/
importMany(ids, cache = true, persist = true) {
var _this = this;
return (0, _bluebird().coroutine)(function* () {
_logger().default.debugAndAddBreadCrumb('ScopeComponentsImporter', 'importMany: {ids}', {
ids: ids.toString()
});
const idsWithoutNils = removeNils(ids);
if (_ramda().default.isEmpty(idsWithoutNils)) return Promise.resolve([]);
const [locals, externals] = _ramda().default.partition(id => id.isLocal(_this.scope.name), idsWithoutNils);
const localDefs = yield _this.sources.getMany(locals);
const versionDeps = yield (0, _pMapSeries().default)(localDefs, def => {
if (!def.component) throw new (_exceptions2().ComponentNotFound)(def.id.toString());
return _this.componentToVersionDependencies(def.component, def.id);
});
_logger().default.debugAndAddBreadCrumb('ScopeComponentsImporter', 'importMany: successfully fetched local components and their dependencies. Going to fetch externals');
const remotes = yield (0, _scopeRemotes().getScopeRemotes)(_this.scope);
const externalDeps = yield _this._getExternalMany(externals, remotes, cache, persist);
return versionDeps.concat(externalDeps);
})();
}
importManyWithoutDependencies(ids, cache = true) {
var _this2 = this;
return (0, _bluebird().coroutine)(function* () {
if (!ids.length) return [];
_logger().default.debug(`importManyWithoutDependencies. Ids: ${ids.join(', ')}, cache: ${cache.toString()}`);
_analytics().Analytics.addBreadCrumb('importManyWithoutDependencies', `Ids: ${_analytics().Analytics.hashData(ids)}`);
const idsWithoutNils = removeNils(ids);
if (_ramda().default.isEmpty(idsWithoutNils)) return Promise.resolve([]);
const [externals, locals] = (0, _utils().splitBy)(idsWithoutNils, id => id.isLocal(_this2.scope.name));
const localDefs = yield _this2.sources.getMany(locals);
const componentVersionArr = yield Promise.all(localDefs.map(def => {
if (!def.component) throw new (_exceptions2().ComponentNotFound)(def.id.toString()); // $FlowFixMe it must have a version
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
return def.component.toComponentVersion(def.id.version);
}));
const remotes = yield (0, _scopeRemotes().getScopeRemotes)(_this2.scope);
const externalDeps = yield _this2._getExternalManyWithoutDependencies(externals, remotes, cache);
return componentVersionArr.concat(externalDeps);
})();
}
/**
* todo: improve performance by finding all versions needed and fetching them in one request from the server
* currently it goes to the server twice. First, it asks for the last version of each id, and then it goes again to
* ask for the older versions.
*/
importManyWithAllVersions(ids, cache = true, allDepsVersions = false // by default, only dependencies of the latest version are imported
) {
var _this3 = this;
return (0, _bluebird().coroutine)(function* () {
_logger().default.debug(`scope.getManyWithAllVersions, Ids: ${ids.join(', ')}`);
_analytics().Analytics.addBreadCrumb('getManyWithAllVersions', `scope.getManyWithAllVersions, Ids: ${_analytics().Analytics.hashData(ids)}`);
const idsWithoutNils = removeNils(ids);
if (_ramda().default.isEmpty(idsWithoutNils)) return Promise.resolve([]);
const versionDependenciesArr = yield _this3.importMany(idsWithoutNils, cache);
const allIdsWithAllVersions = new (_bitId().BitIds)();
versionDependenciesArr.forEach(versionDependencies => {
const versions = versionDependencies.component.component.listVersions();
const idsWithAllVersions = versions.map(version => {
if (version === versionDependencies.component.version) return null; // imported already
const versionId = versionDependencies.component.id;
return versionId.changeVersion(version);
});
allIdsWithAllVersions.push(...removeNils(idsWithAllVersions));
});
if (allDepsVersions) {
const verDepsOfOlderVersions = yield _this3.importMany(allIdsWithAllVersions, cache);
versionDependenciesArr.push(...verDepsOfOlderVersions);
const allFlattenDepsIds = versionDependenciesArr.map(v => v.allDependencies.map(d => d.id));
const dependenciesOnly = _ramda().default.flatten(allFlattenDepsIds).filter(id => !ids.hasWithoutVersion(id));
const verDepsOfAllFlattenDeps = yield _this3.importManyWithAllVersions(_bitId().BitIds.uniqFromArray(dependenciesOnly));
versionDependenciesArr.push(...verDepsOfAllFlattenDeps);
} else {
yield _this3.importManyWithoutDependencies(allIdsWithAllVersions);
}
return versionDependenciesArr;
})();
}
importDependencies(dependencies) {
return new Promise((resolve, reject) => {
return this.importMany(dependencies).then(resolve).catch(e => {
_logger().default.error(`importDependencies got an error: ${JSON.stringify(e)}`);
if (e instanceof _exceptions().RemoteScopeNotFound || e instanceof _exceptions().PermissionDenied) return reject(e);
return reject(new (_exceptions2().DependencyNotFound)(e.id));
});
});
}
componentToVersionDependencies(component, id) {
var _this4 = this;
return (0, _bluebird().coroutine)(function* () {
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
const versionComp = component.toComponentVersion(id.version); // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
const source = id.scope;
const version = yield versionComp.getVersion(_this4.scope.objects);
if (!version) {
_logger().default.debug(`toVersionDependencies, component ${component.id().toString()}, version ${versionComp.version} not found, going to fetch from a remote`);
if (component.scope === _this4.scope.name) {
// it should have been fetched locally, since it wasn't found, this is an error
throw new (_showDoctorError().default)(`Version ${versionComp.version} of ${component.id().toString()} was not found in scope ${_this4.scope.name}`);
}
return (0, _scopeRemotes().getScopeRemotes)(_this4.scope).then(remotes => {
return _this4._getExternal({
id,
remotes,
localFetch: false
});
});
}
_logger().default.debug(`toVersionDependencies, component ${component.id().toString()}, version ${versionComp.version} found, going to collect its dependencies`);
const dependencies = yield _this4.importManyWithoutDependencies(version.flattenedDependencies);
const devDependencies = yield _this4.importManyWithoutDependencies(version.flattenedDevDependencies);
const extensionsDependencies = yield _this4.importManyWithoutDependencies(version.extensions.extensionsBitIds);
return new (_versionDependencies().default)(versionComp, dependencies, devDependencies, extensionsDependencies, source);
})();
}
componentsToComponentsObjects(components, clientVersion) {
return (0, _pMapSeries().default)(components, component => component.toObjects(this.scope.objects, clientVersion));
}
/**
* get ConsumerComponent by bitId. if the component was not found locally, import it from a remote scope
*/
loadRemoteComponent(id) {
return this._getComponentVersion(id).then(component => {
if (!component) throw new (_exceptions2().ComponentNotFound)(id.toString()); // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
return component.toConsumer(this.scope.objects);
});
}
loadComponent(id, localOnly = true) {
_logger().default.debugAndAddBreadCrumb('ScopeComponentsImporter', 'loadComponent {id}', {
id: id.toString()
});
if (localOnly && !id.isLocal(this.scope.name)) {
throw new (_generalError().default)('cannot load a component from remote scope, please import first');
}
return this.loadRemoteComponent(id);
}
/**
* recursive function.
* if found locally, use them. Otherwise, fetch from remote and then, save into the model.
*/
_getExternalMany(ids, remotes, localFetch = true, persist = true, context = {}) {
if (!ids.length) return Promise.resolve([]);
_logger().default.debugAndAddBreadCrumb('scope.getExternalMan', `planning on fetching from ${localFetch ? 'local' : 'remote'} scope. Ids: {ids}`, {
ids: ids.join(', ')
});
(0, _enrichContextFromGlobal().default)(Object.assign(context, {
requestedBitIds: ids.map(id => id.toString())
}));
return this.sources.getMany(ids).then(defs => {
const left = defs.filter(def => {
if (!localFetch) return true;
if (!def.component) return true;
return false;
});
if (left.length === 0) {
_logger().default.debugAndAddBreadCrumb('scope.getExternalMany', 'no more ids left, all found locally, exiting the method');
return (0, _pMapSeries().default)(defs, def => this.componentToVersionDependencies(def.component, def.id));
}
_logger().default.debugAndAddBreadCrumb('scope.getExternalMany', `${left.length} left. Fetching them from a remote`);
return remotes.fetch(left.map(def => def.id), this.scope, undefined, context).then(componentObjects => {
_logger().default.debugAndAddBreadCrumb('scope.getExternalMany', 'writing them to the model');
return this.scope.writeManyComponentsToModel(componentObjects, persist);
}).then(() => this._getExternalMany(ids, remotes));
});
}
/**
* If the component is not in the local scope, fetch it from a remote and save into the local
* scope. (objects directory).
*/
_getExternal({
id,
remotes,
localFetch = true,
context = {}
}) {
(0, _enrichContextFromGlobal().default)(context);
return this.sources.get(id).then(component => {
if (component && localFetch) {
return this.componentToVersionDependencies(component, id);
}
return remotes.fetch([id], this.scope, undefined, context).then(([componentObjects]) => {
return this.scope.writeComponentToModel(componentObjects);
}).then(() => this._getExternal({
id,
remotes,
localFetch: true
}));
});
}
_getExternalWithoutDependencies({
id,
remotes,
localFetch = true,
context = {}
}) {
return this.sources.get(id).then(component => {
if (component && localFetch) {
// $FlowFixMe scope component must have a version
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
return component.toComponentVersion(id.version);
}
return remotes.fetch([id], this.scope, true, context).then(([componentObjects]) => this.scope.writeComponentToModel(componentObjects)).then(() => this._getExternal({
id,
remotes,
localFetch: true
})).then(versionDependencies => versionDependencies.component);
});
}
_getExternalManyWithoutDependencies(ids, remotes, localFetch = false, context = {}) {
if (!ids.length) return Promise.resolve([]);
_logger().default.debugAndAddBreadCrumb('getExternalOnes', `getExternalOnes, ids: {ids}, localFetch: ${localFetch.toString()}`, {
ids: ids.join(', ')
});
(0, _enrichContextFromGlobal().default)(Object.assign(context, {
requestedBitIds: ids.map(id => id.toString())
}));
return this.sources.getMany(ids).then(defs => {
const left = defs.filter(def => {
if (!localFetch) return true;
if (!def.component) return true;
return false;
});
if (left.length === 0) {
_logger().default.debugAndAddBreadCrumb('scope.getExternalOnes', 'no more ids left, all found locally, exiting the method'); // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
return Promise.all(defs.map(def => def.component.toComponentVersion(def.id.version)));
}
_logger().default.debugAndAddBreadCrumb('getExternalOnes', `getExternalOnes: ${left.length} left. Fetching them from a remote`);
return remotes.fetch(left.map(def => def.id), this.scope, true, context).then(componentObjects => {
return this.scope.writeManyComponentsToModel(componentObjects);
}).then(() => this._getExternalManyWithoutDependencies(ids, remotes, true));
});
}
_getComponentVersion(id) {
var _this5 = this;
return (0, _bluebird().coroutine)(function* () {
if (!id.isLocal(_this5.scope.name)) {
const remotes = yield (0, _scopeRemotes().getScopeRemotes)(_this5.scope);
return _this5._getExternalWithoutDependencies({
id,
remotes,
localFetch: true
});
}
return _this5.sources.get(id).then(component => {
if (!component) throw new (_exceptions2().ComponentNotFound)(id.toString()); // $FlowFixMe version is set
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
return component.toComponentVersion(id.version);
});
})();
}
}
exports.default = ScopeComponentsImporter;