generate.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.AngularGenerateRunner = void 0;
  4. const tslib_1 = require("tslib");
  5. const cli_framework_1 = require("@ionic/cli-framework");
  6. const debug_1 = require("debug");
  7. const lodash = tslib_1.__importStar(require("lodash"));
  8. const color_1 = require("../../color");
  9. const config_1 = require("../../config");
  10. const errors_1 = require("../../errors");
  11. const generate_1 = require("../../generate");
  12. // https://github.com/ionic-team/angular-toolkit/blob/master/collection.json
  13. const SCHEMATICS = ['page', 'component', 'service', 'module', 'class', 'directive', 'guard', 'pipe', 'interface', 'enum'];
  14. const SCHEMATIC_ALIAS = new Map([
  15. ['pg', 'page'],
  16. ['cl', 'class'],
  17. ['c', 'component'],
  18. ['d', 'directive'],
  19. ['e', 'enum'],
  20. ['g', 'guard'],
  21. ['i', 'interface'],
  22. ['m', 'module'],
  23. ['p', 'pipe'],
  24. ['s', 'service'],
  25. ]);
  26. const debug = (0, debug_1.debug)('ionic:lib:project:angular:generate');
  27. class AngularGenerateRunner extends generate_1.GenerateRunner {
  28. constructor(e) {
  29. super();
  30. this.e = e;
  31. }
  32. async getCommandMetadata() {
  33. return {
  34. description: `
  35. Automatically create framework features with Ionic Generate. This command uses the Angular CLI to generate features such as ${['pages', 'components', 'directives', 'services'].map(c => (0, color_1.input)(c)).join(', ')}, and more.
  36. - For a full list of available types, use ${(0, color_1.input)('npx ng g --help')}
  37. - For a list of options for a types, use ${(0, color_1.input)('npx ng g <type> --help')}
  38. You can specify a path to nest your feature within any number of subdirectories. For example, specify a name of ${(0, color_1.input)('"pages/New Page"')} to generate page files at ${(0, color_1.strong)('src/app/pages/new-page/')}.
  39. To test a generator before file modifications are made, use the ${(0, color_1.input)('--dry-run')} option.
  40. `,
  41. exampleCommands: [
  42. 'page',
  43. 'page contact',
  44. 'component contact/form',
  45. 'component login-form --change-detection=OnPush',
  46. 'directive ripple --skip-import',
  47. 'service api/user',
  48. ],
  49. inputs: [
  50. {
  51. name: 'schematic',
  52. summary: `The type of feature (e.g. ${['page', 'component', 'directive', 'service'].map(c => (0, color_1.input)(c)).join(', ')})`,
  53. validators: [cli_framework_1.validators.required],
  54. },
  55. {
  56. name: 'name',
  57. summary: 'The name/path of the feature being generated',
  58. validators: [cli_framework_1.validators.required],
  59. },
  60. ],
  61. };
  62. }
  63. async ensureCommandLine(inputs, options) {
  64. if (inputs[0]) {
  65. this.validateFeatureType(inputs[0]);
  66. }
  67. else {
  68. const schematic = await this.e.prompt({
  69. type: 'list',
  70. name: 'schematic',
  71. message: 'What would you like to generate?',
  72. choices: SCHEMATICS,
  73. });
  74. inputs[0] = schematic;
  75. }
  76. if (!inputs[1]) {
  77. const schematic = SCHEMATIC_ALIAS.get(inputs[0]) || inputs[0];
  78. const name = await this.e.prompt({
  79. type: 'input',
  80. name: 'name',
  81. message: `Name/path of ${(0, color_1.input)(schematic)}:`,
  82. validate: v => cli_framework_1.validators.required(v),
  83. });
  84. inputs[1] = name.trim();
  85. }
  86. }
  87. createOptionsFromCommandLine(inputs, options) {
  88. const [schematic, name] = inputs;
  89. const baseOptions = { name, schematic };
  90. const project = options['project'] ? String(options['project']) : 'app';
  91. // TODO: this is a little gross, is there a better way to pass in all the
  92. // options that the command got?
  93. return {
  94. ...lodash.omit(options, '_', '--', ...config_1.GLOBAL_OPTIONS.map(opt => opt.name)),
  95. project,
  96. ...baseOptions,
  97. };
  98. }
  99. async run(options) {
  100. const { name } = options;
  101. const schematic = SCHEMATIC_ALIAS.get(options.schematic) || options.schematic;
  102. try {
  103. await this.generateComponent(schematic, name, lodash.omit(options, 'schematic', 'name'));
  104. }
  105. catch (e) {
  106. debug(e);
  107. throw new errors_1.FatalException(`Could not generate ${(0, color_1.input)(schematic)}.`);
  108. }
  109. if (!options['dry-run']) {
  110. this.e.log.ok(`Generated ${(0, color_1.input)(schematic)}!`);
  111. }
  112. }
  113. validateFeatureType(schematic) {
  114. if (schematic === 'provider') {
  115. throw new errors_1.FatalException(`Please use ${(0, color_1.input)('ionic generate service')} for generating service providers.\n` +
  116. `For more information, please see the Angular documentation${(0, color_1.ancillary)('[1]')} on services.\n\n` +
  117. `${(0, color_1.ancillary)('[1]')}: ${(0, color_1.strong)('https://angular.io/guide/architecture-services')}`);
  118. }
  119. if (!SCHEMATICS.includes(schematic) && !SCHEMATIC_ALIAS.get(schematic)) {
  120. throw new errors_1.FatalException(`${(0, color_1.input)(schematic)} is not a known feature.\n` +
  121. `Use ${(0, color_1.input)('npx ng g --help')} to list available types of features.`);
  122. }
  123. }
  124. async generateComponent(schematic, name, options) {
  125. const args = {
  126. _: ['generate', schematic, name],
  127. // convert `--no-<opt>` style options to `--<opt>=false`
  128. ...lodash.mapValues(options, v => v === false ? 'false' : v),
  129. };
  130. await this.e.shell.run('ng', (0, cli_framework_1.unparseArgs)(args, { useEquals: true }), { cwd: this.e.ctx.execPath, stdio: 'inherit' });
  131. }
  132. }
  133. exports.AngularGenerateRunner = AngularGenerateRunner;