@teambit/snapping 1.0.443 → 1.0.445

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.
@@ -115,6 +115,12 @@ export declare class SnappingMain {
115
115
  rebuildArtifacts?: boolean;
116
116
  ignoreLastPkgJson?: boolean;
117
117
  } & Partial<BasicTagParams>): Promise<TagResults | null>;
118
+ forkAndSnap(snapDataPerCompRaw: SnapDataPerCompRaw[], params: {
119
+ push?: boolean;
120
+ ignoreIssues?: string;
121
+ lane?: string;
122
+ updateDependents?: boolean;
123
+ } & Partial<BasicTagParams>): Promise<SnapFromScopeResults>;
118
124
  snapFromScope(snapDataPerCompRaw: SnapDataPerCompRaw[], params: {
119
125
  push?: boolean;
120
126
  ignoreIssues?: string;
@@ -578,10 +578,10 @@ if you're willing to lose the history from the head to the specified version, us
578
578
  newComponents: new (_componentId().ComponentIdList)()
579
579
  };
580
580
  }
581
- async snapFromScope(snapDataPerCompRaw, params) {
582
- const hasForkedFrom = snapDataPerCompRaw.some(s => s.forkFrom);
583
- if (this.workspace && !hasForkedFrom) {
584
- throw new (_bitError().BitError)(`unable to run this command from a workspace, please create a new bare-scope and run it from there`);
581
+ async forkAndSnap(snapDataPerCompRaw, params) {
582
+ const allAreForkedFrom = snapDataPerCompRaw.every(s => s.forkFrom);
583
+ if (!allAreForkedFrom) {
584
+ throw new (_bitError().BitError)(`when forkedFrom prop is used, all components must have the forkedFrom prop`);
585
585
  }
586
586
  let lane;
587
587
  const laneIdStr = params.lane;
@@ -592,18 +592,9 @@ if you're willing to lose the history from the head to the specified version, us
592
592
  } catch (err) {
593
593
  if (err.constructor.name !== _legacy2().LaneNotFound.name) throw err;
594
594
  // if the lane is not found, it's probably because it's new. create a new lane.
595
- lane = await (0, _lanesModules().createLaneInScope)(laneId.name, this.scope, laneId.scope);
596
- // it's important to set the lane as new in scope.json. otherwise, later, when importing and the lane is loaded
597
- // from the filesystem, it looses the "isNew: true", and then it tries to fetch the lane from the remote scope.
598
- // which fails with the importer.
599
- this.scope.legacyScope.scopeJson.setLaneAsNew(laneId.name);
595
+ lane = await (0, _lanesModules().createLane)(this.workspace, laneId.name, laneId.scope);
600
596
  }
601
- // this is critical. otherwise, later on, when loading aspects and isolating capsules, we'll try to fetch dists
602
- // from the original scope instead of the lane-scope.
603
- this.scope.legacyScope.setCurrentLaneId(laneId);
604
- this.scope.legacyScope.scopeImporter.shouldOnlyFetchFromCurrentLane = true;
605
597
  }
606
- const laneCompIds = lane?.toComponentIdsIncludeUpdateDependents();
607
598
  const snapDataPerComp = snapDataPerCompRaw.map(snapData => {
608
599
  return {
609
600
  componentId: _componentId().ComponentID.fromString(snapData.componentId),
@@ -620,26 +611,22 @@ if you're willing to lose the history from the head to the specified version, us
620
611
  type: dep.type ?? 'runtime'
621
612
  })),
622
613
  removeDependencies: snapData.removeDependencies,
623
- forkFrom: snapData.forkFrom ? _componentId().ComponentID.fromString(snapData.forkFrom) : undefined
614
+ forkFrom: _componentId().ComponentID.fromString(snapData.forkFrom)
624
615
  };
625
616
  });
626
617
 
627
618
  // console.log('snapDataPerComp', JSON.stringify(snapDataPerComp, undefined, 2));
628
619
 
629
- const componentIds = (0, _lodash().compact)(snapDataPerComp.map(t => t.isNew || t.forkFrom ? null : t.componentId));
630
620
  const allCompIds = snapDataPerComp.map(s => s.componentId);
631
- const componentIdsLatest = componentIds.map(id => id.changeVersion(_constants().LATEST));
632
- const newCompsData = (0, _lodash().compact)(snapDataPerComp.map(t => t.isNew && !t.forkFrom ? t : null));
633
621
  const forkedFromData = (0, _lodash().compact)(snapDataPerComp.map(t => t.forkFrom ? t : null));
634
- const newComponents = await Promise.all(newCompsData.map(newComp => (0, _generateCompFromScope().generateCompFromScope)(this.scope, newComp, this)));
635
622
  const forkMultipleData = forkedFromData.map(f => ({
636
623
  sourceId: f.forkFrom.toString(),
637
624
  targetId: f.componentId.fullName,
638
625
  targetScope: f.componentId.scope
639
626
  }));
640
- const forkResults = forkMultipleData.length ? await this.forking.forkMultipleFromRemote(forkMultipleData, {
627
+ const forkResults = await this.forking.forkMultipleFromRemote(forkMultipleData, {
641
628
  refactor: true
642
- }) : [];
629
+ });
643
630
  const newEnvData = {};
644
631
  forkedFromData.forEach(f => {
645
632
  const bitmapElem = this.workspace.bitMap.getBitmapEntry(f.componentId);
@@ -655,7 +642,157 @@ if you're willing to lose the history from the head to the specified version, us
655
642
  await (0, _pMapSeries().default)(Object.entries(newEnvData), async ([env, compIds]) => {
656
643
  await this.workspace.setEnvToComponents(_componentId().ComponentID.fromString(env), compIds, false);
657
644
  });
658
- const newForkedComponents = forkResults.length ? await this.workspace.getMany(forkResults.map(f => f.targetCompId)) : [];
645
+ const getSnapData = id => {
646
+ const snapData = snapDataPerComp.find(t => {
647
+ return t.componentId.isEqual(id, {
648
+ ignoreVersion: true
649
+ });
650
+ });
651
+ if (!snapData) throw new Error(`unable to find ${id.toString()} in snapDataPerComp`);
652
+ return snapData;
653
+ };
654
+ const newForkedComponents = await this.workspace.getMany(forkResults.map(f => f.targetCompId));
655
+ await Promise.all(newForkedComponents.map(async comp => {
656
+ const snapData = getSnapData(comp.id);
657
+ if (snapData.files?.length) {
658
+ await this.updateSourceFiles(comp, snapData.files);
659
+ await this.workspace.write(comp);
660
+ }
661
+ if (snapData.aspects) {
662
+ const bitmapElem = this.workspace.bitMap.getBitmapEntry(comp.id);
663
+ if (!bitmapElem) throw new Error(`unable to find ${comp.id.toString()} in the bitmap`);
664
+ const currentConfig = bitmapElem.config;
665
+ if (!currentConfig) {
666
+ this.workspace.bitMap.setEntireConfig(comp.id, snapData.aspects);
667
+ return;
668
+ }
669
+ const currentEnvSettings = currentConfig['teambit.envs/envs'];
670
+ const currentEnv = currentEnvSettings !== '-' && currentEnvSettings.env;
671
+ const newEnv = snapData.aspects['teambit.envs/envs']?.env;
672
+ if (!currentEnv || !newEnv) {
673
+ this.workspace.bitMap.setEntireConfig(comp.id, _objectSpread(_objectSpread({}, currentConfig), snapData.aspects));
674
+ return;
675
+ }
676
+ const currentEnvWithPotentialVer = Object.keys(currentConfig).find(c => c === currentEnv || c.startsWith(`${currentEnv}@`));
677
+ if (currentEnvWithPotentialVer) delete currentConfig[currentEnvWithPotentialVer];
678
+ delete currentConfig['teambit.envs/envs'];
679
+ this.workspace.bitMap.setEntireConfig(comp.id, _objectSpread(_objectSpread({}, currentConfig), snapData.aspects));
680
+ }
681
+ }));
682
+ await this.workspace.bitMap.write();
683
+ // if you don't clear the cache here, the installation assumes all components have the old env.
684
+ await this.workspace.clearCache();
685
+ await this.install.install(undefined, {
686
+ dedupe: true,
687
+ import: false,
688
+ copyPeerToRuntimeOnRoot: true,
689
+ copyPeerToRuntimeOnComponents: false,
690
+ updateExisting: false
691
+ });
692
+ // if we don't clear the cache here, the "build" process during tag doesn't install the necessary packages
693
+ // on the capsules.
694
+ await this.workspace.clearCache();
695
+ const components = await this.workspace.getMany(forkedFromData.map(f => f.componentId));
696
+ const consumerComponents = components.map(c => c.state._consumer);
697
+ const ids = _componentId().ComponentIdList.fromArray(allCompIds);
698
+ const results = await (0, _tagModelComponent().tagModelComponent)(_objectSpread(_objectSpread({}, params), {}, {
699
+ scope: this.scope,
700
+ consumerComponents,
701
+ tagDataPerComp: snapDataPerComp.map(s => ({
702
+ componentId: s.componentId,
703
+ message: s.message,
704
+ dependencies: []
705
+ })),
706
+ snapping: this,
707
+ builder: this.builder,
708
+ dependencyResolver: this.dependencyResolver,
709
+ skipAutoTag: true,
710
+ persist: true,
711
+ isSnap: true,
712
+ ids,
713
+ message: params.message,
714
+ updateDependentsOnLane: params.updateDependents
715
+ }));
716
+ const {
717
+ taggedComponents
718
+ } = results;
719
+ let exportedIds;
720
+ if (params.push) {
721
+ const updatedLane = lane ? await this.scope.legacyScope.loadLane(lane.toLaneId()) : undefined;
722
+ const {
723
+ exported
724
+ } = await this.exporter.exportMany({
725
+ scope: this.scope.legacyScope,
726
+ ids,
727
+ idsWithFutureScope: ids,
728
+ allVersions: false,
729
+ laneObject: updatedLane,
730
+ // no need other snaps. only the latest one. without this option, when snapping on lane from another-scope, it
731
+ // may throw an error saying the previous snaps don't exist on the filesystem.
732
+ // (see the e2e - "snap on a lane when the component is new to the lane and the scope")
733
+ exportHeadsOnly: true
734
+ });
735
+ exportedIds = exported;
736
+ }
737
+ return {
738
+ snappedComponents: taggedComponents,
739
+ snappedIds: taggedComponents.map(comp => comp.id),
740
+ exportedIds
741
+ };
742
+ }
743
+ async snapFromScope(snapDataPerCompRaw, params) {
744
+ const hasForkedFrom = snapDataPerCompRaw.some(s => s.forkFrom);
745
+ if (hasForkedFrom) return this.forkAndSnap(snapDataPerCompRaw, params);
746
+ if (this.workspace) {
747
+ throw new (_bitError().BitError)(`unable to run this command from a workspace, please create a new bare-scope and run it from there`);
748
+ }
749
+ let lane;
750
+ const laneIdStr = params.lane;
751
+ if (laneIdStr) {
752
+ const laneId = _laneId().LaneId.parse(laneIdStr);
753
+ try {
754
+ lane = await this.importer.importLaneObject(laneId);
755
+ } catch (err) {
756
+ if (err.constructor.name !== _legacy2().LaneNotFound.name) throw err;
757
+ // if the lane is not found, it's probably because it's new. create a new lane.
758
+ lane = await (0, _lanesModules().createLaneInScope)(laneId.name, this.scope, laneId.scope);
759
+ // it's important to set the lane as new in scope.json. otherwise, later, when importing and the lane is loaded
760
+ // from the filesystem, it looses the "isNew: true", and then it tries to fetch the lane from the remote scope.
761
+ // which fails with the importer.
762
+ this.scope.legacyScope.scopeJson.setLaneAsNew(laneId.name);
763
+ }
764
+ // this is critical. otherwise, later on, when loading aspects and isolating capsules, we'll try to fetch dists
765
+ // from the original scope instead of the lane-scope.
766
+ this.scope.legacyScope.setCurrentLaneId(laneId);
767
+ this.scope.legacyScope.scopeImporter.shouldOnlyFetchFromCurrentLane = true;
768
+ }
769
+ const laneCompIds = lane?.toComponentIdsIncludeUpdateDependents();
770
+ const snapDataPerComp = snapDataPerCompRaw.map(snapData => {
771
+ return {
772
+ componentId: _componentId().ComponentID.fromString(snapData.componentId),
773
+ dependencies: snapData.dependencies || [],
774
+ aspects: snapData.aspects,
775
+ message: snapData.message,
776
+ files: snapData.files,
777
+ isNew: snapData.isNew,
778
+ mainFile: snapData.mainFile,
779
+ newDependencies: (snapData.newDependencies || []).map(dep => ({
780
+ id: dep.id,
781
+ version: dep.version,
782
+ isComponent: dep.isComponent ?? true,
783
+ type: dep.type ?? 'runtime'
784
+ })),
785
+ removeDependencies: snapData.removeDependencies
786
+ };
787
+ });
788
+
789
+ // console.log('snapDataPerComp', JSON.stringify(snapDataPerComp, undefined, 2));
790
+
791
+ const componentIds = (0, _lodash().compact)(snapDataPerComp.map(t => t.isNew ? null : t.componentId));
792
+ const allCompIds = snapDataPerComp.map(s => s.componentId);
793
+ const componentIdsLatest = componentIds.map(id => id.changeVersion(_constants().LATEST));
794
+ const newCompsData = (0, _lodash().compact)(snapDataPerComp.map(t => t.isNew ? t : null));
795
+ const newComponents = await Promise.all(newCompsData.map(newComp => (0, _generateCompFromScope().generateCompFromScope)(this.scope, newComp, this)));
659
796
  await this.scope.import(componentIdsLatest, {
660
797
  preferDependencyGraph: false,
661
798
  lane,
@@ -685,7 +822,7 @@ if you're willing to lose the history from the head to the specified version, us
685
822
  });
686
823
  });
687
824
  }
688
- const components = [...existingComponents, ...newComponents, ...newForkedComponents];
825
+ const components = [...existingComponents, ...newComponents];
689
826
 
690
827
  // this must be done before we load component aspects later on, because this updated deps may update aspects.
691
828
  await (0, _pMapSeries().default)(components, async component => {
@@ -695,33 +832,22 @@ if you're willing to lose the history from the head to the specified version, us
695
832
  });
696
833
 
697
834
  // for new components these are not needed. coz when generating them we already add the aspects and the files.
698
- await Promise.all([...existingComponents, ...newForkedComponents].map(async comp => {
835
+ await Promise.all(existingComponents.map(async comp => {
699
836
  const snapData = getSnapData(comp.id);
700
837
  if (snapData.aspects) await this.scope.addAspectsFromConfigObject(comp, snapData.aspects);
701
838
  if (snapData.files?.length) {
702
839
  await this.updateSourceFiles(comp, snapData.files);
703
840
  }
704
841
  }));
705
- if (!this.workspace) {
706
- // load the aspects user configured to set on the components. it creates capsules if needed.
707
- // otherwise, when a user set a custom-env, it won't be loaded and the Version object will leave the
708
- // teambit.envs/envs in a weird state. the config will be set correctly but the data will be set to the default
709
- // node env.
710
- await this.scope.loadManyCompsAspects(components);
711
842
 
712
- // this is similar to what happens in the workspace. the "onLoad" is running and populating the "data" of the aspects.
713
- await (0, _pMapSeries().default)(components, async comp => this.scope.executeOnCompAspectReCalcSlot(comp));
714
- } else {
715
- await this.workspace.clearCache();
716
- // for the forked components, it's on the workspace, so all it is missing now is the installation
717
- await this.install.install(undefined, {
718
- dedupe: true,
719
- import: false,
720
- copyPeerToRuntimeOnRoot: true,
721
- copyPeerToRuntimeOnComponents: false,
722
- updateExisting: false
723
- });
724
- }
843
+ // load the aspects user configured to set on the components. it creates capsules if needed.
844
+ // otherwise, when a user set a custom-env, it won't be loaded and the Version object will leave the
845
+ // teambit.envs/envs in a weird state. the config will be set correctly but the data will be set to the default
846
+ // node env.
847
+ await this.scope.loadManyCompsAspects(components);
848
+
849
+ // this is similar to what happens in the workspace. the "onLoad" is running and populating the "data" of the aspects.
850
+ await (0, _pMapSeries().default)(components, async comp => this.scope.executeOnCompAspectReCalcSlot(comp));
725
851
  const consumerComponents = components.map(c => c.state._consumer);
726
852
  const ids = _componentId().ComponentIdList.fromArray(allCompIds);
727
853
  const results = await (0, _tagModelComponent().tagModelComponent)(_objectSpread(_objectSpread({}, params), {}, {