generator-easy-ui5 3.7.0 → 3.8.1

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/README.md CHANGED
@@ -104,9 +104,27 @@ yo easy-ui5 [project|library] <sub-generator-id>
104
104
  If you are running Easy UI5 behind a coporate proxy, just use the default proxy environment variables for Node.js to configure your corporate proxy:
105
105
 
106
106
  - `HTTP_PROXY`: Specify the value to use as the HTTP proxy for all connections, e.g., `HTTP_PROXY="http://proxy.mycompany.com:8080/"`.
107
- - `HTTPS_PROXY`: Specify the value to use as the HTTPS proxy for all connections, e.g., `HTTPS_PROXY="https://proxy.mycompany.com:8080/"`.
107
+ - `HTTPS_PROXY`: Specify the value to use as the HTTPS proxy for all connections, e.g., `HTTPS_PROXY="http://proxy.mycompany.com:8080/"`.
108
108
  - `NO_PROXY`: Define the hosts that should bypass the proxy, e.g., `NO_PROXY="localhost,.mycompany.com,192.168.6.254:80"`.
109
109
 
110
+ In addition, Easy UI5 also supports proxy configuration from the `.npmrc` configuration:
111
+
112
+ ```text
113
+ http-proxy=http://proxy.mycompany.com:8080/
114
+ https-proxy=http://proxy.mycompany.com:8080/
115
+ proxy=http://proxy.mycompany.com:8080/
116
+ no-proxy=localhost,.mycompany.com,192.168.6.254:80
117
+ ```
118
+
119
+ This configuration is shared with npm itself since this proxy configuration is used to download the packages from npm.
120
+
121
+ Proxies can be passed as env variables or as npm config options. The highest precedence have the `GLOBAL_AGENT_*` env variables before the regular env variables followed by the npm configuration options, e.g.:
122
+
123
+ 1. env: `GLOBAL_AGENT_HTTP_PROXY`
124
+ 2. env: `HTTP_PROXY`
125
+ 3. npm: `http-proxy`
126
+ 4. npm: `proxy`
127
+
110
128
  ## How to obtain support
111
129
 
112
130
  Please use the GitHub bug tracking system to post questions, bug reports or to create pull requests.
@@ -15,29 +15,33 @@ import { Octokit } from "@octokit/rest";
15
15
  import { throttling } from "@octokit/plugin-throttling";
16
16
  const MyOctokit = Octokit.plugin(throttling);
17
17
  import spawn from "cross-spawn";
18
+ import nodeFetch from "node-fetch";
18
19
 
19
20
  const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
20
21
 
21
- // apply proxy settings to GLOBAL_AGENT to support the proxy configuration
22
- // provided via the standard Node.js environment varibales (used for fetch API)
23
- let HTTP_PROXY, HTTPS_PROXY, NO_PROXY;
24
- if (global?.GLOBAL_AGENT) {
25
- HTTP_PROXY = global.GLOBAL_AGENT.HTTP_PROXY = process.env.HTTP_PROXY || process.env.http_proxy;
26
- HTTPS_PROXY = global.GLOBAL_AGENT.HTTPS_PROXY = process.env.HTTPS_PROXY || process.env.https_proxy;
27
- NO_PROXY = global.GLOBAL_AGENT.NO_PROXY = process.env.NO_PROXY || process.env.no_proxy;
28
- }
29
-
30
22
  // helper to retrieve config entries from npm
31
23
  // --> npm config set easy-ui5_addGhOrg XYZ
32
- const NPM_CONFIG_PREFIX = "easy-ui5_";
33
24
  let npmConfig;
34
- const getNPMConfig = (configName) => {
25
+ const getNPMConfig = (configName, prefix = "easy-ui5_") => {
35
26
  if (!npmConfig) {
36
27
  npmConfig = libnpmconfig.read();
37
28
  }
38
- return npmConfig && npmConfig[`${NPM_CONFIG_PREFIX}${configName}`];
29
+ return npmConfig && npmConfig[`${prefix}${configName}`];
39
30
  };
40
31
 
32
+ // apply proxy settings to GLOBAL_AGENT to support the proxy configuration for node-fetch using the GLOBAL_AGENT
33
+ // ==> the configuration is derived from the environment variables ([GLOBAL_AGENT_](HTTP|HTTPS|NO)_PROXY) and the npm config ((http|https|no)-proxy)
34
+ // ==> empty values will allow to override the more general proxy settings and make the proxy value undefined
35
+ let HTTP_PROXY, HTTPS_PROXY, NO_PROXY;
36
+ if (global?.GLOBAL_AGENT) {
37
+ HTTP_PROXY = process.env.GLOBAL_AGENT_HTTP_PROXY ?? process.env.HTTP_PROXY ?? process.env.http_proxy ?? getNPMConfig("http-proxy", "") ?? getNPMConfig("proxy", "");
38
+ global.GLOBAL_AGENT.HTTP_PROXY = HTTP_PROXY = HTTP_PROXY || global.GLOBAL_AGENT.HTTP_PROXY;
39
+ HTTPS_PROXY = process.env.GLOBAL_AGENT_HTTPS_PROXY ?? process.env.HTTPS_PROXY ?? process.env.https_proxy ?? getNPMConfig("https-proxy", "") ?? getNPMConfig("proxy", "");
40
+ global.GLOBAL_AGENT.HTTPS_PROXY = HTTPS_PROXY = HTTPS_PROXY || global.GLOBAL_AGENT.HTTPS_PROXY;
41
+ NO_PROXY = process.env.GLOBAL_AGENT_NO_PROXY ?? process.env.NO_PROXY ?? process.env.no_proxy ?? getNPMConfig("no-proxy", "");
42
+ global.GLOBAL_AGENT.NO_PROXY = NO_PROXY = NO_PROXY || global.GLOBAL_AGENT.NO_PROXY;
43
+ }
44
+
41
45
  // the command line options of the generator
42
46
  const generatorOptions = {
43
47
  pluginsHome: {
@@ -134,6 +138,10 @@ const generatorOptions = {
134
138
  type: Boolean,
135
139
  description: "Preview the next mode to consume subgenerators from bestofui5.org",
136
140
  },
141
+ skipNested: {
142
+ type: Boolean,
143
+ description: "Skips the nested generators and runs only the first subgenerator",
144
+ },
137
145
  };
138
146
 
139
147
  const generatorArgs = {
@@ -149,6 +157,7 @@ const generatorArgs = {
149
157
  },
150
158
  };
151
159
 
160
+ // The Easy UI5 Generator!
152
161
  export default class extends Generator {
153
162
  constructor(args, opts) {
154
163
  super(args, opts, {
@@ -239,6 +248,104 @@ export default class extends Generator {
239
248
  return "Easy UI5";
240
249
  }
241
250
 
251
+ async _getGeneratorMetadata({ env, generatorPath }) {
252
+ // filter the hidden subgenerators already
253
+ // -> subgenerators must be found in env as they are returned by lookup!
254
+ const lookupGeneratorMeta = await env.lookup({ localOnly: true, packagePaths: generatorPath });
255
+ const subGenerators = lookupGeneratorMeta.filter((sub) => {
256
+ const subGenerator = env.get(sub.namespace);
257
+ return !subGenerator.hidden;
258
+ });
259
+ return subGenerators;
260
+ }
261
+
262
+ async _installGenerator({ octokit, generator, generatorPath }) {
263
+ // lookup the default path of the generator if not set
264
+ if (!generator.branch) {
265
+ try {
266
+ const repoInfo = await octokit.repos.get({
267
+ owner: generator.org,
268
+ repo: generator.name,
269
+ });
270
+ generator.branch = repoInfo.data.default_branch;
271
+ } catch (e) {
272
+ console.error(`Generator "${owner}/${repo}!${dir}${branch ? "#" + branch : ""}" not found! Run with --verbose for details!\n(Hint: ${e.message})`);
273
+ if (this.options.verbose) {
274
+ console.error(e);
275
+ }
276
+ return;
277
+ }
278
+ }
279
+ // fetch the branch to retrieve the latest commit SHA
280
+ let commitSHA;
281
+ try {
282
+ // determine the commitSHA
283
+ const reqBranch = await octokit.repos.getBranch({
284
+ owner: generator.org,
285
+ repo: generator.name,
286
+ branch: generator.branch,
287
+ });
288
+ commitSHA = reqBranch.data.commit.sha;
289
+ } catch (ex) {
290
+ console.error(
291
+ chalk.red(`Failed to retrieve the branch "${generator.branch}" for repository "${generator.name}" for "${generator.org}" organization! Run with --verbose for details!\n(Hint: ${e.message})`)
292
+ );
293
+ if (this.options.verbose) {
294
+ console.error(chalk.red(ex.message));
295
+ }
296
+ return;
297
+ }
298
+
299
+ if (this.options.verbose) {
300
+ this.log(`Using commit ${commitSHA} from @${generator.org}/${generator.name}#${generator.branch}!`);
301
+ }
302
+ const shaMarker = path.join(generatorPath, `.${commitSHA}`);
303
+
304
+ if (fs.existsSync(generatorPath) && !this.options.skipUpdate) {
305
+ // check if the SHA marker exists to know whether the generator is up-to-date or not
306
+ if (this.options.forceUpdate || !fs.existsSync(shaMarker)) {
307
+ if (this.options.verbose) {
308
+ this.log(`Generator ${chalk.yellow(generator.name)} in "${generatorPath}" is outdated!`);
309
+ }
310
+ // remove if the SHA marker doesn't exist => outdated!
311
+ this._showBusy(` Deleting subgenerator ${chalk.yellow(generator.name)}...`);
312
+ fs.rmSync(generatorPath, { recursive: true });
313
+ }
314
+ }
315
+
316
+ // re-fetch the generator and extract into local plugin folder
317
+ if (!fs.existsSync(generatorPath)) {
318
+ // unzip the archive
319
+ if (this.options.verbose) {
320
+ this.log(`Extracting ZIP to "${generatorPath}"...`);
321
+ }
322
+ this._showBusy(` Downloading subgenerator ${chalk.yellow(generator.name)}...`);
323
+ const reqZIPArchive = await octokit.repos.downloadZipballArchive({
324
+ owner: generator.org,
325
+ repo: generator.name,
326
+ ref: commitSHA,
327
+ });
328
+
329
+ this._showBusy(` Extracting subgenerator ${chalk.yellow(generator.name)}...`);
330
+ const buffer = Buffer.from(new Uint8Array(reqZIPArchive.data));
331
+ this._unzip(buffer, generatorPath, generator.dir);
332
+
333
+ // write the sha marker
334
+ fs.writeFileSync(shaMarker, commitSHA);
335
+ }
336
+
337
+ // run npm install when not embedding the generator (always for self-healing!)
338
+ if (!this.options.embed) {
339
+ if (this.options.verbose) {
340
+ this.log("Installing the subgenerator dependencies...");
341
+ }
342
+ this._showBusy(` Preparing ${chalk.yellow(generator.name)}...`);
343
+ await this._npmInstall(generatorPath, this.options.pluginsWithDevDeps);
344
+ }
345
+
346
+ this._clearBusy(true);
347
+ }
348
+
242
349
  async prompting() {
243
350
  const home = path.join(__dirname, "..", "..");
244
351
  const pkgJson = JSON.parse(fs.readFileSync(path.join(home, "package.json"), "utf8"));
@@ -304,6 +411,13 @@ export default class extends Generator {
304
411
  // define the options for the Octokit API
305
412
  const octokitOptions = {
306
413
  userAgent: `${this.rootGeneratorName()}:${this.rootGeneratorVersion()}`,
414
+ request: {
415
+ fetch: (_url, _options) => {
416
+ return nodeFetch(_url, {
417
+ ..._options,
418
+ });
419
+ },
420
+ },
307
421
  auth: this.options.ghAuthToken,
308
422
  baseUrl: this.options.ghBaseUrl,
309
423
  throttle: {
@@ -369,31 +483,28 @@ export default class extends Generator {
369
483
  // determine the generator to be used
370
484
  let generator;
371
485
 
372
- // try to identify whether concrete generator is defined
373
- if (!generator) {
374
- // determine generator by ${owner}/${repo}(!${dir})? syntax, e.g.:
375
- // > yo easy-ui5 SAP-samples/ui5-typescript-tutorial
376
- // > yo easy-ui5 SAP-samples/ui5-typescript-tutorial#1.0
377
- // > yo easy-ui5 SAP-samples/ui5-typescript-tutorial\!/generator
378
- // > yo easy-ui5 SAP-samples/ui5-typescript-tutorial\!/generator#1.0
379
- const reGenerator = /([^\/]+)\/([^\!\#]+)(?:\!([^\#]+))?(?:\#(.+))?/;
380
- const matchGenerator = reGenerator.exec(this.options.generator);
381
- if (matchGenerator) {
382
- // derive and path the generator information from command line
383
- const [owner, repo, dir = "/generator", branch] = matchGenerator.slice(1);
384
- // the plugin path is derived from the owner, repo, dir and branch
385
- const pluginPath = `_/${owner}/${repo}${dir.replace(/[\/\\]/g, "_")}${branch ? `#${branch.replace(/[\/\\]/g, "_")}` : ""}`;
386
- generator = {
387
- org: owner,
388
- name: repo,
389
- branch,
390
- dir,
391
- pluginPath,
392
- };
393
- // log which generator is being used!
394
- if (this.options.verbose) {
395
- this.log(`Using generator ${chalk.green(`${owner}/${repo}!${dir}${branch ? "#" + branch : ""}`)}`);
396
- }
486
+ // determine generator by ${owner}/${repo}(!${dir})? syntax, e.g.:
487
+ // > yo easy-ui5 SAP-samples/ui5-typescript-tutorial
488
+ // > yo easy-ui5 SAP-samples/ui5-typescript-tutorial#1.0
489
+ // > yo easy-ui5 SAP-samples/ui5-typescript-tutorial\!/generator
490
+ // > yo easy-ui5 SAP-samples/ui5-typescript-tutorial\!/generator#1.0
491
+ const reGenerator = /([^\/]+)\/([^\!\#]+)(?:\!([^\#]+))?(?:\#(.+))?/;
492
+ const matchGenerator = reGenerator.exec(this.options.generator);
493
+ if (matchGenerator) {
494
+ // derive and path the generator information from command line
495
+ const [owner, repo, dir = "/generator", branch] = matchGenerator.slice(1);
496
+ // the plugin path is derived from the owner, repo, dir and branch
497
+ const pluginPath = `_/${owner}/${repo}${dir.replace(/[\/\\]/g, "_")}${branch ? `#${branch.replace(/[\/\\]/g, "_")}` : ""}`;
498
+ generator = {
499
+ org: owner,
500
+ name: repo,
501
+ branch,
502
+ dir,
503
+ pluginPath,
504
+ };
505
+ // log which generator is being used!
506
+ if (this.options.verbose) {
507
+ this.log(`Using generator ${chalk.green(`${owner}/${repo}!${dir}${branch ? "#" + branch : ""}`)}`);
397
508
  }
398
509
  }
399
510
 
@@ -457,7 +568,7 @@ export default class extends Generator {
457
568
  };
458
569
  });
459
570
  } catch (e) {
460
- console.error("Failed to connect to bestofui5.org to retrieve all available generators! Run with --verbose for details!");
571
+ console.error(`Failed to connect to bestofui5.org to retrieve all available generators! Run with --verbose for details!\n(Hint: ${e.message})`);
461
572
  if (this.options.verbose) {
462
573
  console.error(e);
463
574
  }
@@ -468,7 +579,7 @@ export default class extends Generator {
468
579
  try {
469
580
  availGenerators = await listGeneratorsForOrg(this.options.ghOrg, this.options.subGeneratorPrefix, this.options.ghThreshold);
470
581
  } catch (e) {
471
- console.error(`Failed to connect to GitHub to retrieve all available generators for "${this.options.ghOrg}" organization! Run with --verbose for details!`);
582
+ console.error(`Failed to connect to GitHub to retrieve all available generators for "${this.options.ghOrg}" organization! Run with --verbose for details!\n(Hint: ${e.message})`);
472
583
  if (this.options.verbose) {
473
584
  console.error(e);
474
585
  }
@@ -487,7 +598,7 @@ export default class extends Generator {
487
598
  try {
488
599
  availGenerators = availGenerators.concat(await listGeneratorsForUser(this.options.addGhOrg, this.options.addSubGeneratorPrefix, this.options.ghThreshold));
489
600
  } catch (e1) {
490
- console.error(`Failed to connect to GitHub to retrieve additional generators for organization or user "${this.options.addGhOrg}"! Run with --verbose for details!`);
601
+ console.error(`Failed to connect to GitHub to retrieve additional generators for organization or user "${this.options.addGhOrg}"! Run with --verbose for details!\n(Hint: ${e.message})`);
491
602
  if (this.options.verbose) {
492
603
  console.error(e1);
493
604
  }
@@ -527,85 +638,10 @@ export default class extends Generator {
527
638
  }
528
639
  }
529
640
 
530
- let generatorPath = path.join(pluginsHome, generator.pluginPath || generator.name);
641
+ // install the generator if not running in offline mode
642
+ const generatorPath = path.join(pluginsHome, generator.pluginPath || generator.name);
531
643
  if (!this.options.offline) {
532
- // lookup the default path of the generator if not set
533
- if (!generator.branch) {
534
- try {
535
- const repoInfo = await octokit.repos.get({
536
- owner: generator.org,
537
- repo: generator.name,
538
- });
539
- generator.branch = repoInfo.data.default_branch;
540
- } catch (e) {
541
- console.error(`Generator "${owner}/${repo}!${dir}${branch ? "#" + branch : ""}" not found! Run with --verbose for details!`);
542
- if (this.options.verbose) {
543
- console.error(e);
544
- }
545
- return;
546
- }
547
- }
548
- // fetch the branch to retrieve the latest commit SHA
549
- let commitSHA;
550
- try {
551
- // determine the commitSHA
552
- const reqBranch = await octokit.repos.getBranch({
553
- owner: generator.org,
554
- repo: generator.name,
555
- branch: generator.branch,
556
- });
557
- commitSHA = reqBranch.data.commit.sha;
558
- } catch (ex) {
559
- console.error(chalk.red(`Failed to retrieve the branch "${generator.branch}" for repository "${generator.name}" for "${generator.org}" organization! Run with --verbose for details!`));
560
- if (this.options.verbose) {
561
- console.error(chalk.red(ex.message));
562
- }
563
- return;
564
- }
565
-
566
- if (this.options.verbose) {
567
- this.log(`Using commit ${commitSHA} from @${generator.org}/${generator.name}#${generator.branch}!`);
568
- }
569
- const shaMarker = path.join(generatorPath, `.${commitSHA}`);
570
-
571
- if (fs.existsSync(generatorPath) && !this.options.skipUpdate) {
572
- // check if the SHA marker exists to know whether the generator is up-to-date or not
573
- if (this.options.forceUpdate || !fs.existsSync(shaMarker)) {
574
- if (this.options.verbose) {
575
- this.log(`Generator ${chalk.yellow(generator.name)} in "${generatorPath}" is outdated!`);
576
- }
577
- // remove if the SHA marker doesn't exist => outdated!
578
- this._showBusy(` Deleting subgenerator ${chalk.yellow(generator.name)}...`);
579
- fs.rmSync(generatorPath, { recursive: true });
580
- }
581
- }
582
-
583
- // re-fetch the generator and extract into local plugin folder
584
- if (!fs.existsSync(generatorPath)) {
585
- // unzip the archive
586
- if (this.options.verbose) {
587
- this.log(`Extracting ZIP to "${generatorPath}"...`);
588
- }
589
- this._showBusy(` Downloading subgenerator ${chalk.yellow(generator.name)}...`);
590
- const reqZIPArchive = await octokit.repos.downloadZipballArchive({
591
- owner: generator.org,
592
- repo: generator.name,
593
- ref: commitSHA,
594
- });
595
-
596
- this._showBusy(` Extracting subgenerator ${chalk.yellow(generator.name)}...`);
597
- const buffer = Buffer.from(new Uint8Array(reqZIPArchive.data));
598
- this._unzip(buffer, generatorPath, generator.dir);
599
-
600
- // write the sha marker
601
- fs.writeFileSync(shaMarker, commitSHA);
602
- }
603
-
604
- // only when embedding we clear the busy state as otherwise
605
- // the npm install will immediately again show the busy state
606
- if (this.options.embed) {
607
- this._clearBusy(true);
608
- }
644
+ await this._installGenerator({ octokit, generator, generatorPath });
609
645
  }
610
646
 
611
647
  // do not execute the plugin generator during the setup/embed mode
@@ -613,14 +649,6 @@ export default class extends Generator {
613
649
  // filter the local options and the help command
614
650
  const opts = Object.keys(this._options).filter((optionName) => !(generatorOptions.hasOwnProperty(optionName) || optionName === "help"));
615
651
 
616
- // run npm install (always for self-healing!)
617
- if (this.options.verbose) {
618
- this.log("Installing the subgenerator dependencies...");
619
- }
620
- this._showBusy(` Preparing ${chalk.yellow(generator.name)}...`);
621
- await this._npmInstall(generatorPath, this.options.pluginsWithDevDeps);
622
- this._clearBusy(true);
623
-
624
652
  // create the env for the plugin generator
625
653
  let env = this.env; // in case of Yeoman UI the env is injected!
626
654
  if (!env) {
@@ -628,19 +656,20 @@ export default class extends Generator {
628
656
  env = yeoman.createEnv(this.args, opts);
629
657
  }
630
658
 
631
- // helper to derive the subcommand
632
- function deriveSubcommand(namespace) {
633
- const match = namespace.match(/[^:]+:(.+)/);
634
- return match ? match[1] : namespace;
659
+ // read the generator metadata
660
+ let subGenerators = await this._getGeneratorMetadata({ env, generatorPath });
661
+
662
+ // helper to derive the generator from the namespace
663
+ function deriveGenerator(namespace, defaultValue) {
664
+ const match = namespace.match(/([^:]+):.+/);
665
+ return match ? match[1] : defaultValue === undefined ? namespace : defaultValue;
635
666
  }
636
667
 
637
- // filter the hidden subgenerators already
638
- // -> subgenerators must be found in env as they are returned by lookup!
639
- const lookupGeneratorMeta = await env.lookup({ localOnly: true, packagePaths: generatorPath });
640
- let subGenerators = lookupGeneratorMeta.filter((sub) => {
641
- const subGenerator = env.get(sub.namespace);
642
- return !subGenerator.hidden;
643
- });
668
+ // helper to derive the subcommand from the namespace
669
+ function deriveSubcommand(namespace, defaultValue) {
670
+ const match = namespace.match(/^[^:]+:(.+)$/);
671
+ return match ? match[1] : defaultValue === undefined ? namespace : defaultValue;
672
+ }
644
673
 
645
674
  // list the available subgenerators in the console (as help)
646
675
  if (this.options.list) {
@@ -726,16 +755,79 @@ export default class extends Generator {
726
755
  ).subGenerator;
727
756
  }
728
757
 
729
- if (this.options.verbose) {
730
- this.log(`Calling ${chalk.red(subGenerator)}...\n \\_ in "${generatorPath}"`);
758
+ // determine the list of subgenerators to be executed
759
+ const subGensToRun = [subGenerator];
760
+
761
+ // method to resolve nested generators (only once!)
762
+ const resolved = [];
763
+ const resolveNestedGenerator = async (generatorToResolve) => {
764
+ const constructor = await env.get(generatorToResolve);
765
+ await Promise.all(
766
+ constructor.nestedGenerators?.map(async (nestedGenerator) => {
767
+ const theNestedGenerator = deriveGenerator(nestedGenerator);
768
+ if (resolved.indexOf(theNestedGenerator) === -1) {
769
+ resolved.push(theNestedGenerator);
770
+ const nestedGeneratorInfo = availGenerators.find((repo) => repo.subGeneratorName === theNestedGenerator);
771
+ const nestedGeneratorPath = path.join(pluginsHome, nestedGeneratorInfo.pluginPath || nestedGeneratorInfo.name);
772
+ await this._installGenerator({ octokit, generator: nestedGeneratorInfo, generatorPath: nestedGeneratorPath });
773
+ const nestedGens = await this._getGeneratorMetadata({ env, generatorPath: nestedGeneratorPath });
774
+ const subcommand = deriveSubcommand(nestedGenerator, "");
775
+ const theNestedGen = nestedGens.filter((nested) => {
776
+ const nestedSubcommand = deriveSubcommand(nested.namespace, "");
777
+ return subcommand ? nestedSubcommand === subcommand : !nestedSubcommand;
778
+ })?.[0];
779
+ if (theNestedGen) {
780
+ subGensToRun.push(theNestedGen.namespace);
781
+ await resolveNestedGenerator(theNestedGen.namespace);
782
+ } else {
783
+ this.log(`The nested generator "${nestedGeneratorInfo.org}/${nestedGeneratorInfo.name}" has no subgenerator "${subcommand || "default"}"! Ignoring execution...`);
784
+ }
785
+ }
786
+ }) || []
787
+ );
788
+ };
789
+
790
+ // only resolve nested generators when they should not be skipped
791
+ if (!this.options.skipNested) {
792
+ await resolveNestedGenerator(subGenerator);
731
793
  }
732
794
 
733
- // finally, run the subgenerator
734
- env.run(subGenerator, {
735
- verbose: this.options.verbose,
736
- embedded: true,
737
- destinationRoot: this.destinationRoot(),
738
- });
795
+ // intercept the environments runGenerator method to determine
796
+ // and forward the destinationRoot between the generator executions
797
+ const runGenerator = env.runGenerator;
798
+ let cwd;
799
+ env.runGenerator = async function (gen) {
800
+ if (cwd) {
801
+ // apply the cwd to the next gen
802
+ gen.destinationRoot(cwd);
803
+ }
804
+ return runGenerator.apply(this, arguments).then((retval) => {
805
+ // store the cwd from the current gen
806
+ cwd = gen.destinationRoot();
807
+ return retval;
808
+ });
809
+ };
810
+
811
+ // chain the execution of the generators
812
+ let chain = Promise.resolve();
813
+ for (const subGen of subGensToRun) {
814
+ chain = chain.then(
815
+ function () {
816
+ // we need to use env.run and not composeWith
817
+ // to ensure that subgenerators can have different
818
+ // dependencies than the root generator
819
+ return env.run(subGen, {
820
+ verbose: this.options.verbose,
821
+ embedded: true,
822
+ destinationRoot: this.destinationRoot(),
823
+ });
824
+ }.bind(this)
825
+ );
826
+ }
827
+
828
+ if (this.options.verbose) {
829
+ this.log(`Running generators in "${generatorPath}"...`);
830
+ }
739
831
  } else {
740
832
  this.log(`The generator ${chalk.red(this.options.generator)} has no visible subgenerators!`);
741
833
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "generator-easy-ui5",
3
- "version": "3.7.0",
3
+ "version": "3.8.1",
4
4
  "description": "Generator for UI5-based project",
5
5
  "main": "generators/app/index.js",
6
6
  "type": "module",
@@ -55,6 +55,7 @@
55
55
  "colors": "^1.4.0",
56
56
  "glob": "^10.3.10",
57
57
  "libnpmconfig": "^1.2.1",
58
+ "node-fetch": "^3.3.2",
58
59
  "rimraf": "^5.0.5",
59
60
  "yeoman-environment": "^3.19.3",
60
61
  "yeoman-generator": "^5.10.0",
Binary file