init.js 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.InitCommand = void 0;
  4. const tslib_1 = require("tslib");
  5. const cli_framework_1 = require("@ionic/cli-framework");
  6. const string_1 = require("@ionic/cli-framework/utils/string");
  7. const utils_terminal_1 = require("@ionic/utils-terminal");
  8. const path = tslib_1.__importStar(require("path"));
  9. const constants_1 = require("../constants");
  10. const color_1 = require("../lib/color");
  11. const command_1 = require("../lib/command");
  12. const errors_1 = require("../lib/errors");
  13. const project_1 = require("../lib/project");
  14. class InitCommand extends command_1.Command {
  15. async getMetadata() {
  16. return {
  17. name: 'init',
  18. type: 'global',
  19. summary: 'Initialize existing projects with Ionic',
  20. description: `
  21. This command will initialize an Ionic app within the current directory. Usually, this means an ${(0, color_1.input)(constants_1.PROJECT_FILE)} file is created. If used within a multi-app project, the app is initialized in the root ${(0, color_1.input)(constants_1.PROJECT_FILE)}.
  22. ${(0, color_1.input)('ionic init')} will prompt for a project name and then proceed to determine the type of your project. You can specify the ${(0, color_1.input)('name')} argument and ${(0, color_1.input)('--type')} option to provide these values via command-line.
  23. If the ${(0, color_1.input)('--multi-app')} flag is specified, this command will initialize your project as a multi-app project, allowing for apps within monorepos and unconventional repository structures. See the multi-app docs[^multi-app-docs] for details. Once a multi-app project is initialized, you can run ${(0, color_1.input)('ionic init')} again within apps in your project to initialize them.
  24. `,
  25. exampleCommands: [
  26. '',
  27. '"My App"',
  28. '"My App" --type=angular',
  29. '--multi-app',
  30. ],
  31. inputs: [
  32. {
  33. name: 'name',
  34. summary: `The name of your project (e.g. ${(0, color_1.input)('myApp')}, ${(0, color_1.input)('"My App"')})`,
  35. },
  36. ],
  37. options: [
  38. {
  39. name: 'type',
  40. summary: `Type of project (e.g. ${constants_1.MODERN_PROJECT_TYPES.map(type => (0, color_1.input)(type)).join(', ')})`,
  41. },
  42. {
  43. name: 'force',
  44. summary: 'Initialize even if a project already exists',
  45. type: Boolean,
  46. aliases: ['f'],
  47. default: false,
  48. },
  49. {
  50. name: 'multi-app',
  51. summary: 'Initialize a multi-app project',
  52. type: Boolean,
  53. default: false,
  54. },
  55. {
  56. name: 'project-id',
  57. summary: 'Specify a slug for your app',
  58. groups: ["advanced" /* MetadataGroup.ADVANCED */],
  59. spec: { value: 'slug' },
  60. hint: (0, color_1.weak)('[multi-app]'),
  61. },
  62. {
  63. name: 'default',
  64. summary: 'Mark the initialized app as the default project',
  65. type: Boolean,
  66. groups: ["advanced" /* MetadataGroup.ADVANCED */],
  67. hint: (0, color_1.weak)('[multi-app]'),
  68. },
  69. ],
  70. groups: ["beta" /* MetadataGroup.BETA */],
  71. footnotes: [
  72. {
  73. id: 'multi-app-docs',
  74. url: 'https://ionicframework.com/docs/cli/configuration#multi-app-projects',
  75. shortUrl: 'https://ion.link/multi-app-docs',
  76. },
  77. ],
  78. };
  79. }
  80. async preRun(inputs, options) {
  81. const force = options['force'] ? true : false;
  82. if (this.project && !force) {
  83. // TODO: check for existing project config in multi-app
  84. if (this.project.details.context === 'app' || (this.project.details.context === 'multiapp' && options['multi-app'])) {
  85. throw new errors_1.FatalException(`Existing Ionic project file found: ${(0, color_1.strong)((0, utils_terminal_1.prettyPath)(this.project.filePath))}\n` +
  86. `You can re-initialize your project using the ${(0, color_1.input)('--force')} option.`);
  87. }
  88. }
  89. if (!options['multi-app']) {
  90. if (!inputs[0]) {
  91. const name = await this.env.prompt({
  92. type: 'input',
  93. name: 'name',
  94. message: 'Project name:',
  95. validate: v => cli_framework_1.validators.required(v),
  96. });
  97. inputs[0] = name;
  98. }
  99. if (!options['type']) {
  100. const details = new project_1.ProjectDetails({ rootDirectory: this.env.ctx.execPath, e: this.env });
  101. options['type'] = await details.getTypeFromDetection();
  102. }
  103. if (!options['type']) {
  104. if (this.env.flags.interactive) {
  105. this.env.log.warn(`Could not determine project type.\n` +
  106. `Please choose a project type from the list.`);
  107. this.env.log.nl();
  108. }
  109. const type = await this.env.prompt({
  110. type: 'list',
  111. name: 'type',
  112. message: 'Project type:',
  113. choices: constants_1.MODERN_PROJECT_TYPES.map(t => ({
  114. name: `${(0, project_1.prettyProjectName)(t)} (${(0, color_1.input)(t)})`,
  115. value: t,
  116. })),
  117. });
  118. options['type'] = type;
  119. }
  120. }
  121. }
  122. async run(inputs, options) {
  123. if (options['multi-app']) {
  124. await this.initializeMultiProject(inputs, options);
  125. }
  126. else {
  127. await this.initializeApp(inputs, options);
  128. }
  129. this.env.log.ok('Your Ionic project has been initialized!');
  130. }
  131. async initializeMultiProject(inputs, options) {
  132. const configPath = this.getProjectFilePath();
  133. const config = new project_1.MultiProjectConfig(configPath);
  134. config.c = { projects: {} };
  135. }
  136. async initializeApp(inputs, options) {
  137. const name = inputs[0] ? inputs[0].trim() : '';
  138. const type = options['type'] ? String(options['type']) : undefined;
  139. const projectId = options['project-id'] ? String(options['project-id']) : (0, string_1.slugify)(name); // TODO validate --project-id
  140. if (!name) {
  141. throw new errors_1.FatalException(`Project name not specified.\n` +
  142. `Please specify ${(0, color_1.input)('name')}, the first argument of ${(0, color_1.input)('ionic init')}. See ${(0, color_1.input)('ionic init --help')} for details.`);
  143. }
  144. if (!type) {
  145. throw new errors_1.FatalException(`Could not determine project type.\n` +
  146. `Please specify ${(0, color_1.input)('--type')}. See ${(0, color_1.input)('ionic init --help')} for details.`);
  147. }
  148. let project;
  149. if (this.project && this.project.details.context === 'multiapp') {
  150. const configPath = path.resolve(this.project.rootDirectory, constants_1.PROJECT_FILE);
  151. const projectRoot = path.relative(this.project.rootDirectory, this.env.ctx.execPath);
  152. const config = new project_1.MultiProjectConfig(configPath);
  153. if (!projectRoot) {
  154. if (this.env.flags.interactive) {
  155. this.env.log.warn(`About to initialize app in the root directory of your multi-app project.\n` +
  156. `Please confirm that you want your app initialized in the root of your multi-app project. If this wasn't intended, please ${(0, color_1.input)('cd')} into the appropriate directory and run ${(0, color_1.input)('ionic init')} again.\n`);
  157. }
  158. const confirm = await this.env.prompt({
  159. type: 'confirm',
  160. message: 'Continue?',
  161. default: false,
  162. });
  163. if (!confirm) {
  164. throw new errors_1.FatalException(`Not initializing app in root directory.`);
  165. }
  166. }
  167. const defaultProject = config.get('defaultProject');
  168. if (!defaultProject && typeof options['default'] !== 'boolean') {
  169. const confirm = await this.env.prompt({
  170. type: 'confirm',
  171. message: `Would you like to make this app the default project?`,
  172. default: true,
  173. });
  174. if (confirm) {
  175. options['default'] = true;
  176. }
  177. }
  178. if (options['default']) {
  179. config.set('defaultProject', projectId);
  180. }
  181. project = await (0, project_1.createProjectFromDetails)({ context: 'multiapp', configPath, id: projectId, type, errors: [] }, this.env);
  182. project.config.set('root', projectRoot);
  183. }
  184. else {
  185. const configPath = this.getProjectFilePath();
  186. project = await (0, project_1.createProjectFromDetails)({ context: 'app', configPath, type, errors: [] }, this.env);
  187. }
  188. project.config.set('name', name);
  189. project.config.set('type', type);
  190. }
  191. getProjectFilePath() {
  192. return path.resolve(this.env.ctx.execPath, constants_1.PROJECT_FILE);
  193. }
  194. }
  195. exports.InitCommand = InitCommand;