build.js 9.6 KB

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