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
460 lines (371 loc) • 14.2 kB
JavaScript
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 _pMapSeries() {
const data = _interopRequireDefault(require("p-map-series"));
_pMapSeries = function () {
return data;
};
return data;
}
function _ramda() {
const data = _interopRequireDefault(require("ramda"));
_ramda = function () {
return data;
};
return data;
}
function _abstractConfig() {
const data = _interopRequireDefault(require("./abstract-config"));
_abstractConfig = function () {
return data;
};
return data;
}
function _logger() {
const data = _interopRequireDefault(require("../../logger/logger"));
_logger = function () {
return data;
};
return data;
}
function _filterObject() {
const data = _interopRequireDefault(require("../../utils/filter-object"));
_filterObject = function () {
return data;
};
return data;
}
function _packageJsonFile() {
const data = _interopRequireDefault(require("../component/package-json-file"));
_packageJsonFile = function () {
return data;
};
return data;
}
function _showDoctorError() {
const data = _interopRequireDefault(require("../../error/show-doctor-error"));
_showDoctorError = function () {
return data;
};
return data;
}
function _extensionData() {
const data = require("./extension-data");
_extensionData = function () {
return data;
};
return data;
}
function _constants() {
const data = require("../../constants");
_constants = function () {
return data;
};
return data;
}
class ComponentConfig extends _abstractConfig().default {
// whether a component has bit.json written to FS or package.json written with 'bit' property
static registerOnComponentConfigLoading(extId, func) {
this.componentConfigLoadingRegistry[extId] = func;
}
static registerAddConfigAction(extId, func) {
this.addConfigRegistry[extId] = func;
}
constructor({
compiler,
tester,
lang,
bindingPrefix,
extensions,
overrides
}) {
super({
compiler,
tester,
lang,
bindingPrefix,
extensions
});
(0, _defineProperty2().default)(this, "overrides", void 0);
(0, _defineProperty2().default)(this, "componentHasWrittenConfig", false);
(0, _defineProperty2().default)(this, "packageJsonFile", void 0);
(0, _defineProperty2().default)(this, "extensionsAddedConfig", void 0);
this.overrides = overrides;
this.writeToBitJson = true; // will be changed later to work similar to workspace-config
}
toPlainObject() {
const superObject = super.toPlainObject();
const componentObject = _ramda().default.merge(superObject, {
overrides: this.overrides
});
const isPropDefaultOrEmpty = (val, key) => {
if (key === 'overrides') return !_ramda().default.isEmpty(val);
return true;
};
return (0, _filterObject().default)(componentObject, isPropDefaultOrEmpty);
}
validate(bitJsonPath) {
if (typeof this.compiler !== 'object' || typeof this.tester !== 'object' || // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
this.extensions() && typeof this.extensions() !== 'object') {
throw new (_showDoctorError().default)(`bit.json at "${bitJsonPath}" is invalid, re-import the component with "--conf" flag to recreate it`);
}
}
/**
* Return the extensions as ExtensionDataList
*
* @returns {ExtensionDataList}
* @memberof ComponentConfig
*/
parseExtensions() {
return _extensionData().ExtensionDataList.fromArray(this.extensions);
}
static fromPlainObject(object) {
const {
env,
lang,
bindingPrefix,
extensions,
overrides
} = object;
return new ComponentConfig({
compiler: env ? _ramda().default.prop('compiler', env) : undefined,
tester: env ? _ramda().default.prop('tester', env) : undefined,
extensions,
lang,
bindingPrefix,
overrides
}); // TODO: run runOnLoadEvent
}
static fromComponent(component) {
return new ComponentConfig({
version: component.version,
scope: component.scope,
lang: component.lang,
bindingPrefix: component.bindingPrefix,
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
compiler: component.compiler || {},
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
tester: component.tester || {},
overrides: component.overrides.componentOverridesData
}); // TODO: run runOnLoadEvent
}
mergeWithComponentData(component) {
this.bindingPrefix = this.bindingPrefix || component.bindingPrefix;
this.lang = this.lang || component.lang;
this.extensions = this.extensions.length ? this.extensions : component.extensions;
}
/**
* Use the workspaceConfig as a base. Override values if exist in componentConfig
* This only used for legacy props that were defined in the root like compiler / tester
*/
static mergeWithWorkspaceRootConfigs(consumer, componentId, componentConfig, workspaceConfig) {
const plainWorkspaceConfig = workspaceConfig ? workspaceConfig._legacyPlainObject() : undefined;
let legacyWorkspaceConfigToMerge = {};
if (plainWorkspaceConfig) {
legacyWorkspaceConfigToMerge = (0, _filterObject().default)(plainWorkspaceConfig, (val, key) => key !== 'overrides');
}
const componentConfigFromWorkspaceToMerge = (workspaceConfig === null || workspaceConfig === void 0 ? void 0 : workspaceConfig.getComponentConfig(componentId)) || {};
const defaultOwner = workspaceConfig === null || workspaceConfig === void 0 ? void 0 : workspaceConfig.defaultOwner;
if (defaultOwner && defaultOwner !== _constants().DEFAULT_REGISTRY_DOMAIN_PREFIX) {
componentConfigFromWorkspaceToMerge.bindingPrefix = defaultOwner.startsWith('@') ? defaultOwner : `@${defaultOwner}`;
}
const mergedObject = _ramda().default.mergeAll([legacyWorkspaceConfigToMerge, componentConfigFromWorkspaceToMerge, componentConfig]);
mergedObject.extensions = _extensionData().ExtensionDataList.fromObject(mergedObject.extensions, consumer); // Do not try to load extension for itself (usually happen when using '*' pattern)
mergedObject.extensions = mergedObject.extensions.remove(componentId);
return ComponentConfig.fromPlainObject(mergedObject);
}
/**
* component config is written by default to package.json inside "bit" property.
* in case "eject-conf" was running or the component was imported with "--conf" flag, the
* bit.json is written as well.
*
* @param {*} componentDir root component directory, needed for loading package.json file.
* in case a component is authored, leave this param empty to not load the project package.json
* @param {*} workspaceConfig
*/
static loadConfigFromFolder({
componentDir,
workspaceDir
}) {
return (0, _bluebird().coroutine)(function* () {
let bitJsonPath;
let componentHasWrittenConfig = false;
let packageJsonFile;
if (componentDir) {
bitJsonPath = _abstractConfig().default.composeBitJsonPath(componentDir);
}
const loadBitJson = /*#__PURE__*/function () {
var _ref = (0, _bluebird().coroutine)(function* () {
if (!bitJsonPath) {
return {};
}
try {
const file = yield _abstractConfig().default.loadJsonFileIfExist(bitJsonPath);
if (file) {
componentHasWrittenConfig = true;
return file;
}
return {};
} catch (e) {
throw new (_showDoctorError().default)(`bit.json at "${bitJsonPath}" is not a valid JSON file, re-import the component with "--conf" flag to recreate it`);
}
});
return function loadBitJson() {
return _ref.apply(this, arguments);
};
}();
const loadPackageJson = /*#__PURE__*/function () {
var _ref2 = (0, _bluebird().coroutine)(function* () {
if (!componentDir) return {};
try {
const file = yield _packageJsonFile().default.load(workspaceDir, componentDir);
packageJsonFile = file;
const packageJsonObject = file.fileExist ? file.packageJsonObject : undefined;
const packageJsonHasConfig = Boolean(packageJsonObject && packageJsonObject.bit);
if (packageJsonHasConfig) {
const packageJsonConfig = packageJsonObject === null || packageJsonObject === void 0 ? void 0 : packageJsonObject.bit;
componentHasWrittenConfig = true;
return packageJsonConfig;
}
return {};
} catch (e) {
throw new (_showDoctorError().default)(`package.json at ${_abstractConfig().default.composePackageJsonPath(componentDir)} is not a valid JSON file, consider to re-import the file to re-generate the file`);
}
});
return function loadPackageJson() {
return _ref2.apply(this, arguments);
};
}();
const [bitJsonConfig, packageJsonConfig] = yield Promise.all([loadBitJson(), loadPackageJson()]); // in case of conflicts, bit.json wins package.json
const config = Object.assign(packageJsonConfig, bitJsonConfig);
return {
config,
bitJsonPath,
packageJsonFile,
componentHasWrittenConfig
};
})();
}
/**
* component config is written by default to package.json inside "bit" property.
* in case "eject-conf" was running or the component was imported with "--conf" flag, the
* bit.json is written as well.
*
* @param {*} componentDir root component directory, needed for loading package.json file.
* in case a component is authored, leave this param empty to not load the project package.json
* @param {*} workspaceConfig
*/
static load({
consumer,
componentId,
componentDir,
workspaceDir,
workspaceConfig
}) {
var _this = this;
return (0, _bluebird().coroutine)(function* () {
const {
config,
bitJsonPath,
packageJsonFile,
componentHasWrittenConfig
} = yield _this.loadConfigFromFolder({
componentDir,
workspaceDir
});
const componentConfig = ComponentConfig.mergeWithWorkspaceRootConfigs(consumer, componentId, config, workspaceConfig);
componentConfig.path = bitJsonPath;
yield _this.runOnLoadEvent(_this.componentConfigLoadingRegistry, componentId, componentConfig);
const extensionsAddedConfig = yield runOnAddConfigEvent(_this.addConfigRegistry, componentConfig.parseExtensions());
componentConfig.extensionsAddedConfig = extensionsAddedConfig;
componentConfig.componentHasWrittenConfig = componentHasWrittenConfig; // @ts-ignore seems to be a bug in ts v3.7.x, it doesn't recognize Promise.all array correctly
componentConfig.packageJsonFile = packageJsonFile;
return componentConfig;
})();
}
/**
* Run all subscribers to the component config load event
*
* @static
* @param {ConfigLoadRegistry} componentConfigLoadingRegistry
* @param {BitId} id
* @param {*} config
* @memberof ComponentConfig
*/
static runOnLoadEvent(componentConfigLoadingRegistry, id, config) {
return (0, _bluebird().coroutine)(function* () {
try {
yield (0, _pMapSeries().default)(Object.keys(componentConfigLoadingRegistry), /*#__PURE__*/function () {
var _ref3 = (0, _bluebird().coroutine)(function* (extId) {
const func = componentConfigLoadingRegistry[extId];
return func(id, config);
});
return function (_x) {
return _ref3.apply(this, arguments);
};
}());
} catch (err) {
// TODO: improve texts
_logger().default.console(`\nfailed loading an extension for component ${id.toString()}, error is:`, 'warn', 'yellow'); // TODO: this show an ugly error, we should somehow show a proper errors
_logger().default.console(err, 'warn', 'yellow');
_logger().default.console('the error has been ignored', 'warn', 'yellow');
_logger().default.warn('extension on load event throw an error', err);
}
})();
}
}
/**
* Runs all the functions from the registry and merged their results
*
* @param {AddConfigRegistry} configsRegistry
* @returns {Promise<any>} A merge results of the added config by all the extensions
*/
exports.default = ComponentConfig;
(0, _defineProperty2().default)(ComponentConfig, "componentConfigLoadingRegistry", {});
(0, _defineProperty2().default)(ComponentConfig, "addConfigRegistry", {});
function runOnAddConfigEvent(_x2, _x3) {
return _runOnAddConfigEvent.apply(this, arguments);
}
/**
* Merge added configs from many extensions
*
* @param {any[]} configs
* @returns A merge results of all config
*/
function _runOnAddConfigEvent() {
_runOnAddConfigEvent = (0, _bluebird().coroutine)(function* (configsRegistry, extensions) {
const extensionsConfigModificationsP = Object.keys(configsRegistry).map(extId => {
// TODO: only running func for relevant extensions
const func = configsRegistry[extId];
return func(extensions);
});
const extensionsConfigModifications = yield Promise.all(extensionsConfigModificationsP);
const extensionsConfigModificationsObject = mergeExtensionsConfig(extensionsConfigModifications);
return extensionsConfigModificationsObject;
});
return _runOnAddConfigEvent.apply(this, arguments);
}
function mergeExtensionsConfig(configs) {
return configs.reduce((prev, curr) => {
return _ramda().default.mergeDeepLeft(prev, curr);
}, {});
}
;