index.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.Integration = void 0;
  4. const tslib_1 = require("tslib");
  5. const cli_framework_1 = require("@ionic/cli-framework");
  6. const utils_fs_1 = require("@ionic/utils-fs");
  7. const utils_terminal_1 = require("@ionic/utils-terminal");
  8. const chalk_1 = tslib_1.__importDefault(require("chalk"));
  9. const debug_1 = require("debug");
  10. const lodash = tslib_1.__importStar(require("lodash"));
  11. const path = tslib_1.__importStar(require("path"));
  12. const debug = (0, debug_1.debug)('ionic:lib:integrations:capacitor');
  13. const __1 = require("../");
  14. const color_1 = require("../../color");
  15. const npm_1 = require("../../utils/npm");
  16. const config_1 = require("./config");
  17. class Integration extends __1.BaseIntegration {
  18. constructor() {
  19. super(...arguments);
  20. this.name = 'capacitor';
  21. this.summary = `Target native iOS and Android with Capacitor, Ionic's new native layer`;
  22. this.archiveUrl = undefined;
  23. this.getCapacitorCLIVersion = lodash.memoize(async () => {
  24. return this.e.shell.cmdinfo('capacitor', ['--version'], { cwd: this.root });
  25. });
  26. this.getCapacitorCLIConfig = lodash.memoize(async () => {
  27. const args = ['config', '--json'];
  28. debug('Getting config with Capacitor CLI: %O', args);
  29. let output = undefined;
  30. try {
  31. output = await (async (_command, _args = [], opts = {}) => {
  32. try {
  33. const proc = await this.e.shell.createSubprocess(_command, _args, opts);
  34. const out = await proc.output();
  35. return out.split('\n').join(' ').trim();
  36. }
  37. catch (err) {
  38. throw err;
  39. }
  40. })('capacitor', args, { cwd: this.root });
  41. }
  42. catch (error) {
  43. if (error.code === 'ERR_SUBPROCESS_COMMAND_NOT_FOUND') {
  44. throw new Error(`Capacitor command not found. Is the Capacitor CLI installed? (npm i -D @capacitor/cli)`);
  45. }
  46. else {
  47. throw new Error(error.message);
  48. }
  49. }
  50. if (!output) {
  51. debug('Could not get config from Capacitor CLI (probably old version)');
  52. return;
  53. }
  54. else {
  55. try {
  56. // Capacitor 1 returns the `command not found` error in stdout instead of stderror like in Capacitor 2
  57. // This ensures that the output from the command is valid JSON to account for this
  58. return JSON.parse(output);
  59. }
  60. catch (e) {
  61. debug('Could not get config from Capacitor CLI (probably old version)', e);
  62. return;
  63. }
  64. }
  65. });
  66. this.getCapacitorConfig = lodash.memoize(async () => {
  67. try {
  68. const cli = await this.getCapacitorCLIConfig();
  69. if (cli) {
  70. debug('Loaded Capacitor config!');
  71. return cli.app.extConfig;
  72. }
  73. }
  74. catch (ex) {
  75. // ignore
  76. }
  77. // fallback to reading capacitor.config.json if it exists
  78. const confPath = this.getCapacitorConfigJsonPath();
  79. if (!(await (0, utils_fs_1.pathExists)(confPath))) {
  80. debug('Capacitor config file does not exist at %O', confPath);
  81. debug('Failed to load Capacitor config');
  82. return;
  83. }
  84. const conf = new config_1.CapacitorJSONConfig(confPath);
  85. const extConfig = conf.c;
  86. debug('Loaded Capacitor config!');
  87. return extConfig;
  88. });
  89. }
  90. get config() {
  91. return new __1.IntegrationConfig(this.e.project.filePath, { pathPrefix: [...this.e.project.pathPrefix, 'integrations', this.name] });
  92. }
  93. get root() {
  94. return this.config.get('root', this.e.project.directory);
  95. }
  96. async add(details) {
  97. const confPath = this.getCapacitorConfigJsonPath();
  98. if (await (0, utils_fs_1.pathExists)(confPath)) {
  99. this.e.log.nl();
  100. this.e.log.warn(`Capacitor already exists in project.\n` +
  101. `Since the Capacitor config already exists (${(0, color_1.strong)((0, utils_terminal_1.prettyPath)(confPath))}), the Capacitor integration has been ${chalk_1.default.green('enabled')}.\n\n` +
  102. `You can re-integrate this project by doing the following:\n\n` +
  103. `- Run ${(0, color_1.input)(`ionic integrations disable ${this.name}`)}\n` +
  104. `- Remove the ${(0, color_1.strong)((0, utils_terminal_1.prettyPath)(confPath))} file\n` +
  105. `- Run ${(0, color_1.input)(`ionic integrations enable ${this.name} --add`)}\n`);
  106. }
  107. else {
  108. let name = this.e.project.config.get('name');
  109. let packageId = 'io.ionic.starter';
  110. let webDir = await this.e.project.getDefaultDistDir();
  111. const options = [];
  112. if (details.enableArgs && details.enableArgs.length > 0) {
  113. const parsedArgs = (0, cli_framework_1.parseArgs)(details.enableArgs);
  114. name = String(parsedArgs._[0]) || name;
  115. packageId = parsedArgs._[1] || packageId;
  116. if (parsedArgs['web-dir']) {
  117. webDir = parsedArgs['web-dir'];
  118. }
  119. }
  120. options.push('--web-dir', webDir);
  121. await this.installCapacitorCore();
  122. await this.installCapacitorCLI();
  123. await this.installCapacitorPlugins();
  124. await (0, utils_fs_1.mkdirp)(details.root);
  125. await this.e.shell.run('capacitor', ['init', name, packageId, ...options], { cwd: details.root });
  126. }
  127. await super.add(details);
  128. }
  129. getCapacitorConfigJsonPath() {
  130. return path.resolve(this.root, 'capacitor.config.json');
  131. }
  132. async installCapacitorCore() {
  133. const [manager, ...managerArgs] = await (0, npm_1.pkgManagerArgs)(this.e.config.get('npmClient'), { command: 'install', pkg: '@capacitor/core@latest' });
  134. await this.e.shell.run(manager, managerArgs, { cwd: this.root });
  135. }
  136. async installCapacitorCLI() {
  137. const [manager, ...managerArgs] = await (0, npm_1.pkgManagerArgs)(this.e.config.get('npmClient'), { command: 'install', pkg: '@capacitor/cli@latest', saveDev: true });
  138. await this.e.shell.run(manager, managerArgs, { cwd: this.root });
  139. }
  140. async installCapacitorPlugins() {
  141. const [manager, ...managerArgs] = await (0, npm_1.pkgManagerArgs)(this.e.config.get('npmClient'), { command: 'install', pkg: ['@capacitor/haptics', '@capacitor/app', '@capacitor/keyboard', '@capacitor/status-bar'] });
  142. await this.e.shell.run(manager, managerArgs, { cwd: this.root });
  143. }
  144. async personalize({ name, packageId }) {
  145. const confPath = this.getCapacitorConfigJsonPath();
  146. if (await (0, utils_fs_1.pathExists)(confPath)) {
  147. const conf = new config_1.CapacitorJSONConfig(confPath);
  148. conf.set('appName', name);
  149. if (packageId) {
  150. conf.set('appId', packageId);
  151. }
  152. }
  153. }
  154. async getInfo() {
  155. const conf = await this.getCapacitorConfig();
  156. const bundleId = conf?.appId;
  157. const [[capacitorCorePkg, capacitorCorePkgPath], capacitorCLIVersion, [capacitorIOSPkg, capacitorIOSPkgPath], [capacitorAndroidPkg, capacitorAndroidPkgPath],] = await (Promise.all([
  158. this.e.project.getPackageJson('@capacitor/core'),
  159. this.getCapacitorCLIVersion(),
  160. this.e.project.getPackageJson('@capacitor/ios'),
  161. this.e.project.getPackageJson('@capacitor/android'),
  162. ]));
  163. const info = [
  164. {
  165. group: 'capacitor',
  166. name: 'Capacitor CLI',
  167. key: 'capacitor_cli_version',
  168. value: capacitorCLIVersion || 'not installed',
  169. },
  170. {
  171. group: 'capacitor',
  172. name: '@capacitor/core',
  173. key: 'capacitor_core_version',
  174. value: capacitorCorePkg ? capacitorCorePkg.version : 'not installed',
  175. path: capacitorCorePkgPath,
  176. },
  177. {
  178. group: 'capacitor',
  179. name: '@capacitor/ios',
  180. key: 'capacitor_ios_version',
  181. value: capacitorIOSPkg ? capacitorIOSPkg.version : 'not installed',
  182. path: capacitorIOSPkgPath,
  183. },
  184. {
  185. group: 'capacitor',
  186. name: '@capacitor/android',
  187. key: 'capacitor_android_version',
  188. value: capacitorAndroidPkg ? capacitorAndroidPkg.version : 'not installed',
  189. path: capacitorAndroidPkgPath,
  190. },
  191. {
  192. group: 'capacitor',
  193. name: 'Bundle ID',
  194. key: 'bundle_id',
  195. value: bundleId || 'unknown',
  196. hidden: true,
  197. },
  198. ];
  199. return info;
  200. }
  201. }
  202. exports.Integration = Integration;