@teambit/isolator 0.0.551 → 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.
@@ -4,13 +4,44 @@ import { Component } from '@teambit/component';
4
4
  import FsContainer, { BitExecOption } from './container';
5
5
  import ContainerExec from './container-exec';
6
6
  export default class Capsule extends CapsuleTemplate<Exec, NodeFS> {
7
+ /**
8
+ * container implementation the capsule is being executed within.
9
+ */
7
10
  protected container: FsContainer;
11
+ /**
12
+ * the capsule's file system.
13
+ */
8
14
  readonly fs: NodeFS;
15
+ /**
16
+ * console for controlling process streams as stdout, stdin and stderr.
17
+ */
9
18
  readonly console: Console;
19
+ /**
20
+ * capsule's state.
21
+ */
10
22
  readonly state: State;
11
23
  readonly component: Component;
12
24
  private _wrkDir;
13
- constructor(container: FsContainer, fs: NodeFS, console: Console, state: State, component: Component);
25
+ constructor(
26
+ /**
27
+ * container implementation the capsule is being executed within.
28
+ */
29
+ container: FsContainer,
30
+ /**
31
+ * the capsule's file system.
32
+ */
33
+ fs: NodeFS,
34
+ /**
35
+ * console for controlling process streams as stdout, stdin and stderr.
36
+ */
37
+ console: Console,
38
+ /**
39
+ * capsule's state.
40
+ */
41
+ state: State, component: Component);
42
+ /**
43
+ * @deprecated please use `this.path`
44
+ */
14
45
  get wrkDir(): string;
15
46
  get path(): string;
16
47
  start(): Promise<any>;
@@ -20,6 +51,13 @@ export default class Capsule extends CapsuleTemplate<Exec, NodeFS> {
20
51
  removePath(dir: string): Promise<any>;
21
52
  symlink(src: string, dest: string): Promise<any>;
22
53
  execute(cmd: string, options?: Record<string, any> | null | undefined): Promise<unknown>;
54
+ /**
55
+ * @todo: fix.
56
+ * it skips the capsule fs because for some reason `capsule.fs.promises.readdir` doesn't work
57
+ * the same as `capsule.fs.readdir` and it doesn't have the capsule dir as pwd.
58
+ *
59
+ * returns the paths inside the capsule
60
+ */
23
61
  getAllFilesPaths(dir?: string, options?: {
24
62
  ignore?: string[];
25
63
  }): any;
@@ -19,21 +19,60 @@ export declare type IsolateComponentsInstallOptions = {
19
19
  installTeambitBit?: boolean;
20
20
  };
21
21
  declare type CreateGraphOptions = {
22
+ /**
23
+ * include components that exists in nested hosts. for example include components that exist in scope but not in the workspace
24
+ */
22
25
  includeFromNestedHosts?: boolean;
26
+ /**
27
+ * Force specific host to get the component from.
28
+ */
23
29
  host?: ComponentFactory;
24
30
  };
25
31
  export declare type IsolateComponentsOptions = CreateGraphOptions & {
26
32
  name?: string;
33
+ /**
34
+ * absolute path to put all the capsules dirs inside.
35
+ */
27
36
  rootBaseDir?: string;
37
+ /**
38
+ * the capsule root-dir based on a *hash* of this baseDir, not on the baseDir itself.
39
+ * A folder with this hash as its name will be created in the rootBaseDir
40
+ * By default this value will be the host path
41
+ */
28
42
  baseDir?: string;
43
+ /**
44
+ * create a new capsule with a random string attached to the path suffix
45
+ */
29
46
  alwaysNew?: boolean;
47
+ /**
48
+ * installation options
49
+ */
30
50
  installOptions?: IsolateComponentsInstallOptions;
31
51
  linkingOptions?: LinkingOptions;
52
+ /**
53
+ * delete the capsule rootDir first. it makes sure that the isolation process starts fresh with
54
+ * no previous capsules. for build and tag this is true.
55
+ */
32
56
  emptyRootDir?: boolean;
57
+ /**
58
+ * skip the reproduction of the capsule in case it exists.
59
+ */
33
60
  skipIfExists?: boolean;
61
+ /**
62
+ * get existing capsule without doing any changes, no writes, no installations.
63
+ */
34
64
  getExistingAsIs?: boolean;
65
+ /**
66
+ * place the package-manager cache on the capsule-root
67
+ */
35
68
  cachePackagesOnCapsulesRoot?: boolean;
69
+ /**
70
+ * do not build graph with all dependencies. isolate the seeders only.
71
+ */
36
72
  seedersOnly?: boolean;
73
+ /**
74
+ * Force specific host to get the component from.
75
+ */
37
76
  host?: ComponentFactory;
38
77
  };
39
78
  export declare class IsolatorMain {
@@ -58,6 +97,13 @@ export declare class IsolatorMain {
58
97
  constructor(dependencyResolver: DependencyResolverMain, logger: Logger, componentAspect: ComponentMain, graphBuilder: GraphBuilder, globalConfig: GlobalConfigMain);
59
98
  isolateComponents(seeders: ComponentID[], opts?: IsolateComponentsOptions, legacyScope?: LegacyScope): Promise<Network>;
60
99
  private createGraph;
100
+ /**
101
+ * Create capsules for the provided components
102
+ * do not use this outside directly, use isolate components which build the entire network
103
+ * @param components
104
+ * @param opts
105
+ * @param legacyScope
106
+ */
61
107
  private createCapsules;
62
108
  private installInCapsules;
63
109
  private linkInCapsules;
package/dist/network.d.ts CHANGED
@@ -6,7 +6,14 @@ export declare class Network {
6
6
  private seedersIds;
7
7
  private _capsulesRootDir;
8
8
  constructor(_graphCapsules: CapsuleList, seedersIds: ComponentID[], _capsulesRootDir: string);
9
+ /**
10
+ * seeders capsules only without the entire graph. normally, this includes the capsules of one
11
+ * env.
12
+ */
9
13
  get seedersCapsules(): CapsuleList;
14
+ /**
15
+ * all capsules, including the dependencies of the seeders. (even when they belong to another env)
16
+ */
10
17
  get graphCapsules(): CapsuleList;
11
18
  get capsulesRootDir(): PathOsBasedAbsolute;
12
19
  }
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@teambit/isolator",
3
- "version": "0.0.551",
3
+ "version": "0.0.556",
4
4
  "homepage": "https://bit.dev/teambit/component/isolator",
5
5
  "main": "dist/index.js",
6
6
  "componentId": {
7
7
  "scope": "teambit.component",
8
8
  "name": "isolator",
9
- "version": "0.0.551"
9
+ "version": "0.0.556"
10
10
  },
11
11
  "dependencies": {
12
12
  "@teambit/harmony": "0.2.11",
@@ -23,14 +23,14 @@
23
23
  "execa": "2.1.0",
24
24
  "@babel/runtime": "7.12.18",
25
25
  "core-js": "^3.0.0",
26
- "@teambit/component": "0.0.551",
27
- "@teambit/legacy-bit-id": "0.0.371",
28
- "@teambit/cli": "0.0.382",
29
- "@teambit/component-package-version": "0.0.368",
30
- "@teambit/dependency-resolver": "0.0.551",
31
- "@teambit/global-config": "0.0.383",
32
- "@teambit/graph": "0.0.551",
33
- "@teambit/logger": "0.0.467"
26
+ "@teambit/component": "0.0.556",
27
+ "@teambit/legacy-bit-id": "0.0.376",
28
+ "@teambit/cli": "0.0.387",
29
+ "@teambit/component-package-version": "0.0.373",
30
+ "@teambit/dependency-resolver": "0.0.556",
31
+ "@teambit/global-config": "0.0.388",
32
+ "@teambit/graph": "0.0.556",
33
+ "@teambit/logger": "0.0.472"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/fs-extra": "9.0.7",
@@ -45,7 +45,7 @@
45
45
  "@types/node": "12.20.4"
46
46
  },
47
47
  "peerDependencies": {
48
- "@teambit/legacy": "1.0.169",
48
+ "@teambit/legacy": "1.0.173",
49
49
  "react-dom": "^16.8.0 || ^17.0.0",
50
50
  "react": "^16.8.0 || ^17.0.0"
51
51
  },
@@ -73,12 +73,18 @@
73
73
  "react": "-"
74
74
  },
75
75
  "peerDependencies": {
76
- "@teambit/legacy": "1.0.169",
76
+ "@teambit/legacy": "1.0.173",
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
+ "README.md",
86
+ "README.mdx"
87
+ ],
82
88
  "private": false,
83
89
  "engines": {
84
90
  "node": ">=12.22.0"
@@ -1,138 +0,0 @@
1
- import { NodeFS } from '@teambit/any-fs';
2
- import { Capsule as CapsuleTemplate, Console, Exec, State } from '@teambit/capsule';
3
- import { Component } from '@teambit/component';
4
- import filenamify from 'filenamify';
5
- import { realpathSync } from 'fs';
6
- import glob from 'glob';
7
- import path from 'path';
8
- import v4 from 'uuid';
9
-
10
- import FsContainer, { BitExecOption } from './container';
11
- import ContainerExec from './container-exec';
12
-
13
- export default class Capsule extends CapsuleTemplate<Exec, NodeFS> {
14
- private _wrkDir: string;
15
- constructor(
16
- /**
17
- * container implementation the capsule is being executed within.
18
- */
19
- protected container: FsContainer,
20
- /**
21
- * the capsule's file system.
22
- */
23
- readonly fs: NodeFS,
24
- /**
25
- * console for controlling process streams as stdout, stdin and stderr.
26
- */
27
- readonly console: Console = new Console(),
28
- /**
29
- * capsule's state.
30
- */
31
- readonly state: State,
32
- readonly component: Component
33
- ) {
34
- super(container, fs, console, state);
35
- this._wrkDir = container.wrkDir;
36
- }
37
-
38
- /**
39
- * @deprecated please use `this.path`
40
- */
41
- get wrkDir(): string {
42
- return this.path;
43
- }
44
-
45
- get path(): string {
46
- return realpathSync(this._wrkDir);
47
- }
48
-
49
- start(): Promise<any> {
50
- return this.container.start();
51
- }
52
-
53
- async execNode(executable: string, args: any, exec: ContainerExec) {
54
- return this.typedExec(
55
- {
56
- command: ['node', executable, ...(args.args || [])],
57
- cwd: '',
58
- },
59
- exec
60
- );
61
- }
62
-
63
- async typedExec(opts: BitExecOption, exec = new ContainerExec()) {
64
- return this.container.exec(opts, exec);
65
- }
66
-
67
- outputFile(file: string, data: any, options?: any): Promise<any> {
68
- return this.container.outputFile(file, data, options);
69
- }
70
-
71
- removePath(dir: string): Promise<any> {
72
- return this.container.removePath(dir);
73
- }
74
-
75
- symlink(src: string, dest: string): Promise<any> {
76
- return this.container.symlink(src, dest);
77
- }
78
-
79
- // TODO: refactor this crap and simplify capsule API
80
- async execute(cmd: string, options?: Record<string, any> | null | undefined) {
81
- // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
82
- const execResults = await this.exec({ command: cmd.split(' '), options });
83
- let stdout = '';
84
- let stderr = '';
85
- return new Promise((resolve, reject) => {
86
- execResults.stdout.on('data', (data: string) => {
87
- stdout += data;
88
- });
89
- execResults.stdout.on('error', (error: string) => {
90
- return reject(error);
91
- });
92
- // @ts-ignore
93
- execResults.on('close', () => {
94
- return resolve({ stdout, stderr });
95
- });
96
- execResults.stderr.on('error', (error: string) => {
97
- return reject(error);
98
- });
99
- execResults.stderr.on('data', (data: string) => {
100
- stderr += data;
101
- });
102
- });
103
- }
104
-
105
- /**
106
- * @todo: fix.
107
- * it skips the capsule fs because for some reason `capsule.fs.promises.readdir` doesn't work
108
- * the same as `capsule.fs.readdir` and it doesn't have the capsule dir as pwd.
109
- *
110
- * returns the paths inside the capsule
111
- */
112
- getAllFilesPaths(dir = '.', options: { ignore?: string[] } = {}) {
113
- const files = glob.sync('**', { cwd: path.join(this.path, dir), nodir: true, ...options });
114
- return files.map((file) => path.join(dir, file));
115
- }
116
-
117
- static getCapsuleDirName(component: Component, config: { alwaysNew?: boolean; name?: string } = {}) {
118
- return config.name || filenamify(component.id.toString(), { replacement: '_' });
119
- }
120
-
121
- static getCapsuleRootDir(component: Component, baseDir: string, config: { alwaysNew?: boolean; name?: string } = {}) {
122
- return path.join(baseDir, Capsule.getCapsuleDirName(component, config));
123
- }
124
-
125
- static async createFromComponent(
126
- component: Component,
127
- baseDir: string,
128
- config: { alwaysNew?: boolean; name?: string } = {}
129
- ): Promise<Capsule> {
130
- // TODO: make this a static method and combine with ComponentCapsule
131
- const capsuleDirName = Capsule.getCapsuleDirName(component, config);
132
- const wrkDir = path.join(baseDir, config.alwaysNew ? `${capsuleDirName}_${v4()}` : capsuleDirName);
133
- const container = new FsContainer(wrkDir);
134
- const capsule = new Capsule(container, container.fs, new Console(), new State(), component);
135
- await capsule.start();
136
- return capsule;
137
- }
138
- }
@@ -1,31 +0,0 @@
1
- import { DuplexBufferStream, Exec, ExecStatus } from '@teambit/capsule';
2
- import { EventEmitter } from 'events';
3
-
4
- export default class ContainerExec extends EventEmitter implements Exec {
5
- constructor(private _code: number = 0) {
6
- super();
7
- }
8
-
9
- stdout: DuplexBufferStream = new DuplexBufferStream();
10
- stderr: DuplexBufferStream = new DuplexBufferStream();
11
- stdin: DuplexBufferStream = new DuplexBufferStream();
12
-
13
- setStatus(status: number): void {
14
- this._code = status;
15
- this.emit('close');
16
- }
17
-
18
- get code(): number {
19
- return this._code;
20
- }
21
-
22
- inspect(): Promise<ExecStatus> {
23
- return Promise.resolve({
24
- running: true,
25
- pid: 1,
26
- });
27
- }
28
- abort(): Promise<void> {
29
- throw new Error('Method not implemented.');
30
- }
31
- }
@@ -1,128 +0,0 @@
1
- import { AnyFS, NodeFS } from '@teambit/any-fs';
2
- import { Container, ContainerFactoryOptions, ContainerStatus, Exec, ExecOptions } from '@teambit/capsule';
3
- import execa from 'execa';
4
- import fs from 'fs-extra';
5
- import * as path from 'path';
6
- import { Stream } from 'stream';
7
-
8
- import ContainerExec from './container-exec';
9
-
10
- const debug = require('debug')('fs-container');
11
-
12
- export interface BitExecOption extends ExecOptions {
13
- cwd: string;
14
- stdio?: 'pipe' | 'ipc' | 'ignore' | 'inherit' | Stream | number | undefined;
15
- }
16
- export interface BitContainerConfig extends ContainerFactoryOptions {
17
- other?: string;
18
- }
19
-
20
- export default class FsContainer implements Container<Exec, AnyFS> {
21
- id = 'FS Container';
22
-
23
- fs: NodeFS = new NodeFS(this.wrkDir);
24
-
25
- constructor(readonly wrkDir: string) {}
26
-
27
- // TODO: do we need this?
28
- public getPath() {
29
- return this.wrkDir;
30
- }
31
-
32
- private composePath(pathToCompose) {
33
- return path.join(this.getPath(), pathToCompose);
34
- }
35
-
36
- outputFile(file, data, options) {
37
- const filePath = this.composePath(file);
38
- debug(`writing file on ${filePath}`);
39
- return fs.outputFile(filePath, data, options);
40
- }
41
-
42
- removePath(dir: string): Promise<any> {
43
- const pathToRemove = this.composePath(dir);
44
- return fs.remove(pathToRemove);
45
- }
46
-
47
- async symlink(src: string, dest: string): Promise<any> {
48
- const srcPath = this.composePath(src);
49
- const destPath = this.composePath(dest);
50
- await fs.ensureDir(path.dirname(destPath));
51
- return fs.ensureSymlink(srcPath, destPath);
52
- }
53
-
54
- async exec(execOptions: BitExecOption, exec = new ContainerExec()): Promise<ContainerExec> {
55
- const cwd = execOptions.cwd ? this.composePath(execOptions.cwd) : this.getPath();
56
- debug(`executing the following command: ${execOptions.command.join(' ')}, on cwd: ${cwd}`);
57
- const subprocessP = execa.command(execOptions.command.join(' '), {
58
- shell: true,
59
- cwd,
60
- stdio: ['ipc'],
61
- });
62
-
63
- // @TODO: FIX! This probably causes errors ad the promise is not handled properly!
64
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
65
- subprocessP.on('message', function (msg: any) {
66
- exec.emit('message', msg);
67
- });
68
- /* eslint-disable @typescript-eslint/no-non-null-assertion */
69
- subprocessP.stderr?.pipe(exec.stderr);
70
- subprocessP.stdout?.pipe(exec.stdout);
71
- ['close', 'exit'].forEach(function (eventName: string) {
72
- // @TODO: FIX! This probably causes errors ad the promise is not handled properly!
73
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
74
- subprocessP.on(eventName, function (statusCode) {
75
- exec.setStatus(statusCode);
76
- });
77
- });
78
-
79
- return exec;
80
- }
81
-
82
- async execP(execOptions: BitExecOption): Promise<string> {
83
- let hasError = false;
84
- const exec = await this.exec(execOptions);
85
- return new Promise((resolve, reject) => {
86
- exec.stdout.on('error', () => {
87
- hasError = true;
88
- });
89
- exec.on('close', () => {
90
- if (hasError) reject(exec.stderr.getContents!(exec.stderr.size).toString());
91
- resolve(exec.stdout.getContents!(exec.stdout.size).toString());
92
- });
93
- });
94
- }
95
-
96
- async terminal() {
97
- const cwd = this.getPath();
98
- return execa.command(process.env.SHELL || '/bin/zsh', { cwd, stdio: 'inherit' });
99
- }
100
-
101
- start(): Promise<void> {
102
- return fs.ensureDir(this.wrkDir);
103
- }
104
- // @ts-ignore
105
- async inspect(): Promise<ContainerStatus> {
106
- // todo: probably not needed for this container
107
- }
108
- async pause(): Promise<void> {
109
- // do nothing
110
- }
111
- async resume(): Promise<void> {
112
- // do nothing
113
- }
114
- // eslint-disable-next-line
115
- stop(ttl?: number | undefined): Promise<void> {
116
- return fs.remove(this.wrkDir);
117
- }
118
- async destroy(): Promise<void> {
119
- await this.stop();
120
- }
121
- log(): Promise<Exec> {
122
- throw new Error('Method not implemented.');
123
- }
124
- on(event: string, fn: (data: any) => void): void {
125
- return fn(event);
126
- // throw new Error('Method not implemented.');
127
- }
128
- }
package/capsule/index.ts DELETED
@@ -1,3 +0,0 @@
1
- export { default as Capsule } from './capsule';
2
- export { default as FsContainer } from './container';
3
- export { default as ContainerExec } from './container-exec';
package/capsule-list.ts DELETED
@@ -1,33 +0,0 @@
1
- import type { Component, ComponentID } from '@teambit/component';
2
- import { normalize } from 'path';
3
- import { BitId } from '@teambit/legacy-bit-id';
4
- import { Capsule } from './capsule';
5
-
6
- export default class CapsuleList extends Array<Capsule> {
7
- getCapsule(id: ComponentID): Capsule | undefined {
8
- return this.find((capsule) => capsule.component.id.isEqual(id));
9
- }
10
- getCapsuleByLegacyId(id: BitId): Capsule | undefined {
11
- return this.find((capsule) => capsule.component.id._legacy.isEqual(id));
12
- }
13
- getCapsuleIgnoreVersion(id: ComponentID): Capsule | undefined {
14
- return this.find((capsule) => capsule.component.id._legacy.isEqualWithoutVersion(id._legacy));
15
- }
16
- getCapsuleIgnoreScopeAndVersion(id: ComponentID): Capsule | undefined {
17
- return this.find((capsule) => capsule.component.id._legacy.isEqualWithoutScopeAndVersion(id._legacy));
18
- }
19
- getAllCapsuleDirs(): string[] {
20
- return this.map((capsule) => capsule.path);
21
- }
22
- getIdByPathInCapsule(pathInCapsule: string): ComponentID | null {
23
- const normalizedPathInCapsule = normalize(pathInCapsule);
24
- const found = this.find((capsule) => normalizedPathInCapsule === normalize(capsule.path));
25
- return found ? found.component.id : null;
26
- }
27
- getAllComponents(): Component[] {
28
- return this.map((c) => c.component);
29
- }
30
- static fromArray(capsules: Capsule[]) {
31
- return new CapsuleList(...capsules);
32
- }
33
- }
package/index.ts DELETED
@@ -1,6 +0,0 @@
1
- export { IsolateComponentsOptions } from './isolator.main.runtime';
2
- export { Network } from './network';
3
- export { FsContainer, Capsule, ContainerExec } from './capsule';
4
- export type { IsolatorMain } from './isolator.main.runtime';
5
- export { IsolatorAspect } from './isolator.aspect';
6
- export { default as CapsuleList } from './capsule-list';
@@ -1,7 +0,0 @@
1
- import { Aspect } from '@teambit/harmony';
2
-
3
- export const IsolatorAspect = Aspect.create({
4
- id: 'teambit.component/isolator',
5
- dependencies: [],
6
- defaultConfig: {},
7
- });
package/isolator.docs.md DELETED
@@ -1,41 +0,0 @@
1
- ---
2
- description: Isolate components for build, debugging, development and testing.
3
- labels: ['isolation', 'component']
4
- ---
5
-
6
- ## Isolate a component
7
-
8
- ```bash
9
- bit create-capsule ui/button
10
- ```
11
-
12
- ## Entities
13
-
14
- ### Capsule
15
-
16
- Bit implements a filesystem capsule, which is an isolated folder containing the component files.
17
- Capsules include the component files and links to other capsules that include the component's dependencies.
18
-
19
- ### Network
20
-
21
- A network is a group of capsules, related to one another by their dependencies.
22
- A network includes a graph of all seed components given to it, as well as a list of the capsules.
23
-
24
- Example:
25
-
26
- ```javascript
27
- const Network = {
28
- graph: Graph,
29
- capsules: CapsuleList,
30
- };
31
- ```
32
-
33
- ## API
34
-
35
- The exact particularities of this API are beyond the scope of this readme. Instead, this document opts to
36
- provide a general description of the methods of this API and their purpose.
37
-
38
- ### Isolator.isolateComponents
39
-
40
- This method receives a list of components, create capsule for the components and write the components data into the capsule.
41
- It returns a list of capsules.