@teambit/workspace 0.0.555 → 0.0.556

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.
Files changed (68) hide show
  1. package/package.json +56 -50
  2. package/build-graph-from-fs.ts +0 -160
  3. package/capsule.cmd.ts +0 -136
  4. package/component-config-file/component-config-file.ts +0 -98
  5. package/component-config-file/exceptions/already-exists.ts +0 -7
  6. package/component-config-file/exceptions/index.ts +0 -1
  7. package/component-config-file/index.ts +0 -2
  8. package/component-tree.widget.tsx +0 -16
  9. package/constants.ts +0 -1
  10. package/eject-conf.cmd.tsx +0 -62
  11. package/events/index.ts +0 -3
  12. package/events/on-component-add-event.ts +0 -14
  13. package/events/on-component-change-event.ts +0 -14
  14. package/events/on-component-removed-event.ts +0 -14
  15. package/exceptions/dependency-type-not-supported-in-policy.ts +0 -7
  16. package/exceptions/incorrect-env-aspect.ts +0 -8
  17. package/exceptions/index.ts +0 -1
  18. package/index.ts +0 -19
  19. package/install.cmd.tsx +0 -67
  20. package/link/component-list-links.ts +0 -50
  21. package/link/core-aspects-links.ts +0 -50
  22. package/link/get-package-name-from-target.ts +0 -5
  23. package/link/index.ts +0 -1
  24. package/link/link-row.ts +0 -20
  25. package/link/link-to-dir.ts +0 -13
  26. package/link/link.cmd.ts +0 -96
  27. package/link/nested-deps-in-nm-links.ts +0 -47
  28. package/link/rewire-row.ts +0 -17
  29. package/list.cmd.tsx +0 -30
  30. package/on-component-events.ts +0 -14
  31. package/package-tar/teambit-workspace-0.0.555.tgz +0 -0
  32. package/tag-cmd.ts +0 -247
  33. package/tsconfig.json +0 -34
  34. package/types/asset.d.ts +0 -29
  35. package/types/style.d.ts +0 -42
  36. package/types.ts +0 -40
  37. package/ui/index.ts +0 -1
  38. package/ui/workspace/default-component.ts +0 -7
  39. package/ui/workspace/index.ts +0 -1
  40. package/ui/workspace/use-workspace.ts +0 -193
  41. package/ui/workspace/workspace-context.tsx +0 -5
  42. package/ui/workspace/workspace-model.ts +0 -66
  43. package/ui/workspace/workspace-overview/index.ts +0 -1
  44. package/ui/workspace/workspace-overview/workspace-overview.module.scss +0 -6
  45. package/ui/workspace/workspace-overview/workspace-overview.tsx +0 -21
  46. package/ui/workspace/workspace-provider.tsx +0 -23
  47. package/ui/workspace/workspace.module.scss +0 -40
  48. package/ui/workspace/workspace.tsx +0 -99
  49. package/ui/workspace-components-drawer/index.ts +0 -1
  50. package/ui/workspace-components-drawer/workspace-components-drawer.module.scss +0 -4
  51. package/ui/workspace-components-drawer/workspace-components.drawer.tsx +0 -49
  52. package/watch/REFACTOR_GUIDE.md +0 -14
  53. package/watch/check-types.ts +0 -5
  54. package/watch/output-formatter.ts +0 -50
  55. package/watch/watch.cmd.tsx +0 -142
  56. package/watch/watcher.ts +0 -289
  57. package/workspace-component/component-status.ts +0 -67
  58. package/workspace-component/index.ts +0 -2
  59. package/workspace-component/workspace-component-loader.ts +0 -276
  60. package/workspace-component/workspace-component.ts +0 -51
  61. package/workspace-section.ts +0 -14
  62. package/workspace.aspect.ts +0 -9
  63. package/workspace.graphql.ts +0 -133
  64. package/workspace.main.runtime.ts +0 -50
  65. package/workspace.provider.ts +0 -218
  66. package/workspace.ts +0 -1539
  67. package/workspace.ui-root.ts +0 -64
  68. package/workspace.ui.runtime.tsx +0 -215
package/watch/watcher.ts DELETED
@@ -1,289 +0,0 @@
1
- import { PubsubMain } from '@teambit/pubsub';
2
- import { dirname, sep } from 'path';
3
- import { difference } from 'lodash';
4
- import { ComponentID } from '@teambit/component';
5
- import { BitId } from '@teambit/legacy-bit-id';
6
- import loader from '@teambit/legacy/dist/cli/loader';
7
- import { BIT_MAP, COMPONENT_ORIGINS } from '@teambit/legacy/dist/constants';
8
- import { Consumer } from '@teambit/legacy/dist/consumer';
9
- import logger from '@teambit/legacy/dist/logger/logger';
10
- import { pathNormalizeToLinux } from '@teambit/legacy/dist/utils';
11
- import mapSeries from 'p-map-series';
12
- import chalk from 'chalk';
13
- import { ChildProcess } from 'child_process';
14
- import chokidar, { FSWatcher } from 'chokidar';
15
- import ComponentMap from '@teambit/legacy/dist/consumer/bit-map/component-map';
16
- import { PathLinux, PathOsBasedAbsolute } from '@teambit/legacy/dist/utils/path';
17
- import { CompilationInitiator } from '@teambit/compiler';
18
- import { WorkspaceAspect } from '../';
19
- import { OnComponentChangeEvent, OnComponentAddEvent, OnComponentRemovedEvent } from '../events';
20
- import { Workspace } from '../workspace';
21
- import { OnComponentEventResult } from '../on-component-events';
22
- import { CheckTypes } from './check-types';
23
-
24
- export type WatcherProcessData = { watchProcess: ChildProcess; compilerId: BitId; componentIds: BitId[] };
25
-
26
- export type WatchOptions = {
27
- msgs?: any;
28
- initiator?: CompilationInitiator;
29
- verbose?: boolean; // print watch events to the console. (also ts-server events if spawnTSServer is true)
30
- spawnTSServer?: boolean; // needed for check types and extract API/docs.
31
- checkTypes?: CheckTypes; // if enabled, the spawnTSServer becomes true.
32
- preCompile?: boolean; // whether compile all components before start watching
33
- };
34
-
35
- export class Watcher {
36
- private fsWatcher: FSWatcher;
37
- constructor(
38
- private workspace: Workspace,
39
- private pubsub: PubsubMain,
40
- private trackDirs: { [dir: PathLinux]: ComponentID } = {},
41
- private verbose = false,
42
- private multipleWatchers: WatcherProcessData[] = []
43
- ) {}
44
-
45
- get consumer(): Consumer {
46
- return this.workspace.consumer;
47
- }
48
-
49
- async watchAll(opts: WatchOptions) {
50
- const { msgs, ...watchOpts } = opts;
51
- // TODO: run build in the beginning of process (it's work like this in other envs)
52
- const pathsToWatch = await this.getPathsToWatch();
53
- const componentIds = Object.values(this.trackDirs);
54
- await this.workspace.triggerOnPreWatch(componentIds, watchOpts);
55
- await this.createWatcher(pathsToWatch);
56
- const watcher = this.fsWatcher;
57
- msgs?.onStart(this.workspace);
58
-
59
- return new Promise((resolve, reject) => {
60
- // prefix your command with "BIT_LOG=*" to see all watch events
61
- if (process.env.BIT_LOG) {
62
- if (msgs?.onAll) watcher.on('all', msgs?.onAll);
63
- }
64
- watcher.on('ready', () => {
65
- msgs?.onReady(this.workspace, this.trackDirs, this.verbose);
66
- });
67
- // eslint-disable-next-line @typescript-eslint/no-misused-promises
68
- watcher.on('change', async (filePath) => {
69
- const startTime = new Date().getTime();
70
- const buildResults = (await this.handleChange(filePath, opts?.initiator)) || [];
71
- const duration = new Date().getTime() - startTime;
72
- msgs?.onChange(filePath, buildResults, this.verbose, duration);
73
- });
74
- // eslint-disable-next-line @typescript-eslint/no-misused-promises
75
- watcher.on('add', async (filePath) => {
76
- const startTime = new Date().getTime();
77
- const buildResults = (await this.handleChange(filePath)) || [];
78
- const duration = new Date().getTime() - startTime;
79
- msgs?.onAdd(filePath, buildResults, this.verbose, duration);
80
- });
81
- // eslint-disable-next-line @typescript-eslint/no-misused-promises
82
- watcher.on('unlink', async (p) => {
83
- msgs?.onUnlink(p);
84
- await this.handleChange(p);
85
- });
86
- watcher.on('error', (err) => {
87
- msgs?.onError(err);
88
- reject(err);
89
- });
90
- });
91
- }
92
-
93
- private async handleChange(filePath: string, initiator?: CompilationInitiator): Promise<OnComponentEventResult[]> {
94
- try {
95
- if (filePath.endsWith(BIT_MAP)) {
96
- const buildResults = await this.handleBitmapChanges();
97
- this.completeWatch();
98
- return buildResults;
99
- }
100
- const componentId = await this.getComponentIdAndClearItsCache(filePath);
101
- if (!componentId) {
102
- logger.debug(`file ${filePath} is not part of any component, ignoring it`);
103
- return this.completeWatch();
104
- }
105
-
106
- const buildResults = await this.executeWatchOperationsOnComponent(componentId, [filePath], true, initiator);
107
- this.completeWatch();
108
- return buildResults;
109
- } catch (err: any) {
110
- const msg = `watcher found an error while handling ${filePath}`;
111
- logger.error(msg, err);
112
- logger.console(`${msg}, ${err.message}`);
113
- return [];
114
- }
115
- }
116
-
117
- /**
118
- * if .bitmap changed, it's possible that a new component has been added. trigger onComponentAdd.
119
- */
120
- private async handleBitmapChanges(): Promise<OnComponentEventResult[]> {
121
- const previewsTrackDirs = { ...this.trackDirs };
122
- await this.workspace._reloadConsumer();
123
- await this.setTrackDirs();
124
- const newDirs: string[] = difference(Object.keys(this.trackDirs), Object.keys(previewsTrackDirs));
125
- const removedDirs: string[] = difference(Object.keys(previewsTrackDirs), Object.keys(this.trackDirs));
126
- const results: OnComponentEventResult[] = [];
127
- if (newDirs.length) {
128
- this.fsWatcher.add(newDirs);
129
- const addResults = await mapSeries(newDirs, async (dir) =>
130
- this.executeWatchOperationsOnComponent(this.trackDirs[dir], [], false)
131
- );
132
- results.push(...addResults.flat());
133
- }
134
- if (removedDirs.length) {
135
- await this.fsWatcher.unwatch(removedDirs);
136
- await mapSeries(removedDirs, (dir) => this.executeWatchOperationsOnRemove(previewsTrackDirs[dir]));
137
- }
138
- return results;
139
- }
140
-
141
- private async executeWatchOperationsOnRemove(componentId: ComponentID) {
142
- logger.debug(`running OnComponentRemove hook for ${chalk.bold(componentId.toString())}`);
143
- this.pubsub.pub(WorkspaceAspect.id, this.creatOnComponentRemovedEvent(componentId.toString()));
144
- await this.workspace.triggerOnComponentRemove(componentId);
145
- }
146
-
147
- private async executeWatchOperationsOnComponent(
148
- componentId: ComponentID,
149
- files: string[],
150
- isChange = true,
151
- initiator?: CompilationInitiator
152
- ): Promise<OnComponentEventResult[]> {
153
- if (this.isComponentWatchedExternally(componentId)) {
154
- // update capsule, once done, it automatically triggers the external watcher
155
- await this.workspace.get(componentId);
156
- return [];
157
- }
158
- const idStr = componentId.toString();
159
-
160
- if (isChange) {
161
- logger.debug(`running OnComponentChange hook for ${chalk.bold(idStr)}`);
162
- this.pubsub.pub(WorkspaceAspect.id, this.creatOnComponentChangeEvent(idStr, 'OnComponentChange'));
163
- } else {
164
- logger.debug(`running OnComponentAdd hook for ${chalk.bold(idStr)}`);
165
- this.pubsub.pub(WorkspaceAspect.id, this.creatOnComponentAddEvent(idStr, 'OnComponentAdd'));
166
- }
167
-
168
- let buildResults: OnComponentEventResult[];
169
- try {
170
- buildResults = isChange
171
- ? await this.workspace.triggerOnComponentChange(componentId, files, initiator)
172
- : await this.workspace.triggerOnComponentAdd(componentId);
173
- } catch (err: any) {
174
- // do not exit the watch process on errors, just print them
175
- const msg = `found an issue during onComponentChange or onComponentAdd hooks`;
176
- logger.error(msg, err);
177
- logger.console(`\n${msg}: ${err.message || err}`);
178
- return [];
179
- }
180
- if (buildResults && buildResults.length) {
181
- return buildResults;
182
- }
183
- logger.console(`${idStr} doesn't have a compiler, nothing to build`);
184
- return [];
185
- }
186
-
187
- private creatOnComponentRemovedEvent(idStr) {
188
- return new OnComponentRemovedEvent(Date.now(), idStr);
189
- }
190
-
191
- private creatOnComponentChangeEvent(idStr, hook) {
192
- return new OnComponentChangeEvent(Date.now(), idStr, hook);
193
- }
194
-
195
- private creatOnComponentAddEvent(idStr, hook) {
196
- return new OnComponentAddEvent(Date.now(), idStr, hook);
197
- }
198
-
199
- private completeWatch() {
200
- loader.stop();
201
- return [];
202
- }
203
-
204
- private isComponentWatchedExternally(componentId: ComponentID) {
205
- const watcherData = this.multipleWatchers.find((m) => m.componentIds.find((id) => id.isEqual(componentId._legacy)));
206
- if (watcherData) {
207
- logger.debug(`${componentId.toString()} is watched by ${watcherData.compilerId.toString()}`);
208
- return true;
209
- }
210
- return false;
211
- }
212
-
213
- /**
214
- * if a file was added/remove, once the component is loaded, it changes .bitmap, and then the
215
- * entire cache is invalidated and the consumer is reloaded.
216
- * when a file just changed, no need to reload the consumer, it is enough to just delete the
217
- * component from the cache (both, workspace and consumer)
218
- */
219
- private async getComponentIdAndClearItsCache(filePath: string): Promise<ComponentID | null> {
220
- const relativeFile = pathNormalizeToLinux(this.consumer.getPathRelativeToConsumer(filePath));
221
- const trackDir = this.findTrackDirByFilePathRecursively(relativeFile);
222
- if (!trackDir) {
223
- // the file is not part of any component. If it was a new component, or a new file of
224
- // existing component, then, handleBitmapChanges() should deal with it.
225
- return null;
226
- }
227
- const componentId = this.trackDirs[trackDir];
228
- this.workspace.clearComponentCache(componentId);
229
- const component = await this.workspace.get(componentId);
230
- const componentMap: ComponentMap = component.state._consumer.componentMap;
231
- if (componentMap.getFilesRelativeToConsumer().find((p) => p === relativeFile)) {
232
- return componentId;
233
- }
234
- // the file is inside the component dir but it's ignored. (e.g. it's in IGNORE_LIST)
235
- return null;
236
- }
237
-
238
- private findTrackDirByFilePathRecursively(filePath: string): string | null {
239
- if (this.trackDirs[filePath]) return filePath;
240
- const parentDir = dirname(filePath);
241
- if (parentDir === filePath) return null;
242
- return this.findTrackDirByFilePathRecursively(parentDir);
243
- }
244
-
245
- private async createWatcher(pathsToWatch: string[]) {
246
- this.fsWatcher = chokidar.watch(pathsToWatch, {
247
- ignoreInitial: true,
248
- // Using the function way since the regular way not working as expected
249
- // It might be solved when upgrading to chokidar > 3.0.0
250
- // See:
251
- // https://github.com/paulmillr/chokidar/issues/773
252
- // https://github.com/paulmillr/chokidar/issues/492
253
- // https://github.com/paulmillr/chokidar/issues/724
254
- ignored: (path) => {
255
- // Ignore package.json temporarily since it cerates endless loop since it's re-written after each build
256
- if (path.includes(`${sep}node_modules${sep}`) || path.includes(`${sep}package.json`)) {
257
- return true;
258
- }
259
- return false;
260
- },
261
- persistent: true,
262
- useFsEvents: false,
263
- });
264
- }
265
-
266
- async setTrackDirs() {
267
- this.trackDirs = {};
268
- const componentsFromBitMap = this.consumer.bitMap.getAllComponents([
269
- COMPONENT_ORIGINS.AUTHORED,
270
- COMPONENT_ORIGINS.IMPORTED,
271
- ]);
272
- await Promise.all(
273
- componentsFromBitMap.map(async (componentMap) => {
274
- const bitId = componentMap.id;
275
- const trackDir = componentMap.getTrackDir();
276
- if (!trackDir) throw new Error(`${bitId.toString()} has no rootDir, which is invalid in Harmony`);
277
- const componentId = await this.workspace.resolveComponentId(bitId);
278
- this.trackDirs[trackDir] = componentId;
279
- })
280
- );
281
- }
282
-
283
- private async getPathsToWatch(): Promise<PathOsBasedAbsolute[]> {
284
- await this.setTrackDirs();
285
- const paths = [...Object.keys(this.trackDirs), BIT_MAP];
286
- const pathsAbsolute = paths.map((dir) => this.consumer.toAbsolutePath(dir));
287
- return pathsAbsolute;
288
- }
289
- }
@@ -1,67 +0,0 @@
1
- import { ComponentStatus as LegacyComponentStatus } from '@teambit/legacy/dist/consumer/component-ops/component-status-loader';
2
-
3
- export type ModifyInfo = {
4
- hasModifiedFiles: boolean;
5
- hasModifiedDependencies: boolean;
6
- };
7
-
8
- export class ComponentStatus {
9
- constructor(
10
- /**
11
- * is the component modified.
12
- */
13
- readonly modifyInfo: ModifyInfo,
14
-
15
- /**
16
- * is the new component new.
17
- */
18
- readonly isNew: boolean,
19
-
20
- /**
21
- * is the component deleted from the workspace.
22
- */
23
- readonly isDeleted: boolean,
24
-
25
- /**
26
- * is the component staged.
27
- */
28
- readonly isStaged: boolean,
29
-
30
- /**
31
- * does the component exists in the workspace.
32
- */
33
- readonly isInWorkspace: boolean,
34
-
35
- /**
36
- * does the component exists in the scope.
37
- */
38
- readonly isInScope: boolean,
39
-
40
- /**
41
- * does the component is outdated (pending for update).
42
- */
43
- readonly isOutdated: boolean,
44
-
45
- /**
46
- * the component is not authored and not imported.
47
- */
48
- readonly nested?: boolean
49
- ) {}
50
-
51
- static fromLegacy(status: LegacyComponentStatus, hasModifiedDependencies: boolean, isOutdated: boolean) {
52
- const modify: ModifyInfo = {
53
- hasModifiedFiles: !!status.modified,
54
- hasModifiedDependencies,
55
- };
56
- return new ComponentStatus(
57
- modify,
58
- !!status.newlyCreated,
59
- !!status.deleted,
60
- !!status.staged,
61
- !status.notExist,
62
- !status.missingFromScope,
63
- isOutdated,
64
- !!status.nested
65
- );
66
- }
67
- }
@@ -1,2 +0,0 @@
1
- export { WorkspaceComponent } from './workspace-component';
2
- export { ComponentStatus } from './component-status';
@@ -1,276 +0,0 @@
1
- import { Component, ComponentFS, ComponentID, Config, InvalidComponent, State, TagMap } from '@teambit/component';
2
- import { BitId } from '@teambit/legacy-bit-id';
3
- import { ExtensionDataList } from '@teambit/legacy/dist/consumer/config/extension-data';
4
- import mapSeries from 'p-map-series';
5
- import { compact } from 'lodash';
6
- import ConsumerComponent from '@teambit/legacy/dist/consumer/component';
7
- import { MissingBitMapComponent } from '@teambit/legacy/dist/consumer/bit-map/exceptions';
8
- import { getLatestVersionNumber } from '@teambit/legacy/dist/utils';
9
- import { IssuesClasses } from '@teambit/component-issues';
10
- import { ComponentNotFound } from '@teambit/legacy/dist/scope/exceptions';
11
- import { DependencyResolverAspect, DependencyResolverMain } from '@teambit/dependency-resolver';
12
- import { Logger } from '@teambit/logger';
13
- import { EnvsAspect, EnvsMain } from '@teambit/envs';
14
- import { ExtensionDataEntry } from '@teambit/legacy/dist/consumer/config';
15
- import { getMaxSizeForComponents, InMemoryCache } from '@teambit/legacy/dist/cache/in-memory-cache';
16
- import { createInMemoryCache } from '@teambit/legacy/dist/cache/cache-factory';
17
- import ComponentNotFoundInPath from '@teambit/legacy/dist/consumer/component/exceptions/component-not-found-in-path';
18
- import { Workspace } from '../workspace';
19
- import { WorkspaceComponent } from './workspace-component';
20
-
21
- export class WorkspaceComponentLoader {
22
- private componentsCache: InMemoryCache<Component>; // cache loaded components
23
- private componentsCacheForCapsule: InMemoryCache<Component>; // cache loaded components for capsule, must not use the cache for the workspace
24
- constructor(
25
- private workspace: Workspace,
26
- private logger: Logger,
27
- private dependencyResolver: DependencyResolverMain,
28
- private envs: EnvsMain
29
- ) {
30
- this.componentsCache = createInMemoryCache({ maxSize: getMaxSizeForComponents() });
31
- this.componentsCacheForCapsule = createInMemoryCache({ maxSize: getMaxSizeForComponents() });
32
- }
33
-
34
- async getMany(ids: Array<ComponentID>, forCapsule = false): Promise<Component[]> {
35
- const idsWithoutEmpty = compact(ids);
36
- const errors: { id: ComponentID; err: Error }[] = [];
37
- const longProcessLogger = this.logger.createLongProcessLogger('loading components', ids.length);
38
- const componentsP = mapSeries(idsWithoutEmpty, async (id: ComponentID) => {
39
- longProcessLogger.logProgress(id.toString());
40
- return this.get(id, forCapsule).catch((err) => {
41
- if (this.isComponentNotExistsError(err)) {
42
- errors.push({
43
- id,
44
- err,
45
- });
46
- return undefined;
47
- }
48
- throw err;
49
- });
50
- });
51
- const components = await componentsP;
52
- errors.forEach((err) => {
53
- if (!this.workspace.consumer.isLegacy) {
54
- this.logger.console(`failed loading component ${err.id.toString()}, see full error in debug.log file`);
55
- }
56
- this.logger.warn(`failed loading component ${err.id.toString()}`, err.err);
57
- });
58
- // remove errored components
59
- const filteredComponents: Component[] = compact(components);
60
- longProcessLogger.end();
61
- return filteredComponents;
62
- }
63
-
64
- async getInvalid(ids: Array<ComponentID>): Promise<InvalidComponent[]> {
65
- const idsWithoutEmpty = compact(ids);
66
- const errors: InvalidComponent[] = [];
67
- const longProcessLogger = this.logger.createLongProcessLogger('loading components', ids.length);
68
- await mapSeries(idsWithoutEmpty, async (id: ComponentID) => {
69
- longProcessLogger.logProgress(id.toString());
70
- try {
71
- await this.workspace.consumer.loadComponent(id._legacy);
72
- } catch (err: any) {
73
- if (ConsumerComponent.isComponentInvalidByErrorType(err)) {
74
- errors.push({
75
- id,
76
- err,
77
- });
78
- return;
79
- }
80
- throw err;
81
- }
82
- });
83
- return errors;
84
- }
85
-
86
- async get(
87
- componentId: ComponentID,
88
- forCapsule = false,
89
- legacyComponent?: ConsumerComponent,
90
- useCache = true,
91
- storeInCache = true
92
- ): Promise<Component> {
93
- const bitIdWithVersion: BitId = getLatestVersionNumber(
94
- this.workspace.consumer.bitmapIdsFromCurrentLane,
95
- componentId._legacy
96
- );
97
- const id = bitIdWithVersion.version ? componentId.changeVersion(bitIdWithVersion.version) : componentId;
98
- const fromCache = this.getFromCache(id, forCapsule);
99
- if (fromCache && useCache) {
100
- return fromCache;
101
- }
102
- const consumerComponent = legacyComponent || (await this.getConsumerComponent(id, forCapsule));
103
- // in case of out-of-sync, the id may changed during the load process
104
- const updatedId = consumerComponent ? ComponentID.fromLegacy(consumerComponent.id, id.scope) : id;
105
- const component = await this.loadOne(updatedId, consumerComponent);
106
- if (storeInCache) {
107
- this.addMultipleEnvsIssueIfNeeded(component); // it's in storeInCache block, otherwise, it wasn't fully loaded
108
- this.saveInCache(component, forCapsule);
109
- }
110
- return component;
111
- }
112
-
113
- private addMultipleEnvsIssueIfNeeded(component: Component) {
114
- const envs = this.envs.getAllEnvsConfiguredOnComponent(component);
115
- if (envs.length < 2) {
116
- return;
117
- }
118
- component.state.issues.getOrCreate(IssuesClasses.MultipleEnvs).data = envs.map((e) => e.id);
119
- }
120
-
121
- clearCache() {
122
- this.componentsCache.deleteAll();
123
- this.componentsCacheForCapsule.deleteAll();
124
- }
125
- clearComponentCache(id: ComponentID) {
126
- const idStr = id.toString();
127
- this.componentsCache.delete(idStr);
128
- this.componentsCacheForCapsule.delete(idStr);
129
- }
130
-
131
- private async loadOne(id: ComponentID, consumerComponent?: ConsumerComponent) {
132
- const componentFromScope = await this.workspace.scope.get(id);
133
- if (!consumerComponent) {
134
- if (!componentFromScope) throw new MissingBitMapComponent(id.toString());
135
- return componentFromScope;
136
- }
137
-
138
- let extensionDataList = await this.workspace.componentExtensions(id, componentFromScope);
139
- const extensionsFromConsumerComponent = consumerComponent.extensions || new ExtensionDataList();
140
- // Merge extensions added by the legacy code in memory (for example data of dependency resolver)
141
- extensionDataList = ExtensionDataList.mergeConfigs([
142
- extensionsFromConsumerComponent,
143
- extensionDataList,
144
- ]).filterRemovedExtensions();
145
-
146
- // temporarily mutate consumer component extensions until we remove all direct access from legacy to extensions data
147
- // TODO: remove this once we remove all direct access from legacy code to extensions data
148
- consumerComponent.extensions = extensionDataList;
149
-
150
- const state = new State(
151
- new Config(consumerComponent.mainFile, extensionDataList),
152
- await this.workspace.createAspectList(extensionDataList),
153
- ComponentFS.fromVinyls(consumerComponent.files),
154
- consumerComponent.dependencies,
155
- consumerComponent
156
- );
157
- if (componentFromScope) {
158
- // Removed by @gilad. do not mutate the component from the scope
159
- // componentFromScope.state = state;
160
- // const workspaceComponent = WorkspaceComponent.fromComponent(componentFromScope, this.workspace);
161
- const workspaceComponent = new WorkspaceComponent(
162
- componentFromScope.id,
163
- componentFromScope.head,
164
- state,
165
- componentFromScope.tags,
166
- this.workspace
167
- );
168
- return this.executeLoadSlot(workspaceComponent);
169
- }
170
- return this.executeLoadSlot(this.newComponentFromState(id, state));
171
- }
172
-
173
- private saveInCache(component: Component, forCapsule: boolean): void {
174
- if (forCapsule) {
175
- this.componentsCacheForCapsule.set(component.id.toString(), component);
176
- } else {
177
- this.componentsCache.set(component.id.toString(), component);
178
- }
179
- }
180
-
181
- /**
182
- * make sure that not only the id-str match, but also the legacy-id.
183
- * this is needed because the ComponentID.toString() is the same whether or not the legacy-id has
184
- * scope-name, as it includes the defaultScope if the scope is empty.
185
- * as a result, when out-of-sync is happening and the id is changed to include scope-name in the
186
- * legacy-id, the component is the cache has the old id.
187
- */
188
- private getFromCache(id: ComponentID, forCapsule: boolean): Component | undefined {
189
- const fromCache = forCapsule
190
- ? this.componentsCacheForCapsule.get(id.toString())
191
- : this.componentsCache.get(id.toString());
192
- if (fromCache && fromCache.id._legacy.isEqual(id._legacy)) {
193
- return fromCache;
194
- }
195
- return undefined;
196
- }
197
-
198
- private async getConsumerComponent(id: ComponentID, forCapsule = false): Promise<ConsumerComponent | undefined> {
199
- try {
200
- return forCapsule
201
- ? // eslint-disable-next-line @typescript-eslint/return-await
202
- await this.workspace.consumer.loadComponentForCapsule(id._legacy)
203
- : // eslint-disable-next-line @typescript-eslint/return-await
204
- await this.workspace.consumer.loadComponent(id._legacy);
205
- } catch (err: any) {
206
- // don't return undefined for any error. otherwise, if the component is invalid (e.g. main
207
- // file is missing) it returns the model component later unexpectedly, or if it's new, it
208
- // shows MissingBitMapComponent error incorrectly.
209
- if (this.isComponentNotExistsError(err)) {
210
- this.logger.debug(
211
- `failed loading component "${id.toString()}" from the workspace due to "${err.name}" error\n${err.message}`
212
- );
213
- return undefined;
214
- }
215
- throw err;
216
- }
217
- }
218
-
219
- private isComponentNotExistsError(err: Error): boolean {
220
- return (
221
- err instanceof ComponentNotFound ||
222
- err instanceof MissingBitMapComponent ||
223
- err instanceof ComponentNotFoundInPath
224
- );
225
- }
226
-
227
- private async executeLoadSlot(component: Component) {
228
- const entries = this.workspace.onComponentLoadSlot.toArray();
229
- const promises = entries.map(async ([extension, onLoad]) => {
230
- const data = await onLoad(component);
231
- return this.upsertExtensionData(component, extension, data);
232
- });
233
-
234
- // Special load events which runs from the workspace but should run from the correct aspect
235
- // TODO: remove this once those extensions dependent on workspace
236
- const envsData = await this.workspace.getEnvSystemDescriptor(component);
237
-
238
- // Move to deps resolver main runtime once we switch ws<> deps resolver direction
239
- const policy = await this.dependencyResolver.mergeVariantPolicies(component.config.extensions);
240
- const dependencies = await this.dependencyResolver.extractDepsFromLegacy(component, policy);
241
-
242
- const depResolverData = {
243
- dependencies,
244
- policy: policy.serialize(),
245
- };
246
-
247
- promises.push(this.upsertExtensionData(component, EnvsAspect.id, envsData));
248
- promises.push(this.upsertExtensionData(component, DependencyResolverAspect.id, depResolverData));
249
-
250
- await Promise.all(promises);
251
-
252
- // Update the aspect list to have changes happened during the on load slot (new data added above)
253
- const updatedAspectList = await this.workspace.createAspectList(component.state.config.extensions);
254
- component.state.aspects = updatedAspectList;
255
- return component;
256
- }
257
-
258
- private newComponentFromState(id: ComponentID, state: State): Component {
259
- return new WorkspaceComponent(id, null, state, new TagMap(), this.workspace);
260
- }
261
-
262
- private async upsertExtensionData(component: Component, extension: string, data: any) {
263
- const existingExtension = component.state.config.extensions.findExtension(extension);
264
- if (existingExtension) {
265
- // Only merge top level of extension data
266
- Object.assign(existingExtension.data, data);
267
- return;
268
- }
269
- component.state.config.extensions.push(await this.getDataEntry(extension, data));
270
- }
271
-
272
- private async getDataEntry(extension: string, data: { [key: string]: any }): Promise<ExtensionDataEntry> {
273
- // TODO: @gilad we need to refactor the extension data entry api.
274
- return new ExtensionDataEntry(undefined, undefined, extension, undefined, data);
275
- }
276
- }
@@ -1,51 +0,0 @@
1
- import { Component, ComponentID, Snap, State, TagMap } from '@teambit/component';
2
- import { IssuesList } from '@teambit/component-issues';
3
- import { Workspace } from '../workspace';
4
- import { ComponentStatus } from './component-status';
5
-
6
- // TODO: refactor this to a composition rather than to use inheritance
7
- export class WorkspaceComponent extends Component {
8
- constructor(
9
- /**
10
- * component ID represented by the `ComponentId` type.
11
- */
12
- readonly id: ComponentID,
13
-
14
- /**
15
- * head version of the component. can be `null` for new components.
16
- */
17
- readonly head: Snap | null = null,
18
-
19
- /**
20
- * state of the component.
21
- */
22
- workspaceState: State,
23
-
24
- /**
25
- * tags of the component.
26
- */
27
- readonly tags: TagMap = new TagMap(),
28
-
29
- /**
30
- * workspace extension.
31
- */
32
- readonly workspace: Workspace
33
- ) {
34
- super(id, head, workspaceState, tags, workspace);
35
- }
36
-
37
- async getStatus(): Promise<ComponentStatus> {
38
- return this.workspace.getComponentStatus(this);
39
- }
40
-
41
- /**
42
- * get all issues reported on the component.
43
- */
44
- getIssues(): IssuesList | null {
45
- return this.workspace.getComponentIssues(this);
46
- }
47
-
48
- static fromComponent(component: Component, workspace: Workspace) {
49
- return new WorkspaceComponent(component.id, component.head, component.state, component.tags, workspace);
50
- }
51
- }