1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.YarnBuildCLI = exports.PnpmBuildCLI = exports.NpmBuildCLI = exports.BuildCLI = exports.BuildRunner = exports.COMMON_BUILD_COMMAND_OPTIONS = exports.BUILD_SCRIPT = void 0;
|
4 | const cli_framework_1 = require("@ionic/cli-framework");
|
5 | const utils_process_1 = require("@ionic/utils-process");
|
6 | const utils_subprocess_1 = require("@ionic/utils-subprocess");
|
7 | const Debug = require("debug");
|
8 | const color_1 = require("./color");
|
9 | const errors_1 = require("./errors");
|
10 | const hooks_1 = require("./hooks");
|
11 | const debug = Debug('ionic:lib:build');
|
12 | exports.BUILD_SCRIPT = 'ionic:build';
|
13 | exports.COMMON_BUILD_COMMAND_OPTIONS = [
|
14 | {
|
15 | name: 'engine',
|
16 | summary: `Target engine (e.g. ${['browser', 'cordova'].map(e => color_1.input(e)).join(', ')})`,
|
17 | groups: ["advanced" ],
|
18 | },
|
19 | {
|
20 | name: 'platform',
|
21 | summary: `Target platform on chosen engine (e.g. ${['ios', 'android'].map(e => color_1.input(e)).join(', ')})`,
|
22 | groups: ["advanced" ],
|
23 | },
|
24 | ];
|
25 | class BuildRunner {
|
26 | getPkgManagerBuildCLI() {
|
27 | const pkgManagerCLIs = {
|
28 | npm: NpmBuildCLI,
|
29 | pnpm: PnpmBuildCLI,
|
30 | yarn: YarnBuildCLI,
|
31 | };
|
32 | const client = this.e.config.get('npmClient');
|
33 | const CLI = pkgManagerCLIs[client];
|
34 | if (CLI) {
|
35 | return new CLI(this.e);
|
36 | }
|
37 | throw new errors_1.BuildCLIProgramNotFoundException('Unknown CLI client: ' + client);
|
38 | }
|
39 | createBaseOptionsFromCommandLine(inputs, options) {
|
40 | const separatedArgs = options['--'];
|
41 | const [platform] = options['platform'] ? [String(options['platform'])] : inputs;
|
42 | const engine = this.determineEngineFromCommandLine(options);
|
43 | const project = options['project'] ? String(options['project']) : undefined;
|
44 | const verbose = !!options['verbose'];
|
45 | return { '--': separatedArgs ? separatedArgs : [], engine, platform, project, verbose };
|
46 | }
|
47 | determineEngineFromCommandLine(options) {
|
48 | if (options['engine']) {
|
49 | return String(options['engine']);
|
50 | }
|
51 | if (options['cordova']) {
|
52 | return 'cordova';
|
53 | }
|
54 | return 'browser';
|
55 | }
|
56 | async beforeBuild(options) {
|
57 | const hook = new BuildBeforeHook(this.e);
|
58 | try {
|
59 | await hook.run({ name: hook.name, build: options });
|
60 | }
|
61 | catch (e) {
|
62 | if (e instanceof cli_framework_1.BaseError) {
|
63 | throw new errors_1.FatalException(e.message);
|
64 | }
|
65 | throw e;
|
66 | }
|
67 | }
|
68 | async run(options) {
|
69 | debug('build options: %O', options);
|
70 | if (options.engine === 'cordova' && !options.platform) {
|
71 | this.e.log.warn(`Cordova engine chosen without a target platform. This could cause issues. Please use the ${color_1.input('--platform')} option.`);
|
72 | }
|
73 | await this.beforeBuild(options);
|
74 | await this.buildProject(options);
|
75 | await this.afterBuild(options);
|
76 | }
|
77 | async afterBuild(options) {
|
78 | const hook = new BuildAfterHook(this.e);
|
79 | try {
|
80 | await hook.run({ name: hook.name, build: options });
|
81 | }
|
82 | catch (e) {
|
83 | if (e instanceof cli_framework_1.BaseError) {
|
84 | throw new errors_1.FatalException(e.message);
|
85 | }
|
86 | throw e;
|
87 | }
|
88 | }
|
89 | }
|
90 | exports.BuildRunner = BuildRunner;
|
91 | class BuildCLI {
|
92 | constructor(e) {
|
93 | this.e = e;
|
94 | |
95 |
|
96 |
|
97 | this.global = false;
|
98 | }
|
99 | get resolvedProgram() {
|
100 | if (this._resolvedProgram) {
|
101 | return this._resolvedProgram;
|
102 | }
|
103 | return this.program;
|
104 | }
|
105 | |
106 |
|
107 |
|
108 | async buildEnvVars(options) {
|
109 | return process.env;
|
110 | }
|
111 | async resolveScript() {
|
112 | if (typeof this.script === 'undefined') {
|
113 | return;
|
114 | }
|
115 | const pkg = await this.e.project.requirePackageJson();
|
116 | return pkg.scripts && pkg.scripts[this.script];
|
117 | }
|
118 | async build(options) {
|
119 | this._resolvedProgram = await this.resolveProgram();
|
120 | await this.runWrapper(options);
|
121 | }
|
122 | async runWrapper(options) {
|
123 | try {
|
124 | return await this.run(options);
|
125 | }
|
126 | catch (e) {
|
127 | if (!(e instanceof errors_1.BuildCLIProgramNotFoundException)) {
|
128 | throw e;
|
129 | }
|
130 | if (this.global) {
|
131 | this.e.log.nl();
|
132 | throw new errors_1.FatalException(`${color_1.input(this.pkg)} is required for this command to work properly.`);
|
133 | }
|
134 | this.e.log.nl();
|
135 | this.e.log.info(`Looks like ${color_1.input(this.pkg)} isn't installed in this project.\n` +
|
136 | `This package is required for this command to work properly.`);
|
137 | const installed = await this.promptToInstall();
|
138 | if (!installed) {
|
139 | this.e.log.nl();
|
140 | throw new errors_1.FatalException(`${color_1.input(this.pkg)} is required for this command to work properly.`);
|
141 | }
|
142 | return this.run(options);
|
143 | }
|
144 | }
|
145 | async run(options) {
|
146 | const args = await this.buildArgs(options);
|
147 | const env = await this.buildEnvVars(options);
|
148 | try {
|
149 | await this.e.shell.run(this.resolvedProgram, args, { stdio: 'inherit', cwd: this.e.project.directory, fatalOnNotFound: false, env: utils_process_1.createProcessEnv(env) });
|
150 | }
|
151 | catch (e) {
|
152 | if (e instanceof utils_subprocess_1.SubprocessError && e.code === utils_subprocess_1.ERROR_COMMAND_NOT_FOUND) {
|
153 | throw new errors_1.BuildCLIProgramNotFoundException(`${color_1.strong(this.resolvedProgram)} command not found.`);
|
154 | }
|
155 | throw e;
|
156 | }
|
157 | }
|
158 | async resolveProgram() {
|
159 | if (typeof this.script !== 'undefined') {
|
160 | debug(`Looking for ${color_1.ancillary(this.script)} npm script.`);
|
161 | if (await this.resolveScript()) {
|
162 | debug(`Using ${color_1.ancillary(this.script)} npm script.`);
|
163 | return this.e.config.get('npmClient');
|
164 | }
|
165 | }
|
166 | return this.program;
|
167 | }
|
168 | async promptToInstall() {
|
169 | const { pkgManagerArgs } = await Promise.resolve().then(() => require('./utils/npm'));
|
170 | const [manager, ...managerArgs] = await pkgManagerArgs(this.e.config.get('npmClient'), { command: 'install', pkg: this.pkg, saveDev: true, saveExact: true });
|
171 | this.e.log.nl();
|
172 | const confirm = await this.e.prompt({
|
173 | name: 'confirm',
|
174 | message: `Install ${color_1.input(this.pkg)}?`,
|
175 | type: 'confirm',
|
176 | });
|
177 | if (!confirm) {
|
178 | this.e.log.warn(`Not installing--here's how to install manually: ${color_1.input(`${manager} ${managerArgs.join(' ')}`)}`);
|
179 | return false;
|
180 | }
|
181 | await this.e.shell.run(manager, managerArgs, { cwd: this.e.project.directory });
|
182 | return true;
|
183 | }
|
184 | }
|
185 | exports.BuildCLI = BuildCLI;
|
186 | class PkgManagerBuildCLI extends BuildCLI {
|
187 | constructor() {
|
188 | super(...arguments);
|
189 | this.global = true;
|
190 | this.script = exports.BUILD_SCRIPT;
|
191 | }
|
192 | async resolveProgram() {
|
193 | return this.program;
|
194 | }
|
195 | async buildArgs(options) {
|
196 | const { pkgManagerArgs } = await Promise.resolve().then(() => require('./utils/npm'));
|
197 | const [, ...pkgArgs] = await pkgManagerArgs(this.program, { command: 'run', script: this.script, scriptArgs: [...options['--'] || []] });
|
198 | return pkgArgs;
|
199 | }
|
200 | }
|
201 | class NpmBuildCLI extends PkgManagerBuildCLI {
|
202 | constructor() {
|
203 | super(...arguments);
|
204 | this.name = 'npm CLI';
|
205 | this.pkg = 'npm';
|
206 | this.program = 'npm';
|
207 | }
|
208 | }
|
209 | exports.NpmBuildCLI = NpmBuildCLI;
|
210 | class PnpmBuildCLI extends PkgManagerBuildCLI {
|
211 | constructor() {
|
212 | super(...arguments);
|
213 | this.name = 'pnpm CLI';
|
214 | this.pkg = 'pnpm';
|
215 | this.program = 'pnpm';
|
216 | }
|
217 | }
|
218 | exports.PnpmBuildCLI = PnpmBuildCLI;
|
219 | class YarnBuildCLI extends PkgManagerBuildCLI {
|
220 | constructor() {
|
221 | super(...arguments);
|
222 | this.name = 'Yarn';
|
223 | this.pkg = 'yarn';
|
224 | this.program = 'yarn';
|
225 | }
|
226 | }
|
227 | exports.YarnBuildCLI = YarnBuildCLI;
|
228 | class BuildBeforeHook extends hooks_1.Hook {
|
229 | constructor() {
|
230 | super(...arguments);
|
231 | this.name = 'build:before';
|
232 | }
|
233 | }
|
234 | class BuildAfterHook extends hooks_1.Hook {
|
235 | constructor() {
|
236 | super(...arguments);
|
237 | this.name = 'build:after';
|
238 | }
|
239 | }
|