diff --git a/scopes/envs/envs/environments.main.runtime.ts b/scopes/envs/envs/environments.main.runtime.ts index ceeeb64cd7df..c88781dcb6c9 100644 --- a/scopes/envs/envs/environments.main.runtime.ts +++ b/scopes/envs/envs/environments.main.runtime.ts @@ -1,5 +1,5 @@ import { CLIAspect, CLIMain, MainRuntime } from '@teambit/cli'; -import { Component, ComponentAspect, ComponentMain, ComponentID, AspectData } from '@teambit/component'; +import { Component, ComponentAspect, ComponentMain, ComponentID } from '@teambit/component'; import { GraphqlAspect, GraphqlMain } from '@teambit/graphql'; import { Harmony, Slot, SlotRegistry } from '@teambit/harmony'; import { Logger, LoggerAspect, LoggerMain } from '@teambit/logger'; @@ -35,12 +35,36 @@ export type EnvTransformer = (env: Environment) => Environment; export type ServicesRegistry = SlotRegistry>>; -export type Descriptor = { +export type RegularCompDescriptor = { id: string; - icon: string; - services?: []; + icon?: string; + type?: string; + name?: string; + description?: string; +}; +export type EnvCompDescriptorProps = RegularCompDescriptor & { + services?: { + env: { + id: string; + icon: string; + name?: string; + description?: string; + }; + services: Array<{ + id: string; + name?: string; + description?: string; + data: any; + }>; + }; +}; + +export type EnvCompDescriptor = EnvCompDescriptorProps & { + self?: EnvCompDescriptorProps; }; +export type Descriptor = RegularCompDescriptor | EnvCompDescriptor; + export const DEFAULT_ENV = 'teambit.harmony/node'; export class EnvsMain { @@ -160,14 +184,14 @@ export class EnvsMain { return targetEnv as T & S; } - getEnvData(component: Component): AspectData { + getEnvData(component: Component): Descriptor { let envsData = component.state.aspects.get(EnvsAspect.id); if (!envsData) { // TODO: remove this once we re-export old components used to store the data here envsData = component.state.aspects.get('teambit.workspace/workspace'); } if (!envsData) throw new Error(`env was not configured on component ${component.id.toString()}`); - return envsData.data; + return envsData.data as Descriptor; } /** @@ -277,10 +301,65 @@ export class EnvsMain { */ getDescriptor(component: Component): Descriptor | null { const envsData = this.getEnvData(component); + return envsData; + } + + async calcDescriptor(component: Component): Promise { + const componentDescriptor = await this.getComponentEnvDescriptor(component); + if (!componentDescriptor) return undefined; + const envComponentSelfDescriptor = await this.getEnvSelfDescriptor(component); + const result = envComponentSelfDescriptor + ? { ...componentDescriptor, self: envComponentSelfDescriptor } + : componentDescriptor; + return result; + } + + /** + * Get env descriptor from the env itself if the component is an env + * This will be empty for regular component, and will only contain data for env themself + */ + private async getEnvSelfDescriptor(envComponent: Component): Promise { + // !important calculate only on the env itself. + if (!this.isEnvRegistered(envComponent.id.toString())) { + return undefined; + } + + const envDef = this.getEnvFromComponent(envComponent); + if (!envDef) return undefined; + + const services = this.getServices(envDef); + // const selfDescriptor = (await this.getEnvDescriptorFromEnvDef(envDef)) || {}; + const selfDescriptor = await this.getEnvDescriptorFromEnvDef(envDef); + + if (!selfDescriptor) return undefined; + return { + ...selfDescriptor, + services: services.toObject(), + }; + } + + /** + * Get env descriptor from the env that a given component is using + */ + private async getComponentEnvDescriptor(component: Component): Promise { + const envDef = this.calculateEnv(component); + return this.getEnvDescriptorFromEnvDef(envDef); + } + + private async getEnvDescriptorFromEnvDef(envDef: EnvDefinition): Promise { + if (!envDef.env.__getDescriptor || typeof envDef.env.__getDescriptor !== 'function') { + return undefined; + } + const systemDescriptor = await envDef.env.__getDescriptor(); + return { - id: this.getEnvId(component), - icon: envsData.icon, - services: envsData.services, + type: systemDescriptor.type, + // Make sure to store the env id in the data without the version + // The version should always come from the aspect id configured on the component + id: envDef.id.split('@')[0], + name: envDef.name, + icon: envDef.env.icon, + description: envDef.description, }; } @@ -651,7 +730,7 @@ export class EnvsMain { const resolvedAspects = await host.resolveAspects(MainRuntime.name, [id], { requestedOnly: true, filterByRuntime: false, - useScopeAspectsCapsule: true + useScopeAspectsCapsule: true, }); const def = resolvedAspects[0]; diff --git a/scopes/preview/preview/preview.main.runtime.tsx b/scopes/preview/preview/preview.main.runtime.tsx index 153e425c03f2..211a7c86a79d 100644 --- a/scopes/preview/preview/preview.main.runtime.tsx +++ b/scopes/preview/preview/preview.main.runtime.tsx @@ -459,7 +459,7 @@ export class PreviewMain { ENV_STRATEGY_ARTIFACT_NAME ); const envType = this.envs.getEnvData(component).type; - return !!artifacts && !!artifacts.length && ENV_WITH_LEGACY_DOCS.includes(envType); + return !!artifacts && !!artifacts.length && ENV_WITH_LEGACY_DOCS.includes(envType || ''); } /** diff --git a/scopes/scope/scope/scope.main.runtime.ts b/scopes/scope/scope/scope.main.runtime.ts index 56a636714663..92de01c1d6c2 100644 --- a/scopes/scope/scope/scope.main.runtime.ts +++ b/scopes/scope/scope/scope.main.runtime.ts @@ -789,6 +789,10 @@ export class ScopeMain implements ComponentFactory { if (appData?.data?.appName) { aspectIds.push(component.id.toString()); } + const envsData = component.state.aspects.get(EnvsAspect.id); + if (envsData?.data?.services || envsData?.data?.self){ + aspectIds.push(component.id.toString()); + } await this.loadAspects(aspectIds, true, id.toString(), lane); return component; diff --git a/scopes/workspace/workspace/workspace-component/workspace-component-loader.ts b/scopes/workspace/workspace/workspace-component/workspace-component-loader.ts index 3e7704f407a3..fd6067463587 100644 --- a/scopes/workspace/workspace/workspace-component/workspace-component-loader.ts +++ b/scopes/workspace/workspace/workspace-component/workspace-component-loader.ts @@ -241,7 +241,7 @@ export class WorkspaceComponentLoader { // Special load events which runs from the workspace but should run from the correct aspect // TODO: remove this once those extensions dependent on workspace - const envsData = await this.workspace.getEnvSystemDescriptor(component); + const envsData = await this.envs.calcDescriptor(component); // Move to deps resolver main runtime once we switch ws<> deps resolver direction const policy = await this.dependencyResolver.mergeVariantPolicies( diff --git a/scopes/workspace/workspace/workspace.ts b/scopes/workspace/workspace/workspace.ts index f6f60f71f423..84e571c997e3 100644 --- a/scopes/workspace/workspace/workspace.ts +++ b/scopes/workspace/workspace/workspace.ts @@ -13,7 +13,6 @@ import { ComponentFactory, ComponentID, AspectList, - AspectData, InvalidComponent, ResolveAspectsOptions, } from '@teambit/component'; @@ -21,7 +20,7 @@ import { BitError } from '@teambit/bit-error'; import { REMOVE_EXTENSION_SPECIAL_SIGN } from '@teambit/legacy/dist/consumer/config'; import { ComponentScopeDirMap, ConfigMain } from '@teambit/config'; import { DependencyResolverMain } from '@teambit/dependency-resolver'; -import { EnvsMain, EnvsAspect, EnvServiceList } from '@teambit/envs'; +import { EnvsMain, EnvsAspect } from '@teambit/envs'; import { GraphqlMain } from '@teambit/graphql'; import { Harmony } from '@teambit/harmony'; import { Logger } from '@teambit/logger'; @@ -581,31 +580,6 @@ export class Workspace implements ComponentFactory { return workspaceAspectsLoader.getConfiguredUserAspectsPackages(options); } - // TODO: @gilad we should refactor this asap into to the envs aspect. - async getEnvSystemDescriptor(component: Component): Promise { - const env = this.envs.calculateEnv(component); - if (env.env.__getDescriptor && typeof env.env.__getDescriptor === 'function') { - const systemDescriptor = await env.env.__getDescriptor(); - // !important persist services only on the env itself. - let services: undefined | EnvServiceList; - if (this.envs.isEnvRegistered(component.id.toString())) services = this.envs.getServices(env); - const icon = this.aspectLoader.getDescriptor(env.id)?.icon || env.env.icon; - - return { - type: systemDescriptor.type, - // Make sure to store the env id in the data without the version - // The version should always come from the aspect id configured on the component - id: env.id.split('@')[0], - name: env.name, - icon, - description: env.description, - services: services?.toObject(), - }; - } - - return {}; - } - clearCache() { this.aspectLoader.resetFailedLoadAspects(); this.logger.debug('clearing the workspace and scope caches');