@teambit/generator 1.0.108 → 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.
Files changed (41) hide show
  1. package/component-generator.ts +284 -0
  2. package/component-template.ts +152 -0
  3. package/create.cmd.ts +88 -0
  4. package/dist/component-generator.d.ts +3 -3
  5. package/dist/component-generator.js +5 -9
  6. package/dist/component-generator.js.map +1 -1
  7. package/dist/component-template.d.ts +2 -2
  8. package/dist/create.cmd.d.ts +1 -1
  9. package/dist/generator.composition.d.ts +2 -2
  10. package/dist/generator.graphql.d.ts +1 -1
  11. package/dist/generator.main.runtime.d.ts +10 -10
  12. package/dist/generator.main.runtime.js +2 -2
  13. package/dist/generator.main.runtime.js.map +1 -1
  14. package/dist/generator.service.d.ts +1 -1
  15. package/dist/generator.service.js +1 -1
  16. package/dist/generator.service.js.map +1 -1
  17. package/dist/new.cmd.d.ts +1 -1
  18. package/dist/{preview-1703590665075.js → preview-1703647408454.js} +2 -2
  19. package/dist/starter-list.d.ts +1 -1
  20. package/dist/template-list.d.ts +1 -1
  21. package/dist/templates.cmd.d.ts +1 -1
  22. package/dist/workspace-generator.d.ts +2 -2
  23. package/dist/workspace-generator.js +3 -6
  24. package/dist/workspace-generator.js.map +1 -1
  25. package/dist/workspace-template.d.ts +2 -2
  26. package/generator-env-type.ts +14 -0
  27. package/generator.aspect.ts +5 -0
  28. package/generator.graphql.ts +62 -0
  29. package/generator.main.runtime.ts +600 -0
  30. package/index.ts +23 -0
  31. package/new.cmd.ts +120 -0
  32. package/package.json +30 -37
  33. package/starter-list.ts +21 -0
  34. package/starter.plugin.ts +16 -0
  35. package/template-list.ts +21 -0
  36. package/templates.cmd.ts +57 -0
  37. package/tsconfig.json +16 -21
  38. package/types/asset.d.ts +15 -3
  39. package/types.ts +3 -0
  40. package/workspace-generator.ts +220 -0
  41. package/workspace-template.ts +183 -0
@@ -0,0 +1,284 @@
1
+ import Vinyl from 'vinyl';
2
+ import fs from 'fs-extra';
3
+ import pMapSeries from 'p-map-series';
4
+ import path from 'path';
5
+ import { Workspace } from '@teambit/workspace';
6
+ import EnvsAspect, { EnvsMain } from '@teambit/envs';
7
+ import camelcase from 'camelcase';
8
+ import { BitError } from '@teambit/bit-error';
9
+ import { Logger } from '@teambit/logger';
10
+ import { TrackerMain } from '@teambit/tracker';
11
+ import { linkToNodeModulesByIds } from '@teambit/workspace.modules.node-modules-linker';
12
+ import { PathOsBasedRelative } from '@teambit/legacy/dist/utils/path';
13
+ import { AbstractVinyl } from '@teambit/legacy/dist/consumer/component/sources';
14
+ import componentIdToPackageName from '@teambit/legacy/dist/utils/bit/component-id-to-package-name';
15
+ import DataToPersist from '@teambit/legacy/dist/consumer/component/sources/data-to-persist';
16
+ import { NewComponentHelperMain } from '@teambit/new-component-helper';
17
+ import { ComponentID } from '@teambit/component-id';
18
+ import { WorkspaceConfigFilesMain } from '@teambit/workspace-config-files';
19
+
20
+ import { ComponentTemplate, ComponentFile, ComponentConfig } from './component-template';
21
+ import { CreateOptions } from './create.cmd';
22
+ import { OnComponentCreateSlot } from './generator.main.runtime';
23
+
24
+ export type GenerateResult = {
25
+ id: ComponentID;
26
+ dir: string;
27
+ files: string[];
28
+ envId: string;
29
+ envSetBy: string;
30
+ packageName: string;
31
+ isApp?: boolean;
32
+ isEnv?: boolean;
33
+ dependencies?: string[];
34
+ installMissingDependencies?: boolean;
35
+ };
36
+
37
+ export type OnComponentCreateFn = (generateResults: GenerateResult[]) => Promise<void>;
38
+
39
+ export class ComponentGenerator {
40
+ constructor(
41
+ private workspace: Workspace,
42
+ private componentIds: ComponentID[],
43
+ private options: Partial<CreateOptions>,
44
+ private template: ComponentTemplate,
45
+ private envs: EnvsMain,
46
+ private newComponentHelper: NewComponentHelperMain,
47
+ private tracker: TrackerMain,
48
+ private wsConfigFiles: WorkspaceConfigFilesMain,
49
+ private logger: Logger,
50
+ private onComponentCreateSlot: OnComponentCreateSlot,
51
+ private aspectId: string,
52
+ private envId?: ComponentID
53
+ ) {}
54
+
55
+ async generate(): Promise<GenerateResult[]> {
56
+ const dirsToDeleteIfFailed: string[] = [];
57
+ const generateResults = await pMapSeries(this.componentIds, async (componentId) => {
58
+ try {
59
+ const componentPath = this.newComponentHelper.getNewComponentPath(
60
+ componentId,
61
+ this.options.path,
62
+ this.componentIds.length
63
+ );
64
+ if (fs.existsSync(path.join(this.workspace.path, componentPath))) {
65
+ throw new BitError(`unable to create a component at "${componentPath}", this path already exist`);
66
+ }
67
+ if (await this.workspace.hasName(componentId.fullName)) {
68
+ throw new BitError(
69
+ `unable to create a component "${componentId.fullName}", a component with the same name already exist`
70
+ );
71
+ }
72
+ dirsToDeleteIfFailed.push(componentPath);
73
+ return await this.generateOneComponent(componentId, componentPath);
74
+ } catch (err: any) {
75
+ await this.deleteGeneratedComponents(dirsToDeleteIfFailed);
76
+ throw err;
77
+ }
78
+ });
79
+
80
+ await this.workspace.bitMap.write(`create (${this.componentIds.length} components)`);
81
+
82
+ const ids = generateResults.map((r) => r.id);
83
+ await this.tryLinkToNodeModules(ids);
84
+ await this.runOnComponentCreateHook(generateResults);
85
+ // We are running this after the runOnComponentCreateHook as it require
86
+ // the env to be installed to work properly, and the hook might install
87
+ // the env.
88
+ await this.tryWriteConfigFiles(ids);
89
+
90
+ return generateResults;
91
+ }
92
+
93
+ private async tryLinkToNodeModules(ids: ComponentID[]) {
94
+ try {
95
+ await linkToNodeModulesByIds(
96
+ this.workspace,
97
+ ids.map((id) => id)
98
+ );
99
+ } catch (err: any) {
100
+ this.logger.consoleFailure(
101
+ `failed linking the new components to node_modules, please run "bit link" manually. error: ${err.message}`
102
+ );
103
+ }
104
+ }
105
+
106
+ private async runOnComponentCreateHook(generateResults: GenerateResult[]) {
107
+ const fns = this.onComponentCreateSlot.values();
108
+ if (!fns.length) return;
109
+ await Promise.all(fns.map((fn) => fn(generateResults)));
110
+ }
111
+
112
+ /**
113
+ * The function `tryWriteConfigFiles` attempts to write workspace config files, and if it fails, it logs an error
114
+ * message.
115
+ * @returns If the condition `!shouldWrite` is true, then nothing is being returned. Otherwise, if the `writeConfigFiles`
116
+ * function is successfully executed, nothing is being returned. If an error occurs during the execution of
117
+ * `writeConfigFiles`, an error message is being returned.
118
+ */
119
+ private async tryWriteConfigFiles(ids: ComponentID[]) {
120
+ const shouldWrite = this.wsConfigFiles.isWorkspaceConfigWriteEnabled();
121
+ if (!shouldWrite) return;
122
+ ids.map((id) => this.workspace.clearComponentCache(id));
123
+ const { err } = await this.wsConfigFiles.writeConfigFiles({
124
+ clean: true,
125
+ silent: true,
126
+ dedupe: true,
127
+ throw: false,
128
+ });
129
+ if (err) {
130
+ this.logger.consoleFailure(
131
+ `failed generating workspace config files, please run "bit ws-config write" manually. error: ${err.message}`
132
+ );
133
+ }
134
+ }
135
+
136
+ private async deleteGeneratedComponents(dirs: string[]) {
137
+ await Promise.all(
138
+ dirs.map(async (dir) => {
139
+ const absoluteDir = path.join(this.workspace.path, dir);
140
+ try {
141
+ await fs.remove(absoluteDir);
142
+ } catch (err: any) {
143
+ if (err.code !== 'ENOENT') {
144
+ // if not exist, it's fine
145
+ throw err;
146
+ }
147
+ }
148
+ })
149
+ );
150
+ }
151
+
152
+ private async generateOneComponent(componentId: ComponentID, componentPath: string): Promise<GenerateResult> {
153
+ const name = componentId.name;
154
+ const namePascalCase = camelcase(name, { pascalCase: true });
155
+ const nameCamelCase = camelcase(name);
156
+ const aspectId = ComponentID.fromString(this.aspectId);
157
+
158
+ const files = await this.template.generateFiles({
159
+ name,
160
+ namePascalCase,
161
+ nameCamelCase,
162
+ componentId,
163
+ aspectId,
164
+ envId: this.envId,
165
+ });
166
+ const mainFile = files.find((file) => file.isMain);
167
+ await this.writeComponentFiles(componentPath, files);
168
+ const addResults = await this.tracker.track({
169
+ rootDir: componentPath,
170
+ mainFile: mainFile?.relativePath,
171
+ componentName: componentId.fullName,
172
+ defaultScope: this.options.scope,
173
+ });
174
+ const component = await this.workspace.get(componentId);
175
+ const hasEnvConfiguredOriginally = this.envs.hasEnvConfigured(component);
176
+ if (this.template.isApp) {
177
+ await this.workspace.use(componentId.toString());
178
+ }
179
+ const envBeforeConfigChanges = this.envs.getEnv(component);
180
+ let config = this.template.config;
181
+ if (config && typeof config === 'function') {
182
+ const boundConfig = this.template.config?.bind(this.template);
183
+ config = boundConfig({ aspectId: this.aspectId });
184
+ }
185
+
186
+ const userEnv = this.options.env;
187
+
188
+ if (!config && this.envId && !userEnv) {
189
+ const isInWorkspace = this.workspace.exists(this.envId);
190
+ config = {
191
+ [isInWorkspace ? this.envId.toStringWithoutVersion() : this.envId.toString()]: {},
192
+ 'teambit.envs/envs': {
193
+ env: this.envId.toStringWithoutVersion(),
194
+ },
195
+ };
196
+ }
197
+
198
+ const templateEnv = config?.[EnvsAspect.id]?.env;
199
+
200
+ if (config && templateEnv && hasEnvConfiguredOriginally) {
201
+ // remove the env we got from the template.
202
+ delete config[templateEnv];
203
+ delete config[EnvsAspect.id].env;
204
+ if (Object.keys(config[EnvsAspect.id]).length === 0) delete config[EnvsAspect.id];
205
+ if (Object.keys(config).length === 0) config = undefined;
206
+ }
207
+
208
+ const configWithEnv = await this.addEnvIfProvidedByFlag(config);
209
+ if (configWithEnv) this.workspace.bitMap.setEntireConfig(component.id, configWithEnv);
210
+
211
+ const getEnvData = () => {
212
+ const envFromFlag = this.options.env; // env entered by the user when running `bit create --env`
213
+ const envFromTemplate = config?.[EnvsAspect.id]?.env;
214
+ if (envFromFlag) {
215
+ return {
216
+ envId: envFromFlag,
217
+ setBy: '--env flag',
218
+ };
219
+ }
220
+ if (envFromTemplate) {
221
+ return {
222
+ envId: envFromTemplate,
223
+ setBy: 'template',
224
+ };
225
+ }
226
+ return {
227
+ envId: envBeforeConfigChanges.id,
228
+ setBy: hasEnvConfiguredOriginally ? 'workspace variants' : '<default>',
229
+ };
230
+ };
231
+ const { envId, setBy } = getEnvData();
232
+ return {
233
+ id: componentId,
234
+ dir: componentPath,
235
+ files: addResults.files,
236
+ packageName: componentIdToPackageName(component.state._consumer),
237
+ envId,
238
+ envSetBy: setBy,
239
+ isApp: this.template.isApp,
240
+ isEnv: this.template.isEnv,
241
+ dependencies: this.template.dependencies,
242
+ installMissingDependencies: this.template.installMissingDependencies,
243
+ };
244
+ }
245
+
246
+ private async addEnvIfProvidedByFlag(config?: ComponentConfig): Promise<ComponentConfig | undefined> {
247
+ const userEnv = this.options.env; // env entered by the user when running `bit create --env`
248
+ const templateEnv = config?.[EnvsAspect.id]?.env;
249
+ if (!userEnv || userEnv === templateEnv) {
250
+ return config;
251
+ }
252
+ config = config || {};
253
+ if (templateEnv) {
254
+ // the component template has an env and the user wants a different env.
255
+ delete config[templateEnv];
256
+ }
257
+ await this.tracker.addEnvToConfig(userEnv, config);
258
+
259
+ return config;
260
+ }
261
+
262
+ /**
263
+ * writes the generated template files to the default directory set in the workspace config
264
+ */
265
+ private async writeComponentFiles(
266
+ componentPath: string,
267
+ templateFiles: ComponentFile[]
268
+ ): Promise<PathOsBasedRelative[]> {
269
+ const dataToPersist = new DataToPersist();
270
+ const vinylFiles = templateFiles.map((templateFile) => {
271
+ const templateFileVinyl = new Vinyl({
272
+ base: componentPath,
273
+ path: path.join(componentPath, templateFile.relativePath),
274
+ contents: Buffer.from(templateFile.content),
275
+ });
276
+ return AbstractVinyl.fromVinyl(templateFileVinyl);
277
+ });
278
+ const results = vinylFiles.map((v) => v.path);
279
+ dataToPersist.addManyFiles(vinylFiles);
280
+ dataToPersist.addBasePath(this.workspace.path);
281
+ await dataToPersist.persistAllToFS();
282
+ return results;
283
+ }
284
+ }
@@ -0,0 +1,152 @@
1
+ import { ComponentID } from '@teambit/component';
2
+
3
+ /**
4
+ * BaseComponentTemplateOptions describes the foundational properties for components.
5
+ */
6
+ export interface BaseComponentTemplateOptions {
7
+ /**
8
+ * component-name as entered by the user, e.g. `use-date`.
9
+ * without the scope and the namespace.
10
+ */
11
+ name: string;
12
+
13
+ /**
14
+ * component-name as upper camel case, e.g. `use-date` becomes `UseDate`.
15
+ * useful when generating the file content, for example for a class name.
16
+ */
17
+ namePascalCase: string;
18
+
19
+ /**
20
+ * component-name as lower camel case, e.g. `use-date` becomes `useDate`.
21
+ * useful when generating the file content, for example for a function/variable name.
22
+ */
23
+ nameCamelCase: string;
24
+
25
+ /**
26
+ * component id.
27
+ * the name is the name+namespace. the scope is the scope entered by --scope flag or the defaultScope
28
+ */
29
+ componentId: ComponentID;
30
+
31
+ /**
32
+ * aspect id of the aspect that register the template itself
33
+ */
34
+ aspectId: ComponentID | string;
35
+
36
+ /**
37
+ * env id of the env that register the template itself.
38
+ * This will be usually identical to the aspectId but aspectId will always exist,
39
+ * while envId will be undefined if the template is not registered by an env.
40
+ */
41
+ envId?: ComponentID;
42
+
43
+ /**
44
+ * path of the component.
45
+ */
46
+ path?: string;
47
+ /**
48
+ * scope of the component.
49
+ */
50
+ scope?: string;
51
+ /**
52
+ * namespace of the component.
53
+ */
54
+ namespace?: string;
55
+ }
56
+
57
+ /**
58
+ * ComponentContext represents foundational properties for a component context.
59
+ */
60
+ export type ComponentContext = BaseComponentTemplateOptions;
61
+
62
+ export interface ComponentFile {
63
+ /**
64
+ * relative path of the file within the component.
65
+ */
66
+ relativePath: string;
67
+
68
+ /**
69
+ * file content
70
+ */
71
+ content: string;
72
+
73
+ /**
74
+ * whether this file will be tracked as the main file
75
+ */
76
+ isMain?: boolean;
77
+ }
78
+
79
+ export interface ConfigContext {
80
+ /**
81
+ * Aspect id of the aspect that register the template itself
82
+ */
83
+ aspectId: string;
84
+ }
85
+
86
+ export type ComponentConfig = { [aspectName: string]: any };
87
+
88
+ export interface ComponentTemplateOptions {
89
+ /**
90
+ * name of the component template. for example: `hook`, `react-component` or `module`.
91
+ */
92
+ name?: string;
93
+
94
+ /**
95
+ * short description of the template. shown in the `bit templates` command.
96
+ */
97
+ description?: string;
98
+
99
+ /**
100
+ * hide this template so that it is not listed with `bit templates`
101
+ */
102
+ hidden?: boolean;
103
+
104
+ /**
105
+ * env to use for the generated component.
106
+ */
107
+ env?: string;
108
+
109
+ /**
110
+ * adds a metadata that the component that this template creates is of type env.
111
+ * This will be used later to do further configuration for example:
112
+ * - ensure to create the .bit_root for it
113
+ */
114
+ isEnv?: boolean;
115
+
116
+ /**
117
+ * adds a metadata that the component that this template creates is of type app.
118
+ * This will be used later to do further configuration for example:
119
+ * - add it to the workspace.jsonc as app
120
+ * - ensure to create the .bit_root for it
121
+ */
122
+ isApp?: boolean;
123
+
124
+ /**
125
+ * list of dependencies to install when the component is created.
126
+ */
127
+ dependencies?: string[];
128
+
129
+ /**
130
+ * Perform installation of missing dependencies after component generation.
131
+ * This is the same as of running `bit install --add-missing-deps` after component generation.
132
+ */
133
+ installMissingDependencies?: boolean;
134
+ }
135
+
136
+ export interface ComponentTemplate extends ComponentTemplateOptions {
137
+ name: string;
138
+
139
+ /**
140
+ * template function for generating the file of a certain component.,
141
+ */
142
+ generateFiles(context: ComponentContext): Promise<ComponentFile[]> | ComponentFile[];
143
+
144
+ /**
145
+ * component config. gets saved in the .bitmap file and it overrides the workspace.jsonc config.
146
+ * for example, you can set the env that will be used for this component as follows:
147
+ * "teambit.envs/envs": {
148
+ * "env": "teambit.harmony/aspect"
149
+ * },
150
+ */
151
+ config?: ComponentConfig | ((context: ConfigContext) => ComponentConfig);
152
+ }
package/create.cmd.ts ADDED
@@ -0,0 +1,88 @@
1
+ import { Command, CommandOptions } from '@teambit/cli';
2
+ import { ComponentID } from '@teambit/component';
3
+ import chalk from 'chalk';
4
+ import { GeneratorMain } from './generator.main.runtime';
5
+ import type { BaseComponentTemplateOptions } from './component-template';
6
+
7
+ /**
8
+ * CreateOptions combines foundational properties with additional options for creating a component.
9
+ */
10
+ export type CreateOptions = BaseComponentTemplateOptions & {
11
+ env?: string;
12
+ aspect?: string;
13
+ };
14
+
15
+ export class CreateCmd implements Command {
16
+ name = 'create <template-name> <component-names...>';
17
+ description = 'create a new component (source files and config) using a template.';
18
+ alias = '';
19
+ loader = true;
20
+ helpUrl = 'reference/starters/create-starter';
21
+ arguments = [
22
+ {
23
+ name: 'template-name',
24
+ description:
25
+ "the template for generating the component \n(run 'bit templates' for a list of available templates)",
26
+ },
27
+ {
28
+ name: 'component-names...',
29
+ description: 'a list of component names to generate',
30
+ },
31
+ ];
32
+ examples = [
33
+ {
34
+ cmd: 'bit create react ui/button --aspect teambit.react/react-env',
35
+ description: "creates a component named 'ui/button' using the 'react' template",
36
+ },
37
+ {
38
+ cmd: 'bit create node utils/is-string utils/is-number --aspect teambit.node/node',
39
+ description:
40
+ "creates two components, 'utils/is-string' and 'utils/is-number' using the 'node' template from the 'node' aspect(env)",
41
+ },
42
+ {
43
+ cmd: 'bit create mdx docs/create-components --aspect teambit.mdx/mdx-env --scope my-org.my-scope',
44
+ description:
45
+ "creates an mdx component named 'docs/create-components' and sets it scope to 'my-org.my-scope'. \nby default, the scope is the `defaultScope` value, configured in your `workspace.jsonc`.",
46
+ },
47
+ {
48
+ cmd: 'bit create react ui/button --aspect teambit.react/react-env --env teambit.community/envs/community-react@3.0.3',
49
+ description:
50
+ "creates a component named 'ui/button' from the teambit.react/react-env env and sets it to use the 'community-react' env. \n(the template's default env is 'teambit.react/react-env').",
51
+ },
52
+ ];
53
+ group = 'development';
54
+ options = [
55
+ ['n', 'namespace <string>', `sets the component's namespace and nested dirs inside the scope`],
56
+ ['s', 'scope <string>', `sets the component's scope-name. if not entered, the default-scope will be used`],
57
+ ['a', 'aspect <string>', 'aspect-id of the template. helpful when multiple aspects use the same template name'],
58
+ ['t', 'template <string>', 'env-id of the template. alias for --aspect.'],
59
+ ['p', 'path <string>', 'relative path in the workspace. by default the path is `<scope>/<namespace>/<name>`'],
60
+ ['e', 'env <string>', "set the component's environment. (overrides the env from variants and the template)"],
61
+ ] as CommandOptions;
62
+
63
+ constructor(private generator: GeneratorMain) {}
64
+
65
+ async report(
66
+ [templateName, componentNames]: [string, string[]],
67
+ options: Partial<CreateOptions> & {
68
+ template?: string | ComponentID;
69
+ }
70
+ ) {
71
+ options.aspectId = options.aspectId ?? options.template;
72
+ const results = await this.generator.generateComponentTemplate(componentNames, templateName, options);
73
+ const title = `${results.length} component(s) were created`;
74
+
75
+ const componentsData = results
76
+ .map((result) => {
77
+ return `${chalk.bold(result.id.toString())}
78
+ location: ${result.dir}
79
+ env: ${result.envId} (set by ${result.envSetBy})
80
+ package: ${result.packageName}
81
+ `;
82
+ })
83
+ .join('\n');
84
+ const footer = `env configuration is according to workspace variants, template config or --env flag.`;
85
+
86
+ return `${chalk.green(title)}\n\n${componentsData}\n\n${footer}`;
87
+ }
88
+ }
@@ -8,7 +8,7 @@ import { WorkspaceConfigFilesMain } from '@teambit/workspace-config-files';
8
8
  import { ComponentTemplate } from './component-template';
9
9
  import { CreateOptions } from './create.cmd';
10
10
  import { OnComponentCreateSlot } from './generator.main.runtime';
11
- export declare type GenerateResult = {
11
+ export type GenerateResult = {
12
12
  id: ComponentID;
13
13
  dir: string;
14
14
  files: string[];
@@ -20,7 +20,7 @@ export declare type GenerateResult = {
20
20
  dependencies?: string[];
21
21
  installMissingDependencies?: boolean;
22
22
  };
23
- export declare type OnComponentCreateFn = (generateResults: GenerateResult[]) => Promise<void>;
23
+ export type OnComponentCreateFn = (generateResults: GenerateResult[]) => Promise<void>;
24
24
  export declare class ComponentGenerator {
25
25
  private workspace;
26
26
  private componentIds;
@@ -34,7 +34,7 @@ export declare class ComponentGenerator {
34
34
  private onComponentCreateSlot;
35
35
  private aspectId;
36
36
  private envId?;
37
- constructor(workspace: Workspace, componentIds: ComponentID[], options: Partial<CreateOptions>, template: ComponentTemplate, envs: EnvsMain, newComponentHelper: NewComponentHelperMain, tracker: TrackerMain, wsConfigFiles: WorkspaceConfigFilesMain, logger: Logger, onComponentCreateSlot: OnComponentCreateSlot, aspectId: string, envId?: ComponentID | undefined);
37
+ constructor(workspace: Workspace, componentIds: ComponentID[], options: Partial<CreateOptions>, template: ComponentTemplate, envs: EnvsMain, newComponentHelper: NewComponentHelperMain, tracker: TrackerMain, wsConfigFiles: WorkspaceConfigFilesMain, logger: Logger, onComponentCreateSlot: OnComponentCreateSlot, aspectId: string, envId?: ComponentID);
38
38
  generate(): Promise<GenerateResult[]>;
39
39
  private tryLinkToNodeModules;
40
40
  private runOnComponentCreateHook;
@@ -182,7 +182,6 @@ class ComponentGenerator {
182
182
  }));
183
183
  }
184
184
  async generateOneComponent(componentId, componentPath) {
185
- var _config;
186
185
  const name = componentId.name;
187
186
  const namePascalCase = (0, _camelcase().default)(name, {
188
187
  pascalCase: true
@@ -201,7 +200,7 @@ class ComponentGenerator {
201
200
  await this.writeComponentFiles(componentPath, files);
202
201
  const addResults = await this.tracker.track({
203
202
  rootDir: componentPath,
204
- mainFile: mainFile === null || mainFile === void 0 ? void 0 : mainFile.relativePath,
203
+ mainFile: mainFile?.relativePath,
205
204
  componentName: componentId.fullName,
206
205
  defaultScope: this.options.scope
207
206
  });
@@ -213,8 +212,7 @@ class ComponentGenerator {
213
212
  const envBeforeConfigChanges = this.envs.getEnv(component);
214
213
  let config = this.template.config;
215
214
  if (config && typeof config === 'function') {
216
- var _this$template$config;
217
- const boundConfig = (_this$template$config = this.template.config) === null || _this$template$config === void 0 ? void 0 : _this$template$config.bind(this.template);
215
+ const boundConfig = this.template.config?.bind(this.template);
218
216
  config = boundConfig({
219
217
  aspectId: this.aspectId
220
218
  });
@@ -229,7 +227,7 @@ class ComponentGenerator {
229
227
  }
230
228
  };
231
229
  }
232
- const templateEnv = (_config = config) === null || _config === void 0 || (_config = _config[_envs().default.id]) === null || _config === void 0 ? void 0 : _config.env;
230
+ const templateEnv = config?.[_envs().default.id]?.env;
233
231
  if (config && templateEnv && hasEnvConfiguredOriginally) {
234
232
  // remove the env we got from the template.
235
233
  delete config[templateEnv];
@@ -240,9 +238,8 @@ class ComponentGenerator {
240
238
  const configWithEnv = await this.addEnvIfProvidedByFlag(config);
241
239
  if (configWithEnv) this.workspace.bitMap.setEntireConfig(component.id, configWithEnv);
242
240
  const getEnvData = () => {
243
- var _config2;
244
241
  const envFromFlag = this.options.env; // env entered by the user when running `bit create --env`
245
- const envFromTemplate = (_config2 = config) === null || _config2 === void 0 || (_config2 = _config2[_envs().default.id]) === null || _config2 === void 0 ? void 0 : _config2.env;
242
+ const envFromTemplate = config?.[_envs().default.id]?.env;
246
243
  if (envFromFlag) {
247
244
  return {
248
245
  envId: envFromFlag,
@@ -278,9 +275,8 @@ class ComponentGenerator {
278
275
  };
279
276
  }
280
277
  async addEnvIfProvidedByFlag(config) {
281
- var _config3;
282
278
  const userEnv = this.options.env; // env entered by the user when running `bit create --env`
283
- const templateEnv = (_config3 = config) === null || _config3 === void 0 || (_config3 = _config3[_envs().default.id]) === null || _config3 === void 0 ? void 0 : _config3.env;
279
+ const templateEnv = config?.[_envs().default.id]?.env;
284
280
  if (!userEnv || userEnv === templateEnv) {
285
281
  return config;
286
282
  }