@teambit/workspace 0.0.956 → 0.0.957

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/workspace.js CHANGED
@@ -319,9 +319,9 @@ function _buildGraphIdsFromFs() {
319
319
  };
320
320
  return data;
321
321
  }
322
- function _mergeConfigConflict() {
323
- const data = require("./exceptions/merge-config-conflict");
324
- _mergeConfigConflict = function () {
322
+ function _aspectsMerger() {
323
+ const data = require("./aspects-merger");
324
+ _aspectsMerger = function () {
325
325
  return data;
326
326
  };
327
327
  return data;
@@ -343,7 +343,7 @@ const DEFAULT_VENDOR_DIR = 'vendor';
343
343
  */
344
344
  class Workspace {
345
345
  // cache loaded components
346
- // cache env-ids that have been errored about not having "env" type
346
+
347
347
  constructor(
348
348
  /**
349
349
  * private pubsub.
@@ -404,7 +404,7 @@ class Workspace {
404
404
  (0, _defineProperty2().default)(this, "bitMap", void 0);
405
405
  (0, _defineProperty2().default)(this, "_cachedListIds", void 0);
406
406
  (0, _defineProperty2().default)(this, "componentLoadedSelfAsAspects", void 0);
407
- (0, _defineProperty2().default)(this, "warnedAboutMisconfiguredEnvs", []);
407
+ (0, _defineProperty2().default)(this, "aspectsMerger", void 0);
408
408
  (0, _defineProperty2().default)(this, "watcher", new (_watcher().Watcher)(this, this.pubsub));
409
409
  this.componentLoadedSelfAsAspects = (0, _cacheFactory().createInMemoryCache)({
410
410
  maxSize: (0, _inMemoryCache().getMaxSizeForComponents)()
@@ -421,8 +421,9 @@ class Workspace {
421
421
  promise: true,
422
422
  maxAge: 60 * 1000 // 1 min
423
423
  });
424
- }
425
424
 
425
+ this.aspectsMerger = new (_aspectsMerger().AspectsMerger)(this, this.harmony);
426
+ }
426
427
  validateConfig() {
427
428
  if (this.consumer.isLegacy) return;
428
429
  if ((0, _lodash().isEmpty)(this.config)) throw new (_bitError().BitError)(`fatal: workspace config is empty. probably one of bit files is missing. consider running "bit init"`);
@@ -1215,160 +1216,8 @@ the following envs are used in this workspace: ${availableEnvs.join(', ')}`);
1215
1216
  * defaults extensions from workspace config
1216
1217
  * extensions from the model.
1217
1218
  */
1218
- // eslint-disable-next-line complexity
1219
1219
  async componentExtensions(componentId, componentFromScope, excludeOrigins = []) {
1220
- var _componentFromScope$c, _componentConfigFile$, _variantConfig$propag, _wsDefaultExtensions;
1221
- // TODO: consider caching this result
1222
- let configFileExtensions;
1223
- let variantsExtensions;
1224
- let wsDefaultExtensions;
1225
- const mergeFromScope = true;
1226
- const errors = [];
1227
- const bitMapEntry = this.consumer.bitMap.getComponentIfExist(componentId._legacy);
1228
- const bitMapExtensions = bitMapEntry === null || bitMapEntry === void 0 ? void 0 : bitMapEntry.config;
1229
- let configMergeFile;
1230
- try {
1231
- configMergeFile = await this.getConfigMergeFile(componentId);
1232
- } catch (err) {
1233
- if (!(err instanceof _mergeConfigConflict().MergeConfigConflict)) {
1234
- throw err;
1235
- }
1236
- this.logger.error(`unable to parse the config file for ${componentId.toString()} due to conflicts`);
1237
- errors.push(err);
1238
- }
1239
- const adjustEnvsOnConfigMerge = conf => {
1240
- var _conf$EnvsAspect$id;
1241
- const env = (_conf$EnvsAspect$id = conf[_envs().EnvsAspect.id]) === null || _conf$EnvsAspect$id === void 0 ? void 0 : _conf$EnvsAspect$id.env;
1242
- if (!env) return;
1243
- const [id] = env.split('@');
1244
- conf[_envs().EnvsAspect.id] = {
1245
- env: id
1246
- };
1247
- conf[env] = {};
1248
- };
1249
- const unmergedData = this.getUnmergedData(componentId);
1250
- const unmergedDataMergeConf = unmergedData === null || unmergedData === void 0 ? void 0 : unmergedData.mergedConfig;
1251
- const getMergeConfigCombined = () => {
1252
- if (!configMergeFile && !unmergedDataMergeConf) return undefined;
1253
- if (!configMergeFile) return unmergedDataMergeConf;
1254
- if (!unmergedDataMergeConf) return configMergeFile;
1255
- return (0, _lodash().mergeWith)(configMergeFile, unmergedDataMergeConf, (objValue, srcValue) => {
1256
- if (Array.isArray(objValue)) {
1257
- // critical for dependencyResolver.policy.*dependencies. otherwise, it will override the array
1258
- return objValue.concat(srcValue);
1259
- }
1260
- return undefined;
1261
- });
1262
- };
1263
- const mergeConfigCombined = getMergeConfigCombined();
1264
- adjustEnvsOnConfigMerge(mergeConfigCombined || {});
1265
- const configMergeExtensions = mergeConfigCombined ? _extensionData().ExtensionDataList.fromConfigObject(mergeConfigCombined) : undefined;
1266
- const scopeExtensions = (componentFromScope === null || componentFromScope === void 0 ? void 0 : (_componentFromScope$c = componentFromScope.config) === null || _componentFromScope$c === void 0 ? void 0 : _componentFromScope$c.extensions) || new (_extensionData().ExtensionDataList)();
1267
- const [specific, nonSpecific] = (0, _lodash().partition)(scopeExtensions, entry => entry.config[AspectSpecificField] === true);
1268
- const scopeExtensionsNonSpecific = new (_extensionData().ExtensionDataList)(...nonSpecific);
1269
- const scopeExtensionsSpecific = new (_extensionData().ExtensionDataList)(...specific);
1270
- const componentConfigFile = await this.componentConfigFile(componentId);
1271
- if (componentConfigFile) {
1272
- configFileExtensions = componentConfigFile.aspects.toLegacy();
1273
- }
1274
- const relativeComponentDir = this.componentDir(componentId, {
1275
- ignoreVersion: true
1276
- }, {
1277
- relative: true
1278
- });
1279
- const variantConfig = this.variants.byRootDirAndName(relativeComponentDir, componentId.fullName);
1280
- if (variantConfig) {
1281
- variantsExtensions = variantConfig.extensions.clone();
1282
- // Do not merge from scope when there is specific variant (which is not *) that match the component
1283
- // if (variantConfig.maxSpecificity > 0) {
1284
- // mergeFromScope = false;
1285
- // }
1286
- }
1287
-
1288
- const isVendor = this.isVendorComponentByComponentDir(relativeComponentDir);
1289
- if (!isVendor) {
1290
- wsDefaultExtensions = this.getDefaultExtensions();
1291
- }
1292
- // We don't stop on each step because we want to merge the default scope even if propagate=false but the default scope is not defined
1293
- // in the case the same extension pushed twice, the former takes precedence (opposite of Object.assign)
1294
- const extensionsToMerge = [];
1295
- let envWasFoundPreviously = false;
1296
- const removedExtensionIds = [];
1297
- const addExtensionsToMerge = async (extensions, origin, extraData) => {
1298
- if (!extensions.length) {
1299
- return;
1300
- }
1301
- removedExtensionIds.push(...extensions.filter(extData => extData.isRemoved).map(extData => extData.stringId));
1302
- const extsWithoutRemoved = extensions.filterRemovedExtensions();
1303
- const selfInMergedExtensions = extsWithoutRemoved.findExtension(componentId._legacy.toStringWithoutScopeAndVersion(), true, true);
1304
- const extsWithoutSelf = selfInMergedExtensions !== null && selfInMergedExtensions !== void 0 && selfInMergedExtensions.extensionId ? extsWithoutRemoved.remove(selfInMergedExtensions.extensionId) : extsWithoutRemoved;
1305
- const {
1306
- extensionDataListFiltered,
1307
- envIsCurrentlySet
1308
- } = await this.filterEnvsFromExtensionsIfNeeded(extsWithoutSelf, envWasFoundPreviously, origin);
1309
- if (envIsCurrentlySet) {
1310
- await this.warnAboutMisconfiguredEnv(componentId, extensions);
1311
- envWasFoundPreviously = true;
1312
- }
1313
- extensionsToMerge.push({
1314
- origin,
1315
- extensions: extensionDataListFiltered,
1316
- extraData
1317
- });
1318
- };
1319
- const setDataListAsSpecific = extensions => {
1320
- extensions.forEach(dataEntry => dataEntry.config[AspectSpecificField] = true);
1321
- };
1322
- if (configMergeExtensions && !excludeOrigins.includes('ConfigMerge')) {
1323
- await addExtensionsToMerge(_extensionData().ExtensionDataList.fromArray(configMergeExtensions), 'ConfigMerge');
1324
- }
1325
- if (bitMapExtensions && !excludeOrigins.includes('BitmapFile')) {
1326
- const extensionDataList = _extensionData().ExtensionDataList.fromConfigObject(bitMapExtensions);
1327
- setDataListAsSpecific(extensionDataList);
1328
- await addExtensionsToMerge(extensionDataList, 'BitmapFile');
1329
- }
1330
- if (configFileExtensions && !excludeOrigins.includes('ComponentJsonFile')) {
1331
- setDataListAsSpecific(configFileExtensions);
1332
- await addExtensionsToMerge(configFileExtensions, 'ComponentJsonFile');
1333
- }
1334
- if (!excludeOrigins.includes('ModelSpecific')) {
1335
- await addExtensionsToMerge(_extensionData().ExtensionDataList.fromArray(scopeExtensionsSpecific), 'ModelSpecific');
1336
- }
1337
- let continuePropagating = (_componentConfigFile$ = componentConfigFile === null || componentConfigFile === void 0 ? void 0 : componentConfigFile.propagate) !== null && _componentConfigFile$ !== void 0 ? _componentConfigFile$ : true;
1338
- if (variantsExtensions && continuePropagating && !excludeOrigins.includes('WorkspaceVariants')) {
1339
- const appliedRules = variantConfig === null || variantConfig === void 0 ? void 0 : variantConfig.sortedMatches.map(({
1340
- pattern,
1341
- specificity
1342
- }) => ({
1343
- pattern,
1344
- specificity
1345
- }));
1346
- await addExtensionsToMerge(variantsExtensions, 'WorkspaceVariants', {
1347
- appliedRules
1348
- });
1349
- }
1350
- continuePropagating = continuePropagating && ((_variantConfig$propag = variantConfig === null || variantConfig === void 0 ? void 0 : variantConfig.propagate) !== null && _variantConfig$propag !== void 0 ? _variantConfig$propag : true);
1351
- // Do not apply default extensions on the default extensions (it will create infinite loop when loading them)
1352
- const isDefaultExtension = (_wsDefaultExtensions = wsDefaultExtensions) === null || _wsDefaultExtensions === void 0 ? void 0 : _wsDefaultExtensions.findExtension(componentId.toString(), true, true);
1353
- if (wsDefaultExtensions && continuePropagating && !isDefaultExtension && !excludeOrigins.includes('WorkspaceDefault')) {
1354
- await addExtensionsToMerge(wsDefaultExtensions, 'WorkspaceDefault');
1355
- }
1356
- if (mergeFromScope && continuePropagating && !excludeOrigins.includes('ModelNonSpecific')) {
1357
- await addExtensionsToMerge(scopeExtensionsNonSpecific, 'ModelNonSpecific');
1358
- }
1359
-
1360
- // It's important to do this resolution before the merge, otherwise we have issues with extensions
1361
- // coming from scope with local scope name, as opposed to the same extension comes from the workspace with default scope name
1362
- await Promise.all(extensionsToMerge.map(list => this.resolveExtensionListIds(list.extensions)));
1363
- const afterMerge = _extensionData().ExtensionDataList.mergeConfigs(extensionsToMerge.map(ext => ext.extensions));
1364
- await this.loadExtensions(afterMerge, componentId);
1365
- const withoutRemoved = afterMerge.filter(extData => !removedExtensionIds.includes(extData.stringId));
1366
- const extensions = _extensionData().ExtensionDataList.fromArray(withoutRemoved);
1367
- return {
1368
- extensions,
1369
- beforeMerge: extensionsToMerge,
1370
- errors
1371
- };
1220
+ return this.aspectsMerger.merge(componentId, componentFromScope, excludeOrigins);
1372
1221
  }
1373
1222
  getConfigMergeFilePath(componentId) {
1374
1223
  const compDir = this.componentDir(componentId, {
@@ -1381,23 +1230,6 @@ the following envs are used in this workspace: ${availableEnvs.join(', ')}`);
1381
1230
  const bitIds = unmergedComps.map(u => new (_legacyBitId().BitId)(u.id));
1382
1231
  return this.resolveMultipleComponentIds(bitIds);
1383
1232
  }
1384
- async getConfigMergeFile(componentId) {
1385
- const configMergePath = this.getConfigMergeFilePath(componentId);
1386
- let fileContent;
1387
- try {
1388
- fileContent = await _fsExtra().default.readFile(configMergePath, 'utf-8');
1389
- } catch (err) {
1390
- if (err.code === 'ENOENT') {
1391
- return undefined;
1392
- }
1393
- throw err;
1394
- }
1395
- try {
1396
- return JSON.parse(fileContent);
1397
- } catch (err) {
1398
- throw new (_mergeConfigConflict().MergeConfigConflict)(configMergePath);
1399
- }
1400
- }
1401
1233
  async getUnmergedComponent(componentId) {
1402
1234
  const unmerged = this.scope.legacyScope.objects.unmergedComponents.getEntry(componentId._legacy.name);
1403
1235
  if (unmerged !== null && unmerged !== void 0 && unmerged.head) {
@@ -1405,32 +1237,6 @@ the following envs are used in this workspace: ${availableEnvs.join(', ')}`);
1405
1237
  }
1406
1238
  return undefined;
1407
1239
  }
1408
- getUnmergedData(componentId) {
1409
- return this.scope.legacyScope.objects.unmergedComponents.getEntry(componentId._legacy.name);
1410
- }
1411
- async warnAboutMisconfiguredEnv(componentId, extensionDataList) {
1412
- if (!(await this.hasId(componentId))) {
1413
- // if this is a dependency and not belong to the workspace, don't show the warning
1414
- return;
1415
- }
1416
- const envAspect = extensionDataList.findExtension(_envs().EnvsAspect.id);
1417
- const envFromEnvsAspect = envAspect === null || envAspect === void 0 ? void 0 : envAspect.config.env;
1418
- if (!envFromEnvsAspect) return;
1419
- if (this.envs.getCoreEnvsIds().includes(envFromEnvsAspect)) return;
1420
- if (this.warnedAboutMisconfiguredEnvs.includes(envFromEnvsAspect)) return;
1421
- let env;
1422
- try {
1423
- const envId = await this.resolveComponentId(envFromEnvsAspect);
1424
- env = await this.get(envId);
1425
- } catch (err) {
1426
- return; // unable to get the component for some reason. don't sweat it. forget about the warning
1427
- }
1428
-
1429
- if (!this.envs.isUsingEnvEnv(env)) {
1430
- this.warnedAboutMisconfiguredEnvs.push(envFromEnvsAspect);
1431
- this.logger.consoleWarning(`env "${envFromEnvsAspect}" is not of type env. (correct the env's type, or component config with "bit env set ${envFromEnvsAspect} teambit.envs/env")`);
1432
- }
1433
- }
1434
1240
  async isModified(component) {
1435
1241
  const head = component.head;
1436
1242
  if (!head) {
@@ -1442,41 +1248,6 @@ the following envs are used in this workspace: ${availableEnvs.join(', ')}`);
1442
1248
  const componentStatus = await this.consumer.getComponentStatusById(component.id._legacy);
1443
1249
  return componentStatus.modified === true;
1444
1250
  }
1445
- async filterEnvsFromExtensionsIfNeeded(extensionDataList, envWasFoundPreviously, origin) {
1446
- const envAspect = extensionDataList.findExtension(_envs().EnvsAspect.id);
1447
- const envFromEnvsAspect = (envAspect === null || envAspect === void 0 ? void 0 : envAspect.config.env) || (envAspect === null || envAspect === void 0 ? void 0 : envAspect.data.id);
1448
- if (envWasFoundPreviously && envAspect) {
1449
- const nonEnvs = extensionDataList.filter(e => {
1450
- var _e$extensionId;
1451
- // normally the env-id inside the envs aspect doesn't have a version, but the aspect itself has a version.
1452
- if (e.stringId === envFromEnvsAspect || ((_e$extensionId = e.extensionId) === null || _e$extensionId === void 0 ? void 0 : _e$extensionId.toStringWithoutVersion()) === envFromEnvsAspect) return false;
1453
- return true;
1454
- });
1455
- // still, aspect env may have other data other then config.env.
1456
- delete envAspect.config.env;
1457
- return {
1458
- extensionDataListFiltered: new (_extensionData().ExtensionDataList)(...nonEnvs),
1459
- envIsCurrentlySet: true
1460
- };
1461
- }
1462
- if (envFromEnvsAspect && (origin === 'ModelNonSpecific' || origin === 'ModelSpecific')) {
1463
- // if env was found, search for this env in the workspace and if found, replace the env-id with the one from the workspace
1464
- const envAspectExt = extensionDataList.find(e => {
1465
- var _e$extensionId2;
1466
- return ((_e$extensionId2 = e.extensionId) === null || _e$extensionId2 === void 0 ? void 0 : _e$extensionId2.toStringWithoutVersion()) === envFromEnvsAspect;
1467
- });
1468
- const ids = await this.listIds();
1469
- const envAspectId = envAspectExt === null || envAspectExt === void 0 ? void 0 : envAspectExt.extensionId;
1470
- const found = envAspectId && ids.find(id => id._legacy.isEqualWithoutVersion(envAspectId));
1471
- if (found) {
1472
- envAspectExt.extensionId = found._legacy;
1473
- }
1474
- }
1475
- return {
1476
- extensionDataListFiltered: extensionDataList,
1477
- envIsCurrentlySet: Boolean(envFromEnvsAspect)
1478
- };
1479
- }
1480
1251
  async triggerOnPreWatch(componentIds, watchOpts) {
1481
1252
  const components = await this.getMany(componentIds);
1482
1253
  const preWatchFunctions = this.onPreWatchSlot.values();
@@ -1559,30 +1330,13 @@ the following envs are used in this workspace: ${availableEnvs.join(', ')}`);
1559
1330
  var _this$bitMap$getBitma;
1560
1331
  const componentConfigFile = await this.componentConfigFile(id);
1561
1332
  if (componentConfigFile) {
1562
- var _componentConfigFile$2;
1563
- return (_componentConfigFile$2 = componentConfigFile.aspects.get(aspectId)) === null || _componentConfigFile$2 === void 0 ? void 0 : _componentConfigFile$2.config;
1333
+ var _componentConfigFile$;
1334
+ return (_componentConfigFile$ = componentConfigFile.aspects.get(aspectId)) === null || _componentConfigFile$ === void 0 ? void 0 : _componentConfigFile$.config;
1564
1335
  }
1565
1336
  return (_this$bitMap$getBitma = this.bitMap.getBitmapEntry(id, {
1566
1337
  ignoreVersion: true
1567
1338
  }).config) === null || _this$bitMap$getBitma === void 0 ? void 0 : _this$bitMap$getBitma[aspectId];
1568
1339
  }
1569
-
1570
- /**
1571
- * This will mutate the entries with extensionId prop to have resolved legacy id
1572
- * This should be worked on the extension data list not the new aspect list
1573
- * @param extensionList
1574
- */
1575
- async resolveExtensionListIds(extensionList) {
1576
- const promises = extensionList.map(async entry => {
1577
- if (entry.extensionId) {
1578
- const id = await this.resolveComponentId(entry.extensionId);
1579
- entry.extensionId = id._legacy;
1580
- }
1581
- return entry;
1582
- });
1583
- await Promise.all(promises);
1584
- return extensionList;
1585
- }
1586
1340
  isVendorComponentByComponentDir(relativeComponentDir) {
1587
1341
  var _this$config$vendor;
1588
1342
  const vendorDir = ((_this$config$vendor = this.config.vendor) === null || _this$config$vendor === void 0 ? void 0 : _this$config$vendor.directory) || DEFAULT_VENDOR_DIR;
@@ -1841,27 +1595,6 @@ needed-for: ${neededFor || '<unknown>'}`);
1841
1595
  };
1842
1596
  }
1843
1597
 
1844
- /**
1845
- * Load all unloaded extensions from a list
1846
- * @param extensions list of extensions with config to load
1847
- */
1848
- async loadExtensions(extensions, originatedFrom, throwOnError = false) {
1849
- const extensionsIdsP = extensions.map(async extensionEntry => {
1850
- // Core extension
1851
- if (!extensionEntry.extensionId) {
1852
- return extensionEntry.stringId;
1853
- }
1854
- const id = await this.resolveComponentId(extensionEntry.extensionId);
1855
- // return this.resolveComponentId(extensionEntry.extensionId);
1856
- return id.toString();
1857
- });
1858
- const extensionsIds = await Promise.all(extensionsIdsP);
1859
- const loadedExtensions = this.harmony.extensionsIds;
1860
- const extensionsToLoad = (0, _lodash().difference)(extensionsIds, loadedExtensions);
1861
- if (!extensionsToLoad.length) return;
1862
- await this.loadAspects(extensionsToLoad, throwOnError, originatedFrom === null || originatedFrom === void 0 ? void 0 : originatedFrom.toString());
1863
- }
1864
-
1865
1598
  /**
1866
1599
  * Provides a cache folder, unique per key.
1867
1600
  * Return value may be undefined, if workspace folder is unconventional (bare-scope, no node_modules, etc)
@@ -2209,6 +1942,73 @@ your workspace.jsonc has this component-id set. you might want to remove/change
2209
1942
  unchanged
2210
1943
  };
2211
1944
  }
1945
+ async updateEnvForComponents(envIdStr, pattern) {
1946
+ const allWsComps = await this.list();
1947
+ const allWsIds = await this.listIds();
1948
+ const isInWs = envId => allWsIds.find(id => id.isEqual(envId, {
1949
+ ignoreVersion: true
1950
+ }));
1951
+ const allEnvs = await this.envs.createEnvironment(allWsComps);
1952
+ const getEnvWithVersion = async envId => {
1953
+ if (envId.hasVersion()) return envId;
1954
+ try {
1955
+ const fromRemote = await this.scope.getRemoteComponent(envId);
1956
+ return envId.changeVersion(fromRemote.id.version);
1957
+ } catch (err) {
1958
+ throw new (_bitError().BitError)(`unable to find ${envIdStr} in the remote`);
1959
+ }
1960
+ };
1961
+ const getEnvs = async () => {
1962
+ if (envIdStr) {
1963
+ const envCompId = await this.resolveComponentId(envIdStr);
1964
+ if (isInWs(envCompId)) {
1965
+ throw new (_bitError().BitError)(`error: unable to update the env ${envCompId.toString()}, it's already part of the workspace, as such, it's always using the workspace version`);
1966
+ }
1967
+ const envWithVer = await getEnvWithVersion(envCompId);
1968
+ return [envWithVer];
1969
+ }
1970
+ // get all non-local envs.
1971
+ const allEnvsIds = allEnvs.runtimeEnvs.map(env => env.id);
1972
+ const allEnvsCompIds = await this.resolveMultipleComponentIds(allEnvsIds);
1973
+ // also check the envId has version, otherwise, it's a core env.
1974
+ const nonLocalEnvs = allEnvsCompIds.filter(envId => !isInWs(envId) && envId.hasVersion());
1975
+ if (!nonLocalEnvs.length) {
1976
+ throw new (_bitError().BitError)(`error: unable to update envs ${allEnvsIds.map(e => e.toString()).join(', ')}, they're already part of the workspace`);
1977
+ }
1978
+ const envsWithVersions = await (0, _pMapSeries().default)(nonLocalEnvs, envId => getEnvWithVersion(envId.changeVersion(undefined)));
1979
+ return envsWithVersions;
1980
+ };
1981
+ const envsWithVerToUpdate = await getEnvs();
1982
+ const compIdsToUpdate = pattern ? await this.idsByPattern(pattern) : allWsIds;
1983
+ const compsToUpdate = await this.getMany(compIdsToUpdate);
1984
+ const alreadyUpToDate = [];
1985
+ const updated = {};
1986
+ await Promise.all(compsToUpdate.map(async comp => {
1987
+ var _envToUpdate$toString;
1988
+ const compEnvs = (0, _lodash().compact)(envsWithVerToUpdate.map(envId => comp.state.aspects.get(envId.toStringWithoutVersion())));
1989
+ if (!compEnvs.length) return;
1990
+ const compEnv = compEnvs[0]; // should not be more than one
1991
+ const envToUpdate = envsWithVerToUpdate.find(e => e.isEqual(compEnv.id, {
1992
+ ignoreVersion: true
1993
+ }));
1994
+ if (!envToUpdate) throw new Error(`unable to find ${compEnv.id.toString()} in the envs to update`);
1995
+ if (compEnv.id.version === envToUpdate.version) {
1996
+ // nothing to update
1997
+ alreadyUpToDate.push(comp.id);
1998
+ return;
1999
+ }
2000
+ // don't mark with minus if not exist in .bitmap. it's not needed. when the component is loaded, the
2001
+ // merge-operation of the aspects removes duplicate aspect-id with different versions.
2002
+ await this.removeSpecificComponentConfig(comp.id, compEnv.id.toString(), false);
2003
+ await this.addSpecificComponentConfig(comp.id, envToUpdate.toString(), compEnv.config);
2004
+ (updated[_envToUpdate$toString = envToUpdate.toString()] || (updated[_envToUpdate$toString] = [])).push(comp.id);
2005
+ }));
2006
+ await this.bitMap.write();
2007
+ return {
2008
+ updated,
2009
+ alreadyUpToDate
2010
+ };
2011
+ }
2212
2012
  }
2213
2013
 
2214
2014
  /**