@teambit/envs 0.0.568 → 0.0.572

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,30 @@
1
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
3
+ import { Box, Text } from 'ink';
4
+ import React, { useEffect, useState } from 'react';
5
+
6
+ import { EnvRuntime } from '../../runtime';
7
+
8
+ export type EnvConsoleProps = {
9
+ runtime: EnvRuntime;
10
+ };
11
+
12
+ export function EnvConsole() {
13
+ const [counter, setCounter] = useState(0);
14
+
15
+ useEffect(() => {
16
+ const timer = setInterval(() => {
17
+ setCounter((previousCounter) => previousCounter + 1);
18
+ }, 100);
19
+
20
+ return () => {
21
+ clearInterval(timer);
22
+ };
23
+ }, []);
24
+
25
+ return (
26
+ <Box>
27
+ <Text color="green">{counter} tests passed</Text>
28
+ </Box>
29
+ );
30
+ }
@@ -0,0 +1 @@
1
+ export { EnvConsole } from './env-console';
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ import { Text, Newline } from 'ink';
3
+ import { EnvDefinition } from '../../env-definition';
4
+
5
+ export type EnvOverviewProps = {
6
+ envDef: EnvDefinition;
7
+ };
8
+
9
+ /**
10
+ * renders an env overview in the terminal.
11
+ */
12
+ export function EnvOverview({ envDef }: EnvOverviewProps) {
13
+ return (
14
+ <Text>
15
+ <Text bold underline>
16
+ Environment: {envDef.id}
17
+ </Text>
18
+ <Newline />
19
+ </Text>
20
+ );
21
+ }
@@ -0,0 +1 @@
1
+ export { EnvOverview } from './env-overview';
@@ -0,0 +1 @@
1
+ export { EnvConsole } from './env-console';
@@ -0,0 +1,54 @@
1
+ import { EnvDefinition } from '../env-definition';
2
+
3
+ import { EnvRuntime, Runtime } from '../runtime';
4
+
5
+ export type ServiceMap<T> = {
6
+ [env: string]: T;
7
+ };
8
+
9
+ export class ExecutionContext {
10
+ constructor(
11
+ /**
12
+ * upper scope of all environment contexts.
13
+ */
14
+ readonly upper: Runtime,
15
+
16
+ /**
17
+ * runtime instance of the environment.
18
+ */
19
+ readonly envRuntime: EnvRuntime,
20
+
21
+ /**
22
+ * components applied in the execution context.
23
+ */
24
+ public components = envRuntime.components
25
+ ) {}
26
+
27
+ relatedContexts: string[] = [];
28
+
29
+ /**
30
+ * extension ID of the environment
31
+ */
32
+ get id() {
33
+ return this.envRuntime.id;
34
+ }
35
+
36
+ /**
37
+ * environment instance.
38
+ */
39
+ get env(): any {
40
+ return this.envRuntime.env;
41
+ }
42
+
43
+ get envDefinition(): EnvDefinition {
44
+ return new EnvDefinition(this.id, this.env);
45
+ }
46
+
47
+ apply<T>(name: string, args: any[]): T {
48
+ if (!this.env[name]) {
49
+ throw new Error(`method ${name} not implemented`);
50
+ }
51
+
52
+ return this.env[name].apply(this.env, ...args);
53
+ }
54
+ }
@@ -0,0 +1 @@
1
+ export { ExecutionContext } from './context';
package/envs.cmd.tsx ADDED
@@ -0,0 +1,87 @@
1
+ import React from 'react';
2
+ import { Text, Newline } from 'ink';
3
+ import { CLITable } from '@teambit/cli-table';
4
+ import { Command } from '@teambit/cli';
5
+ import { ComponentMain, ComponentFactory, Component } from '@teambit/component';
6
+ import { EnvsMain } from './environments.main.runtime';
7
+ import { EnvOverview } from './components/env-overview';
8
+
9
+ export class EnvsCmd implements Command {
10
+ name = 'envs [name]';
11
+ alias = 'env';
12
+ shortDescription = 'show all component envs';
13
+ description = 'show all components envs';
14
+ options = [];
15
+ group = 'development';
16
+
17
+ constructor(private envs: EnvsMain, private componentAspect: ComponentMain) {}
18
+
19
+ async showEnv(id: string, host: ComponentFactory) {
20
+ const component = await host.get(await host.resolveComponentId(id));
21
+ if (!component) throw new Error(`component for env ${id} was not found`);
22
+ const env = this.envs.getEnv(component);
23
+ const envRuntime = await this.envs.createEnvironment([component]);
24
+ const envExecutionContext = envRuntime.getEnvExecutionContext();
25
+ const services = this.envs.getServices(env);
26
+ const allP = services.services.map(async ([serviceId, service]) => {
27
+ if (service.render)
28
+ return (
29
+ <Text>
30
+ <Text bold underline color="cyan">
31
+ {serviceId}
32
+ </Text>
33
+ <Newline />
34
+ <Newline />
35
+ {await service.render(env, envExecutionContext)}
36
+ </Text>
37
+ );
38
+ return (
39
+ <Text key={serviceId}>
40
+ <Text bold underline>
41
+ {serviceId}
42
+ </Text>
43
+ </Text>
44
+ );
45
+ });
46
+
47
+ const all = await Promise.all(allP);
48
+
49
+ return (
50
+ <Text>
51
+ <EnvOverview envDef={env} />
52
+ {all.map((item) => item)}
53
+ </Text>
54
+ );
55
+ }
56
+
57
+ async render([name]: [string]): Promise<JSX.Element> {
58
+ const host = await this.componentAspect.getHost();
59
+ // TODO: think what to do re this line with gilad.
60
+ if (!host) throw new Error('error: workspace not found');
61
+ if (name) return this.showEnv(name, host);
62
+ const components = await host.list();
63
+ // TODO: refactor to a react table
64
+ return <Text>{this.getTable(components)}</Text>;
65
+ }
66
+
67
+ private getTable(components: Component[]) {
68
+ const tableData = components.map((component) => {
69
+ const env = this.envs.getDescriptor(component);
70
+ return {
71
+ component: component.id.toString(),
72
+ env: env ? env.id : 'N/A',
73
+ };
74
+ });
75
+
76
+ const header = [
77
+ {
78
+ value: 'component',
79
+ },
80
+ {
81
+ value: 'env',
82
+ },
83
+ ];
84
+ const table = CLITable.fromObject(header, tableData);
85
+ return table.render();
86
+ }
87
+ }
@@ -0,0 +1,10 @@
1
+ import { BitError } from '@teambit/bit-error';
2
+
3
+ export class EnvNotConfiguredForComponent extends BitError {
4
+ constructor(id: string, componentId?: string) {
5
+ const suffix = componentId ? ` for the component ${componentId}` : '';
6
+ super(`environment with ID: "${id}" is not configured as extension${suffix}.
7
+ you probably need to add this environment as a key to your variant in the workspace.jsonc. for example, "your-variant": { "${id}": {} }
8
+ `);
9
+ }
10
+ }
@@ -0,0 +1,7 @@
1
+ import { BitError } from '@teambit/bit-error';
2
+
3
+ export class EnvNotFoundInRuntime extends BitError {
4
+ constructor(private id: string) {
5
+ super(`environment with ID: ${id} was not found configured to any of your components`);
6
+ }
7
+ }
@@ -0,0 +1,12 @@
1
+ import { BitError } from '@teambit/bit-error';
2
+
3
+ export class EnvNotFound extends BitError {
4
+ constructor(private id: string, private componentId?: string) {
5
+ super(getMessage(id, componentId));
6
+ }
7
+ }
8
+
9
+ function getMessage(id: string, componentId?: string): string {
10
+ const compIdDetails = componentId ? `configured on component ${componentId}` : '';
11
+ return `environment with ID: ${id} ${compIdDetails} was not found`;
12
+ }
@@ -0,0 +1,3 @@
1
+ export { EnvNotFoundInRuntime } from './env-not-found-in-runtime';
2
+ export { EnvNotFound } from './env-not-found';
3
+ export { EnvNotConfiguredForComponent } from './env-not-configured-for-component';
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@teambit/envs",
3
- "version": "0.0.568",
3
+ "version": "0.0.572",
4
4
  "homepage": "https://bit.dev/teambit/envs/envs",
5
5
  "main": "dist/index.js",
6
6
  "componentId": {
7
7
  "scope": "teambit.envs",
8
8
  "name": "envs",
9
- "version": "0.0.568"
9
+ "version": "0.0.572"
10
10
  },
11
11
  "dependencies": {
12
12
  "@teambit/harmony": "0.2.11",
@@ -16,23 +16,23 @@
16
16
  "p-map-series": "2.1.0",
17
17
  "@babel/runtime": "7.12.18",
18
18
  "core-js": "^3.0.0",
19
- "@teambit/component": "0.0.568",
20
- "@teambit/builder": "0.0.568",
21
- "@teambit/bundler": "0.0.568",
22
- "@teambit/compiler": "0.0.568",
23
- "@teambit/dependency-resolver": "0.0.568",
24
- "@teambit/elements": "0.0.21",
25
- "@teambit/formatter": "0.0.119",
26
- "@teambit/linter": "0.0.568",
27
- "@teambit/pkg": "0.0.568",
28
- "@teambit/schema": "0.0.568",
29
- "@teambit/tester": "0.0.568",
30
- "@teambit/webpack": "0.0.568",
31
- "@teambit/graphql": "0.0.568",
32
- "@teambit/cli": "0.0.394",
33
- "@teambit/logger": "0.0.480",
34
- "@teambit/cli-table": "0.0.17",
35
- "@teambit/bit-error": "0.0.380"
19
+ "@teambit/component": "0.0.572",
20
+ "@teambit/builder": "0.0.572",
21
+ "@teambit/bundler": "0.0.572",
22
+ "@teambit/compiler": "0.0.572",
23
+ "@teambit/dependency-resolver": "0.0.572",
24
+ "@teambit/elements": "0.0.25",
25
+ "@teambit/formatter": "0.0.123",
26
+ "@teambit/linter": "0.0.572",
27
+ "@teambit/pkg": "0.0.572",
28
+ "@teambit/schema": "0.0.572",
29
+ "@teambit/tester": "0.0.572",
30
+ "@teambit/webpack": "0.0.572",
31
+ "@teambit/graphql": "0.0.572",
32
+ "@teambit/cli": "0.0.395",
33
+ "@teambit/logger": "0.0.483",
34
+ "@teambit/cli-table": "0.0.18",
35
+ "@teambit/bit-error": "0.0.381"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/react": "^17.0.8",
@@ -42,10 +42,10 @@
42
42
  "@types/jest": "^26.0.0",
43
43
  "@types/react-dom": "^17.0.5",
44
44
  "@types/node": "12.20.4",
45
- "@teambit/envs.aspect-docs.envs": "0.0.114"
45
+ "@teambit/envs.aspect-docs.envs": "0.0.117"
46
46
  },
47
47
  "peerDependencies": {
48
- "@teambit/legacy": "1.0.180",
48
+ "@teambit/legacy": "1.0.181",
49
49
  "react-dom": "^16.8.0 || ^17.0.0",
50
50
  "react": "^16.8.0 || ^17.0.0"
51
51
  },
@@ -73,27 +73,12 @@
73
73
  "react": "-"
74
74
  },
75
75
  "peerDependencies": {
76
- "@teambit/legacy": "1.0.180",
76
+ "@teambit/legacy": "1.0.181",
77
77
  "react-dom": "^16.8.0 || ^17.0.0",
78
78
  "react": "^16.8.0 || ^17.0.0"
79
79
  }
80
80
  }
81
81
  },
82
- "files": [
83
- "dist",
84
- "!dist/tsconfig.tsbuildinfo",
85
- "**/*.md",
86
- "**/*.mdx",
87
- "**/*.js",
88
- "**/*.json",
89
- "**/*.sass",
90
- "**/*.scss",
91
- "**/*.less",
92
- "**/*.css",
93
- "**/*.css",
94
- "**/*.jpeg",
95
- "**/*.gif"
96
- ],
97
82
  "private": false,
98
83
  "engines": {
99
84
  "node": ">=12.22.0"
@@ -0,0 +1,25 @@
1
+ import { Component } from '@teambit/component';
2
+
3
+ import { Environment } from '../environment';
4
+
5
+ /**
6
+ * env runtime is an instance which represent the given env in a
7
+ */
8
+ export class EnvRuntime {
9
+ constructor(
10
+ /**
11
+ * ID of the wrapping extension.
12
+ */
13
+ readonly id: string,
14
+
15
+ /**
16
+ * environment
17
+ */
18
+ readonly env: Environment,
19
+
20
+ /**
21
+ * components to be loaded in the environment
22
+ */
23
+ readonly components: Component[]
24
+ ) {}
25
+ }
@@ -0,0 +1,46 @@
1
+ import { flatten } from 'lodash';
2
+
3
+ import { ServiceExecutionResult } from '../services';
4
+ import { EnvResult } from './runtime';
5
+
6
+ export class EnvsExecutionResult<T extends ServiceExecutionResult> {
7
+ constructor(readonly results: EnvResult<T>[]) {}
8
+
9
+ hasErrors() {
10
+ return Boolean(this.errors.length);
11
+ }
12
+
13
+ /**
14
+ * execution errors.
15
+ */
16
+ get errors(): Error[] {
17
+ return flatten(this.results.map((envResult) => this.getErrorsOfEnv(envResult)));
18
+ }
19
+
20
+ getErrorsOfEnv(envResult: EnvResult<T>): Error[] {
21
+ const execError = envResult.error;
22
+ const errors = envResult.data ? envResult.data.errors || [] : [];
23
+ if (execError) errors.push(execError);
24
+ return errors;
25
+ }
26
+
27
+ /**
28
+ * if only one error is found, throw it. otherwise, summarize the errors per env and throw the
29
+ * output
30
+ */
31
+ throwErrorsIfExist() {
32
+ if (!this.errors || !this.errors.length) return;
33
+ if (this.errors.length === 1 && this.errors[0] instanceof Error) throw this.errors[0];
34
+ const errorsPerEnvs = this.results.map((envResult) => this.getEnvErrorsAsString(envResult));
35
+ const errorOutput = errorsPerEnvs.join('\n\n');
36
+ throw new Error(errorOutput);
37
+ }
38
+
39
+ getEnvErrorsAsString(envResult: EnvResult<T>): string {
40
+ const errors = this.getErrorsOfEnv(envResult);
41
+ if (!errors.length) return '';
42
+ const title = `found ${errors.length} error(s) for ${envResult.env.id}`;
43
+ const errorsStr = errors.map((error) => `${error.message}\n${error.stack}`).join('\n');
44
+ return `${title}\n${errorsStr}`;
45
+ }
46
+ }
@@ -0,0 +1,2 @@
1
+ export { Runtime } from './runtime';
2
+ export { EnvRuntime } from './env-runtime';
@@ -0,0 +1,97 @@
1
+ import { Logger } from '@teambit/logger';
2
+ import { ComponentID } from '@teambit/component';
3
+ import mapSeries from 'p-map-series';
4
+ import { EnvNotFoundInRuntime } from '../exceptions';
5
+ import { ExecutionContext } from '../context';
6
+ import { EnvService, ServiceExecutionResult } from '../services';
7
+ import { EnvRuntime } from './env-runtime';
8
+ import { EnvsExecutionResult } from './envs-execution-result';
9
+
10
+ export interface EnvResult<T extends ServiceExecutionResult> {
11
+ env: EnvRuntime;
12
+ data?: T;
13
+ error?: Error;
14
+ }
15
+
16
+ export class Runtime {
17
+ constructor(
18
+ /**
19
+ * runtime instances of the environments.
20
+ */
21
+ readonly runtimeEnvs: EnvRuntime[],
22
+
23
+ private logger: Logger
24
+ ) {}
25
+
26
+ /**
27
+ * execute a service on a specific env.
28
+ */
29
+ runEnv<T>(
30
+ envRuntimeId: string,
31
+ service: EnvService<T>,
32
+ options?: { [key: string]: any }
33
+ ): Promise<EnvsExecutionResult<T>> {
34
+ const envRuntime = this.runtimeEnvs.find((runtime) => {
35
+ const id = ComponentID.fromString(runtime.id);
36
+ const withoutVersion = id._legacy.toStringWithoutVersion();
37
+ return withoutVersion === envRuntimeId;
38
+ });
39
+ if (!envRuntime) throw new EnvNotFoundInRuntime(envRuntimeId);
40
+ return this.run(service, options, [envRuntime]);
41
+ }
42
+
43
+ /**
44
+ * execute a service once for all environments.
45
+ */
46
+ async runOnce<T>(service: EnvService<T>, options?: { [key: string]: any }): Promise<any> {
47
+ if (!service.runOnce) throw new Error('a service must implement `runOnce()` in order to be executed');
48
+ const envsExecutionContext = this.getEnvExecutionContext();
49
+ const serviceResult = await service.runOnce(envsExecutionContext, options);
50
+ return serviceResult;
51
+ }
52
+
53
+ getEnvExecutionContext(): ExecutionContext[] {
54
+ const envsExecutionContext = this.runtimeEnvs.map((env) => new ExecutionContext(this, env));
55
+ return envsExecutionContext;
56
+ }
57
+
58
+ /**
59
+ * execute a service on each one of the environments.
60
+ */
61
+ async run<T>(
62
+ /**
63
+ * environment service to execute.
64
+ */
65
+ service: EnvService<T>,
66
+
67
+ /**
68
+ * options to proxy to the service upon execution.
69
+ */
70
+ options?: { [key: string]: any },
71
+ runtimes?: EnvRuntime[]
72
+ ): Promise<EnvsExecutionResult<T>> {
73
+ if (!service.run) throw new Error('a service must implement `run()` in order to be executed');
74
+ const errors: Error[] = [];
75
+ const contexts: EnvResult<T>[] = await mapSeries(runtimes || this.runtimeEnvs, async (env) => {
76
+ try {
77
+ // @ts-ignore
78
+ const serviceResult = await service.run(new ExecutionContext(this, env), options);
79
+
80
+ return {
81
+ env,
82
+ data: serviceResult,
83
+ };
84
+ } catch (err: any) {
85
+ this.logger.error(err.message, err);
86
+ this.logger.consoleFailure(`service ${service.name} env ${env.id} has failed. ${err.message}`);
87
+ errors.push(err);
88
+ return {
89
+ env,
90
+ error: err,
91
+ };
92
+ }
93
+ });
94
+
95
+ return new EnvsExecutionResult(contexts);
96
+ }
97
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * please do not use this.
3
+ * @deprecated
4
+ */
5
+ export interface ConcreteService {
6
+ getPackageJsonProps?: () => Record<string, any>;
7
+ dependencies?: () => any;
8
+ }
@@ -0,0 +1,3 @@
1
+ export { Service as EnvService, ServiceExecutionResult } from './service';
2
+ export { ConcreteService } from './concrete-service';
3
+ export { ServiceHandler } from './service-handler';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * definition of the service handler.
3
+ */
4
+ export interface ServiceHandler {
5
+ identifier: string;
6
+ }
@@ -0,0 +1,52 @@
1
+ import { Component } from '@teambit/component';
2
+ import { Environment } from '../environment';
3
+
4
+ export type EnvContext = {
5
+ components: Component[];
6
+ };
7
+
8
+ export interface ServiceExecutionResult {
9
+ errors?: Error[];
10
+ }
11
+
12
+ /**
13
+ * services allows to reuse and standardize services for development environments.
14
+ * examples for services can be: `linting`, `compilation`, `build`, and others which offer
15
+ * standard services to environments such as `react`, `angular` and `vue` and different compositions of each for
16
+ * more concrete needs.
17
+ *
18
+ * `TData` - type of data returned by the service handler.
19
+ * `TOpts` is the type of options passed to the environment through execution.
20
+ * `TExecResponse` is the execution result of the service.
21
+ */
22
+ export interface Service<TExecResponse extends ServiceExecutionResult, TData = {}, TOpts = {}> {
23
+ /**
24
+ * name of the service. (e.g. `compile`, `test`, etc.)
25
+ */
26
+ name?: string;
27
+
28
+ /**
29
+ * description of the env.
30
+ */
31
+ description?: string;
32
+
33
+ /**
34
+ * create a string to describe to service in the env cli.
35
+ */
36
+ render?(env: Environment, context: EnvContext[]): JSX.Element | Promise<JSX.Element>;
37
+
38
+ /**
39
+ * get service data from an environment.
40
+ */
41
+ getDescriptor?(environment: Environment, context?: EnvContext[]): TData | undefined | Promise<TData | undefined>;
42
+
43
+ /**
44
+ * executes a service on a subset of components.
45
+ */
46
+ run?(context: EnvContext, options?: TOpts): Promise<TExecResponse>;
47
+
48
+ /**
49
+ *
50
+ */
51
+ runOnce?(context: EnvContext[], options?: TOpts): Promise<any>;
52
+ }
@@ -0,0 +1,29 @@
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
+ }
@@ -0,0 +1,42 @@
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
+ }