@teambit/generator 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.
- package/dist/component-generator.d.ts +3 -0
- package/dist/component-template.d.ts +37 -0
- package/dist/generator.main.runtime.d.ts +29 -0
- package/dist/workspace-generator.d.ts +3 -0
- package/dist/workspace-template.d.ts +45 -0
- package/package.json +28 -20
- package/tsconfig.json +1 -2
- package/component-generator.ts +0 -119
- package/component-template.ts +0 -66
- package/create.cmd.ts +0 -44
- package/generator.aspect.ts +0 -5
- package/generator.docs.mdx +0 -8
- package/generator.graphql.ts +0 -66
- package/generator.main.runtime.ts +0 -279
- package/index.ts +0 -4
- package/new.cmd.ts +0 -79
- package/package-tar/teambit-generator-0.0.554.tgz +0 -0
- package/templates/component-generator/files/aspect-file.ts +0 -10
- package/templates/component-generator/files/docs-file.ts +0 -54
- package/templates/component-generator/files/index.ts +0 -10
- package/templates/component-generator/files/main-runtime.ts +0 -125
- package/templates/component-generator/index.ts +0 -32
- package/templates/workspace-generator/files/aspect-file.ts +0 -10
- package/templates/workspace-generator/files/docs-file.ts +0 -37
- package/templates/workspace-generator/files/git-ignore-tpl.ts +0 -113
- package/templates/workspace-generator/files/index-tpl.ts +0 -29
- package/templates/workspace-generator/files/index.ts +0 -10
- package/templates/workspace-generator/files/main-runtime.ts +0 -24
- package/templates/workspace-generator/files/readme-tpl.ts +0 -39
- package/templates/workspace-generator/files/workspace-config-tpl.ts +0 -18
- package/templates/workspace-generator/index.ts +0 -52
- package/templates.cmd.ts +0 -48
- package/types/asset.d.ts +0 -29
- package/types/style.d.ts +0 -42
- package/types.ts +0 -3
- package/workspace-generator.ts +0 -246
- package/workspace-template.ts +0 -82
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
import { GraphqlAspect, GraphqlMain } from '@teambit/graphql';
|
|
2
|
-
import { CLIAspect, CLIMain, MainRuntime } from '@teambit/cli';
|
|
3
|
-
import WorkspaceAspect, { Workspace } from '@teambit/workspace';
|
|
4
|
-
import { EnvsAspect, EnvsMain } from '@teambit/envs';
|
|
5
|
-
import { ConsumerNotFound } from '@teambit/legacy/dist/consumer/exceptions';
|
|
6
|
-
import { Component } from '@teambit/component';
|
|
7
|
-
import { ComponentID } from '@teambit/component-id';
|
|
8
|
-
import { loadBit } from '@teambit/bit';
|
|
9
|
-
import { Slot, SlotRegistry } from '@teambit/harmony';
|
|
10
|
-
import { BitError } from '@teambit/bit-error';
|
|
11
|
-
import { InvalidScopeName, isValidScopeName } from '@teambit/legacy-bit-id';
|
|
12
|
-
import AspectLoaderAspect, { AspectLoaderMain } from '@teambit/aspect-loader';
|
|
13
|
-
import { ComponentTemplate } from './component-template';
|
|
14
|
-
import { GeneratorAspect } from './generator.aspect';
|
|
15
|
-
import { CreateCmd, CreateOptions } from './create.cmd';
|
|
16
|
-
import { TemplatesCmd } from './templates.cmd';
|
|
17
|
-
import { generatorSchema } from './generator.graphql';
|
|
18
|
-
import { ComponentGenerator, GenerateResult } from './component-generator';
|
|
19
|
-
import { WorkspaceGenerator } from './workspace-generator';
|
|
20
|
-
import { WorkspaceTemplate } from './workspace-template';
|
|
21
|
-
import { NewCmd, NewOptions } from './new.cmd';
|
|
22
|
-
import { componentGeneratorTemplate } from './templates/component-generator';
|
|
23
|
-
import { workspaceGeneratorTemplate } from './templates/workspace-generator';
|
|
24
|
-
|
|
25
|
-
export type ComponentTemplateSlot = SlotRegistry<ComponentTemplate[]>;
|
|
26
|
-
export type WorkspaceTemplateSlot = SlotRegistry<WorkspaceTemplate[]>;
|
|
27
|
-
|
|
28
|
-
export type TemplateDescriptor = { aspectId: string; name: string; description?: string; hidden?: boolean };
|
|
29
|
-
|
|
30
|
-
export type GeneratorConfig = {
|
|
31
|
-
/**
|
|
32
|
-
* array of aspects to include in the list of templates.
|
|
33
|
-
*/
|
|
34
|
-
aspects: string[];
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export class GeneratorMain {
|
|
38
|
-
private aspectLoaded = false;
|
|
39
|
-
constructor(
|
|
40
|
-
private componentTemplateSlot: ComponentTemplateSlot,
|
|
41
|
-
private workspaceTemplateSlot: WorkspaceTemplateSlot,
|
|
42
|
-
private config: GeneratorConfig,
|
|
43
|
-
private workspace: Workspace,
|
|
44
|
-
private envs: EnvsMain,
|
|
45
|
-
private aspectLoader: AspectLoaderMain
|
|
46
|
-
) {}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* register a new component template.
|
|
50
|
-
*/
|
|
51
|
-
registerComponentTemplate(templates: ComponentTemplate[]) {
|
|
52
|
-
this.componentTemplateSlot.register(templates);
|
|
53
|
-
return this;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* register a new component template.
|
|
58
|
-
*/
|
|
59
|
-
registerWorkspaceTemplate(templates: WorkspaceTemplate[]) {
|
|
60
|
-
this.workspaceTemplateSlot.register(templates);
|
|
61
|
-
return this;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* list all component templates registered in the workspace or workspace templates in case the
|
|
66
|
-
* workspace is not available
|
|
67
|
-
*/
|
|
68
|
-
async listTemplates(): Promise<TemplateDescriptor[]> {
|
|
69
|
-
const getTemplateDescriptor = ({
|
|
70
|
-
id,
|
|
71
|
-
template,
|
|
72
|
-
}: {
|
|
73
|
-
id: string;
|
|
74
|
-
template: WorkspaceTemplate | ComponentTemplate;
|
|
75
|
-
}) => ({
|
|
76
|
-
aspectId: id,
|
|
77
|
-
name: template.name,
|
|
78
|
-
description: template.description,
|
|
79
|
-
hidden: template.hidden,
|
|
80
|
-
});
|
|
81
|
-
return this.isRunningInsideWorkspace()
|
|
82
|
-
? this.getAllComponentTemplatesFlattened().map(getTemplateDescriptor)
|
|
83
|
-
: this.getAllWorkspaceTemplatesFlattened().map(getTemplateDescriptor);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* @deprecated use this.listTemplates()
|
|
88
|
-
*/
|
|
89
|
-
async listComponentTemplates(): Promise<TemplateDescriptor[]> {
|
|
90
|
-
return this.listTemplates();
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
isRunningInsideWorkspace(): boolean {
|
|
94
|
-
return Boolean(this.workspace);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* get all component templates registered by a specific aspect ID.
|
|
99
|
-
*/
|
|
100
|
-
getComponentTemplateByAspect(aspectId: string): ComponentTemplate[] {
|
|
101
|
-
return this.componentTemplateSlot.get(aspectId) || [];
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* returns a specific component template.
|
|
106
|
-
*/
|
|
107
|
-
getComponentTemplate(name: string, aspectId?: string): ComponentTemplate | undefined {
|
|
108
|
-
const templates = this.getAllComponentTemplatesFlattened();
|
|
109
|
-
const found = templates.find(({ id, template }) => {
|
|
110
|
-
if (aspectId && id !== aspectId) return false;
|
|
111
|
-
return template.name === name;
|
|
112
|
-
});
|
|
113
|
-
return found?.template;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* in the case the aspect-id is given and this aspect doesn't exist locally, import it to the
|
|
118
|
-
* global scope and load it from the capsule
|
|
119
|
-
*/
|
|
120
|
-
async findTemplateInGlobalScope(aspectId: string, name?: string): Promise<WorkspaceTemplate | undefined> {
|
|
121
|
-
const aspects = await this.aspectLoader.loadAspectsFromGlobalScope([aspectId]);
|
|
122
|
-
const fullAspectId = aspects[0].id.toString();
|
|
123
|
-
return this.searchRegisteredWorkspaceTemplate(name, fullAspectId);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
async findTemplateInOtherWorkspace(workspacePath: string, name: string, aspectId?: string) {
|
|
127
|
-
if (!aspectId)
|
|
128
|
-
throw new BitError(
|
|
129
|
-
`to load a template from a different workspace, please provide the aspect-id using --aspect flag`
|
|
130
|
-
);
|
|
131
|
-
const harmony = await loadBit(workspacePath);
|
|
132
|
-
let workspace: Workspace;
|
|
133
|
-
try {
|
|
134
|
-
workspace = harmony.get<Workspace>(WorkspaceAspect.id);
|
|
135
|
-
} catch (err: any) {
|
|
136
|
-
throw new Error(`fatal: "${workspacePath}" is not a valid Bit workspace, make sure the path is correct`);
|
|
137
|
-
}
|
|
138
|
-
const aspectComponentId = await workspace.resolveComponentId(aspectId);
|
|
139
|
-
await workspace.loadAspects([aspectId], true);
|
|
140
|
-
const aspectFullId = aspectComponentId.toString();
|
|
141
|
-
const generator = harmony.get<GeneratorMain>(GeneratorAspect.id);
|
|
142
|
-
return generator.searchRegisteredWorkspaceTemplate(name, aspectFullId);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* returns a specific workspace template.
|
|
147
|
-
*/
|
|
148
|
-
async getWorkspaceTemplate(
|
|
149
|
-
name: string,
|
|
150
|
-
aspectId?: string
|
|
151
|
-
): Promise<{ workspaceTemplate: WorkspaceTemplate; aspect?: Component }> {
|
|
152
|
-
const registeredTemplate = await this.searchRegisteredWorkspaceTemplate(name, aspectId);
|
|
153
|
-
if (registeredTemplate) {
|
|
154
|
-
return { workspaceTemplate: registeredTemplate };
|
|
155
|
-
}
|
|
156
|
-
if (!aspectId) {
|
|
157
|
-
throw new BitError(`template "${name}" was not found, if this is a custom-template, please use --aspect flag`);
|
|
158
|
-
}
|
|
159
|
-
const aspects = await this.aspectLoader.loadAspectsFromGlobalScope([aspectId]);
|
|
160
|
-
const aspect = aspects[0];
|
|
161
|
-
const fullAspectId = aspect.id.toString();
|
|
162
|
-
const fromGlobal = await this.searchRegisteredWorkspaceTemplate(name, fullAspectId);
|
|
163
|
-
if (fromGlobal) {
|
|
164
|
-
return { workspaceTemplate: fromGlobal, aspect };
|
|
165
|
-
}
|
|
166
|
-
throw new BitError(`template "${name}" was not found`);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
async searchRegisteredWorkspaceTemplate(name?: string, aspectId?: string): Promise<WorkspaceTemplate | undefined> {
|
|
170
|
-
const templates = this.getAllWorkspaceTemplatesFlattened();
|
|
171
|
-
const found = templates.find(({ id, template }) => {
|
|
172
|
-
if (aspectId && name) return aspectId === id && name === template.name;
|
|
173
|
-
if (aspectId) return aspectId === id;
|
|
174
|
-
if (name) return name === template.name;
|
|
175
|
-
throw new Error(`searchRegisteredWorkspaceTemplate expects to get "name" or "aspectId"`);
|
|
176
|
-
});
|
|
177
|
-
return found?.template;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
async generateComponentTemplate(
|
|
181
|
-
componentNames: string[],
|
|
182
|
-
templateName: string,
|
|
183
|
-
options: CreateOptions
|
|
184
|
-
): Promise<GenerateResult[]> {
|
|
185
|
-
if (!this.workspace) throw new ConsumerNotFound();
|
|
186
|
-
await this.loadAspects();
|
|
187
|
-
const { namespace, aspect: aspectId } = options;
|
|
188
|
-
const template = this.getComponentTemplate(templateName, aspectId);
|
|
189
|
-
if (!template) throw new BitError(`template "${templateName}" was not found`);
|
|
190
|
-
const scope = options.scope || this.workspace.defaultScope;
|
|
191
|
-
if (!isValidScopeName(scope)) {
|
|
192
|
-
throw new InvalidScopeName(scope);
|
|
193
|
-
}
|
|
194
|
-
if (!scope) throw new BitError(`failed finding defaultScope`);
|
|
195
|
-
|
|
196
|
-
const componentIds = componentNames.map((componentName) => {
|
|
197
|
-
const fullComponentName = namespace ? `${namespace}/${componentName}` : componentName;
|
|
198
|
-
return ComponentID.fromObject({ name: fullComponentName }, scope);
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
const componentGenerator = new ComponentGenerator(this.workspace, componentIds, options, template, this.envs);
|
|
202
|
-
return componentGenerator.generate();
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
async generateWorkspaceTemplate(workspaceName: string, templateName: string, options: NewOptions) {
|
|
206
|
-
if (this.workspace) {
|
|
207
|
-
throw new BitError('Error: unable to generate a new workspace inside of an existing workspace');
|
|
208
|
-
}
|
|
209
|
-
const { aspect: aspectId, loadFrom } = options;
|
|
210
|
-
let template: WorkspaceTemplate | undefined;
|
|
211
|
-
let aspectComponent: Component | undefined;
|
|
212
|
-
if (loadFrom) {
|
|
213
|
-
template = await this.findTemplateInOtherWorkspace(loadFrom, templateName, aspectId);
|
|
214
|
-
} else {
|
|
215
|
-
const { workspaceTemplate, aspect } = await this.getWorkspaceTemplate(templateName, aspectId);
|
|
216
|
-
template = workspaceTemplate;
|
|
217
|
-
aspectComponent = aspect;
|
|
218
|
-
}
|
|
219
|
-
if (!template) throw new BitError(`template "${templateName}" was not found`);
|
|
220
|
-
const workspaceGenerator = new WorkspaceGenerator(workspaceName, options, template, aspectComponent);
|
|
221
|
-
const workspacePath = await workspaceGenerator.generate();
|
|
222
|
-
|
|
223
|
-
return workspacePath;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
private getAllComponentTemplatesFlattened(): Array<{ id: string; template: ComponentTemplate }> {
|
|
227
|
-
const templatesByAspects = this.componentTemplateSlot.toArray();
|
|
228
|
-
return templatesByAspects.flatMap(([id, componentTemplates]) => {
|
|
229
|
-
return componentTemplates.map((template) => ({
|
|
230
|
-
id,
|
|
231
|
-
template,
|
|
232
|
-
}));
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
private getAllWorkspaceTemplatesFlattened(): Array<{ id: string; template: WorkspaceTemplate }> {
|
|
237
|
-
const templatesByAspects = this.workspaceTemplateSlot.toArray();
|
|
238
|
-
return templatesByAspects.flatMap(([id, workspaceTemplates]) => {
|
|
239
|
-
return workspaceTemplates.map((template) => ({
|
|
240
|
-
id,
|
|
241
|
-
template,
|
|
242
|
-
}));
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
private async loadAspects() {
|
|
247
|
-
if (this.aspectLoaded) return;
|
|
248
|
-
await this.workspace.loadAspects(this.config.aspects);
|
|
249
|
-
this.aspectLoaded = true;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
static slots = [Slot.withType<ComponentTemplate[]>(), Slot.withType<WorkspaceTemplate[]>()];
|
|
253
|
-
|
|
254
|
-
static dependencies = [WorkspaceAspect, CLIAspect, GraphqlAspect, EnvsAspect, AspectLoaderAspect];
|
|
255
|
-
|
|
256
|
-
static runtime = MainRuntime;
|
|
257
|
-
|
|
258
|
-
static async provider(
|
|
259
|
-
[workspace, cli, graphql, envs, aspectLoader]: [Workspace, CLIMain, GraphqlMain, EnvsMain, AspectLoaderMain],
|
|
260
|
-
config: GeneratorConfig,
|
|
261
|
-
[componentTemplateSlot, workspaceTemplateSlot]: [ComponentTemplateSlot, WorkspaceTemplateSlot]
|
|
262
|
-
) {
|
|
263
|
-
const generator = new GeneratorMain(
|
|
264
|
-
componentTemplateSlot,
|
|
265
|
-
workspaceTemplateSlot,
|
|
266
|
-
config,
|
|
267
|
-
workspace,
|
|
268
|
-
envs,
|
|
269
|
-
aspectLoader
|
|
270
|
-
);
|
|
271
|
-
const commands = [new CreateCmd(generator), new TemplatesCmd(generator), new NewCmd(generator)];
|
|
272
|
-
cli.register(...commands);
|
|
273
|
-
graphql.register(generatorSchema(generator));
|
|
274
|
-
generator.registerComponentTemplate([componentGeneratorTemplate, workspaceGeneratorTemplate]);
|
|
275
|
-
return generator;
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
GeneratorAspect.addRuntime(GeneratorMain);
|
package/index.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
export type { GeneratorMain } from './generator.main.runtime';
|
|
2
|
-
export { ComponentContext, ComponentTemplate, ComponentFile } from './component-template';
|
|
3
|
-
export { WorkspaceContext, WorkspaceTemplate, WorkspaceFile } from './workspace-template';
|
|
4
|
-
export { GeneratorAspect } from './generator.aspect';
|
package/new.cmd.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { Command, CommandOptions } from '@teambit/cli';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import { GeneratorMain } from './generator.main.runtime';
|
|
4
|
-
|
|
5
|
-
export type NewOptions = {
|
|
6
|
-
aspect?: string;
|
|
7
|
-
defaultScope?: string;
|
|
8
|
-
skipGit?: boolean;
|
|
9
|
-
loadFrom?: string;
|
|
10
|
-
empty?: boolean;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export class NewCmd implements Command {
|
|
14
|
-
name = 'new <templateName> <workspaceName>';
|
|
15
|
-
description = 'Create a new workspace from a template';
|
|
16
|
-
shortDescription = '';
|
|
17
|
-
alias = '';
|
|
18
|
-
loader = true;
|
|
19
|
-
group = 'start';
|
|
20
|
-
options = [
|
|
21
|
-
[
|
|
22
|
-
'a',
|
|
23
|
-
'aspect <string>',
|
|
24
|
-
'aspect-id of the template. mandatory for non-core aspects. helpful for core aspects in case of a name collision',
|
|
25
|
-
],
|
|
26
|
-
['d', 'default-scope <string>', `set defaultScope in the new workspace.jsonc`],
|
|
27
|
-
['', 'standalone', 'DEPRECATED. use --skip-git instead'],
|
|
28
|
-
['s', 'skip-git', 'skip generation of Git repository'],
|
|
29
|
-
['e', 'empty', 'empty workspace with no components (relevant for templates that add components by default)'],
|
|
30
|
-
[
|
|
31
|
-
'',
|
|
32
|
-
'load-from <string>',
|
|
33
|
-
'path to the workspace containing the template. helpful during a development of a workspace-template',
|
|
34
|
-
],
|
|
35
|
-
] as CommandOptions;
|
|
36
|
-
|
|
37
|
-
constructor(private generator: GeneratorMain) {}
|
|
38
|
-
|
|
39
|
-
async report([templateName, workspaceName]: [string, string], options: NewOptions & { standalone: boolean }) {
|
|
40
|
-
options.skipGit = options.skipGit ?? options.standalone;
|
|
41
|
-
const results = await this.generator.generateWorkspaceTemplate(workspaceName, templateName, options);
|
|
42
|
-
return chalk.white(
|
|
43
|
-
`${chalk.green(`
|
|
44
|
-
|
|
45
|
-
Congrats! A new workspace has been created successfully at '${results}'`)}
|
|
46
|
-
|
|
47
|
-
Inside the directory '${workspaceName}' you can run various commands including:
|
|
48
|
-
|
|
49
|
-
${chalk.yellow('bit start')}
|
|
50
|
-
Starts the workspace in development mode
|
|
51
|
-
|
|
52
|
-
${chalk.yellow('bit install')}
|
|
53
|
-
Installs any missing dependencies
|
|
54
|
-
|
|
55
|
-
${chalk.yellow('bit status')}
|
|
56
|
-
Shows the status of the components
|
|
57
|
-
|
|
58
|
-
${chalk.yellow('bit compile')}
|
|
59
|
-
Compiles the components
|
|
60
|
-
|
|
61
|
-
${chalk.yellow('bit test')}
|
|
62
|
-
Runs the tests on all your components
|
|
63
|
-
|
|
64
|
-
${chalk.yellow('bit templates')}
|
|
65
|
-
Shows all available component templates
|
|
66
|
-
|
|
67
|
-
${chalk.yellow('bit help')}
|
|
68
|
-
Shows all available commands
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
${chalk.green.bold("Let's get started!")}
|
|
72
|
-
|
|
73
|
-
${chalk.yellow(`cd ${workspaceName}`)}
|
|
74
|
-
${chalk.yellow(`bit start`)}
|
|
75
|
-
|
|
76
|
-
`
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
Binary file
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { ComponentContext } from '@teambit/generator';
|
|
2
|
-
|
|
3
|
-
export function aspectFile({ namePascalCase, componentId }: ComponentContext) {
|
|
4
|
-
return `import { Aspect } from '@teambit/harmony';
|
|
5
|
-
|
|
6
|
-
export const ${namePascalCase}Aspect = Aspect.create({
|
|
7
|
-
id: '${componentId}',
|
|
8
|
-
});
|
|
9
|
-
`;
|
|
10
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
export function docsFile() {
|
|
2
|
-
return `### Configuring your Generator
|
|
3
|
-
|
|
4
|
-
Edit your \`workspace.jsonc\` file and set this component to use the \`teambit.harmony/aspect\` env under the variants object.
|
|
5
|
-
|
|
6
|
-
\`\`\`json
|
|
7
|
-
"teambit.workspace/variants": {
|
|
8
|
-
"{my-components}": {
|
|
9
|
-
"teambit.harmony/aspect": {}
|
|
10
|
-
},
|
|
11
|
-
}
|
|
12
|
-
\`\`\`
|
|
13
|
-
|
|
14
|
-
To check if your component is using the correct env you can run \`bit envs\` or \`bit show my-components\`
|
|
15
|
-
|
|
16
|
-
Edit your \`workspace.jsonc\` file and add the component id, (scope name / component name) to teambit generator. This should go at root level. The component id can be found in the \`aspect.ts\` file:
|
|
17
|
-
|
|
18
|
-
\`\`\`json
|
|
19
|
-
{
|
|
20
|
-
"teambit.generator/generator": {
|
|
21
|
-
"aspects": ["my-scope-name/my-components"]
|
|
22
|
-
},
|
|
23
|
-
}
|
|
24
|
-
\`\`\`
|
|
25
|
-
|
|
26
|
-
This registers the component aspect so that your templates will appear in the CLI when you run \`bit templates\`.
|
|
27
|
-
|
|
28
|
-
### Modifying your Generator
|
|
29
|
-
|
|
30
|
-
The \`my-components.main.runtime.ts\` file contains an array of templates that you can modify and add to to create different templates and numerous files to be generated.
|
|
31
|
-
|
|
32
|
-
### Using your Generator
|
|
33
|
-
|
|
34
|
-
Use your generator to create the component files
|
|
35
|
-
|
|
36
|
-
\`\`\`bash
|
|
37
|
-
bit create my-components component1
|
|
38
|
-
\`\`\`
|
|
39
|
-
|
|
40
|
-
### Exporting your Generator
|
|
41
|
-
|
|
42
|
-
Tag and export your generator component so you can use it in any other workspace. Make sure the scope name is set correctly in the \`aspect.ts\` file before tagging and exporting. Once you have tagged and exported the component you can add it to the \`workspace.jsonc\` file in the workspace where you want to use this generator.
|
|
43
|
-
|
|
44
|
-
\`\`\`json
|
|
45
|
-
{
|
|
46
|
-
"teambit.generator/generator": {
|
|
47
|
-
"aspects": ["my-scope-name/my-components"]
|
|
48
|
-
},
|
|
49
|
-
}
|
|
50
|
-
\`\`\`
|
|
51
|
-
|
|
52
|
-
Run \`bit templates\` to see your generator and then use it to generate you components.
|
|
53
|
-
`;
|
|
54
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { ComponentContext } from '@teambit/generator';
|
|
2
|
-
|
|
3
|
-
export function indexFile({ namePascalCase, name }: ComponentContext) {
|
|
4
|
-
return `import { ${namePascalCase}Aspect } from './${name}.aspect';
|
|
5
|
-
|
|
6
|
-
export type { ${namePascalCase}Main } from './${name}.main.runtime';
|
|
7
|
-
export default ${namePascalCase}Aspect;
|
|
8
|
-
export { ${namePascalCase}Aspect };
|
|
9
|
-
`;
|
|
10
|
-
}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { ComponentContext } from '@teambit/generator';
|
|
2
|
-
|
|
3
|
-
export function mainRuntime({ name, namePascalCase }: ComponentContext) {
|
|
4
|
-
return `import { MainRuntime } from '@teambit/cli';
|
|
5
|
-
import { GeneratorMain, GeneratorAspect, ComponentContext } from '@teambit/generator';
|
|
6
|
-
import { ${namePascalCase}Aspect } from './${name}.aspect';
|
|
7
|
-
|
|
8
|
-
export class ${namePascalCase}Main {
|
|
9
|
-
static slots = [];
|
|
10
|
-
static dependencies = [GeneratorAspect];
|
|
11
|
-
static runtime = MainRuntime;
|
|
12
|
-
static async provider([generator]: [GeneratorMain]) {
|
|
13
|
-
/**
|
|
14
|
-
* Array of templates. Add as many templates as you want
|
|
15
|
-
* Separate the templates to multiple files if you prefer
|
|
16
|
-
* Modify, add or remove files as needed
|
|
17
|
-
* See the docs file of this component for more info
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
generator.registerComponentTemplate([
|
|
21
|
-
{
|
|
22
|
-
name: 'component1',
|
|
23
|
-
description: 'description for component1',
|
|
24
|
-
generateFiles: (context: ComponentContext) => {
|
|
25
|
-
return [
|
|
26
|
-
|
|
27
|
-
// index file
|
|
28
|
-
{
|
|
29
|
-
relativePath: 'index.ts',
|
|
30
|
-
isMain: true,
|
|
31
|
-
content: \`export { \${context.namePascalCase} } from './\${context.name}';
|
|
32
|
-
export type { \${context.namePascalCase}Props } from './\${context.name}';
|
|
33
|
-
\`,
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
// component file
|
|
37
|
-
{
|
|
38
|
-
relativePath: \`\${context.name}.tsx\`,
|
|
39
|
-
content: \`import React from 'react';
|
|
40
|
-
|
|
41
|
-
export type \${context.namePascalCase}Props = {
|
|
42
|
-
/**
|
|
43
|
-
* a text to be rendered in the component.
|
|
44
|
-
*/
|
|
45
|
-
text: string
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
export function \${context.namePascalCase}({ text }: \${context.namePascalCase}Props) {
|
|
49
|
-
return (
|
|
50
|
-
<div>
|
|
51
|
-
{text}
|
|
52
|
-
</div>
|
|
53
|
-
);
|
|
54
|
-
}\`,
|
|
55
|
-
},
|
|
56
|
-
|
|
57
|
-
// docs file
|
|
58
|
-
{
|
|
59
|
-
relativePath: \`\${context.name}.docs.mdx\`,
|
|
60
|
-
content: \`---
|
|
61
|
-
description: 'A React Component for rendering text.'
|
|
62
|
-
labels: ['text', 'ui']
|
|
63
|
-
---
|
|
64
|
-
|
|
65
|
-
import { \${context.namePascalCase} } from './\${context.name}';
|
|
66
|
-
\`
|
|
67
|
-
},
|
|
68
|
-
|
|
69
|
-
// composition file
|
|
70
|
-
{
|
|
71
|
-
relativePath: \`\${context.name}.composition.tsx\`,
|
|
72
|
-
content: \`import React from 'react';
|
|
73
|
-
import { \${context.namePascalCase} } from './\${context.name}';
|
|
74
|
-
|
|
75
|
-
export const Basic\${context.namePascalCase} = () => (
|
|
76
|
-
<\${context.namePascalCase} text="hello from \${context.namePascalCase} " />
|
|
77
|
-
);
|
|
78
|
-
\`
|
|
79
|
-
},
|
|
80
|
-
|
|
81
|
-
// test file
|
|
82
|
-
{
|
|
83
|
-
relativePath: \`\${context.name}.spec.tsx\`,
|
|
84
|
-
content: \`import React from 'react';
|
|
85
|
-
import { render } from '@testing-library/react';
|
|
86
|
-
import { Basic\${context.namePascalCase} } from './\${context.name}.composition';
|
|
87
|
-
|
|
88
|
-
it('should render with the correct text', () => {
|
|
89
|
-
const { getByText } = render(<Basic\${context.namePascalCase} />);
|
|
90
|
-
const rendered = getByText('hello from \${context.namePascalCase}');
|
|
91
|
-
expect(rendered).toBeTruthy();
|
|
92
|
-
});
|
|
93
|
-
\`
|
|
94
|
-
},
|
|
95
|
-
// add more files here such as css/sass
|
|
96
|
-
];
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
|
-
|
|
100
|
-
// component 2
|
|
101
|
-
{
|
|
102
|
-
name: 'component2',
|
|
103
|
-
description: 'description for component2',
|
|
104
|
-
generateFiles: (context: ComponentContext) => {
|
|
105
|
-
return [
|
|
106
|
-
|
|
107
|
-
// index file
|
|
108
|
-
{
|
|
109
|
-
relativePath: 'index.ts',
|
|
110
|
-
isMain: true,
|
|
111
|
-
content: \`export {} from '';
|
|
112
|
-
\`,
|
|
113
|
-
},
|
|
114
|
-
]
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
]);
|
|
118
|
-
|
|
119
|
-
return new ${namePascalCase}Main();
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
${namePascalCase}Aspect.addRuntime(${namePascalCase}Main);
|
|
124
|
-
`;
|
|
125
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { ComponentContext, ComponentTemplate } from '@teambit/generator';
|
|
2
|
-
import { indexFile } from './files/index';
|
|
3
|
-
import { aspectFile } from './files/aspect-file';
|
|
4
|
-
import { docsFile } from './files/docs-file';
|
|
5
|
-
import { mainRuntime } from './files/main-runtime';
|
|
6
|
-
|
|
7
|
-
export const componentGeneratorTemplate: ComponentTemplate = {
|
|
8
|
-
name: 'component-generator',
|
|
9
|
-
description:
|
|
10
|
-
'create your own component generator \nDocs: https://harmony-docs.bit.dev/extending-bit/creating-a-custom-generator',
|
|
11
|
-
generateFiles: (context: ComponentContext) => {
|
|
12
|
-
return [
|
|
13
|
-
{
|
|
14
|
-
relativePath: 'index.ts',
|
|
15
|
-
content: indexFile(context),
|
|
16
|
-
isMain: true,
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
relativePath: `${context.name}.aspect.ts`,
|
|
20
|
-
content: aspectFile(context),
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
relativePath: `${context.name}.docs.mdx`,
|
|
24
|
-
content: docsFile(),
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
relativePath: `${context.name}.main.runtime.ts`,
|
|
28
|
-
content: mainRuntime(context),
|
|
29
|
-
},
|
|
30
|
-
];
|
|
31
|
-
},
|
|
32
|
-
};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { ComponentContext } from '@teambit/generator';
|
|
2
|
-
|
|
3
|
-
export function aspectFile({ namePascalCase, componentId }: ComponentContext) {
|
|
4
|
-
return `import { Aspect } from '@teambit/harmony';
|
|
5
|
-
|
|
6
|
-
export const ${namePascalCase}Aspect = Aspect.create({
|
|
7
|
-
id: '${componentId}',
|
|
8
|
-
});
|
|
9
|
-
`;
|
|
10
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
export function docsFile() {
|
|
2
|
-
return `---
|
|
3
|
-
description: Generator for generating a workspace
|
|
4
|
-
labels: ['generator', 'templates', 'workspace']
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Registering your Workspace
|
|
8
|
-
|
|
9
|
-
Register your workspace template under the aspect environment in the variants section of the workspace.jsonc file.
|
|
10
|
-
|
|
11
|
-
\`\`\`json
|
|
12
|
-
"teambit.workspace/variants": {
|
|
13
|
-
"{workspace-name}": {
|
|
14
|
-
"teambit.harmony/aspect": {}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
\`\`\`
|
|
18
|
-
|
|
19
|
-
## Customizing your Workspace
|
|
20
|
-
|
|
21
|
-
See the docs for more info on [Customizing your Generator](https://harmony-docs.bit.dev/extending-bit/creating-a-custom-workspace-generator)
|
|
22
|
-
|
|
23
|
-
## Using the Workspace Generator
|
|
24
|
-
|
|
25
|
-
How to use this generator locally, essentially for development purposes:
|
|
26
|
-
|
|
27
|
-
\`\`\`js
|
|
28
|
-
bit new <template-name> <workspace-name> --load-from /Users/me/path/to/this/dir --aspect <workspace-template-id>
|
|
29
|
-
\`\`\`
|
|
30
|
-
|
|
31
|
-
How to use this generator after exporting to a remote scope:
|
|
32
|
-
|
|
33
|
-
\`\`\`js
|
|
34
|
-
bit new <template-name> <workspace-name> --aspect <workspace-template-id>
|
|
35
|
-
\`\`\`
|
|
36
|
-
`;
|
|
37
|
-
}
|