@teambit/workspace 0.0.534 → 0.0.539

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,160 @@
1
+ import mapSeries from 'p-map-series';
2
+ import { flatten } from 'lodash';
3
+ import { Consumer } from '@teambit/legacy/dist/consumer';
4
+ import BitIds from '@teambit/legacy/dist/bit-id/bit-ids';
5
+ import Component from '@teambit/legacy/dist/consumer/component/consumer-component';
6
+ import LegacyGraph from '@teambit/legacy/dist/scope/graph/graph';
7
+ import ScopeComponentsImporter from '@teambit/legacy/dist/scope/component-ops/scope-components-importer';
8
+ import compact from 'lodash.compact';
9
+ import { BitId } from '@teambit/legacy-bit-id';
10
+ import { Logger } from '@teambit/logger';
11
+ import { ComponentNotFound } from '@teambit/scope';
12
+ import { BitError } from '@teambit/bit-error';
13
+ import { Workspace } from './workspace';
14
+
15
+ export type ShouldIgnoreFunc = (bitId: BitId) => Promise<boolean>;
16
+
17
+ export class GraphFromFsBuilder {
18
+ private graph = new LegacyGraph();
19
+ private completed: string[] = [];
20
+ private depth = 1;
21
+ private shouldThrowOnMissingDep = true;
22
+ private consumer: Consumer;
23
+ constructor(
24
+ private workspace: Workspace,
25
+ private logger: Logger,
26
+ private ignoreIds = new BitIds(),
27
+ private shouldLoadItsDeps?: ShouldIgnoreFunc
28
+ ) {
29
+ this.consumer = this.workspace.consumer;
30
+ }
31
+
32
+ /**
33
+ * create a graph with all dependencies and flattened dependencies of the given components.
34
+ * the nodes are components and the edges has a label of the dependency type.
35
+ *
36
+ * the way how it is done is iterations by depths. each depth we gather all the dependencies of
37
+ * that depths, make sure all objects exist and then check their dependencies for the next depth.
38
+ * once there is no dependency left, we're on the last depth level and the graph is ready.
39
+ *
40
+ * for example, imagine the following graph:
41
+ * A1 -> A2 -> A3
42
+ * B1 -> B2 -> B3
43
+ * C1 -> C2 -> C3
44
+ *
45
+ * where the buildGraph is given [A1, B1, C1].
46
+ * first, it saves all these components as nodes in the graph. then, it finds the dependencies of
47
+ * the next level, in this case they're [A2, B2, C2]. it runs `importMany` in case some objects
48
+ * are missing. then, it loads them all (some from FS, some from the model) and sets the edges
49
+ * between the component and the dependencies.
50
+ * once done, it finds all their dependencies, which are [A3, B3, C3] and repeat the process
51
+ * above. since there are no more dependencies, the graph is completed.
52
+ * in this case, the total depth levels are 3.
53
+ *
54
+ * even with a huge project, there are not many depth levels. by iterating through depth levels
55
+ * we keep performance sane as the importMany doesn't run multiple time and therefore the round
56
+ * trips to the remotes are minimal.
57
+ *
58
+ * normally, one importMany of the seeders is enough as importMany knows to fetch all flattened.
59
+ * however, since this buildGraph is performed on the workspace, a dependency may be new or
60
+ * modified and as such, we don't know its flattened yet.
61
+ */
62
+ async buildGraph(ids: BitId[]): Promise<LegacyGraph> {
63
+ this.logger.debug(`GraphFromFsBuilder, buildGraph with ${ids.length} seeders`);
64
+ const start = Date.now();
65
+ const components = await this.loadManyComponents(ids, '<none>');
66
+ await this.processManyComponents(components);
67
+ this.logger.debug(
68
+ `GraphFromFsBuilder, buildGraph with ${ids.length} seeders completed (${(Date.now() - start) / 1000} sec)`
69
+ );
70
+ return this.graph;
71
+ }
72
+
73
+ private getAllDepsUnfiltered(component: Component) {
74
+ return component.getAllDependenciesIds().difference(this.ignoreIds);
75
+ }
76
+
77
+ private async getAllDepsFiltered(component: Component): Promise<BitIds> {
78
+ const depsWithoutIgnore = this.getAllDepsUnfiltered(component);
79
+ const shouldLoadFunc = this.shouldLoadItsDeps;
80
+ if (!shouldLoadFunc) return depsWithoutIgnore;
81
+ const deps = await mapSeries(depsWithoutIgnore, async (depId) => {
82
+ const shouldLoad = await shouldLoadFunc(depId);
83
+ if (!shouldLoad) this.ignoreIds.push(depId);
84
+ return shouldLoad ? depId : null;
85
+ });
86
+ return BitIds.fromArray(compact(deps));
87
+ }
88
+
89
+ private async processManyComponents(components: Component[]) {
90
+ this.logger.debug(`GraphFromFsBuilder.processManyComponents depth ${this.depth}, ${components.length} components`);
91
+ this.depth += 1;
92
+ await this.importObjects(components);
93
+ const allDependencies = await mapSeries(components, (component) => this.processOneComponent(component));
94
+ const allDependenciesFlattened = flatten(allDependencies);
95
+ if (allDependenciesFlattened.length) await this.processManyComponents(allDependenciesFlattened);
96
+ }
97
+
98
+ private async importObjects(components: Component[]) {
99
+ const allDeps = components.map((c) => this.getAllDepsUnfiltered(c)).flat();
100
+ const allDepsWithScope = allDeps.filter((dep) => dep.hasScope());
101
+ const scopeComponentsImporter = new ScopeComponentsImporter(this.consumer.scope);
102
+ await scopeComponentsImporter.importMany(
103
+ BitIds.uniqFromArray(allDepsWithScope),
104
+ undefined,
105
+ this.shouldThrowOnMissingDep
106
+ );
107
+ }
108
+
109
+ private async processOneComponent(component: Component) {
110
+ const idStr = component.id.toString();
111
+ if (this.completed.includes(idStr)) return [];
112
+ const allIds = await this.getAllDepsFiltered(component);
113
+
114
+ const allDependencies = await this.loadManyComponents(allIds, idStr);
115
+ Object.entries(component.depsIdsGroupedByType).forEach(([depType, depsIds]) => {
116
+ depsIds.forEach((depId) => {
117
+ if (this.ignoreIds.has(depId)) return;
118
+ if (!this.graph.hasNode(depId.toString())) {
119
+ throw new Error(`buildOneComponent: missing node of ${depId.toString()}`);
120
+ }
121
+ this.graph.setEdge(idStr, depId.toString(), depType);
122
+ });
123
+ });
124
+ this.completed.push(idStr);
125
+ return allDependencies;
126
+ }
127
+
128
+ private async loadManyComponents(componentsIds: BitId[], dependenciesOf: string): Promise<Component[]> {
129
+ const components = await mapSeries(componentsIds, async (comp: BitId) => {
130
+ const idStr = comp.toString();
131
+ const fromGraph = this.graph.node(idStr);
132
+ if (fromGraph) return fromGraph;
133
+ try {
134
+ const component = await this.loadComponent(comp);
135
+ this.graph.setNode(idStr, component);
136
+ return component;
137
+ } catch (err: any) {
138
+ if (err instanceof ComponentNotFound) {
139
+ throw new BitError(
140
+ `error: component "${idStr}" was not found.\nthis component is a dependency of "${dependenciesOf}" and is needed as part of the graph generation`
141
+ );
142
+ }
143
+ this.logger.error(`failed loading dependencies of ${dependenciesOf}`);
144
+ throw err;
145
+ }
146
+ });
147
+ return components;
148
+ }
149
+ private async loadComponent(componentId: BitId): Promise<Component> {
150
+ const componentMap = this.consumer.bitMap.getComponentIfExist(componentId);
151
+ const isOnWorkspace = Boolean(componentMap);
152
+ if (isOnWorkspace) {
153
+ return this.consumer.loadComponentForCapsule(componentId);
154
+ }
155
+ // a dependency might have been installed as a package in the workspace, and as such doesn't
156
+ // have a componentMap.
157
+ const componentFromModel = await this.consumer.loadComponentFromModel(componentId);
158
+ return componentFromModel.clone();
159
+ }
160
+ }
@@ -0,0 +1,26 @@
1
+ import BitIds from '@teambit/legacy/dist/bit-id/bit-ids';
2
+ import LegacyGraph from '@teambit/legacy/dist/scope/graph/graph';
3
+ import { BitId } from '@teambit/legacy-bit-id';
4
+ import { Logger } from '@teambit/logger';
5
+ import { Workspace } from './workspace';
6
+ export declare type ShouldIgnoreFunc = (bitId: BitId) => Promise<boolean>;
7
+ export declare class GraphFromFsBuilder {
8
+ private workspace;
9
+ private logger;
10
+ private ignoreIds;
11
+ private shouldLoadItsDeps?;
12
+ private graph;
13
+ private completed;
14
+ private depth;
15
+ private shouldThrowOnMissingDep;
16
+ private consumer;
17
+ constructor(workspace: Workspace, logger: Logger, ignoreIds?: BitIds, shouldLoadItsDeps?: ShouldIgnoreFunc | undefined);
18
+ buildGraph(ids: BitId[]): Promise<LegacyGraph>;
19
+ private getAllDepsUnfiltered;
20
+ private getAllDepsFiltered;
21
+ private processManyComponents;
22
+ private importObjects;
23
+ private processOneComponent;
24
+ private loadManyComponents;
25
+ private loadComponent;
26
+ }
@@ -0,0 +1,254 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ require("core-js/modules/es.array.flat.js");
6
+
7
+ require("core-js/modules/es.array.iterator.js");
8
+
9
+ require("core-js/modules/es.array.unscopables.flat.js");
10
+
11
+ require("core-js/modules/es.promise.js");
12
+
13
+ Object.defineProperty(exports, "__esModule", {
14
+ value: true
15
+ });
16
+ exports.GraphFromFsBuilder = void 0;
17
+
18
+ function _defineProperty2() {
19
+ const data = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
20
+
21
+ _defineProperty2 = function () {
22
+ return data;
23
+ };
24
+
25
+ return data;
26
+ }
27
+
28
+ function _pMapSeries() {
29
+ const data = _interopRequireDefault(require("p-map-series"));
30
+
31
+ _pMapSeries = function () {
32
+ return data;
33
+ };
34
+
35
+ return data;
36
+ }
37
+
38
+ function _lodash() {
39
+ const data = require("lodash");
40
+
41
+ _lodash = function () {
42
+ return data;
43
+ };
44
+
45
+ return data;
46
+ }
47
+
48
+ function _bitIds() {
49
+ const data = _interopRequireDefault(require("@teambit/legacy/dist/bit-id/bit-ids"));
50
+
51
+ _bitIds = function () {
52
+ return data;
53
+ };
54
+
55
+ return data;
56
+ }
57
+
58
+ function _graph() {
59
+ const data = _interopRequireDefault(require("@teambit/legacy/dist/scope/graph/graph"));
60
+
61
+ _graph = function () {
62
+ return data;
63
+ };
64
+
65
+ return data;
66
+ }
67
+
68
+ function _scopeComponentsImporter() {
69
+ const data = _interopRequireDefault(require("@teambit/legacy/dist/scope/component-ops/scope-components-importer"));
70
+
71
+ _scopeComponentsImporter = function () {
72
+ return data;
73
+ };
74
+
75
+ return data;
76
+ }
77
+
78
+ function _lodash2() {
79
+ const data = _interopRequireDefault(require("lodash.compact"));
80
+
81
+ _lodash2 = function () {
82
+ return data;
83
+ };
84
+
85
+ return data;
86
+ }
87
+
88
+ function _scope() {
89
+ const data = require("@teambit/scope");
90
+
91
+ _scope = function () {
92
+ return data;
93
+ };
94
+
95
+ return data;
96
+ }
97
+
98
+ function _bitError() {
99
+ const data = require("@teambit/bit-error");
100
+
101
+ _bitError = function () {
102
+ return data;
103
+ };
104
+
105
+ return data;
106
+ }
107
+
108
+ class GraphFromFsBuilder {
109
+ constructor(workspace, logger, ignoreIds = new (_bitIds().default)(), shouldLoadItsDeps) {
110
+ this.workspace = workspace;
111
+ this.logger = logger;
112
+ this.ignoreIds = ignoreIds;
113
+ this.shouldLoadItsDeps = shouldLoadItsDeps;
114
+ (0, _defineProperty2().default)(this, "graph", new (_graph().default)());
115
+ (0, _defineProperty2().default)(this, "completed", []);
116
+ (0, _defineProperty2().default)(this, "depth", 1);
117
+ (0, _defineProperty2().default)(this, "shouldThrowOnMissingDep", true);
118
+ (0, _defineProperty2().default)(this, "consumer", void 0);
119
+ this.consumer = this.workspace.consumer;
120
+ }
121
+ /**
122
+ * create a graph with all dependencies and flattened dependencies of the given components.
123
+ * the nodes are components and the edges has a label of the dependency type.
124
+ *
125
+ * the way how it is done is iterations by depths. each depth we gather all the dependencies of
126
+ * that depths, make sure all objects exist and then check their dependencies for the next depth.
127
+ * once there is no dependency left, we're on the last depth level and the graph is ready.
128
+ *
129
+ * for example, imagine the following graph:
130
+ * A1 -> A2 -> A3
131
+ * B1 -> B2 -> B3
132
+ * C1 -> C2 -> C3
133
+ *
134
+ * where the buildGraph is given [A1, B1, C1].
135
+ * first, it saves all these components as nodes in the graph. then, it finds the dependencies of
136
+ * the next level, in this case they're [A2, B2, C2]. it runs `importMany` in case some objects
137
+ * are missing. then, it loads them all (some from FS, some from the model) and sets the edges
138
+ * between the component and the dependencies.
139
+ * once done, it finds all their dependencies, which are [A3, B3, C3] and repeat the process
140
+ * above. since there are no more dependencies, the graph is completed.
141
+ * in this case, the total depth levels are 3.
142
+ *
143
+ * even with a huge project, there are not many depth levels. by iterating through depth levels
144
+ * we keep performance sane as the importMany doesn't run multiple time and therefore the round
145
+ * trips to the remotes are minimal.
146
+ *
147
+ * normally, one importMany of the seeders is enough as importMany knows to fetch all flattened.
148
+ * however, since this buildGraph is performed on the workspace, a dependency may be new or
149
+ * modified and as such, we don't know its flattened yet.
150
+ */
151
+
152
+
153
+ async buildGraph(ids) {
154
+ this.logger.debug(`GraphFromFsBuilder, buildGraph with ${ids.length} seeders`);
155
+ const start = Date.now();
156
+ const components = await this.loadManyComponents(ids, '<none>');
157
+ await this.processManyComponents(components);
158
+ this.logger.debug(`GraphFromFsBuilder, buildGraph with ${ids.length} seeders completed (${(Date.now() - start) / 1000} sec)`);
159
+ return this.graph;
160
+ }
161
+
162
+ getAllDepsUnfiltered(component) {
163
+ return component.getAllDependenciesIds().difference(this.ignoreIds);
164
+ }
165
+
166
+ async getAllDepsFiltered(component) {
167
+ const depsWithoutIgnore = this.getAllDepsUnfiltered(component);
168
+ const shouldLoadFunc = this.shouldLoadItsDeps;
169
+ if (!shouldLoadFunc) return depsWithoutIgnore;
170
+ const deps = await (0, _pMapSeries().default)(depsWithoutIgnore, async depId => {
171
+ const shouldLoad = await shouldLoadFunc(depId);
172
+ if (!shouldLoad) this.ignoreIds.push(depId);
173
+ return shouldLoad ? depId : null;
174
+ });
175
+ return _bitIds().default.fromArray((0, _lodash2().default)(deps));
176
+ }
177
+
178
+ async processManyComponents(components) {
179
+ this.logger.debug(`GraphFromFsBuilder.processManyComponents depth ${this.depth}, ${components.length} components`);
180
+ this.depth += 1;
181
+ await this.importObjects(components);
182
+ const allDependencies = await (0, _pMapSeries().default)(components, component => this.processOneComponent(component));
183
+ const allDependenciesFlattened = (0, _lodash().flatten)(allDependencies);
184
+ if (allDependenciesFlattened.length) await this.processManyComponents(allDependenciesFlattened);
185
+ }
186
+
187
+ async importObjects(components) {
188
+ const allDeps = components.map(c => this.getAllDepsUnfiltered(c)).flat();
189
+ const allDepsWithScope = allDeps.filter(dep => dep.hasScope());
190
+ const scopeComponentsImporter = new (_scopeComponentsImporter().default)(this.consumer.scope);
191
+ await scopeComponentsImporter.importMany(_bitIds().default.uniqFromArray(allDepsWithScope), undefined, this.shouldThrowOnMissingDep);
192
+ }
193
+
194
+ async processOneComponent(component) {
195
+ const idStr = component.id.toString();
196
+ if (this.completed.includes(idStr)) return [];
197
+ const allIds = await this.getAllDepsFiltered(component);
198
+ const allDependencies = await this.loadManyComponents(allIds, idStr);
199
+ Object.entries(component.depsIdsGroupedByType).forEach(([depType, depsIds]) => {
200
+ depsIds.forEach(depId => {
201
+ if (this.ignoreIds.has(depId)) return;
202
+
203
+ if (!this.graph.hasNode(depId.toString())) {
204
+ throw new Error(`buildOneComponent: missing node of ${depId.toString()}`);
205
+ }
206
+
207
+ this.graph.setEdge(idStr, depId.toString(), depType);
208
+ });
209
+ });
210
+ this.completed.push(idStr);
211
+ return allDependencies;
212
+ }
213
+
214
+ async loadManyComponents(componentsIds, dependenciesOf) {
215
+ const components = await (0, _pMapSeries().default)(componentsIds, async comp => {
216
+ const idStr = comp.toString();
217
+ const fromGraph = this.graph.node(idStr);
218
+ if (fromGraph) return fromGraph;
219
+
220
+ try {
221
+ const component = await this.loadComponent(comp);
222
+ this.graph.setNode(idStr, component);
223
+ return component;
224
+ } catch (err) {
225
+ if (err instanceof _scope().ComponentNotFound) {
226
+ throw new (_bitError().BitError)(`error: component "${idStr}" was not found.\nthis component is a dependency of "${dependenciesOf}" and is needed as part of the graph generation`);
227
+ }
228
+
229
+ this.logger.error(`failed loading dependencies of ${dependenciesOf}`);
230
+ throw err;
231
+ }
232
+ });
233
+ return components;
234
+ }
235
+
236
+ async loadComponent(componentId) {
237
+ const componentMap = this.consumer.bitMap.getComponentIfExist(componentId);
238
+ const isOnWorkspace = Boolean(componentMap);
239
+
240
+ if (isOnWorkspace) {
241
+ return this.consumer.loadComponentForCapsule(componentId);
242
+ } // a dependency might have been installed as a package in the workspace, and as such doesn't
243
+ // have a componentMap.
244
+
245
+
246
+ const componentFromModel = await this.consumer.loadComponentFromModel(componentId);
247
+ return componentFromModel.clone();
248
+ }
249
+
250
+ }
251
+
252
+ exports.GraphFromFsBuilder = GraphFromFsBuilder;
253
+
254
+ //# sourceMappingURL=build-graph-from-fs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["build-graph-from-fs.ts"],"names":["GraphFromFsBuilder","constructor","workspace","logger","ignoreIds","BitIds","shouldLoadItsDeps","LegacyGraph","consumer","buildGraph","ids","debug","length","start","Date","now","components","loadManyComponents","processManyComponents","graph","getAllDepsUnfiltered","component","getAllDependenciesIds","difference","getAllDepsFiltered","depsWithoutIgnore","shouldLoadFunc","deps","depId","shouldLoad","push","fromArray","depth","importObjects","allDependencies","processOneComponent","allDependenciesFlattened","allDeps","map","c","flat","allDepsWithScope","filter","dep","hasScope","scopeComponentsImporter","ScopeComponentsImporter","scope","importMany","uniqFromArray","undefined","shouldThrowOnMissingDep","idStr","id","toString","completed","includes","allIds","Object","entries","depsIdsGroupedByType","forEach","depType","depsIds","has","hasNode","Error","setEdge","componentsIds","dependenciesOf","comp","fromGraph","node","loadComponent","setNode","err","ComponentNotFound","BitError","error","componentId","componentMap","bitMap","getComponentIfExist","isOnWorkspace","Boolean","loadComponentForCapsule","componentFromModel","loadComponentFromModel","clone"],"mappings":"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","sourcesContent":["import mapSeries from 'p-map-series';\nimport { flatten } from 'lodash';\nimport { Consumer } from '@teambit/legacy/dist/consumer';\nimport BitIds from '@teambit/legacy/dist/bit-id/bit-ids';\nimport Component from '@teambit/legacy/dist/consumer/component/consumer-component';\nimport LegacyGraph from '@teambit/legacy/dist/scope/graph/graph';\nimport ScopeComponentsImporter from '@teambit/legacy/dist/scope/component-ops/scope-components-importer';\nimport compact from 'lodash.compact';\nimport { BitId } from '@teambit/legacy-bit-id';\nimport { Logger } from '@teambit/logger';\nimport { ComponentNotFound } from '@teambit/scope';\nimport { BitError } from '@teambit/bit-error';\nimport { Workspace } from './workspace';\n\nexport type ShouldIgnoreFunc = (bitId: BitId) => Promise<boolean>;\n\nexport class GraphFromFsBuilder {\n private graph = new LegacyGraph();\n private completed: string[] = [];\n private depth = 1;\n private shouldThrowOnMissingDep = true;\n private consumer: Consumer;\n constructor(\n private workspace: Workspace,\n private logger: Logger,\n private ignoreIds = new BitIds(),\n private shouldLoadItsDeps?: ShouldIgnoreFunc\n ) {\n this.consumer = this.workspace.consumer;\n }\n\n /**\n * create a graph with all dependencies and flattened dependencies of the given components.\n * the nodes are components and the edges has a label of the dependency type.\n *\n * the way how it is done is iterations by depths. each depth we gather all the dependencies of\n * that depths, make sure all objects exist and then check their dependencies for the next depth.\n * once there is no dependency left, we're on the last depth level and the graph is ready.\n *\n * for example, imagine the following graph:\n * A1 -> A2 -> A3\n * B1 -> B2 -> B3\n * C1 -> C2 -> C3\n *\n * where the buildGraph is given [A1, B1, C1].\n * first, it saves all these components as nodes in the graph. then, it finds the dependencies of\n * the next level, in this case they're [A2, B2, C2]. it runs `importMany` in case some objects\n * are missing. then, it loads them all (some from FS, some from the model) and sets the edges\n * between the component and the dependencies.\n * once done, it finds all their dependencies, which are [A3, B3, C3] and repeat the process\n * above. since there are no more dependencies, the graph is completed.\n * in this case, the total depth levels are 3.\n *\n * even with a huge project, there are not many depth levels. by iterating through depth levels\n * we keep performance sane as the importMany doesn't run multiple time and therefore the round\n * trips to the remotes are minimal.\n *\n * normally, one importMany of the seeders is enough as importMany knows to fetch all flattened.\n * however, since this buildGraph is performed on the workspace, a dependency may be new or\n * modified and as such, we don't know its flattened yet.\n */\n async buildGraph(ids: BitId[]): Promise<LegacyGraph> {\n this.logger.debug(`GraphFromFsBuilder, buildGraph with ${ids.length} seeders`);\n const start = Date.now();\n const components = await this.loadManyComponents(ids, '<none>');\n await this.processManyComponents(components);\n this.logger.debug(\n `GraphFromFsBuilder, buildGraph with ${ids.length} seeders completed (${(Date.now() - start) / 1000} sec)`\n );\n return this.graph;\n }\n\n private getAllDepsUnfiltered(component: Component) {\n return component.getAllDependenciesIds().difference(this.ignoreIds);\n }\n\n private async getAllDepsFiltered(component: Component): Promise<BitIds> {\n const depsWithoutIgnore = this.getAllDepsUnfiltered(component);\n const shouldLoadFunc = this.shouldLoadItsDeps;\n if (!shouldLoadFunc) return depsWithoutIgnore;\n const deps = await mapSeries(depsWithoutIgnore, async (depId) => {\n const shouldLoad = await shouldLoadFunc(depId);\n if (!shouldLoad) this.ignoreIds.push(depId);\n return shouldLoad ? depId : null;\n });\n return BitIds.fromArray(compact(deps));\n }\n\n private async processManyComponents(components: Component[]) {\n this.logger.debug(`GraphFromFsBuilder.processManyComponents depth ${this.depth}, ${components.length} components`);\n this.depth += 1;\n await this.importObjects(components);\n const allDependencies = await mapSeries(components, (component) => this.processOneComponent(component));\n const allDependenciesFlattened = flatten(allDependencies);\n if (allDependenciesFlattened.length) await this.processManyComponents(allDependenciesFlattened);\n }\n\n private async importObjects(components: Component[]) {\n const allDeps = components.map((c) => this.getAllDepsUnfiltered(c)).flat();\n const allDepsWithScope = allDeps.filter((dep) => dep.hasScope());\n const scopeComponentsImporter = new ScopeComponentsImporter(this.consumer.scope);\n await scopeComponentsImporter.importMany(\n BitIds.uniqFromArray(allDepsWithScope),\n undefined,\n this.shouldThrowOnMissingDep\n );\n }\n\n private async processOneComponent(component: Component) {\n const idStr = component.id.toString();\n if (this.completed.includes(idStr)) return [];\n const allIds = await this.getAllDepsFiltered(component);\n\n const allDependencies = await this.loadManyComponents(allIds, idStr);\n Object.entries(component.depsIdsGroupedByType).forEach(([depType, depsIds]) => {\n depsIds.forEach((depId) => {\n if (this.ignoreIds.has(depId)) return;\n if (!this.graph.hasNode(depId.toString())) {\n throw new Error(`buildOneComponent: missing node of ${depId.toString()}`);\n }\n this.graph.setEdge(idStr, depId.toString(), depType);\n });\n });\n this.completed.push(idStr);\n return allDependencies;\n }\n\n private async loadManyComponents(componentsIds: BitId[], dependenciesOf: string): Promise<Component[]> {\n const components = await mapSeries(componentsIds, async (comp: BitId) => {\n const idStr = comp.toString();\n const fromGraph = this.graph.node(idStr);\n if (fromGraph) return fromGraph;\n try {\n const component = await this.loadComponent(comp);\n this.graph.setNode(idStr, component);\n return component;\n } catch (err: any) {\n if (err instanceof ComponentNotFound) {\n throw new BitError(\n `error: component \"${idStr}\" was not found.\\nthis component is a dependency of \"${dependenciesOf}\" and is needed as part of the graph generation`\n );\n }\n this.logger.error(`failed loading dependencies of ${dependenciesOf}`);\n throw err;\n }\n });\n return components;\n }\n private async loadComponent(componentId: BitId): Promise<Component> {\n const componentMap = this.consumer.bitMap.getComponentIfExist(componentId);\n const isOnWorkspace = Boolean(componentMap);\n if (isOnWorkspace) {\n return this.consumer.loadComponentForCapsule(componentId);\n }\n // a dependency might have been installed as a package in the workspace, and as such doesn't\n // have a componentMap.\n const componentFromModel = await this.consumer.loadComponentFromModel(componentId);\n return componentFromModel.clone();\n }\n}\n"]}
@@ -14,6 +14,7 @@ import { RequireableComponent } from '@teambit/harmony.modules.requireable-compo
14
14
  import { ResolvedComponent } from '@teambit/harmony.modules.resolved-component';
15
15
  import type { VariantsMain } from '@teambit/variants';
16
16
  import LegacyGraph from '@teambit/legacy/dist/scope/graph/graph';
17
+ import { BitIds } from '@teambit/legacy/dist/bit-id';
17
18
  import { BitId } from '@teambit/legacy-bit-id';
18
19
  import { LocalLaneId } from '@teambit/legacy/dist/lane-id/lane-id';
19
20
  import { Consumer } from '@teambit/legacy/dist/consumer';
@@ -31,6 +32,7 @@ import { Watcher, WatchOptions } from './watch/watcher';
31
32
  import { ComponentStatus } from './workspace-component/component-status';
32
33
  import { OnComponentAddSlot, OnComponentChangeSlot, OnComponentLoadSlot, OnComponentRemoveSlot, OnPreWatch, OnPreWatchSlot } from './workspace.provider';
33
34
  import { WorkspaceComponentLoader } from './workspace-component/workspace-component-loader';
35
+ import { ShouldIgnoreFunc } from './build-graph-from-fs';
34
36
  export declare type EjectConfResult = {
35
37
  configPath: string;
36
38
  };
@@ -159,8 +161,9 @@ export declare class Workspace implements ComponentFactory {
159
161
  private isVendorComponentByComponentDir;
160
162
  private componentConfigFile;
161
163
  private componentConfigFileFromComponentDirAndName;
162
- getGraphWithoutCore(components: Component[]): Promise<LegacyGraph>;
164
+ getAspectsGraphWithoutCore(components: Component[], isAspect?: ShouldIgnoreFunc): Promise<LegacyGraph>;
163
165
  loadAspects(ids?: string[], throwOnError?: boolean): Promise<void>;
166
+ buildOneGraphForComponents(ids: BitId[], ignoreIds?: BitIds, shouldIgnoreFunc?: ShouldIgnoreFunc): Promise<LegacyGraph>;
164
167
  resolveAspects(runtimeName?: string, componentIds?: ComponentID[]): Promise<AspectDefinition[]>;
165
168
  private groupIdsByWorkspaceAndScope;
166
169
  private groupComponentsByWorkspaceAndScope;
package/dist/workspace.js CHANGED
@@ -225,16 +225,6 @@ function _extensionData() {
225
225
  return data;
226
226
  }
227
227
 
228
- function _componentsGraph() {
229
- const data = require("@teambit/legacy/dist/scope/graph/components-graph");
230
-
231
- _componentsGraph = function () {
232
- return data;
233
- };
234
-
235
- return data;
236
- }
237
-
238
228
  function _utils() {
239
229
  const data = require("@teambit/legacy/dist/utils");
240
230
 
@@ -365,6 +355,16 @@ function _incorrectEnvAspect() {
365
355
  return data;
366
356
  }
367
357
 
358
+ function _buildGraphFromFs() {
359
+ const data = require("./build-graph-from-fs");
360
+
361
+ _buildGraphFromFs = function () {
362
+ return data;
363
+ };
364
+
365
+ return data;
366
+ }
367
+
368
368
  const ComponentAdded = 'componentAdded';
369
369
  exports.ComponentAdded = ComponentAdded;
370
370
  const ComponentChanged = 'componentChanged';
@@ -640,7 +640,7 @@ class Workspace {
640
640
  async getLegacyGraph(ids) {
641
641
  if (!ids || ids.length < 1) ids = await this.listIds();
642
642
  const legacyIds = ids.map(id => id._legacy);
643
- const legacyGraph = await (0, _componentsGraph().buildOneGraphForComponents)(legacyIds, this.consumer);
643
+ const legacyGraph = await this.buildOneGraphForComponents(legacyIds);
644
644
  return legacyGraph;
645
645
  }
646
646
 
@@ -875,7 +875,9 @@ class Workspace {
875
875
 
876
876
 
877
877
  async importAndGetMany(ids, forCapsule = false) {
878
- await this.scope.import(ids);
878
+ await this.scope.import(ids, {
879
+ reFetchUnBuiltVersion: shouldReFetchUnBuiltVersion()
880
+ });
879
881
  return this.componentLoader.getMany(ids, forCapsule);
880
882
  }
881
883
  /**
@@ -901,7 +903,7 @@ class Workspace {
901
903
  const addResults = await addComponent.add(); // @todo: the legacy commands have `consumer.onDestroy()` on command completion, it writes the
902
904
  // .bitmap file. workspace needs a similar mechanism. once done, remove the next line.
903
905
 
904
- await this.consumer.bitMap.write(this.consumer.componentFsCache);
906
+ await this.writeBitMap();
905
907
  return addResults;
906
908
  }
907
909
  /**
@@ -1192,7 +1194,7 @@ class Workspace {
1192
1194
  return componentConfigFile;
1193
1195
  }
1194
1196
 
1195
- async getGraphWithoutCore(components) {
1197
+ async getAspectsGraphWithoutCore(components, isAspect) {
1196
1198
  const ids = components.map(component => component.id._legacy);
1197
1199
  const coreAspectsStringIds = this.aspectLoader.getCoreAspectIds();
1198
1200
  const coreAspectsComponentIds = coreAspectsStringIds.map(id => _legacyBitId().BitId.parse(id, true));
@@ -1216,7 +1218,7 @@ class Workspace {
1216
1218
 
1217
1219
 
1218
1220
  const ignoredIds = coreAspectsBitIds.concat([]);
1219
- return (0, _componentsGraph().buildOneGraphForComponents)(ids, this.consumer, undefined, _bitId().BitIds.fromArray(ignoredIds));
1221
+ return this.buildOneGraphForComponents(ids, _bitId().BitIds.fromArray(ignoredIds), isAspect);
1220
1222
  }
1221
1223
  /**
1222
1224
  * load aspects from the workspace and if not exists in the workspace, load from the scope.
@@ -1232,15 +1234,12 @@ class Workspace {
1232
1234
  const idsWithoutCore = (0, _lodash().difference)(notLoadedIds, coreAspectsStringIds);
1233
1235
  const componentIds = await this.resolveMultipleComponentIds(idsWithoutCore);
1234
1236
  const components = await this.importAndGetAspects(componentIds);
1235
- const graph = await this.getGraphWithoutCore(components);
1236
- const allIdsP = graph.nodes().map(async id => {
1237
- return this.resolveComponentId(id);
1238
- });
1239
- const allIds = await Promise.all(allIdsP);
1240
- const allComponents = await this.getMany(allIds);
1241
- const aspects = allComponents.filter(component => {
1237
+
1238
+ const isAspect = async bitId => {
1242
1239
  var _component$config$ext;
1243
1240
 
1241
+ const id = await this.resolveComponentId(bitId);
1242
+ const component = await this.get(id);
1244
1243
  let data = (_component$config$ext = component.config.extensions.findExtension(_envs().EnvsAspect.id)) === null || _component$config$ext === void 0 ? void 0 : _component$config$ext.data;
1245
1244
 
1246
1245
  if (!data) {
@@ -1264,14 +1263,16 @@ class Workspace {
1264
1263
  }
1265
1264
 
1266
1265
  return data.type === 'aspect';
1267
- }); // no need to filter core aspects as they are not included in the graph
1268
- // here we are trying to load extensions from the workspace.
1266
+ };
1269
1267
 
1268
+ const graph = await this.getAspectsGraphWithoutCore(components, isAspect);
1269
+ const idsStr = graph.nodes();
1270
+ const compIds = await this.resolveMultipleComponentIds(idsStr);
1271
+ const aspects = await this.getMany(compIds);
1270
1272
  const {
1271
1273
  workspaceComps,
1272
1274
  scopeComps
1273
- } = await this.groupComponentsByWorkspaceAndScope(aspects); // load the scope first because we might need it for custom envs that extend external aspects
1274
-
1275
+ } = await this.groupComponentsByWorkspaceAndScope(aspects);
1275
1276
  const scopeIds = scopeComps.map(aspect => aspect.id.toString());
1276
1277
  const workspaceAspects = await this.requireComponents(workspaceComps);
1277
1278
  const workspaceManifests = await this.aspectLoader.getManifestsFromRequireableExtensions(workspaceAspects, throwOnError);
@@ -1280,6 +1281,17 @@ class Workspace {
1280
1281
  const allManifests = [...scopeManifests, ...workspaceManifests];
1281
1282
  await this.aspectLoader.loadExtensionsByManifests(allManifests, throwOnError);
1282
1283
  }
1284
+ /**
1285
+ * Note - this gets called from Harmony only.
1286
+ * returns one graph that includes all dependencies types. each edge has a label of the dependency
1287
+ * type. the nodes content is the Component object.
1288
+ */
1289
+
1290
+
1291
+ async buildOneGraphForComponents(ids, ignoreIds, shouldIgnoreFunc) {
1292
+ const graphFromFsBuilder = new (_buildGraphFromFs().GraphFromFsBuilder)(this, this.logger, ignoreIds, shouldIgnoreFunc);
1293
+ return graphFromFsBuilder.buildGraph(ids);
1294
+ }
1283
1295
 
1284
1296
  async resolveAspects(runtimeName, componentIds) {
1285
1297
  let missingPaths = false;
@@ -1608,21 +1620,16 @@ your workspace.jsonc has this component-id set. you might want to remove/change
1608
1620
  verbose: false,
1609
1621
  merge: false,
1610
1622
  objectsOnly: true,
1611
- withEnvironments: false,
1612
1623
  override: false,
1613
1624
  writeDists: false,
1614
1625
  writeConfig: false,
1615
1626
  installNpmPackages: false,
1616
- writePackageJson: false,
1617
1627
  importDependenciesDirectly: false,
1618
1628
  importDependents: false
1619
1629
  };
1620
1630
 
1621
1631
  try {
1622
- const res = await (0, _consumer().importAction)({
1623
- tester: false,
1624
- compiler: false
1625
- }, importOptions, []);
1632
+ const res = await (0, _consumer().importAction)(importOptions, []);
1626
1633
  return res;
1627
1634
  } catch (err) {
1628
1635
  // TODO: this is a hack since the legacy throw an error, we should provide a way to not throw this error from the legacy
@@ -1808,8 +1815,23 @@ your workspace.jsonc has this component-id set. you might want to remove/change
1808
1815
  }
1809
1816
 
1810
1817
  }
1818
+ /**
1819
+ * this is a super hacky way to do it. problem is that loadAspect is running as onStart hook, where we don't
1820
+ * have the CLI fully loaded yet, so we can't get the command from the CLI aspect, we have to retrieve it from
1821
+ * process.argv.
1822
+ * in general, we don't want every command to try again and again fetching un-built versions. otherwise, every time
1823
+ * Bit loads (even bit --help), it'll fetch them and slow down everything.
1824
+ * instead, long-running commands and those that need the artifacts from the Version objects, should try to re-fetch.
1825
+ */
1826
+
1811
1827
 
1812
1828
  exports.Workspace = Workspace;
1829
+
1830
+ function shouldReFetchUnBuiltVersion() {
1831
+ const commandsToReFetch = ['build', 'show', 'start', 'tag', 'install', 'link', 'import'];
1832
+ return commandsToReFetch.includes(process.argv[2]);
1833
+ }
1834
+
1813
1835
  var _default = Workspace;
1814
1836
  exports.default = _default;
1815
1837