UNPKG

@teambit/workspace

Version:
330 lines (320 loc) • 10.3 kB
"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