@teambit/generator 1.0.107 → 1.0.109
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.
- package/component-generator.ts +284 -0
- package/component-template.ts +152 -0
- package/create.cmd.ts +88 -0
- package/dist/component-generator.d.ts +3 -3
- package/dist/component-generator.js +5 -9
- package/dist/component-generator.js.map +1 -1
- package/dist/component-template.d.ts +2 -2
- package/dist/create.cmd.d.ts +1 -1
- package/dist/generator.composition.d.ts +2 -2
- package/dist/generator.graphql.d.ts +1 -1
- package/dist/generator.main.runtime.d.ts +11 -10
- package/dist/generator.main.runtime.js +2 -2
- package/dist/generator.main.runtime.js.map +1 -1
- package/dist/generator.service.d.ts +1 -1
- package/dist/generator.service.js +1 -1
- package/dist/generator.service.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/new.cmd.d.ts +2 -1
- package/dist/new.cmd.js +1 -1
- package/dist/new.cmd.js.map +1 -1
- package/dist/{preview-1703505948637.js → preview-1703647408454.js} +2 -2
- package/dist/starter-list.d.ts +1 -1
- package/dist/template-list.d.ts +1 -1
- package/dist/templates.cmd.d.ts +1 -1
- package/dist/workspace-generator.d.ts +6 -2
- package/dist/workspace-generator.js +24 -20
- package/dist/workspace-generator.js.map +1 -1
- package/dist/workspace-template.d.ts +36 -2
- package/dist/workspace-template.js.map +1 -1
- package/generator-env-type.ts +14 -0
- package/generator.aspect.ts +5 -0
- package/generator.graphql.ts +62 -0
- package/generator.main.runtime.ts +600 -0
- package/index.ts +23 -0
- package/new.cmd.ts +120 -0
- package/package.json +30 -37
- package/starter-list.ts +21 -0
- package/starter.plugin.ts +16 -0
- package/template-list.ts +21 -0
- package/templates.cmd.ts +57 -0
- package/tsconfig.json +16 -21
- package/types/asset.d.ts +15 -3
- package/types.ts +3 -0
- package/workspace-generator.ts +220 -0
- package/workspace-template.ts +183 -0
package/new.cmd.ts
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
import { Command, CommandOptions } from '@teambit/cli';
|
2
|
+
import chalk from 'chalk';
|
3
|
+
import { GeneratorMain } from './generator.main.runtime';
|
4
|
+
import { BaseWorkspaceOptions } from './workspace-template';
|
5
|
+
|
6
|
+
/**
|
7
|
+
* NewOptions combines foundational properties with additional options for creating a workspace.
|
8
|
+
*/
|
9
|
+
export type NewOptions = BaseWorkspaceOptions;
|
10
|
+
|
11
|
+
export class NewCmd implements Command {
|
12
|
+
name = 'new <template-name> <workspace-name>';
|
13
|
+
description = 'create a new workspace from a template';
|
14
|
+
arguments = [
|
15
|
+
{
|
16
|
+
name: 'template-name',
|
17
|
+
description:
|
18
|
+
"the name of the workspace template (run 'bit templates' outside of a workspace to get a list of available workspace templates)",
|
19
|
+
},
|
20
|
+
{
|
21
|
+
name: 'workspace-name',
|
22
|
+
description: 'the name for the new workspace and workspace directory that will be created',
|
23
|
+
},
|
24
|
+
];
|
25
|
+
alias = '';
|
26
|
+
loader = true;
|
27
|
+
group = 'start';
|
28
|
+
options = [
|
29
|
+
[
|
30
|
+
'a',
|
31
|
+
'aspect <aspect-id>',
|
32
|
+
'id of the aspect that registered the template, mandatory for non-core aspects. helpful for core aspects in case of a name collision',
|
33
|
+
],
|
34
|
+
['t', 'template <env-id>', "env-id of the template's owner. Alias for --env."],
|
35
|
+
['', 'env <env-id>', 'env-id of the template. Alias -t'],
|
36
|
+
['d', 'default-scope <scope-name>', `set defaultScope in the new workspace's workspace.jsonc`],
|
37
|
+
['', 'standalone', 'DEPRECATED. use --skip-git instead'],
|
38
|
+
['s', 'skip-git', 'skip generation of Git repository in the new workspace'],
|
39
|
+
[
|
40
|
+
'e',
|
41
|
+
'empty',
|
42
|
+
"skip template's default component creation (relevant for templates that add components by default)",
|
43
|
+
],
|
44
|
+
[
|
45
|
+
'',
|
46
|
+
'load-from <path-to-template>',
|
47
|
+
'local path to the workspace containing the template. Helpful during a development of a workspace-template',
|
48
|
+
],
|
49
|
+
[
|
50
|
+
'c',
|
51
|
+
'current-dir',
|
52
|
+
'create the new workspace in current directory (default is to create a new directory, inside the current dir)',
|
53
|
+
],
|
54
|
+
] as CommandOptions;
|
55
|
+
|
56
|
+
constructor(private generator: GeneratorMain) {}
|
57
|
+
|
58
|
+
async report(
|
59
|
+
[templateName, workspaceName]: [string, string],
|
60
|
+
options: NewOptions & {
|
61
|
+
standalone: boolean;
|
62
|
+
env?: string;
|
63
|
+
template?: string;
|
64
|
+
aspect?: string;
|
65
|
+
currentDir?: boolean;
|
66
|
+
}
|
67
|
+
) {
|
68
|
+
options.skipGit = options.skipGit ?? options.standalone;
|
69
|
+
options.aspect = options.aspect ?? options.env ?? options.template;
|
70
|
+
const { workspacePath, appName } = await this.generator.generateWorkspaceTemplate(
|
71
|
+
workspaceName,
|
72
|
+
templateName,
|
73
|
+
options
|
74
|
+
);
|
75
|
+
return chalk.white(
|
76
|
+
`${chalk.green(`
|
77
|
+
|
78
|
+
Congrats! A new workspace has been created successfully at '${workspacePath}'`)}
|
79
|
+
|
80
|
+
Inside the directory '${workspaceName}' you can run various commands including:
|
81
|
+
|
82
|
+
${chalk.yellow('bit start')}
|
83
|
+
Starts the local dev server
|
84
|
+
|
85
|
+
${chalk.yellow('bit install')}
|
86
|
+
Installs any missing dependencies
|
87
|
+
|
88
|
+
${chalk.yellow('bit status')}
|
89
|
+
Shows the status of the components
|
90
|
+
|
91
|
+
${chalk.yellow('bit compile')}
|
92
|
+
Compiles the components
|
93
|
+
|
94
|
+
${chalk.yellow('bit test')}
|
95
|
+
Runs the tests on all your components
|
96
|
+
|
97
|
+
${chalk.yellow('bit templates')}
|
98
|
+
Shows all available component templates
|
99
|
+
|
100
|
+
${chalk.yellow('bit help')}
|
101
|
+
Shows all available commands
|
102
|
+
|
103
|
+
|
104
|
+
${chalk.green.bold("Let's get started!")}
|
105
|
+
|
106
|
+
${getBottomSection(workspaceName, appName)}
|
107
|
+
`
|
108
|
+
);
|
109
|
+
}
|
110
|
+
}
|
111
|
+
|
112
|
+
function getBottomSection(workspaceName: string, appName: string | undefined) {
|
113
|
+
const cdLine = chalk.yellow(`cd ${workspaceName}`);
|
114
|
+
const parts = [cdLine];
|
115
|
+
if (appName) {
|
116
|
+
parts.push(chalk.yellow(` bit run ${appName}`));
|
117
|
+
}
|
118
|
+
parts.push(chalk.yellow(` bit start`));
|
119
|
+
return parts.join('\n');
|
120
|
+
}
|
package/package.json
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "@teambit/generator",
|
3
|
-
"version": "1.0.
|
3
|
+
"version": "1.0.109",
|
4
4
|
"homepage": "https://bit.cloud/teambit/generator/generator",
|
5
5
|
"main": "dist/index.js",
|
6
6
|
"componentId": {
|
7
7
|
"scope": "teambit.generator",
|
8
8
|
"name": "generator",
|
9
|
-
"version": "1.0.
|
9
|
+
"version": "1.0.109"
|
10
10
|
},
|
11
11
|
"dependencies": {
|
12
12
|
"camelcase": "6.2.0",
|
@@ -17,47 +17,43 @@
|
|
17
17
|
"graphql-tag": "2.12.1",
|
18
18
|
"lodash": "4.17.21",
|
19
19
|
"execa": "2.1.0",
|
20
|
-
"core-js": "^3.0.0",
|
21
|
-
"@babel/runtime": "7.20.0",
|
22
20
|
"@teambit/bit-error": "0.0.404",
|
23
21
|
"@teambit/component-id": "1.2.0",
|
24
22
|
"@teambit/harmony": "0.4.6",
|
25
23
|
"@teambit/git.modules.git-ignore": "1.0.2",
|
26
|
-
"@teambit/envs": "1.0.
|
27
|
-
"@teambit/logger": "0.0.
|
28
|
-
"@teambit/new-component-helper": "1.0.
|
29
|
-
"@teambit/tracker": "1.0.
|
30
|
-
"@teambit/workspace-config-files": "1.0.
|
31
|
-
"@teambit/workspace.modules.node-modules-linker": "0.0.
|
32
|
-
"@teambit/workspace": "1.0.
|
33
|
-
"@teambit/component": "1.0.
|
34
|
-
"@teambit/cli": "0.0.
|
35
|
-
"@teambit/graphql": "1.0.
|
36
|
-
"@teambit/aspect-loader": "1.0.
|
37
|
-
"@teambit/bit": "1.
|
38
|
-
"@teambit/git": "1.0.
|
39
|
-
"@teambit/compiler": "1.0.
|
40
|
-
"@teambit/forking": "1.0.
|
41
|
-
"@teambit/importer": "1.0.
|
42
|
-
"@teambit/install": "1.0.
|
43
|
-
"@teambit/ui": "1.0.
|
44
|
-
"@teambit/config": "0.0.
|
24
|
+
"@teambit/envs": "1.0.108",
|
25
|
+
"@teambit/logger": "0.0.933",
|
26
|
+
"@teambit/new-component-helper": "1.0.108",
|
27
|
+
"@teambit/tracker": "1.0.108",
|
28
|
+
"@teambit/workspace-config-files": "1.0.108",
|
29
|
+
"@teambit/workspace.modules.node-modules-linker": "0.0.158",
|
30
|
+
"@teambit/workspace": "1.0.108",
|
31
|
+
"@teambit/component": "1.0.108",
|
32
|
+
"@teambit/cli": "0.0.840",
|
33
|
+
"@teambit/graphql": "1.0.108",
|
34
|
+
"@teambit/aspect-loader": "1.0.108",
|
35
|
+
"@teambit/bit": "1.6.1",
|
36
|
+
"@teambit/git": "1.0.108",
|
37
|
+
"@teambit/compiler": "1.0.108",
|
38
|
+
"@teambit/forking": "1.0.108",
|
39
|
+
"@teambit/importer": "1.0.108",
|
40
|
+
"@teambit/install": "1.0.108",
|
41
|
+
"@teambit/ui": "1.0.108",
|
42
|
+
"@teambit/config": "0.0.859"
|
45
43
|
},
|
46
44
|
"devDependencies": {
|
47
45
|
"@types/fs-extra": "9.0.7",
|
48
|
-
"@types/react": "^17.0.8",
|
49
46
|
"@types/lodash": "4.14.165",
|
50
47
|
"@types/mocha": "9.1.0",
|
51
|
-
"@types/
|
52
|
-
"@types/
|
53
|
-
"@
|
54
|
-
"@types/testing-library__jest-dom": "5.9.5",
|
48
|
+
"@types/jest": "^29.2.2",
|
49
|
+
"@types/testing-library__jest-dom": "^5.9.5",
|
50
|
+
"@teambit/harmony.envs.core-aspect-env": "0.0.13",
|
55
51
|
"@teambit/generator.aspect-docs.generator": "0.0.169"
|
56
52
|
},
|
57
53
|
"peerDependencies": {
|
58
|
-
"
|
59
|
-
"react": "^
|
60
|
-
"
|
54
|
+
"react": "^17.0.0 || ^18.0.0",
|
55
|
+
"@types/react": "^18.2.12",
|
56
|
+
"@teambit/legacy": "1.0.624"
|
61
57
|
},
|
62
58
|
"license": "Apache-2.0",
|
63
59
|
"optionalDependencies": {},
|
@@ -71,7 +67,7 @@
|
|
71
67
|
},
|
72
68
|
"private": false,
|
73
69
|
"engines": {
|
74
|
-
"node": ">=
|
70
|
+
"node": ">=16.0.0"
|
75
71
|
},
|
76
72
|
"repository": {
|
77
73
|
"type": "git",
|
@@ -80,12 +76,9 @@
|
|
80
76
|
"keywords": [
|
81
77
|
"bit",
|
82
78
|
"bit-aspect",
|
79
|
+
"bit-core-aspect",
|
83
80
|
"components",
|
84
81
|
"collaboration",
|
85
|
-
"web"
|
86
|
-
"react",
|
87
|
-
"react-components",
|
88
|
-
"angular",
|
89
|
-
"angular-components"
|
82
|
+
"web"
|
90
83
|
]
|
91
84
|
}
|
package/starter-list.ts
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
import { EnvContext, EnvHandler } from '@teambit/envs';
|
2
|
+
import { WorkspaceTemplate } from './workspace-template';
|
3
|
+
|
4
|
+
export type StarterListOptions = {
|
5
|
+
name?: string;
|
6
|
+
};
|
7
|
+
|
8
|
+
export class StarterList {
|
9
|
+
constructor(readonly name: string, private starters: EnvHandler<WorkspaceTemplate>[], private context: EnvContext) {}
|
10
|
+
|
11
|
+
compute(): WorkspaceTemplate[] {
|
12
|
+
return this.starters.map((starter) => starter(this.context));
|
13
|
+
}
|
14
|
+
|
15
|
+
static from(starters: EnvHandler<WorkspaceTemplate>[], options: StarterListOptions = {}) {
|
16
|
+
return (context: EnvContext) => {
|
17
|
+
const name = options.name || 'starter-list';
|
18
|
+
return new StarterList(name, starters, context);
|
19
|
+
};
|
20
|
+
}
|
21
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { PluginDefinition } from '@teambit/aspect-loader';
|
2
|
+
import { MainRuntime } from '@teambit/cli';
|
3
|
+
import { GeneratorMain } from './generator.main.runtime';
|
4
|
+
|
5
|
+
export class StarterPlugin implements PluginDefinition {
|
6
|
+
constructor(private generator: GeneratorMain) {}
|
7
|
+
|
8
|
+
pattern = '*.starter.*';
|
9
|
+
|
10
|
+
runtimes = [MainRuntime.name];
|
11
|
+
|
12
|
+
register(object: any) {
|
13
|
+
const templates = Array.isArray(object) ? object : [object];
|
14
|
+
return this.generator.registerWorkspaceTemplate(templates);
|
15
|
+
}
|
16
|
+
}
|
package/template-list.ts
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
import { EnvContext, EnvHandler } from '@teambit/envs';
|
2
|
+
import { ComponentTemplate } from './component-template';
|
3
|
+
|
4
|
+
export type TemplateListOptions = {
|
5
|
+
name?: string;
|
6
|
+
};
|
7
|
+
|
8
|
+
export class TemplateList {
|
9
|
+
constructor(readonly name: string, private templates: EnvHandler<ComponentTemplate>[], private context: EnvContext) {}
|
10
|
+
|
11
|
+
compute(): ComponentTemplate[] {
|
12
|
+
return this.templates.map((template) => template(this.context));
|
13
|
+
}
|
14
|
+
|
15
|
+
static from(templates: EnvHandler<ComponentTemplate>[], options: TemplateListOptions = {}) {
|
16
|
+
return (context: EnvContext) => {
|
17
|
+
const name = options.name || 'template-list';
|
18
|
+
return new TemplateList(name, templates, context);
|
19
|
+
};
|
20
|
+
}
|
21
|
+
}
|
package/templates.cmd.ts
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
import { Command, CommandOptions } from '@teambit/cli';
|
2
|
+
import chalk from 'chalk';
|
3
|
+
import { groupBy } from 'lodash';
|
4
|
+
import { GeneratorMain, TemplateDescriptor } from './generator.main.runtime';
|
5
|
+
|
6
|
+
export type TemplatesOptions = {
|
7
|
+
showAll?: boolean;
|
8
|
+
aspect?: string;
|
9
|
+
};
|
10
|
+
|
11
|
+
export class TemplatesCmd implements Command {
|
12
|
+
name = 'templates';
|
13
|
+
description = 'list available templates for "bit create" and "bit new"';
|
14
|
+
extendedDescription =
|
15
|
+
'list components templates when inside bit-workspace (for bit-create), otherwise, list workspace templates (for bit-new)';
|
16
|
+
alias = '';
|
17
|
+
loader = true;
|
18
|
+
group = 'development';
|
19
|
+
options = [
|
20
|
+
['s', 'show-all', 'show hidden templates'],
|
21
|
+
['a', 'aspect <aspect-id>', 'show templates provided by the aspect-id'],
|
22
|
+
] as CommandOptions;
|
23
|
+
|
24
|
+
constructor(private generator: GeneratorMain) {}
|
25
|
+
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
27
|
+
async report(args: [], templatesOptions: TemplatesOptions) {
|
28
|
+
let results = await this.generator.listTemplates(templatesOptions);
|
29
|
+
|
30
|
+
// Make sure that we don't list hidden templates
|
31
|
+
if (!templatesOptions.showAll) {
|
32
|
+
results = results.filter((template) => !template.hidden);
|
33
|
+
}
|
34
|
+
|
35
|
+
const grouped = groupBy(results, 'aspectId');
|
36
|
+
const titleStr = this.generator.isRunningInsideWorkspace()
|
37
|
+
? `The following template(s) are available with the command bit create: \nExample - bit create <template-name> <component-name>`
|
38
|
+
: `The following template(s) are available with the command bit new: \nExample - bit new <template-name> <workspace-name>`;
|
39
|
+
const title = chalk.green(`\n${titleStr}\n`);
|
40
|
+
const templateOutput = (template: TemplateDescriptor) => {
|
41
|
+
const desc = template.description ? ` (${template.description})` : '';
|
42
|
+
return ` ${template.name}${chalk.dim(desc)}`;
|
43
|
+
};
|
44
|
+
const output = Object.keys(grouped)
|
45
|
+
.map((aspectId) => {
|
46
|
+
const names = grouped[aspectId].map(templateOutput).join('\n');
|
47
|
+
const groupTitle = grouped[aspectId][0].titlePrefix
|
48
|
+
? `${grouped[aspectId][0].titlePrefix} (${aspectId})`
|
49
|
+
: aspectId;
|
50
|
+
return `${chalk.blue.bold(groupTitle)}\n${names}\n`;
|
51
|
+
})
|
52
|
+
.join('\n');
|
53
|
+
|
54
|
+
const learnMore = `\nfind and add templates in https://bit.dev/reference/generator/use-component-generator`;
|
55
|
+
return title + output + learnMore;
|
56
|
+
}
|
57
|
+
}
|
package/tsconfig.json
CHANGED
@@ -1,38 +1,33 @@
|
|
1
1
|
{
|
2
2
|
"compilerOptions": {
|
3
3
|
"lib": [
|
4
|
-
"
|
5
|
-
"
|
6
|
-
"
|
7
|
-
"DOM.Iterable",
|
8
|
-
"ScriptHost"
|
4
|
+
"esnext",
|
5
|
+
"dom",
|
6
|
+
"dom.Iterable"
|
9
7
|
],
|
10
|
-
"target": "
|
11
|
-
"module": "
|
12
|
-
"jsx": "react",
|
13
|
-
"allowJs": true,
|
14
|
-
"composite": true,
|
8
|
+
"target": "es2020",
|
9
|
+
"module": "es2020",
|
10
|
+
"jsx": "react-jsx",
|
15
11
|
"declaration": true,
|
16
12
|
"sourceMap": true,
|
17
|
-
"skipLibCheck": true,
|
18
13
|
"experimentalDecorators": true,
|
19
|
-
"
|
14
|
+
"skipLibCheck": true,
|
20
15
|
"moduleResolution": "node",
|
21
16
|
"esModuleInterop": true,
|
22
|
-
"rootDir": ".",
|
23
17
|
"resolveJsonModule": true,
|
24
|
-
"
|
25
|
-
"
|
26
|
-
"
|
27
|
-
"strictPropertyInitialization": false,
|
28
|
-
"strict": true,
|
29
|
-
"noImplicitAny": false,
|
30
|
-
"preserveConstEnums": true
|
18
|
+
"allowJs": true,
|
19
|
+
"outDir": "dist",
|
20
|
+
"emitDeclarationOnly": true
|
31
21
|
},
|
32
22
|
"exclude": [
|
23
|
+
"artifacts",
|
24
|
+
"public",
|
33
25
|
"dist",
|
26
|
+
"node_modules",
|
27
|
+
"package.json",
|
34
28
|
"esm.mjs",
|
35
|
-
"
|
29
|
+
"**/*.cjs",
|
30
|
+
"./dist"
|
36
31
|
],
|
37
32
|
"include": [
|
38
33
|
"**/*",
|
package/types/asset.d.ts
CHANGED
@@ -5,12 +5,12 @@ declare module '*.png' {
|
|
5
5
|
declare module '*.svg' {
|
6
6
|
import type { FunctionComponent, SVGProps } from 'react';
|
7
7
|
|
8
|
-
export const ReactComponent: FunctionComponent<
|
8
|
+
export const ReactComponent: FunctionComponent<
|
9
|
+
SVGProps<SVGSVGElement> & { title?: string }
|
10
|
+
>;
|
9
11
|
const src: string;
|
10
12
|
export default src;
|
11
13
|
}
|
12
|
-
|
13
|
-
// @TODO Gilad
|
14
14
|
declare module '*.jpg' {
|
15
15
|
const value: any;
|
16
16
|
export = value;
|
@@ -27,3 +27,15 @@ declare module '*.bmp' {
|
|
27
27
|
const value: any;
|
28
28
|
export = value;
|
29
29
|
}
|
30
|
+
declare module '*.otf' {
|
31
|
+
const value: any;
|
32
|
+
export = value;
|
33
|
+
}
|
34
|
+
declare module '*.woff' {
|
35
|
+
const value: any;
|
36
|
+
export = value;
|
37
|
+
}
|
38
|
+
declare module '*.woff2' {
|
39
|
+
const value: any;
|
40
|
+
export = value;
|
41
|
+
}
|
package/types.ts
ADDED
@@ -0,0 +1,220 @@
|
|
1
|
+
import fs from 'fs-extra';
|
2
|
+
import { loadBit } from '@teambit/bit';
|
3
|
+
import { Harmony } from '@teambit/harmony';
|
4
|
+
import { Component } from '@teambit/component';
|
5
|
+
import execa from 'execa';
|
6
|
+
import pMapSeries from 'p-map-series';
|
7
|
+
import UIAspect, { UiMain } from '@teambit/ui';
|
8
|
+
import { Logger, LoggerAspect, LoggerMain } from '@teambit/logger';
|
9
|
+
import { WorkspaceAspect, Workspace } from '@teambit/workspace';
|
10
|
+
import ForkingAspect, { ForkingMain } from '@teambit/forking';
|
11
|
+
import { init } from '@teambit/legacy/dist/api/consumer';
|
12
|
+
import ImporterAspect, { ImporterMain } from '@teambit/importer';
|
13
|
+
import { CompilerAspect, CompilerMain } from '@teambit/compiler';
|
14
|
+
import getGitExecutablePath from '@teambit/legacy/dist/utils/git/git-executable';
|
15
|
+
import GitNotFound from '@teambit/legacy/dist/utils/git/exceptions/git-not-found';
|
16
|
+
import { resolve, join } from 'path';
|
17
|
+
import { ComponentID } from '@teambit/component-id';
|
18
|
+
import GitAspect, { GitMain } from '@teambit/git';
|
19
|
+
import { InstallAspect, InstallMain } from '@teambit/install';
|
20
|
+
import WorkspaceConfigFilesAspect, { WorkspaceConfigFilesMain } from '@teambit/workspace-config-files';
|
21
|
+
// import { ComponentGenerator } from './component-generator';
|
22
|
+
import { WorkspaceTemplate, WorkspaceContext } from './workspace-template';
|
23
|
+
import { NewOptions } from './new.cmd';
|
24
|
+
import { GeneratorAspect } from './generator.aspect';
|
25
|
+
import { GeneratorMain } from './generator.main.runtime';
|
26
|
+
|
27
|
+
export type GenerateResult = { id: ComponentID; dir: string; files: string[]; envId: string };
|
28
|
+
|
29
|
+
export class WorkspaceGenerator {
|
30
|
+
private workspacePath: string;
|
31
|
+
private harmony: Harmony;
|
32
|
+
private workspace: Workspace;
|
33
|
+
private install: InstallMain;
|
34
|
+
private importer: ImporterMain;
|
35
|
+
private logger?: Logger;
|
36
|
+
private forking: ForkingMain;
|
37
|
+
private git: GitMain;
|
38
|
+
private wsConfigFiles: WorkspaceConfigFilesMain;
|
39
|
+
private generator: GeneratorMain;
|
40
|
+
|
41
|
+
// private componentGenerator?: ComponentGenerator;
|
42
|
+
|
43
|
+
constructor(
|
44
|
+
private workspaceName: string,
|
45
|
+
private options: NewOptions & { currentDir?: boolean },
|
46
|
+
private template: WorkspaceTemplate,
|
47
|
+
private aspectComponent?: Component
|
48
|
+
) {
|
49
|
+
this.workspacePath = options.currentDir ? process.cwd() : resolve(this.workspaceName);
|
50
|
+
}
|
51
|
+
|
52
|
+
async generate(): Promise<string> {
|
53
|
+
if (!this.options.currentDir && fs.existsSync(this.workspacePath)) {
|
54
|
+
throw new Error(`unable to create a workspace at "${this.workspaceName}", this path already exist`);
|
55
|
+
}
|
56
|
+
await fs.ensureDir(this.workspacePath);
|
57
|
+
try {
|
58
|
+
process.chdir(this.workspacePath);
|
59
|
+
await this.initGit();
|
60
|
+
await init(this.workspacePath, this.options.skipGit, false, false, false, false, false, false, {});
|
61
|
+
await this.writeWorkspaceFiles();
|
62
|
+
await this.reloadBitInWorkspaceDir();
|
63
|
+
// Setting the workspace to be in install context to prevent errors during the workspace generation
|
64
|
+
// the workspace will be in install context until the end of the generation install process
|
65
|
+
this.workspace.inInstallContext = true;
|
66
|
+
await this.setupGitBitmapMergeDriver();
|
67
|
+
await this.createComponentsFromRemote();
|
68
|
+
await this.forkComponentsFromRemote();
|
69
|
+
await this.importComponentsFromRemote();
|
70
|
+
await this.workspace.clearCache();
|
71
|
+
await this.install.install(undefined, {
|
72
|
+
dedupe: true,
|
73
|
+
import: false,
|
74
|
+
copyPeerToRuntimeOnRoot: true,
|
75
|
+
copyPeerToRuntimeOnComponents: false,
|
76
|
+
updateExisting: false,
|
77
|
+
});
|
78
|
+
|
79
|
+
// compile the components again now that we have the dependencies installed
|
80
|
+
await this.compileComponents(true);
|
81
|
+
await this.wsConfigFiles.writeConfigFiles({});
|
82
|
+
} catch (err: any) {
|
83
|
+
this.logger?.error(`failed generating a new workspace, will delete the dir ${this.workspacePath}`, err);
|
84
|
+
await fs.remove(this.workspacePath);
|
85
|
+
throw err;
|
86
|
+
}
|
87
|
+
|
88
|
+
return this.workspacePath;
|
89
|
+
}
|
90
|
+
|
91
|
+
private async initGit() {
|
92
|
+
if (this.options.skipGit) return;
|
93
|
+
const gitExecutablePath = getGitExecutablePath();
|
94
|
+
const params = ['init'];
|
95
|
+
try {
|
96
|
+
await execa(gitExecutablePath, params);
|
97
|
+
} catch (err: any) {
|
98
|
+
if (err.exitCodeName === 'ENOENT') {
|
99
|
+
throw new GitNotFound(gitExecutablePath, err);
|
100
|
+
}
|
101
|
+
throw err;
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
private async setupGitBitmapMergeDriver() {
|
106
|
+
if (this.options.skipGit) return;
|
107
|
+
await this.git.setGitMergeDriver({ global: false });
|
108
|
+
}
|
109
|
+
|
110
|
+
private async buildUI() {
|
111
|
+
const uiMain = this.harmony.get<UiMain>(UIAspect.id);
|
112
|
+
await uiMain.createRuntime({});
|
113
|
+
}
|
114
|
+
|
115
|
+
private getWorkspaceContext(): WorkspaceContext {
|
116
|
+
return {
|
117
|
+
name: this.workspaceName,
|
118
|
+
defaultScope: this.options.defaultScope,
|
119
|
+
empty: this.options.empty,
|
120
|
+
aspectComponent: this.aspectComponent,
|
121
|
+
template: this.template,
|
122
|
+
skipGit: this.options.skipGit,
|
123
|
+
};
|
124
|
+
}
|
125
|
+
|
126
|
+
/**
|
127
|
+
* writes the generated template files to the default directory set in the workspace config
|
128
|
+
*/
|
129
|
+
private async writeWorkspaceFiles(): Promise<void> {
|
130
|
+
const workspaceContext = this.getWorkspaceContext();
|
131
|
+
const templateFiles = await this.template.generateFiles(workspaceContext);
|
132
|
+
await Promise.all(
|
133
|
+
templateFiles.map(async (templateFile) => {
|
134
|
+
await fs.outputFile(join(this.workspacePath, templateFile.relativePath), templateFile.content);
|
135
|
+
})
|
136
|
+
);
|
137
|
+
}
|
138
|
+
|
139
|
+
private async reloadBitInWorkspaceDir() {
|
140
|
+
this.harmony = await loadBit(this.workspacePath);
|
141
|
+
this.workspace = this.harmony.get<Workspace>(WorkspaceAspect.id);
|
142
|
+
this.install = this.harmony.get<InstallMain>(InstallAspect.id);
|
143
|
+
const loggerMain = this.harmony.get<LoggerMain>(LoggerAspect.id);
|
144
|
+
this.logger = loggerMain.createLogger(GeneratorAspect.id);
|
145
|
+
this.importer = this.harmony.get<ImporterMain>(ImporterAspect.id);
|
146
|
+
this.forking = this.harmony.get<ForkingMain>(ForkingAspect.id);
|
147
|
+
this.git = this.harmony.get<GitMain>(GitAspect.id);
|
148
|
+
this.wsConfigFiles = this.harmony.get<WorkspaceConfigFilesMain>(WorkspaceConfigFilesAspect.id);
|
149
|
+
this.generator = this.harmony.get<GeneratorMain>(GeneratorAspect.id);
|
150
|
+
}
|
151
|
+
|
152
|
+
private async createComponentsFromRemote() {
|
153
|
+
if (this.options.empty || !this.template.create) return;
|
154
|
+
const workspaceContext = this.getWorkspaceContext();
|
155
|
+
const componentsToCreate = this.template.create(workspaceContext);
|
156
|
+
await pMapSeries(componentsToCreate, async (componentToCreate) => {
|
157
|
+
return this.generator.generateComponentTemplate(
|
158
|
+
[componentToCreate.componentName],
|
159
|
+
componentToCreate.templateName,
|
160
|
+
{
|
161
|
+
aspect: componentToCreate.aspect,
|
162
|
+
env: componentToCreate.env,
|
163
|
+
path: componentToCreate.path,
|
164
|
+
scope: componentToCreate.scope,
|
165
|
+
}
|
166
|
+
);
|
167
|
+
});
|
168
|
+
}
|
169
|
+
|
170
|
+
private async forkComponentsFromRemote() {
|
171
|
+
if (this.options.empty) return;
|
172
|
+
const workspaceContext = this.getWorkspaceContext();
|
173
|
+
const componentsToFork =
|
174
|
+
this.template?.importComponents?.(workspaceContext) || this.template?.fork?.(workspaceContext) || [];
|
175
|
+
if (!componentsToFork.length) return;
|
176
|
+
const componentsToForkRestructured = componentsToFork.map(({ id, targetName, path, env, config, targetScope }) => ({
|
177
|
+
sourceId: id,
|
178
|
+
targetId: targetName,
|
179
|
+
targetScope,
|
180
|
+
path,
|
181
|
+
env,
|
182
|
+
config,
|
183
|
+
}));
|
184
|
+
await this.forking.forkMultipleFromRemote(componentsToForkRestructured, {
|
185
|
+
scope: this.workspace.defaultScope,
|
186
|
+
refactor: true,
|
187
|
+
install: false,
|
188
|
+
});
|
189
|
+
}
|
190
|
+
|
191
|
+
private async importComponentsFromRemote() {
|
192
|
+
if (this.options.empty) return;
|
193
|
+
const workspaceContext = this.getWorkspaceContext();
|
194
|
+
const componentsToImport = this.template?.import?.(workspaceContext) || [];
|
195
|
+
|
196
|
+
if (!componentsToImport.length) return;
|
197
|
+
|
198
|
+
await pMapSeries(componentsToImport, async (componentToImport) => {
|
199
|
+
await this.importer.import(
|
200
|
+
{
|
201
|
+
ids: [componentToImport.id],
|
202
|
+
installNpmPackages: false,
|
203
|
+
writeConfigFiles: false,
|
204
|
+
writeToPath: componentToImport.path,
|
205
|
+
},
|
206
|
+
[]
|
207
|
+
);
|
208
|
+
});
|
209
|
+
|
210
|
+
await this.workspace.bitMap.write('new');
|
211
|
+
}
|
212
|
+
|
213
|
+
private async compileComponents(clearCache = true) {
|
214
|
+
if (clearCache) {
|
215
|
+
await this.workspace.clearCache();
|
216
|
+
}
|
217
|
+
const compiler = this.harmony.get<CompilerMain>(CompilerAspect.id);
|
218
|
+
await compiler.compileOnWorkspace();
|
219
|
+
}
|
220
|
+
}
|