UNPKG

8.67 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const cli_framework_1 = require("@ionic/cli-framework");
4const utils_process_1 = require("@ionic/utils-process");
5const chalk_1 = require("chalk");
6const lodash = require("lodash");
7const path = require("path");
8const color_1 = require("../../lib/color");
9const errors_1 = require("../../lib/errors");
10const config_1 = require("../../lib/integrations/capacitor/config");
11const utils_1 = require("../../lib/integrations/capacitor/utils");
12const serve_1 = require("../../lib/serve");
13const base_1 = require("./base");
14class RunCommand extends base_1.CapacitorCommand {
15 async getMetadata() {
16 const groups = ["beta" /* BETA */];
17 const exampleCommands = [
18 '',
19 'android',
20 'android -l',
21 'ios --livereload',
22 'ios --livereload-url=http://localhost:8100',
23 ].sort();
24 let options = [
25 // Build Options
26 {
27 name: 'build',
28 summary: 'Do not invoke Ionic build',
29 type: Boolean,
30 default: true,
31 },
32 ...serve_1.COMMON_SERVE_COMMAND_OPTIONS.filter(o => !['livereload'].includes(o.name)),
33 {
34 name: 'livereload',
35 summary: 'Spin up dev server to live-reload www files',
36 type: Boolean,
37 aliases: ['l'],
38 },
39 {
40 name: 'livereload-url',
41 summary: 'Provide a custom URL to the dev server',
42 spec: { value: 'url' },
43 },
44 ];
45 const footnotes = [
46 {
47 id: 'remote-debugging-docs',
48 url: 'https://ionicframework.com/docs/developer-resources/developer-tips',
49 shortUrl: 'https://ion.link/remote-debugging-docs',
50 },
51 ];
52 const serveRunner = this.project && await this.project.getServeRunner();
53 const buildRunner = this.project && await this.project.getBuildRunner();
54 if (buildRunner) {
55 const libmetadata = await buildRunner.getCommandMetadata();
56 groups.push(...libmetadata.groups || []);
57 options.push(...libmetadata.options || []);
58 footnotes.push(...libmetadata.footnotes || []);
59 }
60 if (serveRunner) {
61 const libmetadata = await serveRunner.getCommandMetadata();
62 const existingOpts = options.map(o => o.name);
63 groups.push(...libmetadata.groups || []);
64 const runnerOpts = (libmetadata.options || [])
65 .filter(o => !existingOpts.includes(o.name))
66 .map(o => ({ ...o, hint: `${o.hint ? `${o.hint} ` : ''}${color_1.weak('(--livereload)')}` }));
67 options = lodash.uniqWith([...runnerOpts, ...options], (optionA, optionB) => optionA.name === optionB.name);
68 footnotes.push(...libmetadata.footnotes || []);
69 }
70 return {
71 name: 'run',
72 type: 'project',
73 summary: 'Run an Ionic project on a connected device',
74 description: `
75${color_1.input('ionic capacitor run')} will do the following:
76- Perform ${color_1.input('ionic build')} (or run the dev server from ${color_1.input('ionic serve')} with the ${color_1.input('--livereload')} option)
77- Copy web assets into the specified native platform
78- Open the IDE for your native project (Xcode for iOS, Android Studio for Android)
79
80Once the web assets and configuration are copied into your native project, the app can run on devices and emulators/simulators using the native IDE. Unfortunately, programmatically building and launching the native project is not yet supported.
81
82For Android and iOS, you can setup Remote Debugging on your device with browser development tools using these docs[^remote-debugging-docs].
83 `,
84 footnotes,
85 exampleCommands,
86 inputs: [
87 {
88 name: 'platform',
89 summary: `The platform to run (e.g. ${['android', 'ios'].map(v => color_1.input(v)).join(', ')})`,
90 validators: [cli_framework_1.validators.required],
91 },
92 ],
93 options,
94 groups,
95 };
96 }
97 async preRun(inputs, options, runinfo) {
98 await this.preRunChecks(runinfo);
99 if (!inputs[0]) {
100 const platform = await this.env.prompt({
101 type: 'list',
102 name: 'platform',
103 message: 'What platform would you like to run?',
104 choices: ['android', 'ios'],
105 });
106 inputs[0] = platform.trim();
107 }
108 if (options['livereload-url']) {
109 options['livereload'] = true;
110 }
111 if (!options['build'] && options['livereload']) {
112 this.env.log.warn(`No livereload with ${color_1.input('--no-build')}.`);
113 options['livereload'] = false;
114 }
115 await this.checkForPlatformInstallation(inputs[0]);
116 }
117 async run(inputs, options) {
118 if (!this.project) {
119 throw new errors_1.FatalException(`Cannot run ${color_1.input('ionic capacitor run/emulate')} outside a project directory.`);
120 }
121 const [platform] = inputs;
122 try {
123 if (options['livereload']) {
124 await this.runServe(inputs, options);
125 }
126 else {
127 await this.runBuild(inputs, options);
128 }
129 }
130 catch (e) {
131 if (e instanceof errors_1.RunnerException) {
132 throw new errors_1.FatalException(e.message);
133 }
134 throw e;
135 }
136 // copy assets and capacitor.config.json into place
137 await this.runCapacitor(['copy', platform]);
138 // TODO: native-run
139 this.env.log.nl();
140 this.env.log.info('Ready for use in your Native IDE!\n' +
141 `To continue, run your project on a device or ${platform === 'ios' ? 'simulator' : 'emulator'} using ${platform === 'ios' ? 'Xcode' : 'Android Studio'}!`);
142 this.env.log.nl();
143 await this.runCapacitor(['open', platform]);
144 if (options['livereload']) {
145 this.env.log.nl();
146 this.env.log.info('Development server will continue running until manually stopped.\n' +
147 chalk_1.default.yellow('Use Ctrl+C to quit this process'));
148 await utils_process_1.sleepForever();
149 }
150 }
151 async runServe(inputs, options) {
152 if (!this.project) {
153 throw new errors_1.FatalException(`Cannot run ${color_1.input('ionic capacitor run/emulate')} outside a project directory.`);
154 }
155 const runner = await this.project.requireServeRunner();
156 const runnerOpts = runner.createOptionsFromCommandLine(inputs, utils_1.generateOptionsForCapacitorBuild(inputs, options));
157 let serverUrl = options['livereload-url'] ? String(options['livereload-url']) : undefined;
158 if (!serverUrl) {
159 const details = await runner.run(runnerOpts);
160 if (details.externallyAccessible === false) {
161 const extra = serve_1.LOCAL_ADDRESSES.includes(details.externalAddress) ? '\nEnsure you have proper port forwarding setup from your device to your computer.' : '';
162 this.env.log.warn(`Your device or emulator may not be able to access ${color_1.strong(details.externalAddress)}.${extra}\n\n`);
163 }
164 serverUrl = `${details.protocol || 'http'}://${details.externalAddress}:${details.port}`;
165 }
166 const conf = new config_1.CapacitorConfig(path.resolve(this.project.directory, config_1.CAPACITOR_CONFIG_FILE));
167 utils_process_1.onBeforeExit(async () => {
168 conf.resetServerUrl();
169 });
170 conf.setServerUrl(serverUrl);
171 }
172 async runBuild(inputs, options) {
173 if (!this.project) {
174 throw new errors_1.FatalException(`Cannot run ${color_1.input('ionic capacitor run/emulate')} outside a project directory.`);
175 }
176 if (options['build']) {
177 try {
178 const runner = await this.project.requireBuildRunner();
179 const runnerOpts = runner.createOptionsFromCommandLine(inputs, utils_1.generateOptionsForCapacitorBuild(inputs, options));
180 await runner.run(runnerOpts);
181 }
182 catch (e) {
183 if (e instanceof errors_1.RunnerException) {
184 throw new errors_1.FatalException(e.message);
185 }
186 throw e;
187 }
188 }
189 }
190}
191exports.RunCommand = RunCommand;