serve.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.AngularServeCLI = exports.AngularServeRunner = 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_network_1 = require("@ionic/utils-network");
  8. const utils_terminal_1 = require("@ionic/utils-terminal");
  9. const chalk_1 = tslib_1.__importDefault(require("chalk"));
  10. const color_1 = require("../../color");
  11. const serve_1 = require("../../serve");
  12. class AngularServeRunner extends serve_1.ServeRunner {
  13. constructor(e) {
  14. super();
  15. this.e = e;
  16. }
  17. async getCommandMetadata() {
  18. return {
  19. description: `
  20. ${(0, color_1.input)('ionic serve')} uses the Angular CLI. Use ${(0, color_1.input)('ng serve --help')} to list all Angular CLI options for serving your app. See the ${(0, color_1.input)('ng serve')} docs[^ng-serve-docs] for explanations. Options not listed below are considered advanced and can be passed to the Angular CLI using the ${(0, color_1.input)('--')} separator after the Ionic CLI arguments. See the examples.
  21. The dev server can use HTTPS via the ${(0, color_1.input)('--ssl')} option ${chalk_1.default.bold.red('(experimental)')}. There are several known issues with HTTPS. See issue #3305[^issue-3305].
  22. `,
  23. footnotes: [
  24. {
  25. id: 'ng-serve-docs',
  26. url: 'https://angular.io/cli/serve',
  27. },
  28. {
  29. id: 'issue-3305',
  30. url: 'https://github.com/ionic-team/ionic-cli/issues/3305',
  31. },
  32. ],
  33. options: [
  34. {
  35. name: 'consolelogs',
  36. summary: 'Print app console logs to the terminal',
  37. type: Boolean,
  38. groups: ["advanced" /* MetadataGroup.ADVANCED */, 'cordova'],
  39. hint: (0, color_1.weak)('[ng]'),
  40. },
  41. {
  42. name: 'consolelogs-port',
  43. summary: 'Use specific port for console logs server',
  44. type: String,
  45. groups: ["advanced" /* MetadataGroup.ADVANCED */, 'cordova'],
  46. hint: (0, color_1.weak)('[ng]'),
  47. spec: { value: 'port' },
  48. },
  49. {
  50. name: 'ssl',
  51. summary: 'Use HTTPS for the dev server',
  52. type: Boolean,
  53. groups: ["experimental" /* MetadataGroup.EXPERIMENTAL */, 'cordova'],
  54. hint: (0, color_1.weak)('[ng]'),
  55. },
  56. {
  57. name: 'prod',
  58. summary: `Flag to use the ${(0, color_1.input)('production')} configuration`,
  59. type: Boolean,
  60. groups: ['cordova'],
  61. hint: (0, color_1.weak)('[ng]'),
  62. },
  63. {
  64. name: 'configuration',
  65. summary: 'Specify the configuration to use.',
  66. type: String,
  67. groups: ["advanced" /* MetadataGroup.ADVANCED */, 'cordova'],
  68. aliases: ['c'],
  69. hint: (0, color_1.weak)('[ng]'),
  70. spec: { value: 'conf' },
  71. },
  72. {
  73. name: 'source-map',
  74. summary: 'Output sourcemaps',
  75. type: Boolean,
  76. groups: ["advanced" /* MetadataGroup.ADVANCED */, 'cordova'],
  77. hint: (0, color_1.weak)('[ng]'),
  78. },
  79. ],
  80. exampleCommands: [
  81. '-- --proxy-config proxy.conf.json',
  82. ],
  83. };
  84. }
  85. createOptionsFromCommandLine(inputs, options) {
  86. const baseOptions = super.createOptionsFromCommandLine(inputs, options);
  87. const prod = options['prod'] ? Boolean(options['prod']) : undefined;
  88. const ssl = options['ssl'] ? Boolean(options['ssl']) : undefined;
  89. const configuration = options['configuration'] ? String(options['configuration']) : (prod ? 'production' : undefined);
  90. const project = options['project'] ? String(options['project']) : 'app';
  91. const sourcemaps = typeof options['source-map'] === 'boolean' ? Boolean(options['source-map']) : undefined;
  92. const consolelogs = typeof options['consolelogs'] === 'boolean' ? Boolean(options['consolelogs']) : undefined;
  93. const consolelogsPort = consolelogs ? (0, string_1.str2num)(options['consolelogs-port'], serve_1.DEFAULT_DEV_LOGGER_PORT) : undefined;
  94. return {
  95. ...baseOptions,
  96. consolelogs,
  97. consolelogsPort,
  98. ssl,
  99. configuration,
  100. project,
  101. sourcemaps,
  102. };
  103. }
  104. platformToMode(platform) {
  105. if (platform === 'ios') {
  106. return 'ios';
  107. }
  108. return 'md';
  109. }
  110. modifyOpenUrl(url, options) {
  111. return `${url}${options.browserOption ? options.browserOption : ''}${options.platform ? `?ionic:mode=${this.platformToMode(options.platform)}&ionic:persistConfig=true` : ''}`;
  112. }
  113. async serveProject(options) {
  114. const [externalIP, availableInterfaces] = await this.selectExternalIP(options);
  115. const port = options.port = await (0, utils_network_1.findClosestOpenPort)(options.port);
  116. const ng = new AngularServeCLI(this.e);
  117. await ng.serve(options);
  118. return {
  119. custom: ng.resolvedProgram !== ng.program,
  120. protocol: options.ssl ? 'https' : 'http',
  121. localAddress: 'localhost',
  122. externalAddress: externalIP,
  123. externalNetworkInterfaces: availableInterfaces,
  124. port,
  125. externallyAccessible: ![serve_1.BIND_ALL_ADDRESS, ...serve_1.LOCAL_ADDRESSES].includes(externalIP),
  126. };
  127. }
  128. getUsedPorts(options, details) {
  129. return [
  130. ...super.getUsedPorts(options, details),
  131. ...options.consolelogsPort ? [options.consolelogsPort] : [],
  132. ];
  133. }
  134. }
  135. exports.AngularServeRunner = AngularServeRunner;
  136. class AngularServeCLI extends serve_1.ServeCLI {
  137. constructor() {
  138. super(...arguments);
  139. this.name = 'Angular CLI';
  140. this.pkg = '@angular/cli';
  141. this.program = 'ng';
  142. this.prefix = 'ng';
  143. this.script = serve_1.SERVE_SCRIPT;
  144. this.chunks = 0;
  145. }
  146. async serve(options) {
  147. this.on('compile', chunks => {
  148. if (chunks > 0) {
  149. this.e.log.info(`... and ${(0, color_1.strong)(chunks.toString())} additional chunks`);
  150. }
  151. });
  152. return super.serve(options);
  153. }
  154. stdoutFilter(line) {
  155. if (this.resolvedProgram !== this.program) {
  156. return super.stdoutFilter(line);
  157. }
  158. const strippedLine = (0, utils_terminal_1.stripAnsi)(line);
  159. const compileMsgs = [
  160. 'Development Server is listening',
  161. 'Watching for file changes'
  162. ];
  163. if (compileMsgs.some((msg) => strippedLine.includes(msg))) {
  164. this.emit('ready');
  165. return false;
  166. }
  167. if (strippedLine.match(/.*chunk\s{\d+}.+/)) {
  168. this.chunks++;
  169. return false;
  170. }
  171. if (strippedLine.includes('Compiled successfully')) {
  172. this.emit('compile', this.chunks);
  173. this.chunks = 0;
  174. }
  175. return true;
  176. }
  177. async buildArgs(options) {
  178. const { pkgManagerArgs } = await Promise.resolve().then(() => tslib_1.__importStar(require('../../utils/npm')));
  179. const args = await this.serveOptionsToNgArgs(options);
  180. if (this.resolvedProgram === this.program) {
  181. return [...this.buildArchitectCommand(options), ...args];
  182. }
  183. else {
  184. const [, ...pkgArgs] = await pkgManagerArgs(this.e.config.get('npmClient'), { command: 'run', script: this.script, scriptArgs: [...args] });
  185. return pkgArgs;
  186. }
  187. }
  188. async serveOptionsToNgArgs(options) {
  189. const args = {
  190. _: [],
  191. host: options.host,
  192. port: options.port ? options.port.toString() : undefined,
  193. 'source-map': options.sourcemaps !== false ? options.sourcemaps : 'false',
  194. 'ssl': options.ssl !== false ? options.ssl : 'false',
  195. };
  196. const projectArgs = [];
  197. let separatedArgs = options['--'];
  198. if (options.engine === 'cordova') {
  199. const integration = this.e.project.requireIntegration('cordova');
  200. args.platform = options.platform;
  201. if (this.e.project.rootDirectory !== integration.root) {
  202. args.cordovaBasePath = integration.root;
  203. }
  204. separatedArgs = [];
  205. args.consolelogs = options.consolelogs ? true : undefined;
  206. args['consolelogs-port'] = options.consolelogsPort ? String(options.consolelogsPort) : undefined;
  207. }
  208. else {
  209. args['public-host'] = options.publicHost; // TODO: @ionic/angular-toolkit would need to support --public-host
  210. }
  211. if (this.resolvedProgram !== this.program) {
  212. if (options.configuration) {
  213. projectArgs.push(`--configuration=${options.configuration}`);
  214. }
  215. if (options.project) {
  216. projectArgs.push(`--project=${options.project}`);
  217. }
  218. }
  219. if (options.verbose) {
  220. projectArgs.push('--verbose');
  221. }
  222. return [...(0, cli_framework_1.unparseArgs)(args), ...projectArgs, ...separatedArgs];
  223. }
  224. buildArchitectCommand(options) {
  225. const cmd = options.engine === 'cordova' ? 'ionic-cordova-serve' : 'serve';
  226. return ['run', `${options.project}:${cmd}${options.configuration ? `:${options.configuration}` : ''}`];
  227. }
  228. }
  229. exports.AngularServeCLI = AngularServeCLI;