@capacitor-plus/cli 8.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +84 -0
  3. package/assets/android-template.tar.gz +0 -0
  4. package/assets/capacitor-cordova-android-plugins.tar.gz +0 -0
  5. package/assets/capacitor-cordova-ios-plugins.tar.gz +0 -0
  6. package/assets/ios-pods-template.tar.gz +0 -0
  7. package/assets/ios-spm-template.tar.gz +0 -0
  8. package/bin/capacitor +18 -0
  9. package/dist/android/add.js +52 -0
  10. package/dist/android/build.js +104 -0
  11. package/dist/android/common.js +94 -0
  12. package/dist/android/doctor.js +160 -0
  13. package/dist/android/open.js +28 -0
  14. package/dist/android/run.js +42 -0
  15. package/dist/android/update.js +317 -0
  16. package/dist/colors.js +26 -0
  17. package/dist/common.js +435 -0
  18. package/dist/config.js +404 -0
  19. package/dist/cordova.js +801 -0
  20. package/dist/declarations.d.ts +674 -0
  21. package/dist/declarations.js +2 -0
  22. package/dist/definitions.js +13 -0
  23. package/dist/errors.js +27 -0
  24. package/dist/framework-configs.js +109 -0
  25. package/dist/index.js +253 -0
  26. package/dist/ios/add.js +13 -0
  27. package/dist/ios/build.js +96 -0
  28. package/dist/ios/common.js +105 -0
  29. package/dist/ios/doctor.js +45 -0
  30. package/dist/ios/open.js +17 -0
  31. package/dist/ios/run.js +51 -0
  32. package/dist/ios/update.js +449 -0
  33. package/dist/ipc.js +61 -0
  34. package/dist/log.js +39 -0
  35. package/dist/plugin.js +182 -0
  36. package/dist/sysconfig.js +35 -0
  37. package/dist/tasks/add.js +115 -0
  38. package/dist/tasks/build.js +63 -0
  39. package/dist/tasks/config.js +28 -0
  40. package/dist/tasks/copy.js +210 -0
  41. package/dist/tasks/create.js +10 -0
  42. package/dist/tasks/doctor.js +68 -0
  43. package/dist/tasks/init.js +138 -0
  44. package/dist/tasks/list.js +50 -0
  45. package/dist/tasks/migrate-spm.js +19 -0
  46. package/dist/tasks/migrate.js +518 -0
  47. package/dist/tasks/new-plugin.js +10 -0
  48. package/dist/tasks/open.js +62 -0
  49. package/dist/tasks/run.js +118 -0
  50. package/dist/tasks/serve.js +11 -0
  51. package/dist/tasks/sourcemaps.js +39 -0
  52. package/dist/tasks/sync.js +55 -0
  53. package/dist/tasks/telemetry.js +41 -0
  54. package/dist/tasks/update.js +74 -0
  55. package/dist/telemetry.js +119 -0
  56. package/dist/util/cli.js +25 -0
  57. package/dist/util/emoji.js +13 -0
  58. package/dist/util/fn.js +13 -0
  59. package/dist/util/fs.js +43 -0
  60. package/dist/util/iosplugin.js +66 -0
  61. package/dist/util/js.js +21 -0
  62. package/dist/util/livereload.js +148 -0
  63. package/dist/util/monorepotools.js +109 -0
  64. package/dist/util/native-run.js +63 -0
  65. package/dist/util/node.js +54 -0
  66. package/dist/util/promise.js +35 -0
  67. package/dist/util/spm.js +187 -0
  68. package/dist/util/subprocess.js +37 -0
  69. package/dist/util/template.js +11 -0
  70. package/dist/util/term.js +30 -0
  71. package/dist/util/uuid.js +11 -0
  72. package/dist/util/xml.js +55 -0
  73. package/package.json +89 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017-present Drifty Co.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # Capacitor CLI
2
+
3
+ The Capacitor command-line interface (CLI) is a tool for creating and managing Capacitor applications. While it can be installed globally, it's recommended to install it locally in your project and execute through `npm` scripts.
4
+
5
+ ## Installation
6
+
7
+ ### Project Installation (Recommended)
8
+
9
+ Install the CLI locally in your project:
10
+
11
+ ```bash
12
+ npm install @capacitor/cli --save-dev
13
+ ```
14
+
15
+ ### Global Installation
16
+
17
+ While not recommended for project use, you can install the CLI globally:
18
+
19
+ ```bash
20
+ npm install -g @capacitor/cli
21
+ ```
22
+
23
+ ## Using Capacitor CLI
24
+
25
+ The CLI can be used through the `capacitor` or `cap` command. When installed locally, use it through your project's `npm` scripts or `npx`.
26
+
27
+ Common commands:
28
+
29
+ - `cap init`: Initialize a new Capacitor project
30
+ - `cap add`: Add a native platform (ios, android)
31
+ - `cap sync`: Sync your web code to your native projects
32
+
33
+ For detailed information, consult the [Getting Started guide](https://capacitorjs.com/docs/getting-started).
34
+
35
+ ## Local Development
36
+
37
+ If you're contributing to the Capacitor CLI or testing local changes:
38
+
39
+ 1. Clone and setup:
40
+
41
+ ```bash
42
+ git clone https://github.com/ionic-team/capacitor.git
43
+ cd cli
44
+ npm install
45
+ ```
46
+
47
+ 2. Build the CLI:
48
+
49
+ ```bash
50
+ npm run build
51
+ ```
52
+
53
+ 3. Create a local link:
54
+
55
+ ```bash
56
+ npm link
57
+ ```
58
+
59
+ 4. Development workflow:
60
+ - Run `npm run watch` to automatically rebuild on changes
61
+ - Use `capacitor` or `cap` commands to test your changes
62
+ - Run `npm test` to execute the test suite
63
+
64
+ ## Debugging
65
+
66
+ ### Using VS Code Launch Configurations
67
+
68
+ The CLI includes VS Code launch configurations for debugging. To debug a CLI command:
69
+
70
+ 1. Open the project in VS Code
71
+ 2. Right now we don't have debugging working in the ts files, so select one of the .js files inside of /dist/\*\*.js
72
+ 3. Place a breakpoint
73
+ 4. Press F5 or go to Run > Start Debugging
74
+ 5. Select a launch config and run filling out the path you want to run the cli in, and the command that you want run.
75
+
76
+ You can add more configurations by copying and modifying the existing ones in `.vscode/launch.json`.
77
+
78
+ ## Contributing
79
+
80
+ Contributions are welcome! Please read our [Contributing Guide](https://github.com/ionic-team/capacitor/blob/main/CONTRIBUTING.md) for details.
81
+
82
+ ### License
83
+
84
+ - [MIT](https://github.com/ionic-team/capacitor/blob/HEAD/LICENSE)
Binary file
Binary file
Binary file
package/bin/capacitor ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ var satisfies = require('semver/functions/satisfies');
5
+ var packageJson = require('../package.json');
6
+ var requiresNodeVersion = packageJson.engines.node;
7
+
8
+ if (!satisfies(process.version, requiresNodeVersion, { includePrerelease: true})) {
9
+ process.stdout.write(
10
+ '\x1b[31m[fatal]\x1b[39m The Capacitor CLI requires NodeJS ' + requiresNodeVersion + '\n' +
11
+ ' Please install the latest LTS version.\n'
12
+ );
13
+
14
+ process.exit(1);
15
+ }
16
+
17
+ var cli = require('../dist/index');
18
+ cli.run();
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createLocalProperties = exports.addAndroid = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const fs_extra_1 = require("fs-extra");
6
+ const os_1 = require("os");
7
+ const path_1 = require("path");
8
+ const colors_1 = tslib_1.__importDefault(require("../colors"));
9
+ const common_1 = require("../common");
10
+ const subprocess_1 = require("../util/subprocess");
11
+ const template_1 = require("../util/template");
12
+ async function addAndroid(config) {
13
+ await (0, common_1.runTask)(`Adding native android project in ${colors_1.default.strong(config.android.platformDir)}`, async () => {
14
+ return (0, template_1.extractTemplate)(config.cli.assets.android.platformTemplateArchiveAbs, config.android.platformDirAbs);
15
+ });
16
+ }
17
+ exports.addAndroid = addAndroid;
18
+ async function createLocalProperties(platformDir) {
19
+ const defaultAndroidPath = (0, path_1.join)((0, os_1.homedir)(), 'Library/Android/sdk');
20
+ if (await (0, fs_extra_1.pathExists)(defaultAndroidPath)) {
21
+ const localSettings = `
22
+ ## This file is automatically generated by Android Studio.
23
+ # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
24
+ #
25
+ # This file should *NOT* be checked into Version Control Systems,
26
+ # as it contains information specific to your local configuration.
27
+ #
28
+ # Location of the SDK. This is only used by Gradle.
29
+ # For customization when using a Version Control System, please read the
30
+ # header note.
31
+ sdk.dir=${defaultAndroidPath}
32
+ `;
33
+ await (0, fs_extra_1.writeFile)((0, path_1.join)(platformDir, 'local.properties'), localSettings, {
34
+ encoding: 'utf-8',
35
+ });
36
+ // Only sync if we were able to create the local properties above, otherwise
37
+ // this will fail
38
+ try {
39
+ await gradleSync(platformDir);
40
+ }
41
+ catch (e) {
42
+ console.error('Error running gradle sync', e);
43
+ console.error('Unable to infer default Android SDK settings. This is fine, just run npx cap open android and import and sync gradle manually');
44
+ }
45
+ }
46
+ }
47
+ exports.createLocalProperties = createLocalProperties;
48
+ async function gradleSync(platformDir) {
49
+ await (0, subprocess_1.runCommand)(`./gradlew`, [], {
50
+ cwd: platformDir,
51
+ });
52
+ }
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildAndroid = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const path_1 = require("path");
6
+ const colors_1 = tslib_1.__importDefault(require("../colors"));
7
+ const common_1 = require("../common");
8
+ const log_1 = require("../log");
9
+ const subprocess_1 = require("../util/subprocess");
10
+ async function buildAndroid(config, buildOptions) {
11
+ var _a, _b;
12
+ const releaseType = (_a = buildOptions.androidreleasetype) !== null && _a !== void 0 ? _a : 'AAB';
13
+ const releaseTypeIsAAB = releaseType === 'AAB';
14
+ const flavor = (_b = buildOptions.flavor) !== null && _b !== void 0 ? _b : '';
15
+ const arg = releaseTypeIsAAB ? `:app:bundle${flavor}Release` : `assemble${flavor}Release`;
16
+ const gradleArgs = [arg];
17
+ try {
18
+ await (0, common_1.runTask)('Running Gradle build', async () => (0, subprocess_1.runCommand)('./gradlew', gradleArgs, {
19
+ cwd: config.android.platformDirAbs,
20
+ }));
21
+ }
22
+ catch (e) {
23
+ if (e.includes('EACCES')) {
24
+ throw `gradlew file does not have executable permissions. This can happen if the Android platform was added on a Windows machine. Please run ${colors_1.default.strong(`chmod +x ./${config.android.platformDir}/gradlew`)} and try again.`;
25
+ }
26
+ else {
27
+ throw e;
28
+ }
29
+ }
30
+ const releaseDir = releaseTypeIsAAB
31
+ ? flavor !== ''
32
+ ? `${flavor}Release`
33
+ : 'release'
34
+ : flavor !== ''
35
+ ? (0, path_1.join)(flavor, 'release')
36
+ : 'release';
37
+ const releasePath = (0, path_1.join)(config.android.appDirAbs, 'build', 'outputs', releaseTypeIsAAB ? 'bundle' : 'apk', releaseDir);
38
+ const unsignedReleaseName = `app${flavor !== '' ? `-${flavor}` : ''}-release${releaseTypeIsAAB ? '' : '-unsigned'}.${releaseType.toLowerCase()}`;
39
+ const signedReleaseName = unsignedReleaseName.replace(`-release${releaseTypeIsAAB ? '' : '-unsigned'}.${releaseType.toLowerCase()}`, `-release-signed.${releaseType.toLowerCase()}`);
40
+ if (buildOptions.signingtype == 'jarsigner') {
41
+ await signWithJarSigner(config, buildOptions, releasePath, signedReleaseName, unsignedReleaseName);
42
+ }
43
+ else {
44
+ await signWithApkSigner(config, buildOptions, releasePath, signedReleaseName, unsignedReleaseName);
45
+ }
46
+ (0, log_1.logSuccess)(`Successfully generated ${signedReleaseName} at: ${releasePath}`);
47
+ }
48
+ exports.buildAndroid = buildAndroid;
49
+ async function signWithApkSigner(config, buildOptions, releasePath, signedReleaseName, unsignedReleaseName) {
50
+ if (!buildOptions.keystorepath || !buildOptions.keystorepass) {
51
+ throw 'Missing options. Please supply all options for android signing. (Keystore Path, Keystore Password)';
52
+ }
53
+ const signingArgs = [
54
+ 'sign',
55
+ '--ks',
56
+ buildOptions.keystorepath,
57
+ '--ks-pass',
58
+ `pass:${buildOptions.keystorepass}`,
59
+ '--in',
60
+ `${(0, path_1.join)(releasePath, unsignedReleaseName)}`,
61
+ '--out',
62
+ `${(0, path_1.join)(releasePath, signedReleaseName)}`,
63
+ ];
64
+ if (buildOptions.keystorealias) {
65
+ signingArgs.push('--ks-key-alias', buildOptions.keystorealias);
66
+ }
67
+ if (buildOptions.keystorealiaspass) {
68
+ signingArgs.push('--key-pass', `pass:${buildOptions.keystorealiaspass}`);
69
+ }
70
+ await (0, common_1.runTask)('Signing Release', async () => {
71
+ await (0, subprocess_1.runCommand)('apksigner', signingArgs, {
72
+ cwd: config.android.platformDirAbs,
73
+ });
74
+ });
75
+ }
76
+ async function signWithJarSigner(config, buildOptions, releasePath, signedReleaseName, unsignedReleaseName) {
77
+ if (!buildOptions.keystorepath ||
78
+ !buildOptions.keystorealias ||
79
+ !buildOptions.keystorealiaspass ||
80
+ !buildOptions.keystorepass) {
81
+ throw 'Missing options. Please supply all options for android signing. (Keystore Path, Keystore Password, Keystore Key Alias, Keystore Key Password)';
82
+ }
83
+ const signingArgs = [
84
+ '-sigalg',
85
+ 'SHA1withRSA',
86
+ '-digestalg',
87
+ 'SHA1',
88
+ '-keystore',
89
+ buildOptions.keystorepath,
90
+ '-keypass',
91
+ buildOptions.keystorealiaspass,
92
+ '-storepass',
93
+ buildOptions.keystorepass,
94
+ `-signedjar`,
95
+ `${(0, path_1.join)(releasePath, signedReleaseName)}`,
96
+ `${(0, path_1.join)(releasePath, unsignedReleaseName)}`,
97
+ buildOptions.keystorealias,
98
+ ];
99
+ await (0, common_1.runTask)('Signing Release', async () => {
100
+ await (0, subprocess_1.runCommand)('jarsigner', signingArgs, {
101
+ cwd: config.android.platformDirAbs,
102
+ });
103
+ });
104
+ }
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.editProjectSettingsAndroid = exports.resolvePlugin = exports.getAndroidPlugins = exports.checkAndroidPackage = void 0;
4
+ const fs_extra_1 = require("fs-extra");
5
+ const path_1 = require("path");
6
+ const common_1 = require("../common");
7
+ const cordova_1 = require("../cordova");
8
+ const plugin_1 = require("../plugin");
9
+ const fs_1 = require("../util/fs");
10
+ async function checkAndroidPackage(config) {
11
+ return (0, common_1.checkCapacitorPlatform)(config, 'android');
12
+ }
13
+ exports.checkAndroidPackage = checkAndroidPackage;
14
+ async function getAndroidPlugins(allPlugins) {
15
+ const resolved = await Promise.all(allPlugins.map(async (plugin) => await resolvePlugin(plugin)));
16
+ return resolved.filter((plugin) => !!plugin);
17
+ }
18
+ exports.getAndroidPlugins = getAndroidPlugins;
19
+ async function resolvePlugin(plugin) {
20
+ var _a;
21
+ const platform = 'android';
22
+ if ((_a = plugin.manifest) === null || _a === void 0 ? void 0 : _a.android) {
23
+ let pluginFilesPath = plugin.manifest.android.src ? plugin.manifest.android.src : platform;
24
+ const absolutePath = (0, path_1.join)(plugin.rootPath, pluginFilesPath, plugin.id);
25
+ // Android folder shouldn't have subfolders, but they used to, so search for them for compatibility reasons
26
+ if (await (0, fs_extra_1.pathExists)(absolutePath)) {
27
+ pluginFilesPath = (0, path_1.join)(platform, plugin.id);
28
+ }
29
+ plugin.android = {
30
+ type: 0 /* PluginType.Core */,
31
+ path: (0, fs_1.convertToUnixPath)(pluginFilesPath),
32
+ };
33
+ }
34
+ else if (plugin.xml) {
35
+ plugin.android = {
36
+ type: 1 /* PluginType.Cordova */,
37
+ path: 'src/' + platform,
38
+ };
39
+ if ((0, cordova_1.getIncompatibleCordovaPlugins)(platform).includes(plugin.id) || !(0, plugin_1.getPluginPlatform)(plugin, platform)) {
40
+ plugin.android.type = 2 /* PluginType.Incompatible */;
41
+ }
42
+ }
43
+ else {
44
+ return null;
45
+ }
46
+ return plugin;
47
+ }
48
+ exports.resolvePlugin = resolvePlugin;
49
+ /**
50
+ * Update an Android project with the desired app name and appId.
51
+ * This is a little trickier for Android because the appId becomes
52
+ * the package name.
53
+ */
54
+ async function editProjectSettingsAndroid(config) {
55
+ const appId = config.app.appId;
56
+ const appName = config.app.appName
57
+ .replace(/&/g, '&')
58
+ .replace(/</g, '&lt;')
59
+ .replace(/"/g, '\\"')
60
+ .replace(/'/g, "\\'");
61
+ const buildGradlePath = (0, path_1.resolve)(config.android.appDirAbs, 'build.gradle');
62
+ const domainPath = appId.split('.').join('/');
63
+ // Make the package source path to the new plugin Java file
64
+ const newJavaPath = (0, path_1.resolve)(config.android.srcMainDirAbs, `java/${domainPath}`);
65
+ if (!(await (0, fs_extra_1.pathExists)(newJavaPath))) {
66
+ await (0, fs_extra_1.mkdirp)(newJavaPath);
67
+ }
68
+ await (0, fs_extra_1.copy)((0, path_1.resolve)(config.android.srcMainDirAbs, 'java/com/getcapacitor/myapp/MainActivity.java'), (0, path_1.resolve)(newJavaPath, 'MainActivity.java'));
69
+ if (appId.split('.')[1] !== 'getcapacitor') {
70
+ await (0, fs_extra_1.remove)((0, path_1.resolve)(config.android.srcMainDirAbs, 'java/com/getcapacitor'));
71
+ }
72
+ // Remove our template 'com' folder if their ID doesn't have it
73
+ if (appId.split('.')[0] !== 'com') {
74
+ await (0, fs_extra_1.remove)((0, path_1.resolve)(config.android.srcMainDirAbs, 'java/com/'));
75
+ }
76
+ // Update the package in the MainActivity java file
77
+ const activityPath = (0, path_1.resolve)(newJavaPath, 'MainActivity.java');
78
+ let activityContent = await (0, fs_extra_1.readFile)(activityPath, { encoding: 'utf-8' });
79
+ activityContent = activityContent.replace(/package ([^;]*)/, `package ${appId}`);
80
+ await (0, fs_extra_1.writeFile)(activityPath, activityContent, { encoding: 'utf-8' });
81
+ // Update the applicationId in build.gradle
82
+ let gradleContent = await (0, fs_extra_1.readFile)(buildGradlePath, { encoding: 'utf-8' });
83
+ gradleContent = gradleContent.replace(/applicationId "[^"]+"/, `applicationId "${appId}"`);
84
+ // Update the namespace in build.gradle
85
+ gradleContent = gradleContent.replace(/namespace = "[^"]+"/, `namespace = "${appId}"`);
86
+ await (0, fs_extra_1.writeFile)(buildGradlePath, gradleContent, { encoding: 'utf-8' });
87
+ // Update the settings in res/values/strings.xml
88
+ const stringsPath = (0, path_1.resolve)(config.android.resDirAbs, 'values/strings.xml');
89
+ let stringsContent = await (0, fs_extra_1.readFile)(stringsPath, { encoding: 'utf-8' });
90
+ stringsContent = stringsContent.replace(/com.getcapacitor.myapp/g, appId);
91
+ stringsContent = stringsContent.replace(/My App/g, appName);
92
+ await (0, fs_extra_1.writeFile)(stringsPath, stringsContent);
93
+ }
94
+ exports.editProjectSettingsAndroid = editProjectSettingsAndroid;
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.doctorAndroid = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const fs_extra_1 = require("fs-extra");
6
+ const path_1 = require("path");
7
+ const colors_1 = tslib_1.__importDefault(require("../colors"));
8
+ const common_1 = require("../common");
9
+ const errors_1 = require("../errors");
10
+ const log_1 = require("../log");
11
+ const fs_1 = require("../util/fs");
12
+ const xml_1 = require("../util/xml");
13
+ async function doctorAndroid(config) {
14
+ var _a;
15
+ try {
16
+ await (0, common_1.check)([checkAndroidInstalled, () => checkGradlew(config), () => checkAppSrcDirs(config)]);
17
+ (0, log_1.logSuccess)('Android looking great! 👌');
18
+ }
19
+ catch (e) {
20
+ if (!(0, errors_1.isFatal)(e)) {
21
+ (0, errors_1.fatal)((_a = e.stack) !== null && _a !== void 0 ? _a : e);
22
+ }
23
+ throw e;
24
+ }
25
+ }
26
+ exports.doctorAndroid = doctorAndroid;
27
+ async function checkAppSrcDirs(config) {
28
+ if (!(await (0, fs_extra_1.pathExists)(config.android.appDirAbs))) {
29
+ return `${colors_1.default.strong(config.android.appDir)} directory is missing in ${colors_1.default.strong(config.android.platformDir)}`;
30
+ }
31
+ if (!(await (0, fs_extra_1.pathExists)(config.android.srcMainDirAbs))) {
32
+ return `${colors_1.default.strong(config.android.srcMainDir)} directory is missing in ${colors_1.default.strong(config.android.platformDir)}`;
33
+ }
34
+ if (!(await (0, fs_extra_1.pathExists)(config.android.assetsDirAbs))) {
35
+ return `${colors_1.default.strong(config.android.assetsDir)} directory is missing in ${colors_1.default.strong(config.android.platformDir)}`;
36
+ }
37
+ if (!(await (0, fs_extra_1.pathExists)(config.android.webDirAbs))) {
38
+ return `${colors_1.default.strong(config.android.webDir)} directory is missing in ${colors_1.default.strong(config.android.platformDir)}`;
39
+ }
40
+ const appSrcMainAssetsWwwIndexHtmlDir = (0, path_1.join)(config.android.webDirAbs, 'index.html');
41
+ if (!(await (0, fs_extra_1.pathExists)(appSrcMainAssetsWwwIndexHtmlDir))) {
42
+ return `${colors_1.default.strong('index.html')} file is missing in ${colors_1.default.strong(config.android.webDirAbs)}`;
43
+ }
44
+ return checkAndroidManifestFile(config);
45
+ }
46
+ async function checkAndroidManifestFile(config) {
47
+ const manifestFileName = 'AndroidManifest.xml';
48
+ const manifestFilePath = (0, path_1.join)(config.android.srcMainDirAbs, manifestFileName);
49
+ if (!(await (0, fs_extra_1.pathExists)(manifestFilePath))) {
50
+ return `${colors_1.default.strong(manifestFileName)} is missing in ${colors_1.default.strong(config.android.srcMainDir)}`;
51
+ }
52
+ try {
53
+ const xmlData = await (0, xml_1.readXML)(manifestFilePath);
54
+ return checkAndroidManifestData(config, xmlData);
55
+ }
56
+ catch (e) {
57
+ return e;
58
+ }
59
+ }
60
+ async function checkAndroidManifestData(config, xmlData) {
61
+ const manifestNode = xmlData.manifest;
62
+ if (!manifestNode) {
63
+ return `Missing ${colors_1.default.input('<manifest>')} XML node in ${colors_1.default.strong(config.android.srcMainDir)}`;
64
+ }
65
+ const applicationChildNodes = manifestNode.application;
66
+ if (!Array.isArray(manifestNode.application)) {
67
+ return `Missing ${colors_1.default.input('<application>')} XML node as a child node of ${colors_1.default.input('<manifest>')} in ${colors_1.default.strong(config.android.srcMainDir)}`;
68
+ }
69
+ let mainActivityClassPath = '';
70
+ const mainApplicationNode = applicationChildNodes.find((applicationChildNode) => {
71
+ const activityChildNodes = applicationChildNode.activity;
72
+ if (!Array.isArray(activityChildNodes)) {
73
+ return false;
74
+ }
75
+ const mainActivityNode = activityChildNodes.find((activityChildNode) => {
76
+ const intentFilterChildNodes = activityChildNode['intent-filter'];
77
+ if (!Array.isArray(intentFilterChildNodes)) {
78
+ return false;
79
+ }
80
+ return intentFilterChildNodes.find((intentFilterChildNode) => {
81
+ const actionChildNodes = intentFilterChildNode.action;
82
+ if (!Array.isArray(actionChildNodes)) {
83
+ return false;
84
+ }
85
+ const mainActionChildNode = actionChildNodes.find((actionChildNode) => {
86
+ const androidName = actionChildNode.$['android:name'];
87
+ return androidName === 'android.intent.action.MAIN';
88
+ });
89
+ if (!mainActionChildNode) {
90
+ return false;
91
+ }
92
+ const categoryChildNodes = intentFilterChildNode.category;
93
+ if (!Array.isArray(categoryChildNodes)) {
94
+ return false;
95
+ }
96
+ return categoryChildNodes.find((categoryChildNode) => {
97
+ const androidName = categoryChildNode.$['android:name'];
98
+ return androidName === 'android.intent.category.LAUNCHER';
99
+ });
100
+ });
101
+ });
102
+ if (mainActivityNode) {
103
+ mainActivityClassPath = mainActivityNode.$['android:name'];
104
+ }
105
+ return mainActivityNode;
106
+ });
107
+ if (!mainApplicationNode) {
108
+ return `Missing main ${colors_1.default.input('<activity>')} XML node in ${colors_1.default.strong(config.android.srcMainDir)}`;
109
+ }
110
+ if (!mainActivityClassPath) {
111
+ return `Missing ${colors_1.default.input('<activity android:name="">')} attribute for MainActivity class in ${colors_1.default.strong(config.android.srcMainDir)}`;
112
+ }
113
+ return checkPackage(config, mainActivityClassPath);
114
+ }
115
+ async function checkPackage(config, mainActivityClassPath) {
116
+ const appSrcMainJavaDir = (0, path_1.join)(config.android.srcMainDirAbs, 'java');
117
+ if (!(await (0, fs_extra_1.pathExists)(appSrcMainJavaDir))) {
118
+ return `${colors_1.default.strong('java')} directory is missing in ${colors_1.default.strong(appSrcMainJavaDir)}`;
119
+ }
120
+ const mainActivityClassName = mainActivityClassPath.split('.').pop();
121
+ const srcFiles = await (0, fs_1.readdirp)(appSrcMainJavaDir, {
122
+ filter: (entry) => !entry.stats.isDirectory() &&
123
+ ['.java', '.kt'].includes((0, path_1.extname)(entry.path)) &&
124
+ mainActivityClassName === (0, path_1.parse)(entry.path).name,
125
+ });
126
+ if (srcFiles.length == 0) {
127
+ return `Main activity file (${mainActivityClassName}) is missing`;
128
+ }
129
+ return checkBuildGradle(config);
130
+ }
131
+ async function checkBuildGradle(config) {
132
+ const fileName = 'build.gradle';
133
+ const filePath = (0, path_1.join)(config.android.appDirAbs, fileName);
134
+ if (!(await (0, fs_extra_1.pathExists)(filePath))) {
135
+ return `${colors_1.default.strong(fileName)} file is missing in ${colors_1.default.strong(config.android.appDir)}`;
136
+ }
137
+ let fileContent = await (0, fs_extra_1.readFile)(filePath, { encoding: 'utf-8' });
138
+ fileContent = fileContent.replace(/'|"/g, '').replace(/\s+/g, ' ');
139
+ const searchFor = `applicationId`;
140
+ if (fileContent.indexOf(searchFor) === -1) {
141
+ return `${colors_1.default.strong('build.gradle')} file missing ${colors_1.default.input(`applicationId`)} config in ${filePath}`;
142
+ }
143
+ return null;
144
+ }
145
+ async function checkGradlew(config) {
146
+ const fileName = 'gradlew';
147
+ const filePath = (0, path_1.join)(config.android.platformDirAbs, fileName);
148
+ if (!(await (0, fs_extra_1.pathExists)(filePath))) {
149
+ return `${colors_1.default.strong(fileName)} file is missing in ${colors_1.default.strong(config.android.platformDir)}`;
150
+ }
151
+ return null;
152
+ }
153
+ async function checkAndroidInstalled() {
154
+ /*
155
+ if (!await isInstalled('android')) {
156
+ return 'Android is not installed. For information: https://developer.android.com/studio/index.html';
157
+ }
158
+ */
159
+ return null;
160
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.openAndroid = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const debug_1 = tslib_1.__importDefault(require("debug"));
6
+ const fs_extra_1 = require("fs-extra");
7
+ const open_1 = tslib_1.__importDefault(require("open"));
8
+ const colors_1 = tslib_1.__importDefault(require("../colors"));
9
+ const log_1 = require("../log");
10
+ const debug = (0, debug_1.default)('capacitor:android:open');
11
+ async function openAndroid(config) {
12
+ const androidStudioPath = await config.android.studioPath;
13
+ const dir = config.android.platformDirAbs;
14
+ try {
15
+ if (!(await (0, fs_extra_1.pathExists)(androidStudioPath))) {
16
+ throw new Error(`Android Studio does not exist at: ${androidStudioPath}`);
17
+ }
18
+ await (0, open_1.default)(dir, { app: { name: androidStudioPath }, wait: false });
19
+ log_1.logger.info(`Opening Android project at: ${colors_1.default.strong(config.android.platformDir)}.`);
20
+ }
21
+ catch (e) {
22
+ debug('Error opening Android Studio: %O', e);
23
+ log_1.logger.error('Unable to launch Android Studio. Is it installed?\n' +
24
+ `Attempted to open Android Studio at: ${colors_1.default.strong(androidStudioPath)}\n` +
25
+ `You can configure this with the ${colors_1.default.input('CAPACITOR_ANDROID_STUDIO_PATH')} environment variable.`);
26
+ }
27
+ }
28
+ exports.openAndroid = openAndroid;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runAndroid = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const debug_1 = tslib_1.__importDefault(require("debug"));
6
+ const path_1 = require("path");
7
+ const colors_1 = tslib_1.__importDefault(require("../colors"));
8
+ const common_1 = require("../common");
9
+ const native_run_1 = require("../util/native-run");
10
+ const subprocess_1 = require("../util/subprocess");
11
+ const debug = (0, debug_1.default)('capacitor:android:run');
12
+ async function runAndroid(config, { target: selectedTarget, targetName: selectedTargetName, targetNameSdkVersion: selectedTargetSdkVersion, flavor: selectedFlavor, forwardPorts: selectedPorts, }) {
13
+ var _a;
14
+ const target = await (0, common_1.promptForPlatformTarget)(await (0, native_run_1.getPlatformTargets)('android'), selectedTarget !== null && selectedTarget !== void 0 ? selectedTarget : selectedTargetName, selectedTargetSdkVersion, selectedTargetName !== undefined);
15
+ const runFlavor = selectedFlavor || ((_a = config.android) === null || _a === void 0 ? void 0 : _a.flavor) || '';
16
+ const arg = `assemble${runFlavor}Debug`;
17
+ const gradleArgs = [arg];
18
+ debug('Invoking ./gradlew with args: %O', gradleArgs);
19
+ try {
20
+ await (0, common_1.runTask)('Running Gradle build', async () => (0, subprocess_1.runCommand)('./gradlew', gradleArgs, {
21
+ cwd: config.android.platformDirAbs,
22
+ }));
23
+ }
24
+ catch (e) {
25
+ if (e.includes('EACCES')) {
26
+ throw `gradlew file does not have executable permissions. This can happen if the Android platform was added on a Windows machine. Please run ${colors_1.default.strong(`chmod +x ./${config.android.platformDir}/gradlew`)} and try again.`;
27
+ }
28
+ else {
29
+ throw e;
30
+ }
31
+ }
32
+ const pathToApk = `${config.android.platformDirAbs}/${config.android.appDir}/build/outputs/apk${runFlavor !== '' ? '/' + runFlavor : ''}/debug`;
33
+ const apkName = (0, common_1.parseApkNameFromFlavor)(runFlavor);
34
+ const apkPath = (0, path_1.resolve)(pathToApk, apkName);
35
+ const nativeRunArgs = ['android', '--app', apkPath, '--target', target.id];
36
+ if (selectedPorts) {
37
+ nativeRunArgs.push('--forward', `${selectedPorts}`);
38
+ }
39
+ debug('Invoking native-run with args: %O', nativeRunArgs);
40
+ await (0, common_1.runTask)(`Deploying ${colors_1.default.strong(apkName)} to ${colors_1.default.input(target.id)}`, async () => (0, native_run_1.runNativeRun)(nativeRunArgs));
41
+ }
42
+ exports.runAndroid = runAndroid;