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
352 lines (274 loc) • 13.3 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.componentOverridesForbiddenFields = 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 _constants() {
const data = require("../../constants");
_constants = function () {
return data;
};
return data;
}
function _consumerOverrides() {
const data = require("./consumer-overrides");
_consumerOverrides = function () {
return data;
};
return data;
}
function _utils() {
const data = require("../../utils");
_utils = function () {
return data;
};
return data;
}
// consumer internal fields should not be used in component overrides, otherwise, they might conflict upon import
const componentOverridesForbiddenFields = [..._consumerOverrides().overridesForbiddenFields, ..._consumerOverrides().overridesBitInternalFields];
exports.componentOverridesForbiddenFields = componentOverridesForbiddenFields;
class ComponentOverrides {
constructor(overrides) {
(0, _defineProperty2().default)(this, "overrides", void 0);
this.overrides = overrides || {};
}
static registerOnComponentOverridesLoading(extId, func) {
this.componentOverridesLoadingRegistry[extId] = func;
}
/**
* overrides of component can be determined by three different sources.
* 1. component-config. (bit.json/package.json of the component itself).
* authored normally don't have it, most imported have it, unless they choose not to write package.json/bit.json.
* 2. consumer-config. (bit.json/package.json of the consumer when it has overrides of the component).
* 3. model. (when the component is tagged, the overrides data is saved into the model).
*
* the strategy of loading them is as follows:
* a) find the component config. (if exists)
* b) find the overrides of workspace config matching this component. (if exists)
* c) merge between the two. in case of conflict, the component config wins.
*
* the following steps are needed to find the component config
* a) if the component config is written to the filesystem, use it
* b) if the component config is not written, it can be for two reasons:
* 1) it's imported and the user chose not to write package.json nor bit.json. in this case, use
* component from the model.
* 2) it's author. by default, the config is written into consumer-config (if not exist) on import.
* which, in this case, use only consumer-config.
* an exception is when an author runs `eject-conf` command to explicitly write the config, then,
* use the component-config.
*/
static loadFromConsumer(componentId, workspaceConfig, overridesFromModel, componentConfig, origin) {
var _this = this;
return (0, _bluebird().coroutine)(function* () {
const isAuthor = origin === _constants().COMPONENT_ORIGINS.AUTHORED;
const isNotNested = origin !== _constants().COMPONENT_ORIGINS.NESTED; // overrides from consumer-config is not relevant and should not affect imported
let legacyOverridesFromConsumer = isNotNested ? workspaceConfig === null || workspaceConfig === void 0 ? void 0 : workspaceConfig.getComponentConfig(componentId) : null;
if (isAuthor) {
const plainLegacy = workspaceConfig === null || workspaceConfig === void 0 ? void 0 : workspaceConfig._legacyPlainObject();
if (plainLegacy && plainLegacy.env) {
legacyOverridesFromConsumer = legacyOverridesFromConsumer || {};
legacyOverridesFromConsumer.env = {};
legacyOverridesFromConsumer.env.compiler = plainLegacy.env.compiler;
legacyOverridesFromConsumer.env.tester = plainLegacy.env.tester;
}
}
const getFromComponent = () => {
if (componentConfig && componentConfig.componentHasWrittenConfig) {
return componentConfig.overrides;
}
return isAuthor ? null : overridesFromModel;
};
const extensionsAddedOverrides = yield runOnLoadOverridesEvent(_this.componentOverridesLoadingRegistry, componentConfig.parseExtensions());
const mergedLegacyConsumerOverridesWithExtensions = mergeOverrides(legacyOverridesFromConsumer || {}, extensionsAddedOverrides);
const fromComponent = getFromComponent();
if (!fromComponent) {
return new ComponentOverrides(mergedLegacyConsumerOverridesWithExtensions);
}
const mergedOverrides = mergedLegacyConsumerOverridesWithExtensions ? mergeOverrides(fromComponent, mergedLegacyConsumerOverridesWithExtensions) : fromComponent;
return new ComponentOverrides(mergedOverrides);
})();
}
static loadFromScope(overridesFromModel = {}) {
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
return new ComponentOverrides(_ramda().default.clone(overridesFromModel), {});
}
get componentOverridesData() {
const isNotSystemField = (val, field) => !_consumerOverrides().overridesBitInternalFields.includes(field);
return _ramda().default.pickBy(isNotSystemField, this.overrides);
}
get componentOverridesPackageJsonData() {
const isPackageJsonField = (val, field) => !_consumerOverrides().nonPackageJsonFields.includes(field);
return _ramda().default.pickBy(isPackageJsonField, this.overrides);
}
getEnvByType(envType) {
return _ramda().default.path(['env', envType], this.overrides);
}
getComponentDependenciesWithVersion() {
const allDeps = Object.assign({}, this.overrides.dependencies, this.overrides.devDependencies, this.overrides.peerDependencies);
return this._filterForComponentWithValidVersion(allDeps);
}
get defaultScope() {
return this.overrides.defaultScope;
}
_filterForComponentWithValidVersion(deps) {
return Object.keys(deps).reduce((acc, current) => {
if (this._isValidVersion(deps[current]) && current.startsWith(_constants().OVERRIDE_COMPONENT_PREFIX)) {
const component = current.replace(_constants().OVERRIDE_COMPONENT_PREFIX, '');
acc[component] = deps[current];
}
return acc;
}, {});
}
_isValidVersion(ver) {
return ver !== _constants().MANUALLY_ADD_DEPENDENCY && ver !== _constants().MANUALLY_REMOVE_DEPENDENCY;
}
getIgnored(field) {
return _ramda().default.keys(_ramda().default.filter(dep => dep === _constants().MANUALLY_REMOVE_DEPENDENCY, this.overrides[field] || {}));
}
getIgnoredFiles(field) {
const ignoredRules = this.getIgnored(field);
return ignoredRules.filter(rule => rule.startsWith(_constants().OVERRIDE_FILE_PREFIX)).map(rule => rule.replace(_constants().OVERRIDE_FILE_PREFIX, ''));
}
getIgnoredComponents(field) {
const ignoredRules = this.getIgnored(field);
return _ramda().default.flatten(ignoredRules.filter(rule => rule.startsWith(_constants().OVERRIDE_COMPONENT_PREFIX)).map(rule => rule.replace(_constants().OVERRIDE_COMPONENT_PREFIX, '')).map(idStr => [idStr, ...this._getComponentNamesFromPackages(idStr)]));
} // TODO: This strategy should be stopped using since harmony, because a package name
// TODO: might be completely different than a component id
// TODO: instead we should go to the package.json and check the component name there
// TODO: Like we do in build-tree.resolveNodePackage
// TODO: or use some index that store it (doesn't exist at the moment)
/**
* it is possible that a user added the component into the overrides as a package.
* e.g. `@bit/david.utils.is-string` instead of `@bit/david.utils/is-string`
* or, if not using bit.dev, `@bit/utils.is-string` instead of `@bit/utils/is-string`
*/
_getComponentNamesFromPackages(idStr) {
const idSplitByDot = idStr.split('.');
const numberOfDots = idSplitByDot.length - 1;
if (numberOfDots === 0) return []; // nothing to do. it wasn't entered as a package
const localScopeComponent = idSplitByDot.join('/'); // convert all dots to slashes
if (numberOfDots === 1) {
// it can't be from bit.dev, it must be locally
return [localScopeComponent];
} // there are two dots or more. it can be from bit.dev and it can be locally
// for a remoteScopeComponent, leave the first dot and convert only the rest to a slash
const remoteScopeComponent = `${_ramda().default.head(idSplitByDot)}.${_ramda().default.tail(idSplitByDot).join('/')}`;
return [localScopeComponent, remoteScopeComponent];
}
getIgnoredPackages(field) {
const ignoredRules = this.getIgnored(field);
return ignoredRules.filter(rule => !rule.startsWith(_constants().OVERRIDE_FILE_PREFIX) && !rule.startsWith(_constants().OVERRIDE_COMPONENT_PREFIX));
}
stripOriginallySharedDir(sharedDir) {
if (!sharedDir) return;
_constants().DEPENDENCIES_FIELDS.forEach(field => {
if (!this.overrides[field]) return;
Object.keys(this.overrides[field]).forEach(rule => {
if (!rule.startsWith(_constants().OVERRIDE_FILE_PREFIX)) return;
const fileWithSharedDir = rule.replace(_constants().OVERRIDE_FILE_PREFIX, '');
const fileWithoutSharedDir = fileWithSharedDir.replace(`${sharedDir}/`, '');
const value = this.overrides[field][rule];
delete this.overrides[field][rule];
this.overrides[field][`${_constants().OVERRIDE_FILE_PREFIX}${fileWithoutSharedDir}`] = value;
});
});
}
addOriginallySharedDir(sharedDir) {
if (!sharedDir) return;
_constants().DEPENDENCIES_FIELDS.forEach(field => {
if (!this.overrides[field]) return;
Object.keys(this.overrides[field]).forEach(rule => {
if (!rule.startsWith(_constants().OVERRIDE_FILE_PREFIX)) return;
const fileWithoutSharedDir = rule.replace(_constants().OVERRIDE_FILE_PREFIX, '');
const fileWithSharedDir = `${sharedDir}/${fileWithoutSharedDir}`;
const value = this.overrides[field][rule];
delete this.overrides[field][rule];
this.overrides[field][`${_constants().OVERRIDE_FILE_PREFIX}${fileWithSharedDir}`] = value;
});
});
}
static getAllFilesPaths(overrides) {
if (!overrides) return [];
const allDeps = Object.assign({}, overrides.dependencies, overrides.devDependencies, overrides.peerDependencies);
return Object.keys(allDeps).filter(rule => rule.startsWith(_constants().OVERRIDE_FILE_PREFIX)).map(rule => rule.replace(_constants().OVERRIDE_FILE_PREFIX, ''));
}
clone() {
return new ComponentOverrides(_ramda().default.clone(this.overrides));
}
}
exports.default = ComponentOverrides;
(0, _defineProperty2().default)(ComponentOverrides, "componentOverridesLoadingRegistry", {});
function mergeOverrides(overrides1, overrides2) {
// Make sure to not mutate the original object
const result = _ramda().default.clone(overrides1);
const isObjectAndNotArray = val => typeof val === 'object' && !Array.isArray(val);
Object.keys(overrides2 || {}).forEach(field => {
// Do not merge internal fields
if (_consumerOverrides().overridesBitInternalFields.includes(field)) {
return; // do nothing
}
if (isObjectAndNotArray(overrides1[field]) && isObjectAndNotArray(overrides2[field])) {
result[field] = Object.assign({}, overrides2[field], overrides1[field]);
} else if (!result[field]) {
result[field] = overrides2[field];
} // when overrides1[field] is set and not an object, do not override it by overrides2
});
return result;
}
/**
* Merge added overrides from many extensions
*
* @param {any[]} configs
* @returns A merge results of all config
*/
function mergeExtensionsOverrides(configs) {
return configs.reduce((prev, curr) => {
return _ramda().default.mergeDeepLeft(prev, curr);
}, {});
}
/**
* Runs all the functions from the registry and merged their results
*
* @param {OverridesLoadRegistry} configsRegistry
* @returns {Promise<ComponentOverridesData>} A merge results of the added overrides by all the extensions
*/
function runOnLoadOverridesEvent(_x, _x2) {
return _runOnLoadOverridesEvent.apply(this, arguments);
}
function _runOnLoadOverridesEvent() {
_runOnLoadOverridesEvent = (0, _bluebird().coroutine)(function* (configsRegistry, extensions) {
const extensionsAddedOverridesP = Object.keys(configsRegistry).map(extId => {
// TODO: only running func for relevant extensions
const func = configsRegistry[extId];
return func(extensions);
});
const extensionsAddedOverrides = yield Promise.all(extensionsAddedOverridesP);
let extensionsConfigModificationsObject = mergeExtensionsOverrides(extensionsAddedOverrides);
const filterFunc = val => !_ramda().default.isEmpty(val);
extensionsConfigModificationsObject = (0, _utils().filterObject)(extensionsConfigModificationsObject, filterFunc);
return extensionsConfigModificationsObject;
});
return _runOnLoadOverridesEvent.apply(this, arguments);
}
;