@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.
- package/LICENSE +21 -0
- package/README.md +84 -0
- package/assets/android-template.tar.gz +0 -0
- package/assets/capacitor-cordova-android-plugins.tar.gz +0 -0
- package/assets/capacitor-cordova-ios-plugins.tar.gz +0 -0
- package/assets/ios-pods-template.tar.gz +0 -0
- package/assets/ios-spm-template.tar.gz +0 -0
- package/bin/capacitor +18 -0
- package/dist/android/add.js +52 -0
- package/dist/android/build.js +104 -0
- package/dist/android/common.js +94 -0
- package/dist/android/doctor.js +160 -0
- package/dist/android/open.js +28 -0
- package/dist/android/run.js +42 -0
- package/dist/android/update.js +317 -0
- package/dist/colors.js +26 -0
- package/dist/common.js +435 -0
- package/dist/config.js +404 -0
- package/dist/cordova.js +801 -0
- package/dist/declarations.d.ts +674 -0
- package/dist/declarations.js +2 -0
- package/dist/definitions.js +13 -0
- package/dist/errors.js +27 -0
- package/dist/framework-configs.js +109 -0
- package/dist/index.js +253 -0
- package/dist/ios/add.js +13 -0
- package/dist/ios/build.js +96 -0
- package/dist/ios/common.js +105 -0
- package/dist/ios/doctor.js +45 -0
- package/dist/ios/open.js +17 -0
- package/dist/ios/run.js +51 -0
- package/dist/ios/update.js +449 -0
- package/dist/ipc.js +61 -0
- package/dist/log.js +39 -0
- package/dist/plugin.js +182 -0
- package/dist/sysconfig.js +35 -0
- package/dist/tasks/add.js +115 -0
- package/dist/tasks/build.js +63 -0
- package/dist/tasks/config.js +28 -0
- package/dist/tasks/copy.js +210 -0
- package/dist/tasks/create.js +10 -0
- package/dist/tasks/doctor.js +68 -0
- package/dist/tasks/init.js +138 -0
- package/dist/tasks/list.js +50 -0
- package/dist/tasks/migrate-spm.js +19 -0
- package/dist/tasks/migrate.js +518 -0
- package/dist/tasks/new-plugin.js +10 -0
- package/dist/tasks/open.js +62 -0
- package/dist/tasks/run.js +118 -0
- package/dist/tasks/serve.js +11 -0
- package/dist/tasks/sourcemaps.js +39 -0
- package/dist/tasks/sync.js +55 -0
- package/dist/tasks/telemetry.js +41 -0
- package/dist/tasks/update.js +74 -0
- package/dist/telemetry.js +119 -0
- package/dist/util/cli.js +25 -0
- package/dist/util/emoji.js +13 -0
- package/dist/util/fn.js +13 -0
- package/dist/util/fs.js +43 -0
- package/dist/util/iosplugin.js +66 -0
- package/dist/util/js.js +21 -0
- package/dist/util/livereload.js +148 -0
- package/dist/util/monorepotools.js +109 -0
- package/dist/util/native-run.js +63 -0
- package/dist/util/node.js +54 -0
- package/dist/util/promise.js +35 -0
- package/dist/util/spm.js +187 -0
- package/dist/util/subprocess.js +37 -0
- package/dist/util/template.js +11 -0
- package/dist/util/term.js +30 -0
- package/dist/util/uuid.js +11 -0
- package/dist/util/xml.js +55 -0
- 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
|
|
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, '<')
|
|
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;
|