@teambit/workspace
Version:
330 lines (320 loc) • 10.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.BitMap = void 0;
function _lodash() {
const data = require("lodash");
_lodash = function () {
return data;
};
return data;
}
function _legacy() {
const data = require("@teambit/legacy.bit-map");
_legacy = function () {
return data;
};
return data;
}
function _legacy2() {
const data = require("@teambit/legacy.extension-data");
_legacy2 = function () {
return data;
};
return data;
}
function _bitError() {
const data = require("@teambit/bit-error");
_bitError = function () {
return data;
};
return data;
}
function _envs() {
const data = require("@teambit/envs");
_envs = function () {
return data;
};
return data;
}
function _toolboxFs() {
const data = require("@teambit/toolbox.fs.last-modified");
_toolboxFs = function () {
return data;
};
return data;
}
/**
* consider extracting to a new component.
* (pro: making Workspace aspect smaller. con: it's an implementation details of the workspace)
*/
class BitMap {
constructor(legacyBitMap, consumer) {
this.legacyBitMap = legacyBitMap;
this.consumer = consumer;
}
mergeBitmaps(bitmapContent, otherBitmapContent, opts = {}) {
return _legacy().BitMap.mergeContent(bitmapContent, otherBitmapContent, opts);
}
getPath() {
return this.legacyBitMap.mapPath;
}
getAllRootDirs() {
return Object.keys(this.legacyBitMap.getAllTrackDirs());
}
/**
* adds component config to the .bitmap file.
* later, upon `bit tag`, the data is saved in the scope.
* returns a boolean indicating whether a change has been made.
*/
addComponentConfig(id, aspectId, config = {}, shouldMergeConfig = false) {
if (!aspectId || typeof aspectId !== 'string') throw new Error(`expect aspectId to be string, got ${aspectId}`);
const bitMapEntry = this.getBitmapEntry(id, {
ignoreVersion: true
});
const currentConfig = (bitMapEntry.config ||= {})[aspectId];
if ((0, _lodash().isEqual)(currentConfig, config)) {
return false; // no changes
}
const getNewConfig = () => {
if (!config) return null;
if (!shouldMergeConfig) return config;
// should merge
if (!currentConfig) return config;
if (currentConfig === '-') return config;
// lodash merge performs a deep merge. (the native concatenation don't)
return (0, _lodash().merge)(currentConfig, config);
};
const newConfig = getNewConfig();
if (newConfig) {
bitMapEntry.config[aspectId] = newConfig;
} else {
delete bitMapEntry.config[aspectId];
}
this.legacyBitMap.markAsChanged();
return true; // changes have been made
}
updateDefaultScope(oldScope, newScope) {
const changedId = [];
this.legacyBitMap.components.forEach(componentMap => {
// only new components (not snapped/tagged) can be changed
if (componentMap.defaultScope === oldScope && !componentMap.id.hasVersion()) {
componentMap.defaultScope = newScope;
componentMap.id = componentMap.id.changeDefaultScope(newScope);
changedId.push(componentMap.id);
}
});
if (changedId.length) {
this.legacyBitMap.markAsChanged();
}
return changedId;
}
markAsChanged() {
this.legacyBitMap.markAsChanged();
}
removeComponentConfig(id, aspectId, markWithMinusIfNotExist) {
if (!aspectId || typeof aspectId !== 'string') throw new Error(`expect aspectId to be string, got ${aspectId}`);
const bitMapEntry = this.getBitmapEntry(id, {
ignoreVersion: true
});
const currentConfig = (bitMapEntry.config ||= {})[aspectId];
if (currentConfig) {
delete bitMapEntry.config[aspectId];
} else {
if (!markWithMinusIfNotExist) {
return false; // no changes
}
bitMapEntry.config[aspectId] = _legacy2().REMOVE_EXTENSION_SPECIAL_SIGN;
}
this.legacyBitMap.markAsChanged();
return true; // changes have been made
}
removeEntireConfig(id) {
const bitMapEntry = this.getBitmapEntry(id, {
ignoreVersion: true
});
if (!bitMapEntry.config) return false;
delete bitMapEntry.config;
this.legacyBitMap.markAsChanged();
return true;
}
setEntireConfig(id, config) {
const bitMapEntry = this.getBitmapEntry(id, {
ignoreVersion: true
});
bitMapEntry.config = config;
this.legacyBitMap.markAsChanged();
}
removeDefaultScope(id) {
const bitMapEntry = this.getBitmapEntry(id, {
ignoreVersion: true
});
if (bitMapEntry.defaultScope) {
delete bitMapEntry.defaultScope;
this.legacyBitMap.markAsChanged();
}
}
setDefaultScope(id, defaultScope) {
const bitMapEntry = this.getBitmapEntry(id, {
ignoreVersion: true
});
bitMapEntry.defaultScope = defaultScope;
bitMapEntry.id = bitMapEntry.id.changeDefaultScope(defaultScope);
this.legacyBitMap.markAsChanged();
}
setLocalOnly(ids) {
ids.forEach(id => {
const bitMapEntry = this.getBitmapEntry(id);
bitMapEntry.localOnly = true;
});
this.legacyBitMap.markAsChanged();
}
unsetLocalOnly(ids) {
const successfullyUnset = [];
ids.forEach(id => {
const bitMapEntry = this.getBitmapEntry(id);
if (!bitMapEntry.localOnly) return;
bitMapEntry.localOnly = false;
successfullyUnset.push(id);
});
this.legacyBitMap.markAsChanged();
return successfullyUnset;
}
listLocalOnly() {
const allIds = this.legacyBitMap.getAllBitIds();
return allIds.filter(id => this.getBitmapEntry(id).localOnly);
}
/**
* write .bitmap object to the filesystem
* optionally pass a reason for the change to be saved in the local scope `bitmap-history-metadata.txt` file.
*/
async write(reasonForChange) {
await this.consumer.writeBitMap(reasonForChange);
}
/**
* get the data saved in the .bitmap file for this component-id.
* throws if not found
* @see this.getBitmapEntryIfExist
*/
getBitmapEntry(id, {
ignoreVersion
} = {}) {
return this.legacyBitMap.getComponent(id, {
ignoreVersion
});
}
getBitmapEntryIfExist(id, {
ignoreVersion
} = {}) {
return this.legacyBitMap.getComponentIfExist(id, {
ignoreVersion
});
}
getAspectIdFromConfig(componentId, aspectId, ignoreAspectVersion = false) {
const bitMapEntry = this.getBitmapEntry(componentId);
const config = bitMapEntry.config;
if (!config) {
return undefined;
}
if (config[aspectId.toString()]) {
return aspectId.toString();
}
if (!ignoreAspectVersion) {
return undefined;
}
const allVersions = Object.keys(config).filter(id => id.startsWith(`${aspectId.toStringWithoutVersion()}@`));
if (allVersions.length > 1) {
throw new (_bitError().BitError)(`error: the same aspect ${aspectId.toStringWithoutVersion} configured multiple times for "${componentId.toString()}"\n${allVersions.join('\n')}`);
}
return allVersions.length === 1 ? allVersions[0] : undefined;
}
/**
* components that were not tagged yet are safe to rename them from the .bitmap file.
*/
renameNewComponent(sourceId, targetId) {
const bitMapEntry = this.getBitmapEntry(sourceId);
if (bitMapEntry.id.hasVersion()) {
throw new Error(`unable to rename tagged or exported component: ${bitMapEntry.id.toString()}`);
}
if (sourceId.isEqual(targetId)) {
throw new Error(`source-id and target-id are equal: "${sourceId.toString()}"`);
}
if (sourceId.fullName !== targetId.fullName) {
this.legacyBitMap.removeComponent(bitMapEntry.id);
bitMapEntry.id = targetId;
if (sourceId.scope !== targetId.scope) bitMapEntry.defaultScope = targetId.scope;
this.legacyBitMap.setComponent(bitMapEntry.id, bitMapEntry);
} else if (sourceId.scope !== targetId.scope) {
this.setDefaultScope(sourceId, targetId.scope);
}
}
/**
* helpful when reaming an aspect and this aspect is used in the config of other components.
*/
renameAspectInConfig(sourceId, targetId) {
this.legacyBitMap.components.forEach(componentMap => {
const config = componentMap.config;
if (!config) return;
Object.keys(config).forEach(aspectId => {
if (aspectId === sourceId.toString()) {
config[targetId.toString()] = config[aspectId];
delete config[aspectId];
this.markAsChanged();
}
if (aspectId === _envs().EnvsAspect.id) {
const envConfig = config[aspectId];
if (envConfig !== '-' && envConfig.env === sourceId.toString()) {
envConfig.env = targetId.toString();
this.markAsChanged();
}
}
});
componentMap.config = config;
});
}
removeComponent(id) {
this.legacyBitMap.removeComponent(id);
}
/**
* this is the lane-id of the recently exported lane. in case of a new lane, which was not exported yet, this will be
* empty.
*/
getExportedLaneId() {
return this.legacyBitMap.isLaneExported ? this.legacyBitMap.laneId : undefined;
}
makeComponentsAvailableOnMain(ids) {
ids.forEach(id => {
const componentMap = this.getBitmapEntry(id);
componentMap.isAvailableOnCurrentLane = true;
delete componentMap.onLanesOnly;
});
this.legacyBitMap.markAsChanged();
}
/**
* whether .bitmap file has changed in-memory
*/
hasChanged() {
return this.legacyBitMap.hasChanged;
}
takeSnapshot() {
return this.legacyBitMap.components.map(comp => comp.clone());
}
restoreFromSnapshot(componentMaps) {
this.legacyBitMap.components = componentMaps;
this.legacyBitMap._invalidateCache();
}
/**
* .bitmap file could be changed by other sources (e.g. manually or by "git pull") not only by bit.
* this method returns the timestamp when the .bitmap has changed through bit. (e.g. as part of snap/tag/export/merge
* process)
*/
async getLastModifiedBitmapThroughBit() {
const bitmapHistoryDir = this.consumer.getBitmapHistoryDir();
const stat = await (0, _toolboxFs().getPathStatIfExist)(bitmapHistoryDir);
if (!stat) return undefined;
return stat.mtimeMs;
}
}
exports.BitMap = BitMap;
//# sourceMappingURL=bit-map.js.map