@teambit/workspace 0.0.956 → 0.0.958

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.
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ require("core-js/modules/es.array.iterator.js");
5
+ require("core-js/modules/es.promise.js");
6
+ require("core-js/modules/es.regexp.exec.js");
7
+ require("core-js/modules/es.string.trim.js");
8
+ Object.defineProperty(exports, "__esModule", {
9
+ value: true
10
+ });
11
+ exports.MergeConflictFile = void 0;
12
+ function _defineProperty2() {
13
+ const data = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
14
+ _defineProperty2 = function () {
15
+ return data;
16
+ };
17
+ return data;
18
+ }
19
+ function _constants() {
20
+ const data = require("@teambit/legacy/dist/constants");
21
+ _constants = function () {
22
+ return data;
23
+ };
24
+ return data;
25
+ }
26
+ function _path() {
27
+ const data = _interopRequireDefault(require("path"));
28
+ _path = function () {
29
+ return data;
30
+ };
31
+ return data;
32
+ }
33
+ function _fsExtra() {
34
+ const data = _interopRequireDefault(require("fs-extra"));
35
+ _fsExtra = function () {
36
+ return data;
37
+ };
38
+ return data;
39
+ }
40
+ function _mergeConfigConflict() {
41
+ const data = require("./exceptions/merge-config-conflict");
42
+ _mergeConfigConflict = function () {
43
+ return data;
44
+ };
45
+ return data;
46
+ }
47
+ const idPrefix = `[*]`;
48
+ const idDivider = '-'.repeat(80);
49
+ class MergeConflictFile {
50
+ constructor(workspacePath) {
51
+ this.workspacePath = workspacePath;
52
+ (0, _defineProperty2().default)(this, "conflictPerId", void 0);
53
+ }
54
+ addConflict(id, conflict) {
55
+ if (!this.conflictPerId) this.conflictPerId = {};
56
+ this.conflictPerId[id] = conflict;
57
+ }
58
+ removeConflict(id) {
59
+ var _this$conflictPerId;
60
+ (_this$conflictPerId = this.conflictPerId) === null || _this$conflictPerId === void 0 ? true : delete _this$conflictPerId[id];
61
+ }
62
+ async getConflict(id) {
63
+ await this.loadIfNeeded();
64
+ if (!this.conflictPerId) throw new Error(`this.conflictPerId must be instantiated after load`);
65
+ return this.conflictPerId[id];
66
+ }
67
+ async getConflictParsed(id) {
68
+ const configMergeContent = await this.getConflict(id);
69
+ if (!configMergeContent) return undefined;
70
+ try {
71
+ return JSON.parse(configMergeContent);
72
+ } catch (err) {
73
+ if (this.stringHasConflictMarker(configMergeContent)) {
74
+ throw new (_mergeConfigConflict().MergeConfigConflict)(this.getPath());
75
+ }
76
+ throw new Error(`unable to parse the merge-conflict entry for ${id} as the JSON is invalid. err: ${err.message}`);
77
+ }
78
+ }
79
+ hasConflict() {
80
+ return Boolean(this.conflictPerId && Object.keys(this.conflictPerId).length);
81
+ }
82
+ getPath() {
83
+ return _path().default.join(this.workspacePath, _constants().MergeConfigFilename);
84
+ }
85
+ async loadIfNeeded() {
86
+ if (this.conflictPerId) return; // already loaded
87
+ const fileContent = await this.getFileContentIfExists();
88
+ if (!fileContent) {
89
+ this.conflictPerId = {}; // to indicate that it's loaded
90
+ return;
91
+ }
92
+ const parsedConflict = this.parseConflict(fileContent);
93
+ this.conflictPerId = parsedConflict;
94
+ }
95
+ async write() {
96
+ if (!this.hasConflict()) return;
97
+ const afterFormat = this.formatConflicts();
98
+ await _fsExtra().default.writeFile(this.getPath(), afterFormat);
99
+ }
100
+ async delete() {
101
+ await _fsExtra().default.remove(this.getPath());
102
+ }
103
+ formatConflicts() {
104
+ const conflictPerId = this.conflictPerId;
105
+ if (!conflictPerId) throw new Error('conflictPerId is not populated');
106
+ const title = `# Resolve configuration conflicts per component and make sure the Component ID remain in place`;
107
+ const conflicts = Object.keys(conflictPerId).map(id => {
108
+ const conflict = conflictPerId[id];
109
+ return `${idDivider}
110
+ ${idPrefix} ${id}
111
+ ${idDivider}
112
+ ${conflict}`;
113
+ }).join('\n\n');
114
+ return `${title}\n\n${conflicts}`;
115
+ }
116
+ stringHasConflictMarker(str) {
117
+ return str.includes('<<<<<<<') || str.includes('>>>>>>>');
118
+ }
119
+ parseConflict(conflict) {
120
+ // remove irrelevant lines
121
+ conflict = conflict.split('\n').filter(line => line !== idDivider && !line.startsWith('#')).join('\n');
122
+ // split by id
123
+ const conflictPerId = {};
124
+ const split = conflict.split(idPrefix);
125
+ split.forEach(conflictItem => {
126
+ const conflictItemSplit = conflictItem.split('\n');
127
+ const [rawId, ...conflictStr] = conflictItemSplit;
128
+ const id = rawId.trim();
129
+ if (!id) return; // first line has it empty
130
+ conflictPerId[id] = conflictStr.join('\n');
131
+ });
132
+ return conflictPerId;
133
+ }
134
+ async getFileContentIfExists() {
135
+ const filePath = this.getPath();
136
+ let fileContent;
137
+ try {
138
+ fileContent = await _fsExtra().default.readFile(filePath, 'utf-8');
139
+ } catch (err) {
140
+ if (err.code === 'ENOENT') {
141
+ return undefined;
142
+ }
143
+ throw err;
144
+ }
145
+ return fileContent;
146
+ }
147
+ }
148
+ exports.MergeConflictFile = MergeConflictFile;
149
+
150
+ //# sourceMappingURL=merge-conflict-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["idPrefix","idDivider","repeat","MergeConflictFile","constructor","workspacePath","addConflict","id","conflict","conflictPerId","removeConflict","getConflict","loadIfNeeded","Error","getConflictParsed","configMergeContent","undefined","JSON","parse","err","stringHasConflictMarker","MergeConfigConflict","getPath","message","hasConflict","Boolean","Object","keys","length","path","join","MergeConfigFilename","fileContent","getFileContentIfExists","parsedConflict","parseConflict","write","afterFormat","formatConflicts","fs","writeFile","delete","remove","title","conflicts","map","str","includes","split","filter","line","startsWith","forEach","conflictItem","conflictItemSplit","rawId","conflictStr","trim","filePath","readFile","code"],"sources":["merge-conflict-file.ts"],"sourcesContent":["import { MergeConfigFilename } from '@teambit/legacy/dist/constants';\nimport path from 'path';\nimport fs from 'fs-extra';\nimport { MergeConfigConflict } from './exceptions/merge-config-conflict';\n\nconst idPrefix = `[*]`;\nconst idDivider = '-'.repeat(80);\ntype ConflictPerId = { [compIdWithoutVersion: string]: string };\n\nexport class MergeConflictFile {\n conflictPerId: ConflictPerId | undefined;\n constructor(private workspacePath: string) {}\n\n addConflict(id: string, conflict: string) {\n if (!this.conflictPerId) this.conflictPerId = {};\n this.conflictPerId[id] = conflict;\n }\n\n removeConflict(id: string) {\n delete this.conflictPerId?.[id];\n }\n\n async getConflict(id: string): Promise<string | undefined> {\n await this.loadIfNeeded();\n if (!this.conflictPerId) throw new Error(`this.conflictPerId must be instantiated after load`);\n return this.conflictPerId[id];\n }\n\n async getConflictParsed(id: string): Promise<Record<string, any> | undefined> {\n const configMergeContent = await this.getConflict(id);\n if (!configMergeContent) return undefined;\n try {\n return JSON.parse(configMergeContent);\n } catch (err: any) {\n if (this.stringHasConflictMarker(configMergeContent)) {\n throw new MergeConfigConflict(this.getPath());\n }\n throw new Error(`unable to parse the merge-conflict entry for ${id} as the JSON is invalid. err: ${err.message}`);\n }\n }\n\n hasConflict(): boolean {\n return Boolean(this.conflictPerId && Object.keys(this.conflictPerId).length);\n }\n\n getPath() {\n return path.join(this.workspacePath, MergeConfigFilename);\n }\n\n async loadIfNeeded() {\n if (this.conflictPerId) return; // already loaded\n const fileContent = await this.getFileContentIfExists();\n if (!fileContent) {\n this.conflictPerId = {}; // to indicate that it's loaded\n return;\n }\n const parsedConflict = this.parseConflict(fileContent);\n this.conflictPerId = parsedConflict;\n }\n\n async write() {\n if (!this.hasConflict()) return;\n const afterFormat = this.formatConflicts();\n await fs.writeFile(this.getPath(), afterFormat);\n }\n\n async delete() {\n await fs.remove(this.getPath());\n }\n\n private formatConflicts(): string {\n const conflictPerId = this.conflictPerId;\n if (!conflictPerId) throw new Error('conflictPerId is not populated');\n const title = `# Resolve configuration conflicts per component and make sure the Component ID remain in place`;\n const conflicts = Object.keys(conflictPerId)\n .map((id) => {\n const conflict = conflictPerId[id];\n return `${idDivider}\n${idPrefix} ${id}\n${idDivider}\n${conflict}`;\n })\n .join('\\n\\n');\n return `${title}\\n\\n${conflicts}`;\n }\n\n private stringHasConflictMarker(str: string): boolean {\n return str.includes('<<<<<<<') || str.includes('>>>>>>>');\n }\n\n private parseConflict(conflict: string): ConflictPerId {\n // remove irrelevant lines\n conflict = conflict\n .split('\\n')\n .filter((line) => line !== idDivider && !line.startsWith('#'))\n .join('\\n');\n // split by id\n const conflictPerId: ConflictPerId = {};\n const split = conflict.split(idPrefix);\n split.forEach((conflictItem) => {\n const conflictItemSplit = conflictItem.split('\\n');\n const [rawId, ...conflictStr] = conflictItemSplit;\n const id = rawId.trim();\n if (!id) return; // first line has it empty\n conflictPerId[id] = conflictStr.join('\\n');\n });\n return conflictPerId;\n }\n\n private async getFileContentIfExists(): Promise<string | undefined> {\n const filePath = this.getPath();\n let fileContent: string;\n try {\n fileContent = await fs.readFile(filePath, 'utf-8');\n } catch (err: any) {\n if (err.code === 'ENOENT') {\n return undefined;\n }\n throw err;\n }\n return fileContent;\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import * as compositions_0 from '/home/circleci/Library/Caches/Bit/capsules/8891be5ad3d35bfc38b9cd90c0e05b598a5a55af/teambit.workspace_workspace@0.0.956/dist/workspace.composition.js';
2
- import * as overview_0 from '/home/circleci/Library/Caches/Bit/capsules/8891be5ad3d35bfc38b9cd90c0e05b598a5a55af/teambit.workspace_workspace@0.0.956/dist/workspace.docs.mdx';
1
+ import * as compositions_0 from '/home/circleci/Library/Caches/Bit/capsules/8891be5ad3d35bfc38b9cd90c0e05b598a5a55af/teambit.workspace_workspace@0.0.958/dist/workspace.composition.js';
2
+ import * as overview_0 from '/home/circleci/Library/Caches/Bit/capsules/8891be5ad3d35bfc38b9cd90c0e05b598a5a55af/teambit.workspace_workspace@0.0.958/dist/workspace.docs.mdx';
3
3
 
4
4
  export const compositions = [compositions_0];
5
5
  export const overview = [overview_0];
@@ -35,6 +35,7 @@ import { OnComponentAddSlot, OnComponentChangeSlot, OnComponentLoadSlot, OnCompo
35
35
  import { WorkspaceComponentLoader } from './workspace-component/workspace-component-loader';
36
36
  import { ShouldLoadFunc } from './build-graph-from-fs';
37
37
  import { BitMap } from './bit-map';
38
+ import { MergeConflictFile } from './merge-conflict-file';
38
39
  export declare type EjectConfResult = {
39
40
  configPath: string;
40
41
  };
@@ -83,9 +84,9 @@ export declare class Workspace implements ComponentFactory {
83
84
  */
84
85
  private componentAspect;
85
86
  private dependencyResolver;
86
- private variants;
87
+ readonly variants: VariantsMain;
87
88
  private aspectLoader;
88
- private logger;
89
+ readonly logger: Logger;
89
90
  private componentList;
90
91
  /**
91
92
  * private reference to the instance of Harmony.
@@ -99,7 +100,7 @@ export declare class Workspace implements ComponentFactory {
99
100
  * on component change slot.
100
101
  */
101
102
  private onComponentChangeSlot;
102
- private envs;
103
+ readonly envs: EnvsMain;
103
104
  /**
104
105
  * on component add slot.
105
106
  */
@@ -115,7 +116,7 @@ export declare class Workspace implements ComponentFactory {
115
116
  bitMap: BitMap;
116
117
  private _cachedListIds?;
117
118
  private componentLoadedSelfAsAspects;
118
- private warnedAboutMisconfiguredEnvs;
119
+ private aspectsMerger;
119
120
  constructor(
120
121
  /**
121
122
  * private pubsub.
@@ -372,14 +373,11 @@ export declare class Workspace implements ComponentFactory {
372
373
  }>;
373
374
  errors?: Error[];
374
375
  }>;
375
- getConfigMergeFilePath(componentId: ComponentID): string;
376
+ getConfigMergeFilePath(): string;
377
+ getConflictMergeFile(): MergeConflictFile;
376
378
  listComponentsDuringMerge(): Promise<ComponentID[]>;
377
- private getConfigMergeFile;
378
379
  getUnmergedComponent(componentId: ComponentID): Promise<Component | undefined>;
379
- private getUnmergedData;
380
- private warnAboutMisconfiguredEnv;
381
380
  isModified(component: Component): Promise<boolean>;
382
- private filterEnvsFromExtensionsIfNeeded;
383
381
  triggerOnPreWatch(componentIds: ComponentID[], watchOpts: WatchOptions): Promise<void>;
384
382
  /**
385
383
  * filter the given component-ids and set default-scope only to the new ones.
@@ -396,12 +394,6 @@ export declare class Workspace implements ComponentFactory {
396
394
  removeSpecificComponentConfig(id: ComponentID, aspectId: string, markWithMinusIfNotExist: boolean): Promise<void>;
397
395
  getAspectIdFromConfig(componentId: ComponentID, aspectIdStr: string, ignoreAspectVersion?: boolean): Promise<string | undefined>;
398
396
  getSpecificComponentConfig(id: ComponentID, aspectId: string): Promise<any>;
399
- /**
400
- * This will mutate the entries with extensionId prop to have resolved legacy id
401
- * This should be worked on the extension data list not the new aspect list
402
- * @param extensionList
403
- */
404
- private resolveExtensionListIds;
405
397
  private isVendorComponentByComponentDir;
406
398
  /**
407
399
  * return the component config from its folder (component.json)
@@ -427,11 +419,6 @@ export declare class Workspace implements ComponentFactory {
427
419
  resolveAspects(runtimeName?: string, componentIds?: ComponentID[], opts?: ResolveAspectsOptions): Promise<AspectDefinition[]>;
428
420
  private groupIdsByWorkspaceAndScope;
429
421
  private groupComponentsByWorkspaceAndScope;
430
- /**
431
- * Load all unloaded extensions from a list
432
- * @param extensions list of extensions with config to load
433
- */
434
- loadExtensions(extensions: ExtensionDataList, originatedFrom?: ComponentID, throwOnError?: boolean): Promise<void>;
435
422
  /**
436
423
  * Provides a cache folder, unique per key.
437
424
  * Return value may be undefined, if workspace folder is unconventional (bare-scope, no node_modules, etc)
@@ -498,5 +485,11 @@ export declare class Workspace implements ComponentFactory {
498
485
  changed: ComponentID[];
499
486
  unchanged: ComponentID[];
500
487
  }>;
488
+ updateEnvForComponents(envIdStr?: string, pattern?: string): Promise<{
489
+ updated: {
490
+ [envId: string]: ComponentID[];
491
+ };
492
+ alreadyUpToDate: ComponentID[];
493
+ }>;
501
494
  }
502
495
  export default Workspace;