@teambit/aspect-loader 0.0.554 → 0.0.558

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.
@@ -6,12 +6,47 @@ export declare type AspectDefinitionProps = {
6
6
  runtimePath: string | null;
7
7
  };
8
8
  export declare class AspectDefinition {
9
+ /**
10
+ * path the the root directory of the aspect module.
11
+ */
9
12
  readonly aspectPath: string;
13
+ /**
14
+ * path to the runtime entry
15
+ */
10
16
  readonly runtimePath: string | null;
17
+ /**
18
+ * aspect component
19
+ */
11
20
  readonly component?: Component | undefined;
21
+ /**
22
+ * id of the component (used instead of component in the case of core aspect)
23
+ */
12
24
  readonly id?: string | undefined;
25
+ /**
26
+ * aspect defined using 'file://' protocol
27
+ */
13
28
  readonly local?: boolean | undefined;
14
- constructor(aspectPath: string, runtimePath: string | null, component?: Component | undefined, id?: string | undefined, local?: boolean | undefined);
29
+ constructor(
30
+ /**
31
+ * path the the root directory of the aspect module.
32
+ */
33
+ aspectPath: string,
34
+ /**
35
+ * path to the runtime entry
36
+ */
37
+ runtimePath: string | null,
38
+ /**
39
+ * aspect component
40
+ */
41
+ component?: Component | undefined,
42
+ /**
43
+ * id of the component (used instead of component in the case of core aspect)
44
+ */
45
+ id?: string | undefined,
46
+ /**
47
+ * aspect defined using 'file://' protocol
48
+ */
49
+ local?: boolean | undefined);
15
50
  get getId(): string | null;
16
51
  static from({ component, aspectPath, runtimePath, id }: AspectDefinitionProps): AspectDefinition;
17
52
  }
@@ -9,7 +9,13 @@ import { PluginDefinition } from './plugin-definition';
9
9
  import { Plugins } from './plugins';
10
10
  export declare type PluginDefinitionSlot = SlotRegistry<PluginDefinition[]>;
11
11
  export declare type AspectDescriptor = {
12
+ /**
13
+ * name of the extension.
14
+ */
12
15
  id: string;
16
+ /**
17
+ * icon of the extension.
18
+ */
13
19
  icon?: string;
14
20
  };
15
21
  export declare type AspectResolver = (component: Component) => Promise<ResolvedAspect>;
@@ -20,13 +26,34 @@ export declare type ResolvedAspect = {
20
26
  declare type OnAspectLoadError = (err: Error, id: ComponentID) => Promise<boolean>;
21
27
  export declare type OnAspectLoadErrorSlot = SlotRegistry<OnAspectLoadError>;
22
28
  export declare type OnLoadRequireableExtension = (requireableExtension: RequireableComponent, manifest: ExtensionManifest | Aspect) => Promise<ExtensionManifest | Aspect>;
29
+ /**
30
+ * A slot which run during loading the requirable extension (after first manifest calculation)
31
+ */
23
32
  export declare type OnLoadRequireableExtensionSlot = SlotRegistry<OnLoadRequireableExtension>;
24
33
  export declare type MainAspect = {
34
+ /**
35
+ * path to the main aspect.
36
+ */
25
37
  path: string;
38
+ /**
39
+ * version of the aspect.
40
+ */
26
41
  version: string | undefined;
42
+ /**
43
+ * package name of the aspect
44
+ */
27
45
  packageName: string | undefined;
46
+ /**
47
+ * reference to aspect manifest.
48
+ */
28
49
  aspect: Aspect;
50
+ /**
51
+ * The name of the aspect (without the scope prefix)
52
+ */
29
53
  name: string;
54
+ /**
55
+ * The name of the aspect
56
+ */
30
57
  id: string;
31
58
  };
32
59
  export declare class AspectLoaderMain {
@@ -40,6 +67,9 @@ export declare class AspectLoaderMain {
40
67
  private getCompiler;
41
68
  registerOnAspectLoadErrorSlot(onAspectLoadError: OnAspectLoadError): void;
42
69
  registerOnLoadRequireableExtensionSlot(onLoadRequireableExtension: OnLoadRequireableExtension): void;
70
+ /**
71
+ * returns whether the aspect-load issue has been fixed.
72
+ */
43
73
  triggerOnAspectLoadError(err: Error, component: Component): Promise<boolean>;
44
74
  getRuntimePath(component: Component, modulePath: string, runtime: string): Promise<string | null>;
45
75
  isAspectLoaded(id: string): unknown;
@@ -61,7 +91,30 @@ export declare class AspectLoaderMain {
61
91
  private failedLoadAspect;
62
92
  get failedAspects(): string[];
63
93
  private addFailure;
94
+ /**
95
+ * run "require" of the component code to get the manifest
96
+ */
64
97
  doRequire(requireableExtension: RequireableComponent): Promise<ExtensionManifest | Aspect>;
98
+ /**
99
+ * in case the extension failed to load, prefer to throw an error, unless `throwOnError` param
100
+ * passed as `false`.
101
+ * there are cases when throwing an error blocks the user from doing anything else. for example,
102
+ * when a user develops an extension and deletes the node-modules, the extension on the workspace
103
+ * cannot be loaded anymore until "bit compile" is running. however, if this function throws an
104
+ * error, it'll throw for "bit compile" as well, which blocks the user.
105
+ * for the CI, it is important to throw an error because errors on console can be ignored.
106
+ * for now, when loading the extension from the workspace the throwOnError is passed as false.
107
+ * when loading from the scope (CI) it should be true.
108
+ *
109
+ * the console printing here is done directly by "console.error" and not by the logger. the reason
110
+ * is that the logger.console only prints when the loader started (which, btw, happens after
111
+ * entering this function, so it can't work) and here we want it to be printed regardless of the
112
+ * rules of starting the loader. e.g. if by mistake the CI got it as throwOnError=false, it's ok
113
+ * to break the output by the console.error.
114
+ *
115
+ * @todo: this is not the final word however about throwing/non throwing errors here.
116
+ * in some cases, such as "bit tag", it's better not to tag if an extension changes the model.
117
+ */
65
118
  loadRequireableExtensions(requireableExtensions: RequireableComponent[], throwOnError?: boolean): Promise<void>;
66
119
  getManifestsFromRequireableExtensions(requireableExtensions: RequireableComponent[], throwOnError?: boolean): Promise<Array<ExtensionManifest | Aspect>>;
67
120
  handleExtensionLoadingError(error: Error, idStr: string, throwOnError: boolean): void;
@@ -70,8 +123,15 @@ export declare class AspectLoaderMain {
70
123
  getPlugins(component: Component, componentPath: string): Plugins;
71
124
  isAspect(manifest: any): boolean;
72
125
  isAspectComponent(component: Component): boolean;
126
+ /**
127
+ * get or create a global scope, import the non-core aspects, load bit from that scope, create
128
+ * capsules for the aspects and load them from the capsules.
129
+ */
73
130
  loadAspectsFromGlobalScope(aspectIds: string[]): Promise<Component[]>;
74
131
  private prepareManifests;
132
+ /**
133
+ * register a plugin.
134
+ */
75
135
  registerPlugins(pluginDefs: PluginDefinition[]): this;
76
136
  loadExtensionsByManifests(extensionsManifests: Array<ExtensionManifest | Aspect>, throwOnError?: boolean): Promise<void>;
77
137
  static runtime: import("@teambit/harmony").RuntimeDefinition;
@@ -1,5 +1,14 @@
1
1
  export interface PluginDefinition {
2
+ /**
3
+ * regex pattern for detecting the definition file within a component.
4
+ */
2
5
  pattern: string | RegExp;
6
+ /**
7
+ * runtimes for the plugin to apply.
8
+ */
3
9
  runtimes: string[];
10
+ /**
11
+ * register the plugin to its slot registry.
12
+ */
4
13
  register<T>(object: T): void;
5
14
  }
package/dist/plugin.d.ts CHANGED
@@ -4,6 +4,9 @@ export declare class Plugin {
4
4
  readonly path: string;
5
5
  constructor(def: PluginDefinition, path: string);
6
6
  private _instance;
7
+ /**
8
+ * determines whether the plugin supports a certain runtime.
9
+ */
7
10
  supportsRuntime(runtime: string): boolean;
8
11
  register(): void;
9
12
  require(): unknown;
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@teambit/aspect-loader",
3
- "version": "0.0.554",
3
+ "version": "0.0.558",
4
4
  "homepage": "https://bit.dev/teambit/harmony/aspect-loader",
5
5
  "main": "dist/index.js",
6
6
  "componentId": {
7
7
  "scope": "teambit.harmony",
8
8
  "name": "aspect-loader",
9
- "version": "0.0.554"
9
+ "version": "0.0.558"
10
10
  },
11
11
  "dependencies": {
12
12
  "@teambit/harmony": "0.2.11",
@@ -15,15 +15,15 @@
15
15
  "fs-extra": "10.0.0",
16
16
  "@babel/runtime": "7.12.18",
17
17
  "core-js": "^3.0.0",
18
- "@teambit/component": "0.0.554",
19
- "@teambit/bit": "0.0.556",
20
- "@teambit/cli": "0.0.385",
21
- "@teambit/envs": "0.0.554",
22
- "@teambit/harmony.modules.requireable-component": "0.0.460",
23
- "@teambit/legacy-bit-id": "0.0.374",
24
- "@teambit/logger": "0.0.470",
25
- "@teambit/scope": "0.0.554",
26
- "@teambit/bit-error": "0.0.371"
18
+ "@teambit/component": "0.0.558",
19
+ "@teambit/bit": "0.0.560",
20
+ "@teambit/cli": "0.0.388",
21
+ "@teambit/envs": "0.0.558",
22
+ "@teambit/harmony.modules.requireable-component": "0.0.463",
23
+ "@teambit/legacy-bit-id": "0.0.377",
24
+ "@teambit/logger": "0.0.473",
25
+ "@teambit/scope": "0.0.558",
26
+ "@teambit/bit-error": "0.0.374"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/lodash": "4.14.165",
@@ -36,7 +36,7 @@
36
36
  "@types/node": "12.20.4"
37
37
  },
38
38
  "peerDependencies": {
39
- "@teambit/legacy": "1.0.171",
39
+ "@teambit/legacy": "1.0.174",
40
40
  "react-dom": "^16.8.0 || ^17.0.0",
41
41
  "react": "^16.8.0 || ^17.0.0"
42
42
  },
@@ -64,12 +64,20 @@
64
64
  "react": "-"
65
65
  },
66
66
  "peerDependencies": {
67
- "@teambit/legacy": "1.0.171",
67
+ "@teambit/legacy": "1.0.174",
68
68
  "react-dom": "^16.8.0 || ^17.0.0",
69
69
  "react": "^16.8.0 || ^17.0.0"
70
70
  }
71
71
  }
72
72
  },
73
+ "files": [
74
+ "dist",
75
+ "!dist/tsconfig.tsbuildinfo",
76
+ "README.md",
77
+ "README.mdx",
78
+ "*.js",
79
+ "*.json"
80
+ ],
73
81
  "private": false,
74
82
  "engines": {
75
83
  "node": ">=12.22.0"
package/tsconfig.json CHANGED
@@ -15,9 +15,9 @@
15
15
  "skipLibCheck": true,
16
16
  "moduleResolution": "node",
17
17
  "esModuleInterop": true,
18
- "outDir": "dist",
19
18
  "composite": true,
20
19
  "emitDeclarationOnly": true,
20
+ "outDir": "dist",
21
21
  "experimentalDecorators": true,
22
22
  "emitDecoratorMetadata": true,
23
23
  "allowSyntheticDefaultImports": true,
@@ -25,7 +25,6 @@
25
25
  "strict": true,
26
26
  "noImplicitAny": false,
27
27
  "rootDir": ".",
28
- "removeComments": true,
29
28
  "preserveConstEnums": true,
30
29
  "resolveJsonModule": true
31
30
  },
@@ -1,44 +0,0 @@
1
- import { Component } from '@teambit/component';
2
-
3
- export type AspectDefinitionProps = {
4
- id?: string;
5
- component?: Component;
6
- aspectPath: string;
7
- runtimePath: string | null;
8
- };
9
-
10
- export class AspectDefinition {
11
- constructor(
12
- /**
13
- * path the the root directory of the aspect module.
14
- */
15
- readonly aspectPath: string,
16
-
17
- /**
18
- * path to the runtime entry
19
- */
20
- readonly runtimePath: string | null,
21
- /**
22
- * aspect component
23
- */
24
- readonly component?: Component,
25
- /**
26
- * id of the component (used instead of component in the case of core aspect)
27
- */
28
- readonly id?: string,
29
- /**
30
- * aspect defined using 'file://' protocol
31
- */
32
- readonly local?: boolean
33
- ) {}
34
-
35
- get getId() {
36
- if (this.id) return this.id;
37
- if (this.component) return this.component.id.toString();
38
- return null;
39
- }
40
-
41
- static from({ component, aspectPath, runtimePath, id }: AspectDefinitionProps) {
42
- return new AspectDefinition(aspectPath, runtimePath, component, id);
43
- }
44
- }
@@ -1,8 +0,0 @@
1
- import { Aspect } from '@teambit/harmony';
2
-
3
- export const AspectLoaderAspect = Aspect.create({
4
- id: 'teambit.harmony/aspect-loader',
5
- dependencies: [],
6
- });
7
-
8
- export default AspectLoaderAspect;
@@ -1,490 +0,0 @@
1
- import { join } from 'path';
2
- import { BitId } from '@teambit/legacy-bit-id';
3
- import LegacyScope from '@teambit/legacy/dist/scope/scope';
4
- import { GLOBAL_SCOPE } from '@teambit/legacy/dist/constants';
5
- import { MainRuntime } from '@teambit/cli';
6
- import { ExtensionManifest, Harmony, Aspect, SlotRegistry, Slot } from '@teambit/harmony';
7
- import type { LoggerMain } from '@teambit/logger';
8
- import { ComponentID, Component } from '@teambit/component';
9
- import { Logger, LoggerAspect } from '@teambit/logger';
10
- import { RequireableComponent } from '@teambit/harmony.modules.requireable-component';
11
- import { EnvsAspect, EnvsMain } from '@teambit/envs';
12
- import { loadBit } from '@teambit/bit';
13
- import { ScopeAspect, ScopeMain } from '@teambit/scope';
14
- import mapSeries from 'p-map-series';
15
- import { difference, compact, flatten } from 'lodash';
16
- import { AspectDefinition, AspectDefinitionProps } from './aspect-definition';
17
- import { PluginDefinition } from './plugin-definition';
18
- import { AspectLoaderAspect } from './aspect-loader.aspect';
19
- import { UNABLE_TO_LOAD_EXTENSION, UNABLE_TO_LOAD_EXTENSION_FROM_LIST } from './constants';
20
- import { CannotLoadExtension } from './exceptions';
21
- import { getAspectDef } from './core-aspects';
22
- import { Plugins } from './plugins';
23
-
24
- export type PluginDefinitionSlot = SlotRegistry<PluginDefinition[]>;
25
-
26
- export type AspectDescriptor = {
27
- /**
28
- * name of the extension.
29
- */
30
- id: string;
31
-
32
- /**
33
- * icon of the extension.
34
- */
35
- icon?: string;
36
- };
37
-
38
- export type AspectResolver = (component: Component) => Promise<ResolvedAspect>;
39
-
40
- export type ResolvedAspect = {
41
- aspectPath: string;
42
- runtimePath: string | null;
43
- };
44
-
45
- type OnAspectLoadError = (err: Error, id: ComponentID) => Promise<boolean>;
46
- export type OnAspectLoadErrorSlot = SlotRegistry<OnAspectLoadError>;
47
-
48
- export type OnLoadRequireableExtension = (
49
- requireableExtension: RequireableComponent,
50
- manifest: ExtensionManifest | Aspect
51
- ) => Promise<ExtensionManifest | Aspect>;
52
- /**
53
- * A slot which run during loading the requirable extension (after first manifest calculation)
54
- */
55
- export type OnLoadRequireableExtensionSlot = SlotRegistry<OnLoadRequireableExtension>;
56
-
57
- export type MainAspect = {
58
- /**
59
- * path to the main aspect.
60
- */
61
- path: string;
62
-
63
- /**
64
- * version of the aspect.
65
- */
66
- version: string | undefined;
67
-
68
- /**
69
- * package name of the aspect
70
- */
71
- packageName: string | undefined;
72
-
73
- /**
74
- * reference to aspect manifest.
75
- */
76
- aspect: Aspect;
77
-
78
- /**
79
- * The name of the aspect (without the scope prefix)
80
- */
81
- name: string;
82
-
83
- /**
84
- * The name of the aspect
85
- */
86
- id: string;
87
- };
88
-
89
- export class AspectLoaderMain {
90
- constructor(
91
- private logger: Logger,
92
- private envs: EnvsMain,
93
- private harmony: Harmony,
94
- private onAspectLoadErrorSlot: OnAspectLoadErrorSlot,
95
- private onLoadRequireableExtensionSlot: OnLoadRequireableExtensionSlot,
96
- private pluginSlot: PluginDefinitionSlot
97
- ) {}
98
-
99
- private getCompiler(component: Component) {
100
- const env = this.envs.getEnv(component)?.env;
101
- return env?.getCompiler();
102
- }
103
-
104
- registerOnAspectLoadErrorSlot(onAspectLoadError: OnAspectLoadError) {
105
- this.onAspectLoadErrorSlot.register(onAspectLoadError);
106
- }
107
-
108
- registerOnLoadRequireableExtensionSlot(onLoadRequireableExtension: OnLoadRequireableExtension) {
109
- this.onLoadRequireableExtensionSlot.register(onLoadRequireableExtension);
110
- }
111
-
112
- /**
113
- * returns whether the aspect-load issue has been fixed.
114
- */
115
- async triggerOnAspectLoadError(err: Error, component: Component): Promise<boolean> {
116
- const entries = this.onAspectLoadErrorSlot.toArray(); // e.g. [ [ 'teambit.bit/compiler', [Function: bound onAspectLoadError] ] ]
117
- let isFixed = false;
118
- await mapSeries(entries, async ([, onAspectFailFunc]) => {
119
- const result = await onAspectFailFunc(err, component.id);
120
- if (result) isFixed = true;
121
- });
122
-
123
- return isFixed;
124
- }
125
-
126
- async getRuntimePath(component: Component, modulePath: string, runtime: string): Promise<string | null> {
127
- const runtimeFile = component.filesystem.files.find((file: any) => {
128
- return file.relative.includes(`.${runtime}.runtime`);
129
- });
130
-
131
- // @david we should add a compiler api for this.
132
- if (!runtimeFile) return null;
133
-
134
- const compiler = this.getCompiler(component);
135
-
136
- if (!compiler) {
137
- return join(modulePath, runtimeFile.relative);
138
- }
139
-
140
- const dist = compiler.getDistPathBySrcPath(runtimeFile.relative);
141
- return join(modulePath, dist);
142
- }
143
-
144
- isAspectLoaded(id: string) {
145
- if (this.failedAspects.includes(id)) return true;
146
- try {
147
- return this.harmony.get(id);
148
- } catch (err: any) {
149
- return false;
150
- }
151
- }
152
-
153
- getDescriptor(id: string): AspectDescriptor {
154
- const instance = this.harmony.get<any>(id);
155
- const iconFn = instance.icon;
156
-
157
- const icon = iconFn ? iconFn.apply(instance) : undefined;
158
-
159
- return {
160
- id,
161
- icon,
162
- };
163
- }
164
-
165
- getNotLoadedConfiguredExtensions() {
166
- const configuredAspects = Array.from(this.harmony.config.raw.keys());
167
- const loadedExtensions = this.harmony.extensionsIds;
168
- const extensionsToLoad = difference(configuredAspects, loadedExtensions);
169
- return extensionsToLoad;
170
- }
171
-
172
- loadDefinition(props: AspectDefinitionProps): AspectDefinition {
173
- return AspectDefinition.from(props);
174
- }
175
-
176
- private _coreAspects: Aspect[] = [];
177
-
178
- get coreAspects() {
179
- return this._coreAspects;
180
- }
181
-
182
- isCoreAspect(id: string) {
183
- const ids = this.getCoreAspectIds();
184
- return ids.includes(id);
185
- }
186
-
187
- setCoreAspects(aspects: Aspect[]) {
188
- this._coreAspects = aspects;
189
- return this;
190
- }
191
-
192
- getCoreAspectIds() {
193
- const ids = this.coreAspects.map((aspect) => aspect.id);
194
- return ids.concat(this._reserved);
195
- }
196
-
197
- private _reserved = ['teambit.harmony/bit', 'teambit.harmony/config'];
198
-
199
- getUserAspects(): string[] {
200
- const coreAspectIds = this.getCoreAspectIds();
201
- return difference(this.harmony.extensionsIds, coreAspectIds);
202
- }
203
-
204
- async getCoreAspectDefs(runtimeName?: string) {
205
- const defs = await Promise.all(
206
- this.coreAspects.map(async (aspect) => {
207
- const id = aspect.id;
208
- const rawDef = await getAspectDef(id, runtimeName);
209
- return this.loadDefinition(rawDef);
210
- })
211
- );
212
-
213
- return defs.filter((def) => def.runtimePath);
214
- }
215
-
216
- async resolveAspects(components: Component[], resolver: AspectResolver): Promise<AspectDefinition[]> {
217
- const promises = components.map(async (component) => {
218
- const resolvedAspect = await resolver(component);
219
- return new AspectDefinition(resolvedAspect.aspectPath, resolvedAspect.runtimePath, component);
220
- });
221
-
222
- const aspectDefs = await Promise.all(promises);
223
- // return aspectDefs.filter((def) => def.runtimePath);
224
- return aspectDefs;
225
- }
226
-
227
- private _mainAspect: MainAspect;
228
-
229
- get mainAspect() {
230
- return this._mainAspect;
231
- }
232
-
233
- setMainAspect(mainAspect: MainAspect) {
234
- this._mainAspect = mainAspect;
235
- return this;
236
- }
237
-
238
- private failedLoadAspect: string[] = [];
239
-
240
- get failedAspects() {
241
- return this.failedLoadAspect;
242
- }
243
-
244
- private addFailure(id: string): void {
245
- if (this.failedAspects.includes(id)) return;
246
- this.failedLoadAspect.push(id);
247
- }
248
-
249
- /**
250
- * run "require" of the component code to get the manifest
251
- */
252
- async doRequire(requireableExtension: RequireableComponent): Promise<ExtensionManifest | Aspect> {
253
- const idStr = requireableExtension.component.id.toString();
254
- const aspect = await requireableExtension.require();
255
- const manifest = aspect.default || aspect;
256
- manifest.id = idStr;
257
- const newManifest = await this.runOnLoadRequireableExtensionSubscribers(requireableExtension, manifest);
258
- return newManifest;
259
- }
260
-
261
- /**
262
- * in case the extension failed to load, prefer to throw an error, unless `throwOnError` param
263
- * passed as `false`.
264
- * there are cases when throwing an error blocks the user from doing anything else. for example,
265
- * when a user develops an extension and deletes the node-modules, the extension on the workspace
266
- * cannot be loaded anymore until "bit compile" is running. however, if this function throws an
267
- * error, it'll throw for "bit compile" as well, which blocks the user.
268
- * for the CI, it is important to throw an error because errors on console can be ignored.
269
- * for now, when loading the extension from the workspace the throwOnError is passed as false.
270
- * when loading from the scope (CI) it should be true.
271
- *
272
- * the console printing here is done directly by "console.error" and not by the logger. the reason
273
- * is that the logger.console only prints when the loader started (which, btw, happens after
274
- * entering this function, so it can't work) and here we want it to be printed regardless of the
275
- * rules of starting the loader. e.g. if by mistake the CI got it as throwOnError=false, it's ok
276
- * to break the output by the console.error.
277
- *
278
- * @todo: this is not the final word however about throwing/non throwing errors here.
279
- * in some cases, such as "bit tag", it's better not to tag if an extension changes the model.
280
- */
281
- async loadRequireableExtensions(requireableExtensions: RequireableComponent[], throwOnError = false): Promise<void> {
282
- const manifests = await this.getManifestsFromRequireableExtensions(requireableExtensions, throwOnError);
283
- return this.loadExtensionsByManifests(manifests, throwOnError);
284
- }
285
-
286
- async getManifestsFromRequireableExtensions(
287
- requireableExtensions: RequireableComponent[],
288
- throwOnError = false
289
- ): Promise<Array<ExtensionManifest | Aspect>> {
290
- const manifestsP = mapSeries(requireableExtensions, async (requireableExtension) => {
291
- if (!requireableExtensions) return undefined;
292
- const idStr = requireableExtension.component.id.toString();
293
- try {
294
- return await this.doRequire(requireableExtension);
295
- } catch (e: any) {
296
- this.addFailure(idStr);
297
- const errorMsg = UNABLE_TO_LOAD_EXTENSION(idStr);
298
- this.logger.error(errorMsg, e);
299
- const isFixed = await this.triggerOnAspectLoadError(e, requireableExtension.component);
300
- let errAfterReLoad;
301
- if (isFixed) {
302
- this.logger.info(`the loading issue has been fixed, re-loading ${idStr}`);
303
- try {
304
- return await this.doRequire(requireableExtension);
305
- } catch (err: any) {
306
- this.logger.error('re-load of the aspect failed as well', err);
307
- errAfterReLoad = err;
308
- }
309
- }
310
- const error = errAfterReLoad || e;
311
- this.handleExtensionLoadingError(error, idStr, throwOnError);
312
- }
313
- return undefined;
314
- });
315
- const manifests = await manifestsP;
316
-
317
- // Remove empty manifests as a result of loading issue
318
- return compact(manifests);
319
- }
320
-
321
- handleExtensionLoadingError(error: Error, idStr: string, throwOnError: boolean) {
322
- const errorMsg = UNABLE_TO_LOAD_EXTENSION(idStr);
323
- if (throwOnError) {
324
- // @ts-ignore
325
- this.logger.console(error);
326
- throw new CannotLoadExtension(idStr, error);
327
- }
328
- if (this.logger.isLoaderStarted) {
329
- this.logger.consoleFailure(errorMsg);
330
- } else {
331
- this.logger.console(errorMsg);
332
- this.logger.console(error.message);
333
- }
334
- }
335
-
336
- async runOnLoadRequireableExtensionSubscribers(
337
- requireableExtension: RequireableComponent,
338
- manifest: ExtensionManifest | Aspect
339
- ): Promise<ExtensionManifest | Aspect> {
340
- let updatedManifest = manifest;
341
- const entries = this.onLoadRequireableExtensionSlot.toArray();
342
- await mapSeries(entries, async ([, onLoadRequireableExtensionFunc]) => {
343
- updatedManifest = await onLoadRequireableExtensionFunc(requireableExtension, updatedManifest);
344
- });
345
- return updatedManifest;
346
- }
347
-
348
- getPluginDefs() {
349
- return flatten(this.pluginSlot.values());
350
- }
351
-
352
- getPlugins(component: Component, componentPath: string): Plugins {
353
- const defs = this.getPluginDefs();
354
- return Plugins.from(component, defs, (relativePath) => {
355
- const compiler = this.getCompiler(component);
356
- if (!compiler) {
357
- return join(componentPath, relativePath);
358
- }
359
-
360
- const dist = compiler.getDistPathBySrcPath(relativePath);
361
- return join(componentPath, dist);
362
- });
363
- }
364
-
365
- isAspect(manifest: any) {
366
- return !!(manifest.addRuntime && manifest.getRuntime);
367
- }
368
-
369
- isAspectComponent(component: Component): boolean {
370
- const data = component.config.extensions.findExtension(EnvsAspect.id)?.data;
371
- return Boolean(data && data.type === 'aspect');
372
- }
373
-
374
- /**
375
- * get or create a global scope, import the non-core aspects, load bit from that scope, create
376
- * capsules for the aspects and load them from the capsules.
377
- */
378
- async loadAspectsFromGlobalScope(aspectIds: string[]): Promise<Component[]> {
379
- const globalScope = await LegacyScope.ensure(GLOBAL_SCOPE, 'global-scope');
380
- await globalScope.ensureDir();
381
- const globalScopeHarmony = await loadBit(globalScope.path);
382
- const scope = globalScopeHarmony.get<ScopeMain>(ScopeAspect.id);
383
- // @todo: Gilad make this work
384
- // const ids = await scope.resolveMultipleComponentIds(aspectIds);
385
- const ids = aspectIds.map((id) => ComponentID.fromLegacy(BitId.parse(id, true)));
386
- const hasVersions = ids.every((id) => id.hasVersion());
387
- const useCache = hasVersions; // if all components has versions, try to use the cached aspects
388
- const components = await scope.import(ids, { useCache, throwIfNotExist: true });
389
-
390
- // don't use `await scope.loadAspectsFromCapsules(components, true);`
391
- // it won't work for globalScope because `this !== scope.aspectLoader` (this instance
392
- // is not the same as the aspectLoader instance Scope has)
393
- const resolvedAspects = await scope.getResolvedAspects(components);
394
- try {
395
- await this.loadRequireableExtensions(resolvedAspects, true);
396
- } catch (err: any) {
397
- if (err?.error.code === 'MODULE_NOT_FOUND') {
398
- const resolvedAspectsAgain = await scope.getResolvedAspects(components, { skipIfExists: false });
399
- await this.loadRequireableExtensions(resolvedAspectsAgain, true);
400
- } else {
401
- throw err;
402
- }
403
- }
404
-
405
- return components;
406
- }
407
-
408
- private prepareManifests(manifests: Array<ExtensionManifest | Aspect>): Aspect[] {
409
- return manifests.map((manifest: any) => {
410
- if (this.isAspect(manifest)) return manifest as Aspect;
411
- manifest.runtime = MainRuntime;
412
- if (!manifest.id) throw new Error('manifest must have static id');
413
- const aspect = Aspect.create({
414
- id: manifest.id,
415
- });
416
- aspect.addRuntime(manifest);
417
- return aspect;
418
- });
419
- }
420
-
421
- /**
422
- * register a plugin.
423
- */
424
- registerPlugins(pluginDefs: PluginDefinition[]) {
425
- this.pluginSlot.register(pluginDefs);
426
- return this;
427
- }
428
-
429
- // TODO: change to use the new logger, see more info at loadExtensions function in the workspace
430
- async loadExtensionsByManifests(extensionsManifests: Array<ExtensionManifest | Aspect>, throwOnError = true) {
431
- try {
432
- const manifests = extensionsManifests.filter((manifest) => {
433
- // @ts-ignore TODO: fix this
434
- const isValid = this.isAspect(manifest) || manifest.provider;
435
- if (!isValid) this.logger.warn(`${manifest.id} is invalid. please make sure the extension is valid.`);
436
- return isValid;
437
- });
438
- const preparedManifests = this.prepareManifests(manifests);
439
- // @ts-ignore TODO: fix this
440
- await this.harmony.load(preparedManifests);
441
- } catch (e: any) {
442
- const ids = extensionsManifests.map((manifest) => manifest.id || 'unknown');
443
- // TODO: improve texts
444
- const warning = UNABLE_TO_LOAD_EXTENSION_FROM_LIST(ids);
445
- this.logger.warn(warning, e);
446
- if (this.logger.isLoaderStarted) {
447
- this.logger.consoleFailure(warning);
448
- } else {
449
- this.logger.console(warning);
450
- this.logger.console(e);
451
- }
452
- if (throwOnError) {
453
- throw e;
454
- }
455
- }
456
- }
457
-
458
- static runtime = MainRuntime;
459
- static dependencies = [LoggerAspect, EnvsAspect];
460
- static slots = [
461
- Slot.withType<OnAspectLoadError>(),
462
- Slot.withType<OnLoadRequireableExtension>(),
463
- Slot.withType<PluginDefinition[]>(),
464
- ];
465
-
466
- static async provider(
467
- [loggerExt, envs]: [LoggerMain, EnvsMain],
468
- config,
469
- [onAspectLoadErrorSlot, onLoadRequireableExtensionSlot, pluginSlot]: [
470
- OnAspectLoadErrorSlot,
471
- OnLoadRequireableExtensionSlot,
472
- PluginDefinitionSlot
473
- ],
474
- harmony: Harmony
475
- ) {
476
- const logger = loggerExt.createLogger(AspectLoaderAspect.id);
477
- const aspectLoader = new AspectLoaderMain(
478
- logger,
479
- envs,
480
- harmony,
481
- onAspectLoadErrorSlot,
482
- onLoadRequireableExtensionSlot,
483
- pluginSlot
484
- );
485
-
486
- return aspectLoader;
487
- }
488
- }
489
-
490
- AspectLoaderAspect.addRuntime(AspectLoaderMain);
package/constants.ts DELETED
@@ -1,5 +0,0 @@
1
- // Warnings
2
- export const UNABLE_TO_LOAD_EXTENSION = (id: string) =>
3
- `error: unable to load the extension "${id}", please use the '--log' flag for the full error.`;
4
- export const UNABLE_TO_LOAD_EXTENSION_FROM_LIST = (ids: string[]) =>
5
- `couldn't load one of the following extensions ${ids.join(', ')}, please use the '--log' flag for the full error.`;
@@ -1,10 +0,0 @@
1
- import { getCoreAspectName } from './core-aspects';
2
-
3
- describe('core-aspects', () => {
4
- describe('getCoreAspectName', () => {
5
- it('should include the namespace in the aspect name', () => {
6
- const aspectName = getCoreAspectName('teambit.workspace/e2e/workspace');
7
- expect(aspectName).toEqual('e2e.workspace');
8
- });
9
- });
10
- });
package/core-aspects.ts DELETED
@@ -1,49 +0,0 @@
1
- import { existsSync, readdir } from 'fs-extra';
2
- import { join, resolve } from 'path';
3
-
4
- export function getAspectDir(id: string): string {
5
- const aspectName = getCoreAspectName(id);
6
- const packageName = getCoreAspectPackageName(id);
7
- let dirPath: string;
8
- try {
9
- const moduleDirectory = require.resolve(packageName);
10
- dirPath = join(moduleDirectory, '../..'); // to remove the "index.js" at the end
11
- } catch (err: any) {
12
- dirPath = resolve(__dirname, '../..', aspectName, 'dist');
13
- }
14
- if (!existsSync(dirPath)) {
15
- throw new Error(`unable to find ${aspectName} in ${dirPath}`);
16
- }
17
- return dirPath;
18
- }
19
-
20
- export function getAspectDistDir(id: string) {
21
- return resolve(`${getAspectDir(id)}/dist`);
22
- }
23
-
24
- export function getCoreAspectName(id: string): string {
25
- const [, ...name] = id.split('/');
26
- const aspectName = name.join('.');
27
- return aspectName;
28
- }
29
-
30
- export function getCoreAspectPackageName(id: string): string {
31
- const aspectName = getCoreAspectName(id);
32
- return `@teambit/${aspectName}`;
33
- }
34
-
35
- export async function getAspectDef(aspectName: string, runtime?: string) {
36
- const dirPath = getAspectDistDir(aspectName);
37
-
38
- const files = await readdir(dirPath);
39
- let runtimeFile;
40
- if (runtime) {
41
- runtimeFile = files.find((file) => file.includes(`.${runtime}.runtime.js`)) || null;
42
- }
43
-
44
- return {
45
- id: aspectName,
46
- aspectPath: join(dirPath, '..'),
47
- runtimePath: runtimeFile ? resolve(`${dirPath}/${runtimeFile}`) : null,
48
- };
49
- }
@@ -1,14 +0,0 @@
1
- import { BitError } from '@teambit/bit-error';
2
-
3
- export class CannotLoadExtension extends BitError {
4
- constructor(private extensionName: string, private error: Error) {
5
- super(`could not load extension: ${extensionName} with error: ${error}`);
6
- }
7
-
8
- report(verbose?: boolean) {
9
- if (verbose) return `could not load extension: ${this.extensionName}. ${this.error} `;
10
- return this.message;
11
- }
12
-
13
- toJson() {}
14
- }
@@ -1 +0,0 @@
1
- export { CannotLoadExtension } from './cannot-load-extension';
package/index.ts DELETED
@@ -1,19 +0,0 @@
1
- import { AspectLoaderAspect } from './aspect-loader.aspect';
2
-
3
- export type {
4
- AspectLoaderMain,
5
- AspectDescriptor,
6
- MainAspect,
7
- OnLoadRequireableExtension,
8
- } from './aspect-loader.main.runtime';
9
- export {
10
- getAspectDef,
11
- getAspectDir,
12
- getAspectDistDir,
13
- getCoreAspectPackageName,
14
- getCoreAspectName,
15
- } from './core-aspects';
16
- export { PluginDefinition } from './plugin-definition';
17
- export { AspectDefinition } from './aspect-definition';
18
- export { AspectLoaderAspect };
19
- export default AspectLoaderAspect;
@@ -1,16 +0,0 @@
1
- export interface PluginDefinition {
2
- /**
3
- * regex pattern for detecting the definition file within a component.
4
- */
5
- pattern: string | RegExp;
6
-
7
- /**
8
- * runtimes for the plugin to apply.
9
- */
10
- runtimes: string[];
11
-
12
- /**
13
- * register the plugin to its slot registry.
14
- */
15
- register<T>(object: T): void;
16
- }
package/plugin.ts DELETED
@@ -1,26 +0,0 @@
1
- import { PluginDefinition } from './plugin-definition';
2
-
3
- export class Plugin {
4
- constructor(readonly def: PluginDefinition, readonly path: string) {}
5
-
6
- // consider adding a more abstract type here to allow users to ask for dependencies.
7
- private _instance: undefined | unknown;
8
-
9
- /**
10
- * determines whether the plugin supports a certain runtime.
11
- */
12
- supportsRuntime(runtime: string) {
13
- return this.def.runtimes.includes(runtime);
14
- }
15
-
16
- register() {
17
- const object = this.require();
18
- this.def.register<unknown>(object);
19
- }
20
-
21
- require() {
22
- // eslint-disable-next-line global-require, import/no-dynamic-require
23
- this._instance = require(this.path).default;
24
- return this._instance;
25
- }
26
- }
package/plugins.ts DELETED
@@ -1,62 +0,0 @@
1
- import { Component } from '@teambit/component';
2
- import { Aspect } from '@teambit/harmony';
3
- import { PluginDefinition } from './plugin-definition';
4
- import { Plugin } from './plugin';
5
-
6
- export type PluginMap = { [filePath: string]: PluginDefinition };
7
-
8
- export class Plugins {
9
- constructor(readonly component: Component, readonly plugins: Plugin[]) {}
10
-
11
- // computeDependencies(runtime: string): Aspect[] {
12
- // const inRuntime = this.getByRuntime(runtime);
13
- // return inRuntime.flatMap((plugin) => {
14
- // return plugin.def.dependencies;
15
- // });
16
- // }
17
-
18
- getByRuntime(runtime: string) {
19
- return this.plugins.filter((plugin) => {
20
- return plugin.supportsRuntime(runtime);
21
- });
22
- }
23
-
24
- load(runtime: string) {
25
- const plugins = this.getByRuntime(runtime);
26
- const aspect = Aspect.create({
27
- id: this.component.id.toString(),
28
- });
29
-
30
- aspect.addRuntime({
31
- provider: async () => {
32
- plugins.forEach((plugin) => {
33
- plugin.register();
34
- });
35
- },
36
- runtime,
37
- // dependencies: this.computeDependencies(runtime)
38
- dependencies: [],
39
- });
40
-
41
- return aspect;
42
- }
43
-
44
- has() {
45
- return Boolean(this.plugins.length);
46
- }
47
-
48
- static from(component: Component, defs: PluginDefinition[], resolvePath?: (path: string) => string) {
49
- const plugins = defs.flatMap((pluginDef) => {
50
- const files =
51
- typeof pluginDef.pattern === 'string'
52
- ? component.filesystem.byGlob([pluginDef.pattern])
53
- : component.filesystem.byRegex(pluginDef.pattern);
54
-
55
- return files.map((file) => {
56
- return new Plugin(pluginDef, resolvePath ? resolvePath(file.relative) : file.path);
57
- });
58
- });
59
-
60
- return new Plugins(component, plugins);
61
- }
62
- }
package/types/asset.d.ts DELETED
@@ -1,29 +0,0 @@
1
- declare module '*.png' {
2
- const value: any;
3
- export = value;
4
- }
5
- declare module '*.svg' {
6
- import type { FunctionComponent, SVGProps } from 'react';
7
-
8
- export const ReactComponent: FunctionComponent<SVGProps<SVGSVGElement> & { title?: string }>;
9
- const src: string;
10
- export default src;
11
- }
12
-
13
- // @TODO Gilad
14
- declare module '*.jpg' {
15
- const value: any;
16
- export = value;
17
- }
18
- declare module '*.jpeg' {
19
- const value: any;
20
- export = value;
21
- }
22
- declare module '*.gif' {
23
- const value: any;
24
- export = value;
25
- }
26
- declare module '*.bmp' {
27
- const value: any;
28
- export = value;
29
- }
package/types/style.d.ts DELETED
@@ -1,42 +0,0 @@
1
- declare module '*.module.css' {
2
- const classes: { readonly [key: string]: string };
3
- export default classes;
4
- }
5
- declare module '*.module.scss' {
6
- const classes: { readonly [key: string]: string };
7
- export default classes;
8
- }
9
- declare module '*.module.sass' {
10
- const classes: { readonly [key: string]: string };
11
- export default classes;
12
- }
13
-
14
- declare module '*.module.less' {
15
- const classes: { readonly [key: string]: string };
16
- export default classes;
17
- }
18
-
19
- declare module '*.less' {
20
- const classes: { readonly [key: string]: string };
21
- export default classes;
22
- }
23
-
24
- declare module '*.css' {
25
- const classes: { readonly [key: string]: string };
26
- export default classes;
27
- }
28
-
29
- declare module '*.sass' {
30
- const classes: { readonly [key: string]: string };
31
- export default classes;
32
- }
33
-
34
- declare module '*.scss' {
35
- const classes: { readonly [key: string]: string };
36
- export default classes;
37
- }
38
-
39
- declare module '*.mdx' {
40
- const component: any;
41
- export default component;
42
- }