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
353 lines (272 loc) • 11.7 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.nonPackageJsonFields = exports.overridesBitInternalFields = exports.overridesForbiddenFields = 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 _chalk() {
const data = _interopRequireDefault(require("chalk"));
_chalk = function () {
return data;
};
return data;
}
function _ramda() {
const data = _interopRequireDefault(require("ramda"));
_ramda = function () {
return data;
};
return data;
}
function _hasWildcard() {
const data = _interopRequireDefault(require("../../utils/string/has-wildcard"));
_hasWildcard = function () {
return data;
};
return data;
}
function _isBitIdMatchByWildcards() {
const data = _interopRequireDefault(require("../../utils/bit/is-bit-id-match-by-wildcards"));
_isBitIdMatchByWildcards = function () {
return data;
};
return data;
}
function _validateType() {
const data = require("../../utils/validate-type");
_validateType = function () {
return data;
};
return data;
}
function _generalError() {
const data = _interopRequireDefault(require("../../error/general-error"));
_generalError = function () {
return data;
};
return data;
}
function _abstractConfig() {
const data = _interopRequireDefault(require("./abstract-config"));
_abstractConfig = function () {
return data;
};
return data;
}
function _constants() {
const data = require("../../constants");
_constants = function () {
return data;
};
return data;
}
function _logger() {
const data = _interopRequireDefault(require("../../logger/logger"));
_logger = function () {
return data;
};
return data;
}
const overridesForbiddenFields = ['name', 'main', 'version', 'bit'];
exports.overridesForbiddenFields = overridesForbiddenFields;
const overridesBitInternalFields = ['propagate', 'exclude', 'env', 'defaultScope', 'extensions'];
exports.overridesBitInternalFields = overridesBitInternalFields;
const nonPackageJsonFields = [..._constants().DEPENDENCIES_FIELDS, ...overridesBitInternalFields];
exports.nonPackageJsonFields = nonPackageJsonFields;
class ConsumerOverrides {
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
// whether the overrides has been changed (so then it should write them to fs)
constructor(overrides) {
(0, _defineProperty2().default)(this, "overrides", void 0);
(0, _defineProperty2().default)(this, "hasChanged", void 0);
this.overrides = overrides;
}
static load(overrides = {}) {
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
return new ConsumerOverrides(overrides);
}
getOverrideComponentData(bitId) {
const matches = this._getAllRulesMatchedById(bitId);
if (!matches.length) {
return null;
}
const overrideValues = matches.map(match => _ramda().default.clone(this.overrides[match]));
let stopPropagation = false;
return overrideValues.reduce((acc, current) => {
if (stopPropagation) return acc;
if (!current.propagate) {
stopPropagation = true;
}
this._updateSpecificOverridesWithGeneralOverrides(current, acc);
return acc;
}, {});
}
_updateSpecificOverridesWithGeneralOverrides(generalOverrides, specificOverrides) {
const isObjectAndNotArray = val => typeof val === 'object' && !Array.isArray(val);
Object.keys(generalOverrides).forEach(field => {
switch (field) {
case 'env':
if (!specificOverrides[field]) specificOverrides[field] = {};
['compiler', 'tester'].forEach(envField => {
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
if (specificOverrides.env[envField] || !generalOverrides.env[envField]) return; // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
specificOverrides.env[envField] = generalOverrides.env[envField];
});
break;
case 'propagate':
case 'exclude':
// it's a system field, do nothing
break;
default:
if (isObjectAndNotArray(specificOverrides[field]) && isObjectAndNotArray(generalOverrides[field])) {
specificOverrides[field] = Object.assign({}, generalOverrides[field], specificOverrides[field]);
} else if (!specificOverrides[field]) {
specificOverrides[field] = generalOverrides[field];
}
// when specificOverrides[field] is set and not an object, do not override it by the general one
}
});
}
_getAllRulesMatchedById(bitId) {
const exactMatch = this.findExactMatch(bitId);
const matchByGlobPattern = Object.keys(this.overrides).filter(idStr => this._isMatchByWildcard(bitId, idStr));
const nonExcluded = matchByGlobPattern.filter(match => !this._isExcluded(this.overrides[match], bitId));
const allMatches = nonExcluded.sort(ConsumerOverrides.sortWildcards);
if (exactMatch) allMatches.unshift(exactMatch);
return allMatches;
}
_isMatchByWildcard(bitId, idWithPossibleWildcard) {
if (!(0, _hasWildcard().default)(idWithPossibleWildcard)) return false;
return (0, _isBitIdMatchByWildcards().default)(bitId, idWithPossibleWildcard);
}
_isExcluded(overridesValues, bitId) {
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
if (!overridesValues.exclude || !overridesValues.exclude.length) {
return false;
} // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
return overridesValues.exclude.some(excludeRule => this._isMatchByWildcard(bitId, excludeRule) || bitId.toStringWithoutVersion() === excludeRule || bitId.toStringWithoutScopeAndVersion() === excludeRule);
}
/**
* sort from the more specific (more namespaces) to the more generic (less namespaces)
* e.g.
* src/utils/javascript/*
* src/utils/javascript/*
* src/utils/*
* src/*
*
* more namespaces (slashes) === more specific
* more wildcards === less specific
*
* if both have the same number of namespaces (slashes), the one with less wildcards is first.
* if both have the same number of wildcards, the one with more namespaces is first.
*
* a reminder about compare function:
* If the result is negative a is sorted before b.
* If the result is positive b is sorted before a.
* If the result is 0 no changes is done with the sort order of the two values.
*/
static sortWildcards(a, b) {
const numOfNamespaces = str => (str.match(/\//g) || []).length;
const numOfWildcards = str => (str.match(/\*/g) || []).length;
const indexOfFirstWildcard = str => str.indexOf('*');
const byNamespaces = numOfNamespaces(b) - numOfNamespaces(a);
if (byNamespaces !== 0) return byNamespaces;
const byWildcards = numOfWildcards(a) - numOfWildcards(b);
if (byWildcards !== 0) return byWildcards; // both have the same number of namespaces and the same number of wildcards
// e.g. a component `utils/is-string` matches two rules: `utils/*` and `*/is-string`.
// the one with the wildcard more left should be first as it is more specific.
return indexOfFirstWildcard(a) - indexOfFirstWildcard(b);
}
updateOverridesIfChanged(component, areEnvsChanged) {
var _this = this;
return (0, _bluebird().coroutine)(function* () {
const overrides = component.overrides.componentOverridesData;
const id = component.id;
const existingOverrides = _this.getOverrideComponentData(id);
if (!areEnvsChanged && _this.areOverridesObjectsEqual(existingOverrides, overrides)) return false;
const exactMatch = _this.findExactMatch(id);
const key = exactMatch || id.toStringWithoutVersion();
const env = {};
if (component.compiler) {
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
env.compiler = _abstractConfig().default.convertEnvToStringIfPossible(component.compiler.toBitJsonObject('.'));
}
if (component.tester) {
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
env.tester = _abstractConfig().default.convertEnvToStringIfPossible(component.tester.toBitJsonObject('.'));
}
if (!_ramda().default.isEmpty(env)) overrides.env = env;
_this.overrides[key] = overrides;
_this.hasChanged = true;
return true;
})();
}
areOverridesObjectsEqual(overridesA, overridesB) {
// seems like R.equals does a great job here. it compares objects by values (not by reference).
// also it disregards the keys order.
return _ramda().default.equals(overridesA || {}, overridesB || {});
}
findExactMatch(bitId) {
return Object.keys(this.overrides).find(idStr => bitId.toStringWithoutVersion() === idStr || bitId.toStringWithoutScopeAndVersion() === idStr);
}
removeExactMatch(bitId) {
const exactMatch = this.findExactMatch(bitId);
if (!exactMatch) return false;
delete this.overrides[exactMatch];
return true;
}
static validate(overrides) {
if (typeof overrides === 'undefined') return;
const message = 'consumer-config (either bit.json or package.json "bit")';
(0, _validateType().validateUserInputType)(message, overrides, 'overrides', 'object');
Object.keys(overrides).forEach(id => validateComponentOverride(id, overrides[id]));
function validateComponentOverride(id, override) {
(0, _validateType().validateUserInputType)(message, override, `overrides.${id}`, 'object');
Object.keys(override).forEach(field => {
if (overridesForbiddenFields.includes(field)) {
throw new (_generalError().default)(`${message} found a forbidden field "${field}" inside "overrides.${id}" property.
the following fields are not allowed: ${overridesForbiddenFields.join(', ')}.`);
}
if (_constants().DEPENDENCIES_FIELDS.includes(field)) {
validateDependencyField(field, override, id);
} else if (field === 'env') {
validateEnv(override, id);
} else if (field === 'exclude') {
(0, _validateType().validateUserInputType)(message, override.exclude, `overrides.${id}.exclude`, 'array');
}
});
}
function validateDependencyField(field, override, id) {
(0, _validateType().validateUserInputType)(message, override[field], `overrides.${id}.${field}`, 'object');
Object.keys(override[field]).forEach(rule => {
(0, _validateType().validateUserInputType)(message, override[field][rule], `overrides.${id}.${field}.${rule}`, 'string');
if (rule.startsWith(_constants().OVERRIDE_FILE_PREFIX)) {
// @todo: once v15 is out, this warning should be replaced by an error
_logger().default.console(_chalk().default.yellow(`warning: file overrides (using "${_constants().OVERRIDE_FILE_PREFIX}") is deprecated and will be removed on the next major version`));
}
});
}
function validateEnv(override, id) {
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
(0, _validateType().validateUserInputType)(message, override.env, `overrides.${id}.env`, 'object');
}
}
}
exports.default = ConsumerOverrides;
;