Add dependency
Some checks failed
/ build_android (push) Failing after 21s

This commit is contained in:
Pieter Vander Vennet 2025-06-18 18:50:46 +02:00
parent 55470c090d
commit 6947a1adba
1260 changed files with 111297 additions and 0 deletions

52
@capacitor/cli/dist/android/add.js vendored Normal file
View file

@ -0,0 +1,52 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createLocalProperties = exports.addAndroid = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const os_1 = require("os");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
const subprocess_1 = require("../util/subprocess");
const template_1 = require("../util/template");
async function addAndroid(config) {
await (0, common_1.runTask)(`Adding native android project in ${colors_1.default.strong(config.android.platformDir)}`, async () => {
return (0, template_1.extractTemplate)(config.cli.assets.android.platformTemplateArchiveAbs, config.android.platformDirAbs);
});
}
exports.addAndroid = addAndroid;
async function createLocalProperties(platformDir) {
const defaultAndroidPath = (0, path_1.join)((0, os_1.homedir)(), 'Library/Android/sdk');
if (await (0, utils_fs_1.pathExists)(defaultAndroidPath)) {
const localSettings = `
## This file is automatically generated by Android Studio.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file should *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
sdk.dir=${defaultAndroidPath}
`;
await (0, utils_fs_1.writeFile)((0, path_1.join)(platformDir, 'local.properties'), localSettings, {
encoding: 'utf-8',
});
// Only sync if we were able to create the local properties above, otherwise
// this will fail
try {
await gradleSync(platformDir);
}
catch (e) {
console.error('Error running gradle sync', e);
console.error('Unable to infer default Android SDK settings. This is fine, just run npx cap open android and import and sync gradle manually');
}
}
}
exports.createLocalProperties = createLocalProperties;
async function gradleSync(platformDir) {
await (0, subprocess_1.runCommand)(`./gradlew`, [], {
cwd: platformDir,
});
}

106
@capacitor/cli/dist/android/build.js vendored Normal file
View file

@ -0,0 +1,106 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildAndroid = void 0;
const tslib_1 = require("tslib");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
const log_1 = require("../log");
const subprocess_1 = require("../util/subprocess");
async function buildAndroid(config, buildOptions) {
var _a, _b;
const releaseType = (_a = buildOptions.androidreleasetype) !== null && _a !== void 0 ? _a : 'AAB';
const releaseTypeIsAAB = releaseType === 'AAB';
const flavor = (_b = buildOptions.flavor) !== null && _b !== void 0 ? _b : '';
const arg = releaseTypeIsAAB
? `:app:bundle${flavor}Release`
: `assemble${flavor}Release`;
const gradleArgs = [arg];
try {
await (0, common_1.runTask)('Running Gradle build', async () => (0, subprocess_1.runCommand)('./gradlew', gradleArgs, {
cwd: config.android.platformDirAbs,
}));
}
catch (e) {
if (e.includes('EACCES')) {
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.`;
}
else {
throw e;
}
}
const releaseDir = releaseTypeIsAAB
? flavor !== ''
? `${flavor}Release`
: 'release'
: flavor !== ''
? (0, path_1.join)(flavor, 'release')
: 'release';
const releasePath = (0, path_1.join)(config.android.appDirAbs, 'build', 'outputs', releaseTypeIsAAB ? 'bundle' : 'apk', releaseDir);
const unsignedReleaseName = `app${flavor !== '' ? `-${flavor}` : ''}-release${releaseTypeIsAAB ? '' : '-unsigned'}.${releaseType.toLowerCase()}`;
const signedReleaseName = unsignedReleaseName.replace(`-release${releaseTypeIsAAB ? '' : '-unsigned'}.${releaseType.toLowerCase()}`, `-release-signed.${releaseType.toLowerCase()}`);
if (buildOptions.signingtype == 'jarsigner') {
await signWithJarSigner(config, buildOptions, releasePath, signedReleaseName, unsignedReleaseName);
}
else {
await signWithApkSigner(config, buildOptions, releasePath, signedReleaseName, unsignedReleaseName);
}
(0, log_1.logSuccess)(`Successfully generated ${signedReleaseName} at: ${releasePath}`);
}
exports.buildAndroid = buildAndroid;
async function signWithApkSigner(config, buildOptions, releasePath, signedReleaseName, unsignedReleaseName) {
if (!buildOptions.keystorepath || !buildOptions.keystorepass) {
throw 'Missing options. Please supply all options for android signing. (Keystore Path, Keystore Password)';
}
const signingArgs = [
'sign',
'--ks',
buildOptions.keystorepath,
'--ks-pass',
`pass:${buildOptions.keystorepass}`,
'--in',
`${(0, path_1.join)(releasePath, unsignedReleaseName)}`,
'--out',
`${(0, path_1.join)(releasePath, signedReleaseName)}`,
];
if (buildOptions.keystorealias) {
signingArgs.push('--ks-key-alias', buildOptions.keystorealias);
}
if (buildOptions.keystorealiaspass) {
signingArgs.push('--key-pass', `pass:${buildOptions.keystorealiaspass}`);
}
await (0, common_1.runTask)('Signing Release', async () => {
await (0, subprocess_1.runCommand)('apksigner', signingArgs, {
cwd: config.android.platformDirAbs,
});
});
}
async function signWithJarSigner(config, buildOptions, releasePath, signedReleaseName, unsignedReleaseName) {
if (!buildOptions.keystorepath ||
!buildOptions.keystorealias ||
!buildOptions.keystorealiaspass ||
!buildOptions.keystorepass) {
throw 'Missing options. Please supply all options for android signing. (Keystore Path, Keystore Password, Keystore Key Alias, Keystore Key Password)';
}
const signingArgs = [
'-sigalg',
'SHA1withRSA',
'-digestalg',
'SHA1',
'-keystore',
buildOptions.keystorepath,
'-keypass',
buildOptions.keystorealiaspass,
'-storepass',
buildOptions.keystorepass,
`-signedjar`,
`${(0, path_1.join)(releasePath, signedReleaseName)}`,
`${(0, path_1.join)(releasePath, unsignedReleaseName)}`,
buildOptions.keystorealias,
];
await (0, common_1.runTask)('Signing Release', async () => {
await (0, subprocess_1.runCommand)('jarsigner', signingArgs, {
cwd: config.android.platformDirAbs,
});
});
}

97
@capacitor/cli/dist/android/common.js vendored Normal file
View file

@ -0,0 +1,97 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.editProjectSettingsAndroid = exports.resolvePlugin = exports.getAndroidPlugins = exports.checkAndroidPackage = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const path_1 = require("path");
const common_1 = require("../common");
const cordova_1 = require("../cordova");
const plugin_1 = require("../plugin");
const fs_1 = require("../util/fs");
async function checkAndroidPackage(config) {
return (0, common_1.checkCapacitorPlatform)(config, 'android');
}
exports.checkAndroidPackage = checkAndroidPackage;
async function getAndroidPlugins(allPlugins) {
const resolved = await Promise.all(allPlugins.map(async (plugin) => await resolvePlugin(plugin)));
return resolved.filter((plugin) => !!plugin);
}
exports.getAndroidPlugins = getAndroidPlugins;
async function resolvePlugin(plugin) {
var _a;
const platform = 'android';
if ((_a = plugin.manifest) === null || _a === void 0 ? void 0 : _a.android) {
let pluginFilesPath = plugin.manifest.android.src
? plugin.manifest.android.src
: platform;
const absolutePath = (0, path_1.join)(plugin.rootPath, pluginFilesPath, plugin.id);
// Android folder shouldn't have subfolders, but they used to, so search for them for compatibility reasons
if (await (0, utils_fs_1.pathExists)(absolutePath)) {
pluginFilesPath = (0, path_1.join)(platform, plugin.id);
}
plugin.android = {
type: 0 /* PluginType.Core */,
path: (0, fs_1.convertToUnixPath)(pluginFilesPath),
};
}
else if (plugin.xml) {
plugin.android = {
type: 1 /* PluginType.Cordova */,
path: 'src/' + platform,
};
if ((0, cordova_1.getIncompatibleCordovaPlugins)(platform).includes(plugin.id) ||
!(0, plugin_1.getPluginPlatform)(plugin, platform)) {
plugin.android.type = 2 /* PluginType.Incompatible */;
}
}
else {
return null;
}
return plugin;
}
exports.resolvePlugin = resolvePlugin;
/**
* Update an Android project with the desired app name and appId.
* This is a little trickier for Android because the appId becomes
* the package name.
*/
async function editProjectSettingsAndroid(config) {
const appId = config.app.appId;
const appName = config.app.appName
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/"/g, '\\"')
.replace(/'/g, "\\'");
const buildGradlePath = (0, path_1.resolve)(config.android.appDirAbs, 'build.gradle');
const domainPath = appId.split('.').join('/');
// Make the package source path to the new plugin Java file
const newJavaPath = (0, path_1.resolve)(config.android.srcMainDirAbs, `java/${domainPath}`);
if (!(await (0, utils_fs_1.pathExists)(newJavaPath))) {
await (0, utils_fs_1.mkdirp)(newJavaPath);
}
await (0, utils_fs_1.copy)((0, path_1.resolve)(config.android.srcMainDirAbs, 'java/com/getcapacitor/myapp/MainActivity.java'), (0, path_1.resolve)(newJavaPath, 'MainActivity.java'));
if (appId.split('.')[1] !== 'getcapacitor') {
await (0, utils_fs_1.remove)((0, path_1.resolve)(config.android.srcMainDirAbs, 'java/com/getcapacitor'));
}
// Remove our template 'com' folder if their ID doesn't have it
if (appId.split('.')[0] !== 'com') {
await (0, utils_fs_1.remove)((0, path_1.resolve)(config.android.srcMainDirAbs, 'java/com/'));
}
// Update the package in the MainActivity java file
const activityPath = (0, path_1.resolve)(newJavaPath, 'MainActivity.java');
let activityContent = await (0, utils_fs_1.readFile)(activityPath, { encoding: 'utf-8' });
activityContent = activityContent.replace(/package ([^;]*)/, `package ${appId}`);
await (0, utils_fs_1.writeFile)(activityPath, activityContent, { encoding: 'utf-8' });
// Update the applicationId in build.gradle
let gradleContent = await (0, utils_fs_1.readFile)(buildGradlePath, { encoding: 'utf-8' });
gradleContent = gradleContent.replace(/applicationId "[^"]+"/, `applicationId "${appId}"`);
// Update the namespace in build.gradle
gradleContent = gradleContent.replace(/namespace "[^"]+"/, `namespace "${appId}"`);
await (0, utils_fs_1.writeFile)(buildGradlePath, gradleContent, { encoding: 'utf-8' });
// Update the settings in res/values/strings.xml
const stringsPath = (0, path_1.resolve)(config.android.resDirAbs, 'values/strings.xml');
let stringsContent = await (0, utils_fs_1.readFile)(stringsPath, { encoding: 'utf-8' });
stringsContent = stringsContent.replace(/com.getcapacitor.myapp/g, appId);
stringsContent = stringsContent.replace(/My App/g, appName);
await (0, utils_fs_1.writeFile)(stringsPath, stringsContent);
}
exports.editProjectSettingsAndroid = editProjectSettingsAndroid;

163
@capacitor/cli/dist/android/doctor.js vendored Normal file
View file

@ -0,0 +1,163 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.doctorAndroid = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
const errors_1 = require("../errors");
const log_1 = require("../log");
const xml_1 = require("../util/xml");
async function doctorAndroid(config) {
var _a;
try {
await (0, common_1.check)([
checkAndroidInstalled,
() => checkGradlew(config),
() => checkAppSrcDirs(config),
]);
(0, log_1.logSuccess)('Android looking great! 👌');
}
catch (e) {
if (!(0, errors_1.isFatal)(e)) {
(0, errors_1.fatal)((_a = e.stack) !== null && _a !== void 0 ? _a : e);
}
throw e;
}
}
exports.doctorAndroid = doctorAndroid;
async function checkAppSrcDirs(config) {
if (!(await (0, utils_fs_1.pathExists)(config.android.appDirAbs))) {
return `${colors_1.default.strong(config.android.appDir)} directory is missing in ${colors_1.default.strong(config.android.platformDir)}`;
}
if (!(await (0, utils_fs_1.pathExists)(config.android.srcMainDirAbs))) {
return `${colors_1.default.strong(config.android.srcMainDir)} directory is missing in ${colors_1.default.strong(config.android.platformDir)}`;
}
if (!(await (0, utils_fs_1.pathExists)(config.android.assetsDirAbs))) {
return `${colors_1.default.strong(config.android.assetsDir)} directory is missing in ${colors_1.default.strong(config.android.platformDir)}`;
}
if (!(await (0, utils_fs_1.pathExists)(config.android.webDirAbs))) {
return `${colors_1.default.strong(config.android.webDir)} directory is missing in ${colors_1.default.strong(config.android.platformDir)}`;
}
const appSrcMainAssetsWwwIndexHtmlDir = (0, path_1.join)(config.android.webDirAbs, 'index.html');
if (!(await (0, utils_fs_1.pathExists)(appSrcMainAssetsWwwIndexHtmlDir))) {
return `${colors_1.default.strong('index.html')} file is missing in ${colors_1.default.strong(config.android.webDirAbs)}`;
}
return checkAndroidManifestFile(config);
}
async function checkAndroidManifestFile(config) {
const manifestFileName = 'AndroidManifest.xml';
const manifestFilePath = (0, path_1.join)(config.android.srcMainDirAbs, manifestFileName);
if (!(await (0, utils_fs_1.pathExists)(manifestFilePath))) {
return `${colors_1.default.strong(manifestFileName)} is missing in ${colors_1.default.strong(config.android.srcMainDir)}`;
}
try {
const xmlData = await (0, xml_1.readXML)(manifestFilePath);
return checkAndroidManifestData(config, xmlData);
}
catch (e) {
return e;
}
}
async function checkAndroidManifestData(config, xmlData) {
const manifestNode = xmlData.manifest;
if (!manifestNode) {
return `Missing ${colors_1.default.input('<manifest>')} XML node in ${colors_1.default.strong(config.android.srcMainDir)}`;
}
const applicationChildNodes = manifestNode.application;
if (!Array.isArray(manifestNode.application)) {
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)}`;
}
let mainActivityClassPath = '';
const mainApplicationNode = applicationChildNodes.find(applicationChildNode => {
const activityChildNodes = applicationChildNode.activity;
if (!Array.isArray(activityChildNodes)) {
return false;
}
const mainActivityNode = activityChildNodes.find(activityChildNode => {
const intentFilterChildNodes = activityChildNode['intent-filter'];
if (!Array.isArray(intentFilterChildNodes)) {
return false;
}
return intentFilterChildNodes.find(intentFilterChildNode => {
const actionChildNodes = intentFilterChildNode.action;
if (!Array.isArray(actionChildNodes)) {
return false;
}
const mainActionChildNode = actionChildNodes.find(actionChildNode => {
const androidName = actionChildNode.$['android:name'];
return androidName === 'android.intent.action.MAIN';
});
if (!mainActionChildNode) {
return false;
}
const categoryChildNodes = intentFilterChildNode.category;
if (!Array.isArray(categoryChildNodes)) {
return false;
}
return categoryChildNodes.find(categoryChildNode => {
const androidName = categoryChildNode.$['android:name'];
return androidName === 'android.intent.category.LAUNCHER';
});
});
});
if (mainActivityNode) {
mainActivityClassPath = mainActivityNode.$['android:name'];
}
return mainActivityNode;
});
if (!mainApplicationNode) {
return `Missing main ${colors_1.default.input('<activity>')} XML node in ${colors_1.default.strong(config.android.srcMainDir)}`;
}
if (!mainActivityClassPath) {
return `Missing ${colors_1.default.input('<activity android:name="">')} attribute for MainActivity class in ${colors_1.default.strong(config.android.srcMainDir)}`;
}
return checkPackage(config, mainActivityClassPath);
}
async function checkPackage(config, mainActivityClassPath) {
const appSrcMainJavaDir = (0, path_1.join)(config.android.srcMainDirAbs, 'java');
if (!(await (0, utils_fs_1.pathExists)(appSrcMainJavaDir))) {
return `${colors_1.default.strong('java')} directory is missing in ${colors_1.default.strong(appSrcMainJavaDir)}`;
}
const mainActivityClassName = mainActivityClassPath.split('.').pop();
const srcFiles = await (0, utils_fs_1.readdirp)(appSrcMainJavaDir, {
filter: entry => !entry.stats.isDirectory() &&
['.java', '.kt'].includes((0, path_1.extname)(entry.path)) &&
mainActivityClassName === (0, path_1.parse)(entry.path).name,
});
if (srcFiles.length == 0) {
return `Main activity file (${mainActivityClassName}) is missing`;
}
return checkBuildGradle(config);
}
async function checkBuildGradle(config) {
const fileName = 'build.gradle';
const filePath = (0, path_1.join)(config.android.appDirAbs, fileName);
if (!(await (0, utils_fs_1.pathExists)(filePath))) {
return `${colors_1.default.strong(fileName)} file is missing in ${colors_1.default.strong(config.android.appDir)}`;
}
let fileContent = await (0, utils_fs_1.readFile)(filePath, { encoding: 'utf-8' });
fileContent = fileContent.replace(/'|"/g, '').replace(/\s+/g, ' ');
const searchFor = `applicationId`;
if (fileContent.indexOf(searchFor) === -1) {
return `${colors_1.default.strong('build.gradle')} file missing ${colors_1.default.input(`applicationId`)} config in ${filePath}`;
}
return null;
}
async function checkGradlew(config) {
const fileName = 'gradlew';
const filePath = (0, path_1.join)(config.android.platformDirAbs, fileName);
if (!(await (0, utils_fs_1.pathExists)(filePath))) {
return `${colors_1.default.strong(fileName)} file is missing in ${colors_1.default.strong(config.android.platformDir)}`;
}
return null;
}
async function checkAndroidInstalled() {
/*
if (!await isInstalled('android')) {
return 'Android is not installed. For information: https://developer.android.com/studio/index.html';
}
*/
return null;
}

28
@capacitor/cli/dist/android/open.js vendored Normal file
View file

@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.openAndroid = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const debug_1 = tslib_1.__importDefault(require("debug"));
const open_1 = tslib_1.__importDefault(require("open"));
const colors_1 = tslib_1.__importDefault(require("../colors"));
const log_1 = require("../log");
const debug = (0, debug_1.default)('capacitor:android:open');
async function openAndroid(config) {
const androidStudioPath = await config.android.studioPath;
const dir = config.android.platformDirAbs;
try {
if (!(await (0, utils_fs_1.pathExists)(androidStudioPath))) {
throw new Error(`Android Studio does not exist at: ${androidStudioPath}`);
}
await (0, open_1.default)(dir, { app: { name: androidStudioPath }, wait: false });
log_1.logger.info(`Opening Android project at: ${colors_1.default.strong(config.android.platformDir)}.`);
}
catch (e) {
debug('Error opening Android Studio: %O', e);
log_1.logger.error('Unable to launch Android Studio. Is it installed?\n' +
`Attempted to open Android Studio at: ${colors_1.default.strong(androidStudioPath)}\n` +
`You can configure this with the ${colors_1.default.input('CAPACITOR_ANDROID_STUDIO_PATH')} environment variable.`);
}
}
exports.openAndroid = openAndroid;

42
@capacitor/cli/dist/android/run.js vendored Normal file
View file

@ -0,0 +1,42 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.runAndroid = void 0;
const tslib_1 = require("tslib");
const debug_1 = tslib_1.__importDefault(require("debug"));
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
const native_run_1 = require("../util/native-run");
const subprocess_1 = require("../util/subprocess");
const debug = (0, debug_1.default)('capacitor:android:run');
async function runAndroid(config, { target: selectedTarget, flavor: selectedFlavor, forwardPorts: selectedPorts, }) {
var _a;
const target = await (0, common_1.promptForPlatformTarget)(await (0, native_run_1.getPlatformTargets)('android'), selectedTarget);
const runFlavor = selectedFlavor || ((_a = config.android) === null || _a === void 0 ? void 0 : _a.flavor) || '';
const arg = `assemble${runFlavor}Debug`;
const gradleArgs = [arg];
debug('Invoking ./gradlew with args: %O', gradleArgs);
try {
await (0, common_1.runTask)('Running Gradle build', async () => (0, subprocess_1.runCommand)('./gradlew', gradleArgs, {
cwd: config.android.platformDirAbs,
}));
}
catch (e) {
if (e.includes('EACCES')) {
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.`;
}
else {
throw e;
}
}
const pathToApk = `${config.android.platformDirAbs}/${config.android.appDir}/build/outputs/apk${runFlavor !== '' ? '/' + runFlavor : ''}/debug`;
const apkName = (0, common_1.parseApkNameFromFlavor)(runFlavor);
const apkPath = (0, path_1.resolve)(pathToApk, apkName);
const nativeRunArgs = ['android', '--app', apkPath, '--target', target.id];
if (selectedPorts) {
nativeRunArgs.push('--forward', `${selectedPorts}`);
}
debug('Invoking native-run with args: %O', nativeRunArgs);
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));
}
exports.runAndroid = runAndroid;

323
@capacitor/cli/dist/android/update.js vendored Normal file
View file

@ -0,0 +1,323 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleCordovaPluginsGradle = exports.installGradlePlugins = exports.updateAndroid = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const debug_1 = tslib_1.__importDefault(require("debug"));
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
const cordova_1 = require("../cordova");
const errors_1 = require("../errors");
const plugin_1 = require("../plugin");
const copy_1 = require("../tasks/copy");
const migrate_1 = require("../tasks/migrate");
const fs_1 = require("../util/fs");
const node_1 = require("../util/node");
const template_1 = require("../util/template");
const common_2 = require("./common");
const platform = 'android';
const debug = (0, debug_1.default)('capacitor:android:update');
async function updateAndroid(config) {
const plugins = await getPluginsTask(config);
const capacitorPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 0 /* PluginType.Core */);
(0, plugin_1.printPlugins)(capacitorPlugins, 'android');
await writePluginsJson(config, capacitorPlugins);
await removePluginsNativeFiles(config);
const cordovaPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
await (0, migrate_1.patchOldCapacitorPlugins)(config);
if (cordovaPlugins.length > 0) {
await copyPluginsNativeFiles(config, cordovaPlugins);
}
if (!(await (0, utils_fs_1.pathExists)(config.android.webDirAbs))) {
await (0, copy_1.copy)(config, platform);
}
await (0, cordova_1.handleCordovaPluginsJS)(cordovaPlugins, config, platform);
await (0, cordova_1.checkPluginDependencies)(plugins, platform);
await installGradlePlugins(config, capacitorPlugins, cordovaPlugins);
await handleCordovaPluginsGradle(config, cordovaPlugins);
await (0, cordova_1.writeCordovaAndroidManifest)(cordovaPlugins, config, platform);
const incompatibleCordovaPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 2 /* PluginType.Incompatible */);
(0, plugin_1.printPlugins)(incompatibleCordovaPlugins, platform, 'incompatible');
await (0, common_1.checkPlatformVersions)(config, platform);
}
exports.updateAndroid = updateAndroid;
function getGradlePackageName(id) {
return id.replace('@', '').replace('/', '-');
}
async function writePluginsJson(config, plugins) {
const classes = await findAndroidPluginClasses(plugins);
const pluginsJsonPath = (0, path_1.resolve)(config.android.assetsDirAbs, 'capacitor.plugins.json');
await (0, utils_fs_1.writeJSON)(pluginsJsonPath, classes, { spaces: '\t' });
}
async function findAndroidPluginClasses(plugins) {
const entries = [];
for (const plugin of plugins) {
entries.push(...(await findAndroidPluginClassesInPlugin(plugin)));
}
return entries;
}
async function findAndroidPluginClassesInPlugin(plugin) {
if (!plugin.android || (0, plugin_1.getPluginType)(plugin, platform) !== 0 /* PluginType.Core */) {
return [];
}
const srcPath = (0, path_1.resolve)(plugin.rootPath, plugin.android.path, 'src/main');
const srcFiles = await (0, utils_fs_1.readdirp)(srcPath, {
filter: entry => !entry.stats.isDirectory() &&
['.java', '.kt'].includes((0, path_1.extname)(entry.path)),
});
const classRegex = /^@(?:CapacitorPlugin|NativePlugin)[\s\S]+?class ([\w]+)/gm;
const packageRegex = /^package ([\w.]+);?$/gm;
debug('Searching %O source files in %O by %O regex', srcFiles.length, srcPath, classRegex);
const entries = await Promise.all(srcFiles.map(async (srcFile) => {
const srcFileContents = await (0, utils_fs_1.readFile)(srcFile, { encoding: 'utf-8' });
classRegex.lastIndex = 0;
const classMatch = classRegex.exec(srcFileContents);
if (classMatch) {
const className = classMatch[1];
debug('Searching %O for package by %O regex', srcFile, packageRegex);
packageRegex.lastIndex = 0;
const packageMatch = packageRegex.exec(srcFileContents.substring(0, classMatch.index));
if (!packageMatch) {
(0, errors_1.fatal)(`Package could not be parsed from Android plugin.\n` +
`Location: ${colors_1.default.strong(srcFile)}`);
}
const packageName = packageMatch[1];
const classpath = `${packageName}.${className}`;
debug('%O is a suitable plugin class', classpath);
return {
pkg: plugin.id,
classpath,
};
}
}));
return entries.filter((entry) => !!entry);
}
async function installGradlePlugins(config, capacitorPlugins, cordovaPlugins) {
const capacitorAndroidPackagePath = (0, node_1.resolveNode)(config.app.rootDir, '@capacitor/android', 'package.json');
if (!capacitorAndroidPackagePath) {
(0, errors_1.fatal)(`Unable to find ${colors_1.default.strong('node_modules/@capacitor/android')}.\n` +
`Are you sure ${colors_1.default.strong('@capacitor/android')} is installed?`);
}
const capacitorAndroidPath = (0, path_1.resolve)((0, path_1.dirname)(capacitorAndroidPackagePath), 'capacitor');
const settingsPath = config.android.platformDirAbs;
const dependencyPath = config.android.appDirAbs;
const relativeCapcitorAndroidPath = (0, fs_1.convertToUnixPath)((0, path_1.relative)(settingsPath, capacitorAndroidPath));
const settingsLines = `// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
include ':capacitor-android'
project(':capacitor-android').projectDir = new File('${relativeCapcitorAndroidPath}')
${capacitorPlugins
.map(p => {
if (!p.android) {
return '';
}
const relativePluginPath = (0, fs_1.convertToUnixPath)((0, path_1.relative)(settingsPath, p.rootPath));
return `
include ':${getGradlePackageName(p.id)}'
project(':${getGradlePackageName(p.id)}').projectDir = new File('${relativePluginPath}/${p.android.path}')
`;
})
.join('')}`;
const applyArray = [];
const frameworksArray = [];
let prefsArray = [];
cordovaPlugins.map(p => {
const relativePluginPath = (0, fs_1.convertToUnixPath)((0, path_1.relative)(dependencyPath, p.rootPath));
const frameworks = (0, plugin_1.getPlatformElement)(p, platform, 'framework');
frameworks.map((framework) => {
if (framework.$.custom &&
framework.$.custom === 'true' &&
framework.$.type &&
framework.$.type === 'gradleReference') {
applyArray.push(`apply from: "${relativePluginPath}/${framework.$.src}"`);
}
else if (!framework.$.type && !framework.$.custom) {
if (framework.$.src.startsWith('platform(')) {
frameworksArray.push(` implementation ${framework.$.src}`);
}
else {
frameworksArray.push(` implementation "${framework.$.src}"`);
}
}
});
prefsArray = prefsArray.concat((0, plugin_1.getAllElements)(p, platform, 'preference'));
});
let frameworkString = frameworksArray.join('\n');
frameworkString = await replaceFrameworkVariables(config, prefsArray, frameworkString);
const dependencyLines = `// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
dependencies {
${capacitorPlugins
.map(p => {
return ` implementation project(':${getGradlePackageName(p.id)}')`;
})
.join('\n')}
${frameworkString}
}
${applyArray.join('\n')}
if (hasProperty('postBuildExtras')) {
postBuildExtras()
}
`;
await (0, utils_fs_1.writeFile)((0, path_1.join)(settingsPath, 'capacitor.settings.gradle'), settingsLines);
await (0, utils_fs_1.writeFile)((0, path_1.join)(dependencyPath, 'capacitor.build.gradle'), dependencyLines);
}
exports.installGradlePlugins = installGradlePlugins;
async function handleCordovaPluginsGradle(config, cordovaPlugins) {
var _a, _b, _c;
const pluginsGradlePath = (0, path_1.join)(config.android.cordovaPluginsDirAbs, 'build.gradle');
const kotlinNeeded = await kotlinNeededCheck(config, cordovaPlugins);
const kotlinVersionString = (_c = (_b = (_a = config.app.extConfig.cordova) === null || _a === void 0 ? void 0 : _a.preferences) === null || _b === void 0 ? void 0 : _b.GradlePluginKotlinVersion) !== null && _c !== void 0 ? _c : '1.8.20';
const frameworksArray = [];
let prefsArray = [];
const applyArray = [];
applyArray.push(`apply from: "cordova.variables.gradle"`);
cordovaPlugins.map(p => {
const relativePluginPath = (0, fs_1.convertToUnixPath)((0, path_1.relative)(config.android.cordovaPluginsDirAbs, p.rootPath));
const frameworks = (0, plugin_1.getPlatformElement)(p, platform, 'framework');
frameworks.map((framework) => {
if (!framework.$.type && !framework.$.custom) {
frameworksArray.push(framework.$.src);
}
else if (framework.$.custom &&
framework.$.custom === 'true' &&
framework.$.type &&
framework.$.type === 'gradleReference') {
applyArray.push(`apply from: "${relativePluginPath}/${framework.$.src}"`);
}
});
prefsArray = prefsArray.concat((0, plugin_1.getAllElements)(p, platform, 'preference'));
});
let frameworkString = frameworksArray
.map(f => {
if (f.startsWith('platform(')) {
return ` implementation ${f}`;
}
else {
return ` implementation "${f}"`;
}
})
.join('\n');
frameworkString = await replaceFrameworkVariables(config, prefsArray, frameworkString);
if (kotlinNeeded) {
frameworkString += `\n implementation "androidx.core:core-ktx:$androidxCoreKTXVersion"`;
frameworkString += `\n implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"`;
}
const applyString = applyArray.join('\n');
let buildGradle = await (0, utils_fs_1.readFile)(pluginsGradlePath, { encoding: 'utf-8' });
buildGradle = buildGradle.replace(/(SUB-PROJECT DEPENDENCIES START)[\s\S]*(\/\/ SUB-PROJECT DEPENDENCIES END)/, '$1\n' + frameworkString.concat('\n') + ' $2');
buildGradle = buildGradle.replace(/(PLUGIN GRADLE EXTENSIONS START)[\s\S]*(\/\/ PLUGIN GRADLE EXTENSIONS END)/, '$1\n' + applyString.concat('\n') + '$2');
if (kotlinNeeded) {
buildGradle = buildGradle.replace(/(buildscript\s{\n(\t|\s{4})repositories\s{\n((\t{2}|\s{8}).+\n)+(\t|\s{4})}\n(\t|\s{4})dependencies\s{\n(\t{2}|\s{8}).+)\n((\t|\s{4})}\n}\n)/, `$1\n classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"\n$8`);
buildGradle = buildGradle.replace(/(ext\s{)/, `$1\n androidxCoreKTXVersion = project.hasProperty('androidxCoreKTXVersion') ? rootProject.ext.androidxCoreKTXVersion : '1.8.0'`);
buildGradle = buildGradle.replace(/(buildscript\s{)/, `$1\n ext.kotlin_version = project.hasProperty('kotlin_version') ? rootProject.ext.kotlin_version : '${kotlinVersionString}'`);
buildGradle = buildGradle.replace(/(apply\splugin:\s'com\.android\.library')/, `$1\napply plugin: 'kotlin-android'`);
buildGradle = buildGradle.replace(/(compileOptions\s{\n((\t{2}|\s{8}).+\n)+(\t|\s{4})})\n(})/, `$1\n sourceSets {\n main.java.srcDirs += 'src/main/kotlin'\n }\n$5`);
}
await (0, utils_fs_1.writeFile)(pluginsGradlePath, buildGradle);
const cordovaVariables = `// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
ext {
cdvMinSdkVersion = project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : ${config.android.minVersion}
// Plugin gradle extensions can append to this to have code run at the end.
cdvPluginPostBuildExtras = []
cordovaConfig = [:]
}`;
await (0, utils_fs_1.writeFile)((0, path_1.join)(config.android.cordovaPluginsDirAbs, 'cordova.variables.gradle'), cordovaVariables);
}
exports.handleCordovaPluginsGradle = handleCordovaPluginsGradle;
async function kotlinNeededCheck(config, cordovaPlugins) {
var _a, _b;
if (((_b = (_a = config.app.extConfig.cordova) === null || _a === void 0 ? void 0 : _a.preferences) === null || _b === void 0 ? void 0 : _b.GradlePluginKotlinEnabled) !==
'true') {
for (const plugin of cordovaPlugins) {
const androidPlatform = (0, plugin_1.getPluginPlatform)(plugin, platform);
const sourceFiles = androidPlatform['source-file'];
if (sourceFiles) {
for (const srcFile of sourceFiles) {
if (/^.*\.kt$/.test(srcFile['$'].src)) {
return true;
}
}
}
}
return false;
}
else {
return true;
}
}
async function copyPluginsNativeFiles(config, cordovaPlugins) {
const pluginsPath = (0, path_1.join)(config.android.cordovaPluginsDirAbs, 'src', 'main');
for (const p of cordovaPlugins) {
const androidPlatform = (0, plugin_1.getPluginPlatform)(p, platform);
if (androidPlatform) {
const sourceFiles = androidPlatform['source-file'];
if (sourceFiles) {
for (const sourceFile of sourceFiles) {
const fileName = sourceFile.$.src.split('/').pop();
let baseFolder = 'java/';
if (fileName.split('.').pop() === 'aidl') {
baseFolder = 'aidl/';
}
const target = sourceFile.$['target-dir']
.replace('app/src/main/', '')
.replace('src/', baseFolder);
await (0, utils_fs_1.copy)((0, plugin_1.getFilePath)(config, p, sourceFile.$.src), (0, path_1.join)(pluginsPath, target, fileName));
}
}
const resourceFiles = androidPlatform['resource-file'];
if (resourceFiles) {
for (const resourceFile of resourceFiles) {
const target = resourceFile.$['target'];
if (resourceFile.$.src.split('.').pop() === 'aar') {
await (0, utils_fs_1.copy)((0, plugin_1.getFilePath)(config, p, resourceFile.$.src), (0, path_1.join)(pluginsPath, 'libs', target.split('/').pop()));
}
else if (target !== '.') {
await (0, utils_fs_1.copy)((0, plugin_1.getFilePath)(config, p, resourceFile.$.src), (0, path_1.join)(pluginsPath, target));
}
}
}
const libFiles = (0, plugin_1.getPlatformElement)(p, platform, 'lib-file');
for (const libFile of libFiles) {
await (0, utils_fs_1.copy)((0, plugin_1.getFilePath)(config, p, libFile.$.src), (0, path_1.join)(pluginsPath, 'libs', libFile.$.src.split('/').pop()));
}
}
}
}
async function removePluginsNativeFiles(config) {
await (0, utils_fs_1.remove)(config.android.cordovaPluginsDirAbs);
await (0, template_1.extractTemplate)(config.cli.assets.android.cordovaPluginsTemplateArchiveAbs, config.android.cordovaPluginsDirAbs);
}
async function getPluginsTask(config) {
return await (0, common_1.runTask)('Updating Android plugins', async () => {
const allPlugins = await (0, plugin_1.getPlugins)(config, 'android');
const androidPlugins = await (0, common_2.getAndroidPlugins)(allPlugins);
return androidPlugins;
});
}
async function getVariablesGradleFile(config) {
const variablesFile = (0, path_1.resolve)(config.android.platformDirAbs, 'variables.gradle');
let variablesGradle = '';
if (await (0, utils_fs_1.pathExists)(variablesFile)) {
variablesGradle = await (0, utils_fs_1.readFile)(variablesFile, { encoding: 'utf-8' });
}
return variablesGradle;
}
async function replaceFrameworkVariables(config, prefsArray, frameworkString) {
const variablesGradle = await getVariablesGradleFile(config);
prefsArray.map((preference) => {
if (!variablesGradle.includes(preference.$.name)) {
frameworkString = frameworkString.replace(new RegExp(('$' + preference.$.name).replace('$', '\\$&'), 'g'), preference.$.default);
}
});
return frameworkString;
}

26
@capacitor/cli/dist/colors.js vendored Normal file
View file

@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ancillary = exports.failure = exports.success = exports.input = exports.weak = exports.strong = void 0;
const tslib_1 = require("tslib");
const kleur_1 = tslib_1.__importDefault(require("kleur"));
exports.strong = kleur_1.default.bold;
exports.weak = kleur_1.default.dim;
exports.input = kleur_1.default.cyan;
exports.success = kleur_1.default.green;
exports.failure = kleur_1.default.red;
exports.ancillary = kleur_1.default.cyan;
const COLORS = {
strong: exports.strong,
weak: exports.weak,
input: exports.input,
success: exports.success,
failure: exports.failure,
ancillary: exports.ancillary,
log: {
DEBUG: kleur_1.default.magenta,
INFO: kleur_1.default.cyan,
WARN: kleur_1.default.yellow,
ERROR: kleur_1.default.red,
},
};
exports.default = COLORS;

407
@capacitor/cli/dist/common.js vendored Normal file
View file

@ -0,0 +1,407 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseApkNameFromFlavor = exports.checkJDKMajorVersion = exports.resolvePlatform = exports.checkPlatformVersions = exports.getAddedPlatforms = exports.getPlatformTargetName = exports.promptForPlatformTarget = exports.promptForPlatform = exports.isValidEnterprisePlatform = exports.getKnownEnterprisePlatforms = exports.isValidCommunityPlatform = exports.getKnownCommunityPlatforms = exports.isValidPlatform = exports.getKnownPlatforms = exports.selectPlatforms = exports.getProjectPlatformDirectory = exports.getCLIVersion = exports.getCoreVersion = exports.getCapacitorPackageVersion = exports.requireCapacitorPackage = exports.getCapacitorPackage = exports.runTask = exports.runPlatformHook = exports.runHooks = exports.wait = exports.checkAppName = exports.checkAppId = exports.checkAppDir = exports.checkAppConfig = exports.checkCapacitorPlatform = exports.checkPackage = exports.checkWebDir = exports.check = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const utils_terminal_1 = require("@ionic/utils-terminal");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("./colors"));
const errors_1 = require("./errors");
const log_1 = require("./log");
const plugin_1 = require("./plugin");
const monorepotools_1 = require("./util/monorepotools");
const node_1 = require("./util/node");
const subprocess_1 = require("./util/subprocess");
async function check(checks) {
const results = await Promise.all(checks.map(f => f()));
const errors = results.filter(r => r != null);
if (errors.length > 0) {
throw errors.join('\n');
}
}
exports.check = check;
async function checkWebDir(config) {
var _a;
// We can skip checking the web dir if a server URL is set.
if ((_a = config.app.extConfig.server) === null || _a === void 0 ? void 0 : _a.url) {
return null;
}
const invalidFolders = ['', '.', '..', '../', './'];
if (invalidFolders.includes(config.app.webDir)) {
return `"${config.app.webDir}" is not a valid value for webDir`;
}
if (!(await (0, utils_fs_1.pathExists)(config.app.webDirAbs))) {
return (`Could not find the web assets directory: ${colors_1.default.strong((0, utils_terminal_1.prettyPath)(config.app.webDirAbs))}.\n` +
`Please create it and make sure it has an ${colors_1.default.strong('index.html')} file. You can change the path of this directory in ${colors_1.default.strong(config.app.extConfigName)} (${colors_1.default.input('webDir')} option). You may need to compile the web assets for your app (typically ${colors_1.default.input('npm run build')}). More info: ${colors_1.default.strong('https://capacitorjs.com/docs/basics/workflow#sync-your-project')}`);
}
if (!(await (0, utils_fs_1.pathExists)((0, path_1.join)(config.app.webDirAbs, 'index.html')))) {
return (`The web assets directory (${colors_1.default.strong((0, utils_terminal_1.prettyPath)(config.app.webDirAbs))}) must contain an ${colors_1.default.strong('index.html')} file.\n` +
`It will be the entry point for the web portion of the Capacitor app.`);
}
return null;
}
exports.checkWebDir = checkWebDir;
async function checkPackage() {
if (!(await (0, utils_fs_1.pathExists)('package.json'))) {
if (await (0, utils_fs_1.pathExists)('project.json')) {
return null;
}
else {
return (`The Capacitor CLI needs to run at the root of an npm package or in a valid NX monorepo.\n` +
`Make sure you have a package.json or project.json file in the directory where you run the Capacitor CLI.\n` +
`More info: ${colors_1.default.strong('https://docs.npmjs.com/cli/init')}`);
}
}
return null;
}
exports.checkPackage = checkPackage;
async function checkCapacitorPlatform(config, platform) {
const pkg = await getCapacitorPackage(config, platform);
if (!pkg) {
return (`Could not find the ${colors_1.default.input(platform)} platform.\n` +
`You must install it in your project first, e.g. w/ ${colors_1.default.input(`npm install @capacitor/${platform}`)}`);
}
return null;
}
exports.checkCapacitorPlatform = checkCapacitorPlatform;
async function checkAppConfig(config) {
if (!config.app.appId) {
return (`Missing ${colors_1.default.input('appId')} for new platform.\n` +
`Please add it in ${config.app.extConfigName} or run ${colors_1.default.input('npx cap init')}.`);
}
if (!config.app.appName) {
return (`Missing ${colors_1.default.input('appName')} for new platform.\n` +
`Please add it in ${config.app.extConfigName} or run ${colors_1.default.input('npx cap init')}.`);
}
const appIdError = await checkAppId(config, config.app.appId);
if (appIdError) {
return appIdError;
}
const appNameError = await checkAppName(config, config.app.appName);
if (appNameError) {
return appNameError;
}
return null;
}
exports.checkAppConfig = checkAppConfig;
async function checkAppDir(config, dir) {
if (!/^\S*$/.test(dir)) {
return `Your app directory should not contain spaces`;
}
return null;
}
exports.checkAppDir = checkAppDir;
async function checkAppId(config, id) {
if (!id) {
return `Invalid App ID. Must be in Java package form with no dashes (ex: com.example.app)`;
}
if (/^[a-z][a-z0-9_]*(\.[a-z0-9_]+)+$/.test(id.toLowerCase())) {
return null;
}
return `Invalid App ID "${id}". Must be in Java package form with no dashes (ex: com.example.app)`;
}
exports.checkAppId = checkAppId;
async function checkAppName(config, name) {
// We allow pretty much anything right now, have fun
if (!(name === null || name === void 0 ? void 0 : name.length)) {
return `Must provide an app name. For example: 'Spacebook'`;
}
return null;
}
exports.checkAppName = checkAppName;
async function wait(time) {
return new Promise(resolve => setTimeout(resolve, time));
}
exports.wait = wait;
async function runHooks(config, platformName, dir, hook) {
await runPlatformHook(config, platformName, dir, hook);
const allPlugins = await (0, plugin_1.getPlugins)(config, platformName);
allPlugins.forEach(async (p) => {
await runPlatformHook(config, platformName, p.rootPath, hook);
});
}
exports.runHooks = runHooks;
async function runPlatformHook(config, platformName, platformDir, hook) {
var _a;
const { spawn } = await Promise.resolve().then(() => tslib_1.__importStar(require('child_process')));
let pkg;
if ((0, monorepotools_1.isNXMonorepo)(platformDir)) {
pkg = await (0, utils_fs_1.readJSON)((0, path_1.join)((0, monorepotools_1.findNXMonorepoRoot)(platformDir), 'package.json'));
}
else {
pkg = await (0, utils_fs_1.readJSON)((0, path_1.join)(platformDir, 'package.json'));
}
const cmd = (_a = pkg.scripts) === null || _a === void 0 ? void 0 : _a[hook];
if (!cmd) {
return;
}
return new Promise((resolve, reject) => {
const p = spawn(cmd, {
stdio: 'inherit',
shell: true,
cwd: platformDir,
env: {
INIT_CWD: platformDir,
CAPACITOR_ROOT_DIR: config.app.rootDir,
CAPACITOR_WEB_DIR: config.app.webDirAbs,
CAPACITOR_CONFIG: JSON.stringify(config.app.extConfig),
CAPACITOR_PLATFORM_NAME: platformName,
...process.env,
},
});
p.on('close', () => {
resolve();
});
p.on('error', err => {
reject(err);
});
});
}
exports.runPlatformHook = runPlatformHook;
async function runTask(title, fn) {
const chain = log_1.output.createTaskChain();
chain.next(title);
try {
const value = await fn();
chain.end();
return value;
}
catch (e) {
chain.fail();
throw e;
}
}
exports.runTask = runTask;
async function getCapacitorPackage(config, name) {
const packagePath = (0, node_1.resolveNode)(config.app.rootDir, `@capacitor/${name}`, 'package.json');
if (!packagePath) {
return null;
}
return (0, utils_fs_1.readJSON)(packagePath);
}
exports.getCapacitorPackage = getCapacitorPackage;
async function requireCapacitorPackage(config, name) {
const pkg = await getCapacitorPackage(config, name);
if (!pkg) {
(0, errors_1.fatal)(`Unable to find node_modules/@capacitor/${name}.\n` +
`Are you sure ${colors_1.default.strong(`@capacitor/${name}`)} is installed?`);
}
return pkg;
}
exports.requireCapacitorPackage = requireCapacitorPackage;
async function getCapacitorPackageVersion(config, platform) {
return (await requireCapacitorPackage(config, platform)).version;
}
exports.getCapacitorPackageVersion = getCapacitorPackageVersion;
async function getCoreVersion(config) {
return getCapacitorPackageVersion(config, 'core');
}
exports.getCoreVersion = getCoreVersion;
async function getCLIVersion(config) {
return getCapacitorPackageVersion(config, 'cli');
}
exports.getCLIVersion = getCLIVersion;
function getPlatformDirectory(config, platform) {
switch (platform) {
case 'android':
return config.android.platformDirAbs;
case 'ios':
return config.ios.platformDirAbs;
case 'web':
return config.web.platformDirAbs;
}
return null;
}
async function getProjectPlatformDirectory(config, platform) {
const platformPath = getPlatformDirectory(config, platform);
if (platformPath && (await (0, utils_fs_1.pathExists)(platformPath))) {
return platformPath;
}
return null;
}
exports.getProjectPlatformDirectory = getProjectPlatformDirectory;
async function selectPlatforms(config, selectedPlatformName) {
if (selectedPlatformName) {
// already passed in a platform name
const platformName = selectedPlatformName.toLowerCase().trim();
if (!(await isValidPlatform(platformName))) {
(0, errors_1.fatal)(`Invalid platform: ${colors_1.default.input(platformName)}`);
}
else if (!(await getProjectPlatformDirectory(config, platformName))) {
if (platformName === 'web') {
(0, errors_1.fatal)(`Could not find the web platform directory.\n` +
`Make sure ${colors_1.default.strong(config.app.webDir)} exists.`);
}
(0, errors_1.fatal)(`${colors_1.default.strong(platformName)} platform has not been added yet.\n` +
`See the docs for adding the ${colors_1.default.strong(platformName)} platform: ${colors_1.default.strong(`https://capacitorjs.com/docs/${platformName}#adding-the-${platformName}-platform`)}`);
}
// return the platform in an string array
return [platformName];
}
// wasn't given a platform name, so let's
// get the platforms that have already been created
return getAddedPlatforms(config);
}
exports.selectPlatforms = selectPlatforms;
async function getKnownPlatforms() {
return ['web', 'android', 'ios'];
}
exports.getKnownPlatforms = getKnownPlatforms;
async function isValidPlatform(platform) {
return (await getKnownPlatforms()).includes(platform);
}
exports.isValidPlatform = isValidPlatform;
async function getKnownCommunityPlatforms() {
return ['electron'];
}
exports.getKnownCommunityPlatforms = getKnownCommunityPlatforms;
async function isValidCommunityPlatform(platform) {
return (await getKnownCommunityPlatforms()).includes(platform);
}
exports.isValidCommunityPlatform = isValidCommunityPlatform;
async function getKnownEnterprisePlatforms() {
return ['windows'];
}
exports.getKnownEnterprisePlatforms = getKnownEnterprisePlatforms;
async function isValidEnterprisePlatform(platform) {
return (await getKnownEnterprisePlatforms()).includes(platform);
}
exports.isValidEnterprisePlatform = isValidEnterprisePlatform;
async function promptForPlatform(platforms, promptMessage, selectedPlatformName) {
const { prompt } = await Promise.resolve().then(() => tslib_1.__importStar(require('prompts')));
if (!selectedPlatformName) {
const answers = await prompt([
{
type: 'select',
name: 'mode',
message: promptMessage,
choices: platforms.map(p => ({ title: p, value: p })),
},
], { onCancel: () => process.exit(1) });
return answers.mode.toLowerCase().trim();
}
const platformName = selectedPlatformName.toLowerCase().trim();
if (!(await isValidPlatform(platformName))) {
const knownPlatforms = await getKnownPlatforms();
(0, errors_1.fatal)(`Invalid platform: ${colors_1.default.input(platformName)}.\n` +
`Valid platforms include: ${knownPlatforms.join(', ')}`);
}
return platformName;
}
exports.promptForPlatform = promptForPlatform;
async function promptForPlatformTarget(targets, selectedTarget) {
const { prompt } = await Promise.resolve().then(() => tslib_1.__importStar(require('prompts')));
const validTargets = targets.filter(t => t.id !== undefined);
if (!selectedTarget) {
if (validTargets.length === 1) {
return validTargets[0];
}
else {
const answers = await prompt([
{
type: 'select',
name: 'target',
message: 'Please choose a target device:',
choices: validTargets.map(t => ({
title: `${getPlatformTargetName(t)} (${t.id})`,
value: t,
})),
},
], { onCancel: () => process.exit(1) });
return answers.target;
}
}
const targetID = selectedTarget.trim();
const target = targets.find(t => t.id === targetID);
if (!target) {
(0, errors_1.fatal)(`Invalid target ID: ${colors_1.default.input(targetID)}.\n` +
`Valid targets are: ${targets.map(t => t.id).join(', ')}`);
}
return target;
}
exports.promptForPlatformTarget = promptForPlatformTarget;
function getPlatformTargetName(target) {
var _a, _b, _c;
return `${(_c = (_b = (_a = target.name) !== null && _a !== void 0 ? _a : target.model) !== null && _b !== void 0 ? _b : target.id) !== null && _c !== void 0 ? _c : '?'}${target.virtual
? ` (${target.platform === 'ios' ? 'simulator' : 'emulator'})`
: ''}`;
}
exports.getPlatformTargetName = getPlatformTargetName;
async function getAddedPlatforms(config) {
const platforms = [];
if (await getProjectPlatformDirectory(config, config.android.name)) {
platforms.push(config.android.name);
}
if (await getProjectPlatformDirectory(config, config.ios.name)) {
platforms.push(config.ios.name);
}
platforms.push(config.web.name);
return platforms;
}
exports.getAddedPlatforms = getAddedPlatforms;
async function checkPlatformVersions(config, platform) {
const semver = await Promise.resolve().then(() => tslib_1.__importStar(require('semver')));
const coreVersion = await getCoreVersion(config);
const platformVersion = await getCapacitorPackageVersion(config, platform);
if (semver.diff(coreVersion, platformVersion) === 'minor' ||
semver.diff(coreVersion, platformVersion) === 'major') {
log_1.logger.warn(`${colors_1.default.strong('@capacitor/core')}${colors_1.default.weak(`@${coreVersion}`)} version doesn't match ${colors_1.default.strong(`@capacitor/${platform}`)}${colors_1.default.weak(`@${platformVersion}`)} version.\n` +
`Consider updating to a matching version, e.g. w/ ${colors_1.default.input(`npm install @capacitor/core@${platformVersion}`)}`);
}
}
exports.checkPlatformVersions = checkPlatformVersions;
function resolvePlatform(config, platform) {
if (platform[0] !== '@') {
const core = (0, node_1.resolveNode)(config.app.rootDir, `@capacitor/${platform}`, 'package.json');
if (core) {
return (0, path_1.dirname)(core);
}
const community = (0, node_1.resolveNode)(config.app.rootDir, `@capacitor-community/${platform}`, 'package.json');
if (community) {
return (0, path_1.dirname)(community);
}
const enterprise = (0, node_1.resolveNode)(config.app.rootDir, `@ionic-enterprise/capacitor-${platform}`, 'package.json');
if (enterprise) {
return (0, path_1.dirname)(enterprise);
}
}
// third-party
const thirdParty = (0, node_1.resolveNode)(config.app.rootDir, platform, 'package.json');
if (thirdParty) {
return (0, path_1.dirname)(thirdParty);
}
return null;
}
exports.resolvePlatform = resolvePlatform;
async function checkJDKMajorVersion() {
try {
const string = await (0, subprocess_1.runCommand)('java', ['--version']);
const versionRegex = RegExp(/([0-9]+)\.?([0-9]*)\.?([0-9]*)/);
const versionMatch = versionRegex.exec(string);
if (versionMatch === null) {
return -1;
}
const firstVersionNumber = parseInt(versionMatch[1]);
const secondVersionNumber = parseInt(versionMatch[2]);
if (typeof firstVersionNumber === 'number' && firstVersionNumber != 1) {
return firstVersionNumber;
}
else if (typeof secondVersionNumber === 'number' &&
firstVersionNumber == 1 &&
secondVersionNumber < 9) {
return secondVersionNumber;
}
else {
return -1;
}
}
catch (e) {
return -1;
}
}
exports.checkJDKMajorVersion = checkJDKMajorVersion;
function parseApkNameFromFlavor(flavor) {
const convertedName = flavor.replace(/([A-Z])/g, '$1').toLowerCase();
return `app-${convertedName ? `${convertedName}-` : ''}debug.apk`;
}
exports.parseApkNameFromFlavor = parseApkNameFromFlavor;

398
@capacitor/cli/dist/config.js vendored Normal file
View file

@ -0,0 +1,398 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkExternalConfig = exports.writeConfig = exports.loadConfig = exports.CONFIG_FILE_NAME_JSON = exports.CONFIG_FILE_NAME_JS = exports.CONFIG_FILE_NAME_TS = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const debug_1 = tslib_1.__importDefault(require("debug"));
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("./colors"));
const common_1 = require("./common");
const errors_1 = require("./errors");
const log_1 = require("./log");
const fn_1 = require("./util/fn");
const js_1 = require("./util/js");
const monorepotools_1 = require("./util/monorepotools");
const node_1 = require("./util/node");
const promise_1 = require("./util/promise");
const subprocess_1 = require("./util/subprocess");
const debug = (0, debug_1.default)('capacitor:config');
exports.CONFIG_FILE_NAME_TS = 'capacitor.config.ts';
exports.CONFIG_FILE_NAME_JS = 'capacitor.config.js';
exports.CONFIG_FILE_NAME_JSON = 'capacitor.config.json';
async function loadConfig() {
var _a, _b, _c, _d;
const appRootDir = process.cwd();
const cliRootDir = (0, path_1.dirname)(__dirname);
const conf = await loadExtConfig(appRootDir);
const depsForNx = await (async () => {
var _a, _b;
if ((0, monorepotools_1.isNXMonorepo)(appRootDir)) {
const rootOfNXMonorepo = (0, monorepotools_1.findNXMonorepoRoot)(appRootDir);
const pkgJSONOfMonorepoRoot = await (0, fn_1.tryFn)(utils_fs_1.readJSON, (0, path_1.resolve)(rootOfNXMonorepo, 'package.json'));
const devDependencies = (_a = pkgJSONOfMonorepoRoot === null || pkgJSONOfMonorepoRoot === void 0 ? void 0 : pkgJSONOfMonorepoRoot.devDependencies) !== null && _a !== void 0 ? _a : {};
const dependencies = (_b = pkgJSONOfMonorepoRoot === null || pkgJSONOfMonorepoRoot === void 0 ? void 0 : pkgJSONOfMonorepoRoot.dependencies) !== null && _b !== void 0 ? _b : {};
return {
devDependencies,
dependencies,
};
}
return {};
})();
const appId = (_a = conf.extConfig.appId) !== null && _a !== void 0 ? _a : '';
const appName = (_b = conf.extConfig.appName) !== null && _b !== void 0 ? _b : '';
const webDir = (_c = conf.extConfig.webDir) !== null && _c !== void 0 ? _c : 'www';
const cli = await loadCLIConfig(cliRootDir);
const config = {
android: await loadAndroidConfig(appRootDir, conf.extConfig, cli),
ios: await loadIOSConfig(appRootDir, conf.extConfig),
web: await loadWebConfig(appRootDir, webDir),
cli,
app: {
rootDir: appRootDir,
appId,
appName,
webDir,
webDirAbs: (0, path_1.resolve)(appRootDir, webDir),
package: (_d = (await (0, fn_1.tryFn)(utils_fs_1.readJSON, (0, path_1.resolve)(appRootDir, 'package.json')))) !== null && _d !== void 0 ? _d : {
name: appName,
version: '1.0.0',
...depsForNx,
},
...conf,
},
};
debug('config: %O', config);
return config;
}
exports.loadConfig = loadConfig;
async function writeConfig(extConfig, extConfigFilePath) {
switch ((0, path_1.extname)(extConfigFilePath)) {
case '.json': {
await (0, utils_fs_1.writeJSON)(extConfigFilePath, extConfig, { spaces: 2 });
break;
}
case '.ts': {
await (0, utils_fs_1.writeFile)(extConfigFilePath, formatConfigTS(extConfig));
break;
}
}
}
exports.writeConfig = writeConfig;
async function loadExtConfigTS(rootDir, extConfigName, extConfigFilePath) {
var _a;
try {
const tsPath = (0, node_1.resolveNode)(rootDir, 'typescript');
if (!tsPath) {
(0, errors_1.fatal)('Could not find installation of TypeScript.\n' +
`To use ${colors_1.default.strong(extConfigName)} files, you must install TypeScript in your project, e.g. w/ ${colors_1.default.input('npm install -D typescript')}`);
}
const ts = require(tsPath); // eslint-disable-line @typescript-eslint/no-var-requires
const extConfigObject = (0, node_1.requireTS)(ts, extConfigFilePath);
const extConfig = extConfigObject.default
? await extConfigObject.default
: extConfigObject;
return {
extConfigType: 'ts',
extConfigName,
extConfigFilePath: extConfigFilePath,
extConfig,
};
}
catch (e) {
if (!(0, errors_1.isFatal)(e)) {
(0, errors_1.fatal)(`Parsing ${colors_1.default.strong(extConfigName)} failed.\n\n${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`);
}
throw e;
}
}
async function loadExtConfigJS(rootDir, extConfigName, extConfigFilePath) {
var _a;
try {
return {
extConfigType: 'js',
extConfigName,
extConfigFilePath: extConfigFilePath,
extConfig: await require(extConfigFilePath),
};
}
catch (e) {
(0, errors_1.fatal)(`Parsing ${colors_1.default.strong(extConfigName)} failed.\n\n${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`);
}
}
async function loadExtConfig(rootDir) {
var _a;
const extConfigFilePathTS = (0, path_1.resolve)(rootDir, exports.CONFIG_FILE_NAME_TS);
if (await (0, utils_fs_1.pathExists)(extConfigFilePathTS)) {
return loadExtConfigTS(rootDir, exports.CONFIG_FILE_NAME_TS, extConfigFilePathTS);
}
const extConfigFilePathJS = (0, path_1.resolve)(rootDir, exports.CONFIG_FILE_NAME_JS);
if (await (0, utils_fs_1.pathExists)(extConfigFilePathJS)) {
return loadExtConfigJS(rootDir, exports.CONFIG_FILE_NAME_JS, extConfigFilePathJS);
}
const extConfigFilePath = (0, path_1.resolve)(rootDir, exports.CONFIG_FILE_NAME_JSON);
return {
extConfigType: 'json',
extConfigName: exports.CONFIG_FILE_NAME_JSON,
extConfigFilePath: extConfigFilePath,
extConfig: (_a = (await (0, fn_1.tryFn)(utils_fs_1.readJSON, extConfigFilePath))) !== null && _a !== void 0 ? _a : {},
};
}
async function loadCLIConfig(rootDir) {
const assetsDir = 'assets';
const assetsDirAbs = (0, path_1.join)(rootDir, assetsDir);
const iosPlatformTemplateArchive = 'ios-pods-template.tar.gz';
const iosCordovaPluginsTemplateArchive = 'capacitor-cordova-ios-plugins.tar.gz';
const androidPlatformTemplateArchive = 'android-template.tar.gz';
const androidCordovaPluginsTemplateArchive = 'capacitor-cordova-android-plugins.tar.gz';
return {
rootDir,
assetsDir,
assetsDirAbs,
assets: {
ios: {
platformTemplateArchive: iosPlatformTemplateArchive,
platformTemplateArchiveAbs: (0, path_1.resolve)(assetsDirAbs, iosPlatformTemplateArchive),
cordovaPluginsTemplateArchive: iosCordovaPluginsTemplateArchive,
cordovaPluginsTemplateArchiveAbs: (0, path_1.resolve)(assetsDirAbs, iosCordovaPluginsTemplateArchive),
},
android: {
platformTemplateArchive: androidPlatformTemplateArchive,
platformTemplateArchiveAbs: (0, path_1.resolve)(assetsDirAbs, androidPlatformTemplateArchive),
cordovaPluginsTemplateArchive: androidCordovaPluginsTemplateArchive,
cordovaPluginsTemplateArchiveAbs: (0, path_1.resolve)(assetsDirAbs, androidCordovaPluginsTemplateArchive),
},
},
package: await (0, utils_fs_1.readJSON)((0, path_1.resolve)(rootDir, 'package.json')),
os: determineOS(process.platform),
};
}
async function loadAndroidConfig(rootDir, extConfig, cliConfig) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
const name = 'android';
const platformDir = (_b = (_a = extConfig.android) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : 'android';
const platformDirAbs = (0, path_1.resolve)(rootDir, platformDir);
const appDir = 'app';
const srcDir = `${appDir}/src`;
const srcMainDir = `${srcDir}/main`;
const assetsDir = `${srcMainDir}/assets`;
const webDir = `${assetsDir}/public`;
const resDir = `${srcMainDir}/res`;
let apkPath = `${appDir}/build/outputs/apk/`;
const flavor = ((_c = extConfig.android) === null || _c === void 0 ? void 0 : _c.flavor) || '';
if ((_d = extConfig.android) === null || _d === void 0 ? void 0 : _d.flavor) {
apkPath = `${apkPath}/${(_e = extConfig.android) === null || _e === void 0 ? void 0 : _e.flavor}`;
}
const apkName = (0, common_1.parseApkNameFromFlavor)(flavor);
const buildOutputDir = `${apkPath}/debug`;
const cordovaPluginsDir = 'capacitor-cordova-android-plugins';
const studioPath = (0, promise_1.lazy)(() => determineAndroidStudioPath(cliConfig.os));
const buildOptions = {
keystorePath: (_g = (_f = extConfig.android) === null || _f === void 0 ? void 0 : _f.buildOptions) === null || _g === void 0 ? void 0 : _g.keystorePath,
keystorePassword: (_j = (_h = extConfig.android) === null || _h === void 0 ? void 0 : _h.buildOptions) === null || _j === void 0 ? void 0 : _j.keystorePassword,
keystoreAlias: (_l = (_k = extConfig.android) === null || _k === void 0 ? void 0 : _k.buildOptions) === null || _l === void 0 ? void 0 : _l.keystoreAlias,
keystoreAliasPassword: (_o = (_m = extConfig.android) === null || _m === void 0 ? void 0 : _m.buildOptions) === null || _o === void 0 ? void 0 : _o.keystoreAliasPassword,
signingType: (_q = (_p = extConfig.android) === null || _p === void 0 ? void 0 : _p.buildOptions) === null || _q === void 0 ? void 0 : _q.signingType,
releaseType: (_s = (_r = extConfig.android) === null || _r === void 0 ? void 0 : _r.buildOptions) === null || _s === void 0 ? void 0 : _s.releaseType,
};
return {
name,
minVersion: '22',
studioPath,
platformDir,
platformDirAbs,
cordovaPluginsDir,
cordovaPluginsDirAbs: (0, path_1.resolve)(platformDirAbs, cordovaPluginsDir),
appDir,
appDirAbs: (0, path_1.resolve)(platformDirAbs, appDir),
srcDir,
srcDirAbs: (0, path_1.resolve)(platformDirAbs, srcDir),
srcMainDir,
srcMainDirAbs: (0, path_1.resolve)(platformDirAbs, srcMainDir),
assetsDir,
assetsDirAbs: (0, path_1.resolve)(platformDirAbs, assetsDir),
webDir,
webDirAbs: (0, path_1.resolve)(platformDirAbs, webDir),
resDir,
resDirAbs: (0, path_1.resolve)(platformDirAbs, resDir),
apkName,
buildOutputDir,
buildOutputDirAbs: (0, path_1.resolve)(platformDirAbs, buildOutputDir),
flavor,
buildOptions,
};
}
async function loadIOSConfig(rootDir, extConfig) {
var _a, _b, _c, _d;
const name = 'ios';
const platformDir = (_b = (_a = extConfig.ios) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : 'ios';
const platformDirAbs = (0, path_1.resolve)(rootDir, platformDir);
const scheme = (_d = (_c = extConfig.ios) === null || _c === void 0 ? void 0 : _c.scheme) !== null && _d !== void 0 ? _d : 'App';
const nativeProjectDir = 'App';
const nativeProjectDirAbs = (0, path_1.resolve)(platformDirAbs, nativeProjectDir);
const nativeTargetDir = `${nativeProjectDir}/App`;
const nativeTargetDirAbs = (0, path_1.resolve)(platformDirAbs, nativeTargetDir);
const nativeXcodeProjDir = `${nativeProjectDir}/App.xcodeproj`;
const nativeXcodeProjDirAbs = (0, path_1.resolve)(platformDirAbs, nativeXcodeProjDir);
const nativeXcodeWorkspaceDirAbs = (0, promise_1.lazy)(() => determineXcodeWorkspaceDirAbs(nativeProjectDirAbs));
const podPath = (0, promise_1.lazy)(() => determineGemfileOrCocoapodPath(rootDir, platformDirAbs, nativeProjectDirAbs));
const webDirAbs = (0, promise_1.lazy)(() => determineIOSWebDirAbs(nativeProjectDirAbs, nativeTargetDirAbs, nativeXcodeProjDirAbs));
const cordovaPluginsDir = 'capacitor-cordova-ios-plugins';
return {
name,
minVersion: '13.0',
platformDir,
platformDirAbs,
scheme,
cordovaPluginsDir,
cordovaPluginsDirAbs: (0, path_1.resolve)(platformDirAbs, cordovaPluginsDir),
nativeProjectDir,
nativeProjectDirAbs,
nativeTargetDir,
nativeTargetDirAbs,
nativeXcodeProjDir,
nativeXcodeProjDirAbs,
nativeXcodeWorkspaceDir: (0, promise_1.lazy)(async () => (0, path_1.relative)(platformDirAbs, await nativeXcodeWorkspaceDirAbs)),
nativeXcodeWorkspaceDirAbs,
webDir: (0, promise_1.lazy)(async () => (0, path_1.relative)(platformDirAbs, await webDirAbs)),
webDirAbs,
podPath,
};
}
async function loadWebConfig(rootDir, webDir) {
const platformDir = webDir;
const platformDirAbs = (0, path_1.resolve)(rootDir, platformDir);
return {
name: 'web',
platformDir,
platformDirAbs,
};
}
function determineOS(os) {
switch (os) {
case 'darwin':
return "mac" /* OS.Mac */;
case 'win32':
return "windows" /* OS.Windows */;
case 'linux':
return "linux" /* OS.Linux */;
}
return "unknown" /* OS.Unknown */;
}
async function determineXcodeWorkspaceDirAbs(nativeProjectDirAbs) {
return (0, path_1.resolve)(nativeProjectDirAbs, 'App.xcworkspace');
}
async function determineIOSWebDirAbs(nativeProjectDirAbs, nativeTargetDirAbs, nativeXcodeProjDirAbs) {
const re = /path\s=\spublic[\s\S]+?sourceTree\s=\s([^;]+)/;
const pbxprojPath = (0, path_1.resolve)(nativeXcodeProjDirAbs, 'project.pbxproj');
try {
const pbxproj = await (0, utils_fs_1.readFile)(pbxprojPath, { encoding: 'utf8' });
const m = pbxproj.match(re);
if (m && m[1] === 'SOURCE_ROOT') {
log_1.logger.warn(`Using the iOS project root for the ${colors_1.default.strong('public')} directory is deprecated.\n` +
`Please follow the Upgrade Guide to move ${colors_1.default.strong('public')} inside the iOS target directory: ${colors_1.default.strong('https://capacitorjs.com/docs/updating/3-0#move-public-into-the-ios-target-directory')}`);
return (0, path_1.resolve)(nativeProjectDirAbs, 'public');
}
}
catch (e) {
// ignore
}
return (0, path_1.resolve)(nativeTargetDirAbs, 'public');
}
async function determineAndroidStudioPath(os) {
if (process.env.CAPACITOR_ANDROID_STUDIO_PATH) {
return process.env.CAPACITOR_ANDROID_STUDIO_PATH;
}
switch (os) {
case "mac" /* OS.Mac */:
return '/Applications/Android Studio.app';
case "windows" /* OS.Windows */: {
const { runCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./util/subprocess')));
let p = 'C:\\Program Files\\Android\\Android Studio\\bin\\studio64.exe';
try {
if (!(await (0, utils_fs_1.pathExists)(p))) {
let commandResult = await runCommand('REG', [
'QUERY',
'HKEY_LOCAL_MACHINE\\SOFTWARE\\Android Studio',
'/v',
'Path',
]);
commandResult = commandResult.replace(/(\r\n|\n|\r)/gm, '');
const i = commandResult.indexOf('REG_SZ');
if (i > 0) {
p = commandResult.substring(i + 6).trim() + '\\bin\\studio64.exe';
}
}
}
catch (e) {
debug(`Error checking registry for Android Studio path: %O`, e);
break;
}
return p;
}
case "linux" /* OS.Linux */:
return '/usr/local/android-studio/bin/studio.sh';
}
return '';
}
async function determineGemfileOrCocoapodPath(rootDir, platformDir, nativeProjectDirAbs) {
if (process.env.CAPACITOR_COCOAPODS_PATH) {
return process.env.CAPACITOR_COCOAPODS_PATH;
}
let gemfilePath = '';
if (await (0, utils_fs_1.pathExists)((0, path_1.resolve)(rootDir, 'Gemfile'))) {
gemfilePath = (0, path_1.resolve)(rootDir, 'Gemfile');
}
else if (await (0, utils_fs_1.pathExists)((0, path_1.resolve)(platformDir, 'Gemfile'))) {
gemfilePath = (0, path_1.resolve)(platformDir, 'Gemfile');
}
else if (await (0, utils_fs_1.pathExists)((0, path_1.resolve)(nativeProjectDirAbs, 'Gemfile'))) {
gemfilePath = (0, path_1.resolve)(nativeProjectDirAbs, 'Gemfile');
}
const appSpecificGemfileExists = gemfilePath != '';
// Multi-app projects might share a single global 'Gemfile' at the Git repository root directory.
if (!appSpecificGemfileExists) {
try {
const output = await (0, subprocess_1.getCommandOutput)('git', ['rev-parse', '--show-toplevel'], { cwd: rootDir });
if (output != null) {
gemfilePath = (0, path_1.resolve)(output, 'Gemfile');
}
}
catch (e) {
// Nothing
}
}
try {
const gemfileText = (await (0, utils_fs_1.readFile)(gemfilePath)).toString();
if (!gemfileText) {
return 'pod';
}
const cocoapodsInGemfile = new RegExp(/gem\s+['"]cocoapods/).test(gemfileText);
if (cocoapodsInGemfile) {
return 'bundle exec pod';
}
else {
return 'pod';
}
}
catch {
return 'pod';
}
}
function formatConfigTS(extConfig) {
// TODO: <reference> tags
return `import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = ${(0, js_1.formatJSObject)(extConfig)};
export default config;\n`;
}
function checkExternalConfig(config) {
if (typeof config.extConfig.bundledWebRuntime !== 'undefined') {
let actionMessage = `Can be safely deleted.`;
if (config.extConfig.bundledWebRuntime === true) {
actionMessage = `Please, use a bundler to bundle Capacitor and its plugins.`;
}
log_1.logger.warn(`The ${colors_1.default.strong('bundledWebRuntime')} configuration option has been deprecated. ${actionMessage}`);
}
}
exports.checkExternalConfig = checkExternalConfig;

830
@capacitor/cli/dist/cordova.js vendored Normal file
View file

@ -0,0 +1,830 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.writeCordovaAndroidManifest = exports.getCordovaPreferences = exports.needsStaticPod = exports.getIncompatibleCordovaPlugins = exports.checkPluginDependencies = exports.logCordovaManualSteps = exports.getCordovaPlugins = exports.handleCordovaPluginsJS = exports.autoGenerateConfig = exports.removePluginFiles = exports.createEmptyCordovaJS = exports.copyCordovaJS = exports.copyPluginsJS = exports.generateCordovaPluginsJSFile = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const path_1 = require("path");
const plist_1 = tslib_1.__importDefault(require("plist"));
const prompts_1 = tslib_1.__importDefault(require("prompts"));
const common_1 = require("./android/common");
const colors_1 = tslib_1.__importDefault(require("./colors"));
const errors_1 = require("./errors");
const common_2 = require("./ios/common");
const log_1 = require("./log");
const plugin_1 = require("./plugin");
const node_1 = require("./util/node");
const term_1 = require("./util/term");
const xml_1 = require("./util/xml");
/**
* Build the root cordova_plugins.js file referencing each Plugin JS file.
*/
function generateCordovaPluginsJSFile(config, plugins, platform) {
const pluginModules = [];
const pluginExports = [];
plugins.map(p => {
const pluginId = p.xml.$.id;
const jsModules = (0, plugin_1.getJSModules)(p, platform);
jsModules.map((jsModule) => {
const clobbers = [];
const merges = [];
let clobbersModule = '';
let mergesModule = '';
let runsModule = '';
let clobberKey = '';
let mergeKey = '';
if (jsModule.clobbers) {
jsModule.clobbers.map((clobber) => {
clobbers.push(clobber.$.target);
clobberKey = clobber.$.target;
});
clobbersModule = `,
"clobbers": [
"${clobbers.join('",\n "')}"
]`;
}
if (jsModule.merges) {
jsModule.merges.map((merge) => {
merges.push(merge.$.target);
mergeKey = merge.$.target;
});
mergesModule = `,
"merges": [
"${merges.join('",\n "')}"
]`;
}
if (jsModule.runs) {
runsModule = ',\n "runs": true';
}
const pluginModule = {
clobber: clobberKey,
merge: mergeKey,
// mimics Cordova's module name logic if the name attr is missing
pluginContent: `{
"id": "${pluginId +
'.' +
(jsModule.$.name || jsModule.$.src.match(/([^/]+)\.js/)[1])}",
"file": "plugins/${pluginId}/${jsModule.$.src}",
"pluginId": "${pluginId}"${clobbersModule}${mergesModule}${runsModule}
}`,
};
pluginModules.push(pluginModule);
});
pluginExports.push(`"${pluginId}": "${p.xml.$.version}"`);
});
return `
cordova.define('cordova/plugin_list', function(require, exports, module) {
module.exports = [
${pluginModules
.sort((a, b) => a.clobber && b.clobber // Clobbers in alpha order
? a.clobber.localeCompare(b.clobber)
: a.clobber || b.clobber // Clobbers before anything else
? b.clobber.localeCompare(a.clobber)
: a.merge.localeCompare(b.merge))
.map(e => e.pluginContent)
.join(',\n ')}
];
module.exports.metadata =
// TOP OF METADATA
{
${pluginExports.join(',\n ')}
};
// BOTTOM OF METADATA
});
`;
}
exports.generateCordovaPluginsJSFile = generateCordovaPluginsJSFile;
/**
* Build the plugins/* files for each Cordova plugin installed.
*/
async function copyPluginsJS(config, cordovaPlugins, platform) {
const webDir = await getWebDir(config, platform);
const pluginsDir = (0, path_1.join)(webDir, 'plugins');
const cordovaPluginsJSFile = (0, path_1.join)(webDir, 'cordova_plugins.js');
await removePluginFiles(config, platform);
await Promise.all(cordovaPlugins.map(async (p) => {
const pluginId = p.xml.$.id;
const pluginDir = (0, path_1.join)(pluginsDir, pluginId, 'www');
await (0, utils_fs_1.ensureDir)(pluginDir);
const jsModules = (0, plugin_1.getJSModules)(p, platform);
await Promise.all(jsModules.map(async (jsModule) => {
const filePath = (0, path_1.join)(webDir, 'plugins', pluginId, jsModule.$.src);
await (0, utils_fs_1.copy)((0, path_1.join)(p.rootPath, jsModule.$.src), filePath);
let data = await (0, utils_fs_1.readFile)(filePath, { encoding: 'utf-8' });
data = data.trim();
// mimics Cordova's module name logic if the name attr is missing
const name = pluginId +
'.' +
(jsModule.$.name ||
(0, path_1.basename)(jsModule.$.src, (0, path_1.extname)(jsModule.$.src)));
data = `cordova.define("${name}", function(require, exports, module) { \n${data}\n});`;
data = data.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script\s*>/gi, '');
await (0, utils_fs_1.writeFile)(filePath, data, { encoding: 'utf-8' });
}));
const assets = (0, plugin_1.getAssets)(p, platform);
await Promise.all(assets.map(async (asset) => {
const filePath = (0, path_1.join)(webDir, asset.$.target);
await (0, utils_fs_1.copy)((0, path_1.join)(p.rootPath, asset.$.src), filePath);
}));
}));
await (0, utils_fs_1.writeFile)(cordovaPluginsJSFile, generateCordovaPluginsJSFile(config, cordovaPlugins, platform));
}
exports.copyPluginsJS = copyPluginsJS;
async function copyCordovaJS(config, platform) {
const cordovaPath = (0, node_1.resolveNode)(config.app.rootDir, '@capacitor/core', 'cordova.js');
if (!cordovaPath) {
(0, errors_1.fatal)(`Unable to find ${colors_1.default.strong('node_modules/@capacitor/core/cordova.js')}.\n` + `Are you sure ${colors_1.default.strong('@capacitor/core')} is installed?`);
}
return (0, utils_fs_1.copy)(cordovaPath, (0, path_1.join)(await getWebDir(config, platform), 'cordova.js'));
}
exports.copyCordovaJS = copyCordovaJS;
async function createEmptyCordovaJS(config, platform) {
const webDir = await getWebDir(config, platform);
await (0, utils_fs_1.writeFile)((0, path_1.join)(webDir, 'cordova.js'), '');
await (0, utils_fs_1.writeFile)((0, path_1.join)(webDir, 'cordova_plugins.js'), '');
}
exports.createEmptyCordovaJS = createEmptyCordovaJS;
async function removePluginFiles(config, platform) {
const webDir = await getWebDir(config, platform);
const pluginsDir = (0, path_1.join)(webDir, 'plugins');
const cordovaPluginsJSFile = (0, path_1.join)(webDir, 'cordova_plugins.js');
await (0, utils_fs_1.remove)(pluginsDir);
await (0, utils_fs_1.remove)(cordovaPluginsJSFile);
}
exports.removePluginFiles = removePluginFiles;
async function autoGenerateConfig(config, cordovaPlugins, platform) {
var _a, _b, _c, _d;
let xmlDir = (0, path_1.join)(config.android.resDirAbs, 'xml');
const fileName = 'config.xml';
if (platform === 'ios') {
xmlDir = config.ios.nativeTargetDirAbs;
}
await (0, utils_fs_1.ensureDir)(xmlDir);
const cordovaConfigXMLFile = (0, path_1.join)(xmlDir, fileName);
await (0, utils_fs_1.remove)(cordovaConfigXMLFile);
const pluginEntries = [];
cordovaPlugins.map(p => {
const currentPlatform = (0, plugin_1.getPluginPlatform)(p, platform);
if (currentPlatform) {
const configFiles = currentPlatform['config-file'];
if (configFiles) {
const configXMLEntries = configFiles.filter(function (item) {
var _a;
return (_a = item.$) === null || _a === void 0 ? void 0 : _a.target.includes(fileName);
});
configXMLEntries.map((entry) => {
if (entry.feature) {
const feature = { feature: entry.feature };
pluginEntries.push(feature);
}
});
}
}
});
let accessOriginString = [];
if ((_b = (_a = config.app.extConfig) === null || _a === void 0 ? void 0 : _a.cordova) === null || _b === void 0 ? void 0 : _b.accessOrigins) {
accessOriginString = await Promise.all(config.app.extConfig.cordova.accessOrigins.map(async (host) => {
return `
<access origin="${host}" />`;
}));
}
else {
accessOriginString.push(`<access origin="*" />`);
}
const pluginEntriesString = await Promise.all(pluginEntries.map(async (item) => {
const xmlString = await (0, xml_1.writeXML)(item);
return xmlString;
}));
let pluginPreferencesString = [];
if ((_d = (_c = config.app.extConfig) === null || _c === void 0 ? void 0 : _c.cordova) === null || _d === void 0 ? void 0 : _d.preferences) {
pluginPreferencesString = await Promise.all(Object.entries(config.app.extConfig.cordova.preferences).map(async ([key, value]) => {
return `
<preference name="${key}" value="${value}" />`;
}));
}
const content = `<?xml version='1.0' encoding='utf-8'?>
<widget version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
${accessOriginString.join('')}
${pluginEntriesString.join('')}
${pluginPreferencesString.join('')}
</widget>`;
await (0, utils_fs_1.writeFile)(cordovaConfigXMLFile, content);
}
exports.autoGenerateConfig = autoGenerateConfig;
async function getWebDir(config, platform) {
if (platform === 'ios') {
return config.ios.webDirAbs;
}
if (platform === 'android') {
return config.android.webDirAbs;
}
return '';
}
async function handleCordovaPluginsJS(cordovaPlugins, config, platform) {
const webDir = await getWebDir(config, platform);
await (0, utils_fs_1.mkdirp)(webDir);
if (cordovaPlugins.length > 0) {
(0, plugin_1.printPlugins)(cordovaPlugins, platform, 'cordova');
await copyCordovaJS(config, platform);
await copyPluginsJS(config, cordovaPlugins, platform);
}
else {
await removePluginFiles(config, platform);
await createEmptyCordovaJS(config, platform);
}
await autoGenerateConfig(config, cordovaPlugins, platform);
}
exports.handleCordovaPluginsJS = handleCordovaPluginsJS;
async function getCordovaPlugins(config, platform) {
const allPlugins = await (0, plugin_1.getPlugins)(config, platform);
let plugins = [];
if (platform === config.ios.name) {
plugins = await (0, common_2.getIOSPlugins)(allPlugins);
}
else if (platform === config.android.name) {
plugins = await (0, common_1.getAndroidPlugins)(allPlugins);
}
return plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
}
exports.getCordovaPlugins = getCordovaPlugins;
async function logCordovaManualSteps(cordovaPlugins, config, platform) {
cordovaPlugins.map(p => {
const editConfig = (0, plugin_1.getPlatformElement)(p, platform, 'edit-config');
const configFile = (0, plugin_1.getPlatformElement)(p, platform, 'config-file');
editConfig.concat(configFile).map(async (configElement) => {
if (configElement.$ && !configElement.$.target.includes('config.xml')) {
if (platform === config.ios.name) {
if (configElement.$.target.includes('Info.plist')) {
logiOSPlist(configElement, config, p);
}
}
}
});
});
}
exports.logCordovaManualSteps = logCordovaManualSteps;
async function logiOSPlist(configElement, config, plugin) {
var _a, _b;
let plistPath = (0, path_1.resolve)(config.ios.nativeTargetDirAbs, 'Info.plist');
if ((_a = config.app.extConfig.ios) === null || _a === void 0 ? void 0 : _a.scheme) {
plistPath = (0, path_1.resolve)(config.ios.nativeProjectDirAbs, `${(_b = config.app.extConfig.ios) === null || _b === void 0 ? void 0 : _b.scheme}-Info.plist`);
}
if (!(await (0, utils_fs_1.pathExists)(plistPath))) {
plistPath = (0, path_1.resolve)(config.ios.nativeTargetDirAbs, 'Base.lproj', 'Info.plist');
}
if (await (0, utils_fs_1.pathExists)(plistPath)) {
const xmlMeta = await (0, xml_1.readXML)(plistPath);
const data = await (0, utils_fs_1.readFile)(plistPath, { encoding: 'utf-8' });
const trimmedPlistData = data.replace(/(\t|\r|\n)/g, '');
const plistData = plist_1.default.parse(data);
const dict = xmlMeta.plist.dict.pop();
if (!dict.key.includes(configElement.$.parent)) {
let xml = buildConfigFileXml(configElement);
xml = `<key>${configElement.$.parent}</key>${getConfigFileTagContent(xml)}`;
log_1.logger.warn(`Configuration required for ${colors_1.default.strong(plugin.id)}.\n` +
`Add the following to Info.plist:\n` +
xml);
}
else if (configElement.array || configElement.dict) {
if (configElement.array &&
configElement.array.length > 0 &&
configElement.array[0].string) {
let xml = '';
configElement.array[0].string.map((element) => {
const d = plistData[configElement.$.parent];
if (Array.isArray(d) && !d.includes(element)) {
xml = xml.concat(`<string>${element}</string>\n`);
}
});
if (xml.length > 0) {
log_1.logger.warn(`Configuration required for ${colors_1.default.strong(plugin.id)}.\n` +
`Add the following in the existing ${colors_1.default.strong(configElement.$.parent)} array of your Info.plist:\n` +
xml);
}
}
else {
let xml = buildConfigFileXml(configElement);
xml = `<key>${configElement.$.parent}</key>${getConfigFileTagContent(xml)}`;
xml = `<plist version="1.0"><dict>${xml}</dict></plist>`;
const parseXmlToSearchable = (childElementsObj, arrayToAddTo) => {
for (const childElement of childElementsObj) {
const childElementName = childElement['#name'];
const toAdd = { name: childElementName };
if (childElementName === 'key' || childElementName === 'string') {
toAdd.value = childElement['_'];
}
else {
if (childElement['$']) {
toAdd.attrs = { ...childElement['$'] };
}
if (childElement['$$']) {
toAdd.children = [];
parseXmlToSearchable(childElement['$$'], toAdd['children']);
}
}
arrayToAddTo.push(toAdd);
}
};
const existingElements = (0, xml_1.parseXML)(trimmedPlistData, {
explicitChildren: true,
trim: true,
preserveChildrenOrder: true,
});
const parsedExistingElements = [];
const rootKeyOfExistingElements = Object.keys(existingElements)[0];
const rootOfExistingElementsToAdd = { name: rootKeyOfExistingElements, children: [] };
if (existingElements[rootKeyOfExistingElements]['$']) {
rootOfExistingElementsToAdd.attrs = {
...existingElements[rootKeyOfExistingElements]['$'],
};
}
parseXmlToSearchable(existingElements[rootKeyOfExistingElements]['$$'], rootOfExistingElementsToAdd['children']);
parsedExistingElements.push(rootOfExistingElementsToAdd);
const requiredElements = (0, xml_1.parseXML)(xml, {
explicitChildren: true,
trim: true,
preserveChildrenOrder: true,
});
const parsedRequiredElements = [];
const rootKeyOfRequiredElements = Object.keys(requiredElements)[0];
const rootOfRequiredElementsToAdd = { name: rootKeyOfRequiredElements, children: [] };
if (requiredElements[rootKeyOfRequiredElements]['$']) {
rootOfRequiredElementsToAdd.attrs = {
...requiredElements[rootKeyOfRequiredElements]['$'],
};
}
parseXmlToSearchable(requiredElements[rootKeyOfRequiredElements]['$$'], rootOfRequiredElementsToAdd['children']);
parsedRequiredElements.push(rootOfRequiredElementsToAdd);
const doesContainElements = (requiredElementsArray, existingElementsArray) => {
for (const requiredElement of requiredElementsArray) {
if (requiredElement.name === 'key' ||
requiredElement.name === 'string') {
let foundMatch = false;
for (const existingElement of existingElementsArray) {
if (existingElement.name === requiredElement.name &&
(existingElement.value === requiredElement.value ||
/^[$].{1,}$/.test(requiredElement.value.trim()))) {
foundMatch = true;
break;
}
}
if (!foundMatch) {
return false;
}
}
else {
let foundMatch = false;
for (const existingElement of existingElementsArray) {
if (existingElement.name === requiredElement.name) {
if ((requiredElement.children !== undefined) ===
(existingElement.children !== undefined)) {
if (doesContainElements(requiredElement.children, existingElement.children)) {
foundMatch = true;
break;
}
}
}
}
if (!foundMatch) {
return false;
}
}
}
return true;
};
if (!doesContainElements(parsedRequiredElements, parsedExistingElements)) {
logPossibleMissingItem(configElement, plugin);
}
}
}
}
else {
logPossibleMissingItem(configElement, plugin);
}
}
function logPossibleMissingItem(configElement, plugin) {
let xml = buildConfigFileXml(configElement);
xml = getConfigFileTagContent(xml);
xml = removeOuterTags(xml);
log_1.logger.warn(`Configuration might be missing for ${colors_1.default.strong(plugin.id)}.\n` +
`Add the following to the existing ${colors_1.default.strong(configElement.$.parent)} entry of Info.plist:\n` +
xml);
}
function buildConfigFileXml(configElement) {
return (0, xml_1.buildXmlElement)(configElement, 'config-file');
}
function getConfigFileTagContent(str) {
return str.replace(/<config-file.+">|<\/config-file>/g, '');
}
function removeOuterTags(str) {
const start = str.indexOf('>') + 1;
const end = str.lastIndexOf('<');
return str.substring(start, end);
}
async function checkPluginDependencies(plugins, platform) {
const pluginDeps = new Map();
const cordovaPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
const incompatible = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 2 /* PluginType.Incompatible */);
await Promise.all(cordovaPlugins.map(async (p) => {
let allDependencies = [];
allDependencies = allDependencies.concat((0, plugin_1.getPlatformElement)(p, platform, 'dependency'));
if (p.xml['dependency']) {
allDependencies = allDependencies.concat(p.xml['dependency']);
}
allDependencies = allDependencies.filter((dep) => !getIncompatibleCordovaPlugins(platform).includes(dep.$.id) &&
incompatible.filter(p => p.id === dep.$.id || p.xml.$.id === dep.$.id)
.length === 0);
if (allDependencies) {
await Promise.all(allDependencies.map(async (dep) => {
var _a;
let plugin = dep.$.id;
let version = dep.$.version;
if (plugin.includes('@') && plugin.indexOf('@') !== 0) {
[plugin, version] = plugin.split('@');
}
if (cordovaPlugins.filter(p => p.id === plugin || p.xml.$.id === plugin).length === 0) {
if ((_a = dep.$.url) === null || _a === void 0 ? void 0 : _a.startsWith('http')) {
plugin = dep.$.url;
version = dep.$.commit;
}
const deps = pluginDeps.get(p.id) || [];
deps.push(`${plugin}${version ? colors_1.default.weak(` (${version})`) : ''}`);
pluginDeps.set(p.id, deps);
}
}));
}
}));
if (pluginDeps.size > 0) {
let msg = `${colors_1.default.failure(colors_1.default.strong('Plugins are missing dependencies.'))}\n` +
`Cordova plugin dependencies must be installed in your project (e.g. w/ ${colors_1.default.input('npm install')}).\n`;
for (const [plugin, deps] of pluginDeps.entries()) {
msg +=
`\n ${colors_1.default.strong(plugin)} is missing dependencies:\n` +
deps.map(d => ` - ${d}`).join('\n');
}
log_1.logger.warn(`${msg}\n`);
}
}
exports.checkPluginDependencies = checkPluginDependencies;
function getIncompatibleCordovaPlugins(platform) {
const pluginList = [
'cordova-plugin-splashscreen',
'cordova-plugin-ionic-webview',
'cordova-plugin-crosswalk-webview',
'cordova-plugin-wkwebview-engine',
'cordova-plugin-console',
'cordova-plugin-music-controls',
'cordova-plugin-add-swift-support',
'cordova-plugin-ionic-keyboard',
'cordova-plugin-braintree',
'@ionic-enterprise/filesystem',
'@ionic-enterprise/keyboard',
'@ionic-enterprise/splashscreen',
'cordova-support-google-services',
];
if (platform === 'ios') {
pluginList.push('cordova-plugin-statusbar', '@ionic-enterprise/statusbar', 'SalesforceMobileSDK-CordovaPlugin');
}
if (platform === 'android') {
pluginList.push('cordova-plugin-compat');
}
return pluginList;
}
exports.getIncompatibleCordovaPlugins = getIncompatibleCordovaPlugins;
function needsStaticPod(plugin, config) {
var _a, _b, _c, _d;
let pluginList = [
'phonegap-plugin-push',
'@batch.com/cordova-plugin',
'onesignal-cordova-plugin',
];
if ((_b = (_a = config.app.extConfig) === null || _a === void 0 ? void 0 : _a.cordova) === null || _b === void 0 ? void 0 : _b.staticPlugins) {
log_1.logger.warn('cordova.staticPlugins is deprecated, make sure you are using latest version of the plugin');
pluginList = pluginList.concat((_d = (_c = config.app.extConfig) === null || _c === void 0 ? void 0 : _c.cordova) === null || _d === void 0 ? void 0 : _d.staticPlugins);
}
return pluginList.includes(plugin.id) || useFrameworks(plugin);
}
exports.needsStaticPod = needsStaticPod;
function useFrameworks(plugin) {
const podspecs = (0, plugin_1.getPlatformElement)(plugin, 'ios', 'podspec');
const frameworkPods = podspecs.filter((podspec) => podspec.pods.filter((pods) => pods.$ && pods.$['use-frameworks'] === 'true').length > 0);
return frameworkPods.length > 0;
}
async function getCordovaPreferences(config) {
var _a, _b, _c, _d, _e;
const configXml = (0, path_1.join)(config.app.rootDir, 'config.xml');
let cordova = {};
if (await (0, utils_fs_1.pathExists)(configXml)) {
cordova.preferences = {};
const xmlMeta = await (0, xml_1.readXML)(configXml);
if (xmlMeta.widget.preference) {
xmlMeta.widget.preference.map((pref) => {
cordova.preferences[pref.$.name] = pref.$.value;
});
}
}
if (cordova.preferences && Object.keys(cordova.preferences).length > 0) {
if ((0, term_1.isInteractive)()) {
const answers = await (0, log_1.logPrompt)(`${colors_1.default.strong(`Cordova preferences can be automatically ported to ${colors_1.default.strong(config.app.extConfigName)}.`)}\n` +
`Keep in mind: Not all values can be automatically migrated from ${colors_1.default.strong('config.xml')}. There may be more work to do.\n` +
`More info: ${colors_1.default.strong('https://capacitorjs.com/docs/cordova/migrating-from-cordova-to-capacitor')}`, {
type: 'confirm',
name: 'confirm',
message: `Migrate Cordova preferences from config.xml?`,
initial: true,
});
if (answers.confirm) {
if ((_b = (_a = config.app.extConfig) === null || _a === void 0 ? void 0 : _a.cordova) === null || _b === void 0 ? void 0 : _b.preferences) {
const answers = await (0, prompts_1.default)([
{
type: 'confirm',
name: 'confirm',
message: `${config.app.extConfigName} already contains Cordova preferences. Overwrite?`,
},
], { onCancel: () => process.exit(1) });
if (!answers.confirm) {
cordova = (_c = config.app.extConfig) === null || _c === void 0 ? void 0 : _c.cordova;
}
}
}
else {
cordova = (_d = config.app.extConfig) === null || _d === void 0 ? void 0 : _d.cordova;
}
}
}
else {
cordova = (_e = config.app.extConfig) === null || _e === void 0 ? void 0 : _e.cordova;
}
return cordova;
}
exports.getCordovaPreferences = getCordovaPreferences;
async function writeCordovaAndroidManifest(cordovaPlugins, config, platform, cleartext) {
var _a;
const manifestPath = (0, path_1.join)(config.android.cordovaPluginsDirAbs, 'src', 'main', 'AndroidManifest.xml');
const rootXMLEntries = [];
const applicationXMLEntries = [];
const applicationXMLAttributes = [];
let prefsArray = [];
cordovaPlugins.map(async (p) => {
const editConfig = (0, plugin_1.getPlatformElement)(p, platform, 'edit-config');
const configFile = (0, plugin_1.getPlatformElement)(p, platform, 'config-file');
prefsArray = prefsArray.concat((0, plugin_1.getAllElements)(p, platform, 'preference'));
editConfig.concat(configFile).map(async (configElement) => {
var _a, _b;
if (configElement.$ &&
(((_a = configElement.$.target) === null || _a === void 0 ? void 0 : _a.includes('AndroidManifest.xml')) ||
((_b = configElement.$.file) === null || _b === void 0 ? void 0 : _b.includes('AndroidManifest.xml')))) {
const keys = Object.keys(configElement).filter(k => k !== '$');
keys.map(k => {
configElement[k].map(async (e) => {
const xmlElement = (0, xml_1.buildXmlElement)(e, k);
const pathParts = getPathParts(configElement.$.parent || configElement.$.target);
if (pathParts.length > 1) {
if (pathParts.pop() === 'application') {
if (configElement.$.mode &&
configElement.$.mode === 'merge' &&
xmlElement.startsWith('<application')) {
Object.keys(e.$).map((ek) => {
applicationXMLAttributes.push(`${ek}="${e.$[ek]}"`);
});
}
else if (!applicationXMLEntries.includes(xmlElement) &&
!contains(applicationXMLEntries, xmlElement, k)) {
applicationXMLEntries.push(xmlElement);
}
}
else {
const manifestPathOfCapApp = (0, path_1.join)(config.android.appDirAbs, 'src', 'main', 'AndroidManifest.xml');
const manifestContentTrimmed = (await (0, utils_fs_1.readFile)(manifestPathOfCapApp))
.toString()
.trim()
.replace(/\n|\t|\r/g, '')
.replace(/[\s]{1,}</g, '<')
.replace(/>[\s]{1,}/g, '>')
.replace(/[\s]{2,}/g, ' ');
const requiredManifestContentTrimmed = xmlElement
.trim()
.replace(/\n|\t|\r/g, '')
.replace(/[\s]{1,}</g, '<')
.replace(/>[\s]{1,}/g, '>')
.replace(/[\s]{2,}/g, ' ');
const pathPartList = getPathParts(configElement.$.parent || configElement.$.target);
const doesXmlManifestContainRequiredInfo = (requiredElements, existingElements, pathTarget) => {
const findElementsToSearchIn = (existingElements, pathTarget) => {
const parts = [...pathTarget];
const elementsToSearchNextIn = [];
for (const existingElement of existingElements) {
if (existingElement.name === pathTarget[0]) {
if (existingElement.children) {
for (const el of existingElement.children) {
elementsToSearchNextIn.push(el);
}
}
else {
elementsToSearchNextIn.push(existingElement);
}
}
}
if (elementsToSearchNextIn.length === 0) {
return [];
}
else {
parts.splice(0, 1);
if (parts.length <= 0) {
return elementsToSearchNextIn;
}
else {
return findElementsToSearchIn(elementsToSearchNextIn, parts);
}
}
};
const parseXmlToSearchable = (childElementsObj, arrayToAddTo) => {
for (const childElementKey of Object.keys(childElementsObj)) {
for (const occurannceOfElement of childElementsObj[childElementKey]) {
const toAdd = { name: childElementKey };
if (occurannceOfElement['$']) {
toAdd.attrs = { ...occurannceOfElement['$'] };
}
if (occurannceOfElement['$$']) {
toAdd.children = [];
parseXmlToSearchable(occurannceOfElement['$$'], toAdd['children']);
}
arrayToAddTo.push(toAdd);
}
}
};
const doesElementMatch = (requiredElement, existingElement) => {
var _a;
if (requiredElement.name !== existingElement.name) {
return false;
}
if ((requiredElement.attrs !== undefined) !==
(existingElement.attrs !== undefined)) {
return false;
}
else {
if (requiredElement.attrs !== undefined) {
const requiredELementAttrKeys = Object.keys(requiredElement.attrs);
for (const key of requiredELementAttrKeys) {
if (!/^[$].{1,}$/.test(requiredElement.attrs[key].trim())) {
if (requiredElement.attrs[key] !==
existingElement.attrs[key]) {
return false;
}
}
}
}
}
if ((requiredElement.children !== undefined) !==
(existingElement.children !== undefined) &&
((_a = requiredElement.children) === null || _a === void 0 ? void 0 : _a.length) !== 0) {
return false;
}
else {
if (requiredElement.children !== undefined) {
// each req element is in existing element
for (const requiredElementItem of requiredElement.children) {
let foundRequiredElement = false;
for (const existingElementItem of existingElement.children) {
const foundRequiredElementIn = doesElementMatch(requiredElementItem, existingElementItem);
if (foundRequiredElementIn) {
foundRequiredElement = true;
break;
}
}
if (!foundRequiredElement) {
return false;
}
}
}
else {
if (requiredElement.children === undefined &&
existingElement.children === undefined) {
return true;
}
else {
let foundRequiredElement = false;
for (const existingElementItem of existingElement.children) {
const foundRequiredElementIn = doesElementMatch(requiredElement, existingElementItem);
if (foundRequiredElementIn) {
foundRequiredElement = true;
break;
}
}
if (!foundRequiredElement) {
return false;
}
}
}
}
return true;
};
const parsedExistingElements = [];
const rootKeyOfExistingElements = Object.keys(existingElements)[0];
const rootOfExistingElementsToAdd = { name: rootKeyOfExistingElements, children: [] };
if (existingElements[rootKeyOfExistingElements]['$']) {
rootOfExistingElementsToAdd.attrs = {
...existingElements[rootKeyOfExistingElements]['$'],
};
}
parseXmlToSearchable(existingElements[rootKeyOfExistingElements]['$$'], rootOfExistingElementsToAdd['children']);
parsedExistingElements.push(rootOfExistingElementsToAdd);
const parsedRequiredElements = [];
const rootKeyOfRequiredElements = Object.keys(requiredElements)[0];
const rootOfRequiredElementsToAdd = { name: rootKeyOfRequiredElements, children: [] };
if (requiredElements[rootKeyOfRequiredElements]['$']) {
rootOfRequiredElementsToAdd.attrs = {
...requiredElements[rootKeyOfRequiredElements]['$'],
};
}
if (requiredElements[rootKeyOfRequiredElements]['$$'] !==
undefined) {
parseXmlToSearchable(requiredElements[rootKeyOfRequiredElements]['$$'], rootOfRequiredElementsToAdd['children']);
}
parsedRequiredElements.push(rootOfRequiredElementsToAdd);
const elementsToSearch = findElementsToSearchIn(parsedExistingElements, pathTarget);
for (const requiredElement of parsedRequiredElements) {
let foundMatch = false;
for (const existingElement of elementsToSearch) {
const doesContain = doesElementMatch(requiredElement, existingElement);
if (doesContain) {
foundMatch = true;
break;
}
}
if (!foundMatch) {
return false;
}
}
return true;
};
if (!doesXmlManifestContainRequiredInfo((0, xml_1.parseXML)(requiredManifestContentTrimmed, {
explicitChildren: true,
trim: true,
}), (0, xml_1.parseXML)(manifestContentTrimmed, {
explicitChildren: true,
trim: true,
}), pathPartList)) {
log_1.logger.warn(`Android Configuration required for ${colors_1.default.strong(p.id)}.\n` +
`Add the following to AndroidManifest.xml:\n` +
xmlElement);
}
}
}
else {
if (!rootXMLEntries.includes(xmlElement) &&
!contains(rootXMLEntries, xmlElement, k)) {
rootXMLEntries.push(xmlElement);
}
}
});
});
}
});
});
const cleartextString = 'android:usesCleartextTraffic="true"';
const cleartextValue = (cleartext || ((_a = config.app.extConfig.server) === null || _a === void 0 ? void 0 : _a.cleartext)) &&
!applicationXMLAttributes.includes(cleartextString)
? cleartextString
: '';
let content = `<?xml version='1.0' encoding='utf-8'?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:amazon="http://schemas.amazon.com/apk/res/android">
<application ${applicationXMLAttributes.join('\n')} ${cleartextValue}>
${applicationXMLEntries.join('\n')}
</application>
${rootXMLEntries.join('\n')}
</manifest>`;
content = content.replace(new RegExp('$PACKAGE_NAME'.replace('$', '\\$&'), 'g'), '${applicationId}');
for (const preference of prefsArray) {
content = content.replace(new RegExp(('$' + preference.$.name).replace('$', '\\$&'), 'g'), preference.$.default);
}
if (await (0, utils_fs_1.pathExists)(manifestPath)) {
await (0, utils_fs_1.writeFile)(manifestPath, content);
}
}
exports.writeCordovaAndroidManifest = writeCordovaAndroidManifest;
function getPathParts(path) {
const rootPath = 'manifest';
path = path.replace('/*', rootPath);
const parts = path.split('/').filter(part => part !== '');
if (parts.length > 1 || parts.includes(rootPath)) {
return parts;
}
return [rootPath, path];
}
function contains(entries, obj, k) {
const element = (0, xml_1.parseXML)(obj);
for (const entry of entries) {
const current = (0, xml_1.parseXML)(entry);
if (element &&
current &&
current[k] &&
element[k] &&
current[k].$ &&
element[k].$ &&
element[k].$['android:name'] === current[k].$['android:name']) {
return true;
}
}
return false;
}

592
@capacitor/cli/dist/declarations.d.ts vendored Normal file
View file

@ -0,0 +1,592 @@
export interface CapacitorConfig {
/**
* The unique identifier of your packaged app.
*
* This is also known as the Bundle ID in iOS and the Application ID in
* Android. It must be in reverse domain name notation, generally
* representing a domain name that you or your company owns.
*
* @since 1.0.0
*/
appId?: string;
/**
* The human-friendly name of your app.
*
* This should be what you'd see in the App Store, but can be changed after
* within each native platform after it is generated.
*
* @since 1.0.0
*/
appName?: string;
/**
* The directory of your compiled web assets.
*
* This directory should contain the final `index.html` of your app.
*
* @since 1.0.0
*/
webDir?: string;
/**
* Whether to copy the Capacitor runtime bundle or not.
*
* If your app is not using a bundler, set this to `true`, then Capacitor
* will create a `capacitor.js` file that you'll need to add as a script in
* your `index.html` file.
*
* It's deprecated and will be removed in Capacitor 6
*
* @since 1.0.0
* @deprecated 5.0.0
* @default false
*/
bundledWebRuntime?: boolean;
/**
* The build configuration (as defined by the native app) under which Capacitor
* will send statements to the log system. This applies to log statements in
* native code as well as statements redirected from JavaScript (`console.debug`,
* `console.error`, etc.). Enabling logging will let statements render in the
* Xcode and Android Studio windows but can leak information on device if enabled
* in released builds.
*
* 'none' = logs are never produced
* 'debug' = logs are produced in debug builds but not production builds
* 'production' = logs are always produced
*
* @since 3.0.0
* @default debug
*/
loggingBehavior?: 'none' | 'debug' | 'production';
/**
* User agent of Capacitor Web View.
*
* @since 1.4.0
*/
overrideUserAgent?: string;
/**
* String to append to the original user agent of Capacitor Web View.
*
* This is disregarded if `overrideUserAgent` is used.
*
* @since 1.4.0
*/
appendUserAgent?: string;
/**
* Background color of the Capacitor Web View.
*
* @since 1.1.0
*/
backgroundColor?: string;
/**
* Enable zooming within the Capacitor Web View.
*
* @default false
* @since 6.0.0
*/
zoomEnabled?: boolean;
android?: {
/**
* Specify a custom path to the native Android project.
*
* @since 3.0.0
* @default android
*/
path?: string;
/**
* User agent of Capacitor Web View on Android.
*
* Overrides global `overrideUserAgent` option.
*
* @since 1.4.0
*/
overrideUserAgent?: string;
/**
* String to append to the original user agent of Capacitor Web View for Android.
*
* Overrides global `appendUserAgent` option.
*
* This is disregarded if `overrideUserAgent` is used.
*
* @since 1.4.0
*/
appendUserAgent?: string;
/**
* Background color of the Capacitor Web View for Android.
*
* Overrides global `backgroundColor` option.
*
* @since 1.1.0
*/
backgroundColor?: string;
/**
* Enable zooming within the Capacitor Web View for Android.
*
* @default false
* @since 6.0.0
*/
zoomEnabled?: boolean;
/**
* Enable mixed content in the Capacitor Web View for Android.
*
* [Mixed
* content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content)
* is disabled by default for security. During development, you may need to
* enable it to allow the Web View to load files from different schemes.
*
* **This is not intended for use in production.**
*
* @since 1.0.0
* @default false
*/
allowMixedContent?: boolean;
/**
* This enables a simpler keyboard which may have some limitations.
*
* This will capture JS keys using an alternative
* [`InputConnection`](https://developer.android.com/reference/android/view/inputmethod/InputConnection).
*
* @since 1.0.0
* @default false
*/
captureInput?: boolean;
/**
* Always enable debuggable web content.
*
* This is automatically enabled during development.
*
* @since 1.0.0
* @default false
*/
webContentsDebuggingEnabled?: boolean;
/**
* The build configuration under which Capacitor will generate logs on Android.
*
* Overrides global `loggingBehavior` option.
*
* @since 3.0.0
* @default debug
*/
loggingBehavior?: 'none' | 'debug' | 'production';
/**
* Allowlist of plugins to include during `npx cap sync` for Android.
*
* Overrides global `includePlugins` option.
*
* @since 3.0.0
*/
includePlugins?: string[];
/**
* Android flavor to use.
*
* If the app has flavors declared in the `build.gradle`
* configure the flavor you want to run with `npx cap run` command.
*
* @since 3.1.0
*/
flavor?: string;
/**
* Whether to give the webview initial focus.
*
* @since 3.5.1
* @default true
*/
initialFocus?: boolean;
/**
* The minimum supported webview version on Android supported by your app.
*
* The minimum supported cannot be lower than version `55`, which is required for Capacitor.
*
* If the device uses a lower WebView version, an error message will be shown on Logcat.
* If `server.errorPath` is configured, the WebView will redirect to that file, so can be
* used to show a custom error.
*
* @since 4.0.0
* @default 60
*/
minWebViewVersion?: number;
/**
* The minimum supported Huawei webview version on Android supported by your app.
*
* The minimum supported cannot be lower than version `10`, which is required for Capacitor.
*
* If the device uses a lower WebView version, an error message will be shown on Logcat.
* If `server.errorPath` is configured, the WebView will redirect to that file, so can be
* used to show a custom error.
*
* @since 4.6.4
* @default 10
*/
minHuaweiWebViewVersion?: number;
buildOptions?: {
/**
* Path to your keystore
*
* @since 4.4.0
*/
keystorePath?: string;
/**
* Password to your keystore
*
* @since 4.4.0
*/
keystorePassword?: string;
/**
* Alias in the keystore to use
*
* @since 4.4.0
*/
keystoreAlias?: string;
/**
* Password for the alias in the keystore to use
*
* @since 4.4.0
*/
keystoreAliasPassword?: string;
/**
* Bundle type for your release build
*
* @since 4.4.0
* @default "AAB"
*/
releaseType?: 'AAB' | 'APK';
/**
* Program to sign your build with
*
* @since 5.1.0
* @default "jarsigner"
*/
signingType?: 'apksigner' | 'jarsigner';
};
/**
* Use legacy [addJavascriptInterface](https://developer.android.com/reference/android/webkit/WebView#addJavascriptInterface(java.lang.Object,%20java.lang.String))
* instead of the new and more secure [addWebMessageListener](https://developer.android.com/reference/androidx/webkit/WebViewCompat#addWebMessageListener(android.webkit.WebView,java.lang.String,java.util.Set%3Cjava.lang.String%3E,androidx.webkit.WebViewCompat.WebMessageListener))
*
* @since 4.5.0
* @default false
*/
useLegacyBridge?: boolean;
};
ios?: {
/**
* Specify a custom path to the native iOS project.
*
* @since 3.0.0
* @default ios
*/
path?: string;
/**
* iOS build scheme to use.
*
* Usually this matches your app's target in Xcode. You can use the
* following command to list schemes:
*
* ```shell
* xcodebuild -workspace ios/App/App.xcworkspace -list
* ```
*
* @since 3.0.0
* @default App
*/
scheme?: string;
/**
* User agent of Capacitor Web View on iOS.
*
* Overrides global `overrideUserAgent` option.
*
* @since 1.4.0
*/
overrideUserAgent?: string;
/**
* String to append to the original user agent of Capacitor Web View for iOS.
*
* Overrides global `appendUserAgent` option.
*
* This is disregarded if `overrideUserAgent` is used.
*
* @since 1.4.0
*/
appendUserAgent?: string;
/**
* Background color of the Capacitor Web View for iOS.
*
* Overrides global `backgroundColor` option.
*
* @since 1.1.0
*/
backgroundColor?: string;
/**
* Enable zooming within the Capacitor Web View for iOS.
*
* @default false
* @since 6.0.0
*/
zoomEnabled?: boolean;
/**
* Configure the scroll view's content inset adjustment behavior.
*
* This will set the
* [`contentInsetAdjustmentBehavior`](https://developer.apple.com/documentation/uikit/uiscrollview/2902261-contentinsetadjustmentbehavior)
* property on the Web View's
* [`UIScrollView`](https://developer.apple.com/documentation/uikit/uiscrollview).
*
* @since 2.0.0
* @default never
*/
contentInset?: 'automatic' | 'scrollableAxes' | 'never' | 'always';
/**
* Configure whether the scroll view is scrollable.
*
* This will set the
* [`isScrollEnabled`](https://developer.apple.com/documentation/uikit/uiscrollview/1619395-isscrollenabled)
* property on the Web View's
* [`UIScrollView`](https://developer.apple.com/documentation/uikit/uiscrollview).
*
* @since 1.0.0
*/
scrollEnabled?: boolean;
/**
* Configure custom linker flags for compiling Cordova plugins.
*
* @since 1.0.0
* @default []
*/
cordovaLinkerFlags?: string[];
/**
* Allow destination previews when pressing on links.
*
* This will set the
* [`allowsLinkPreview`](https://developer.apple.com/documentation/webkit/wkwebview/1415000-allowslinkpreview)
* property on the Web View, instead of using the default value.
*
* @since 2.0.0
*/
allowsLinkPreview?: boolean;
/**
* The build configuration under which Capacitor will generate logs on iOS.
*
* Overrides global `loggingBehavior` option.
*
* @since 3.0.0
* @default debug
*/
loggingBehavior?: 'none' | 'debug' | 'production';
/**
* Allowlist of plugins to include during `npx cap sync` for iOS.
*
* Overrides global `includePlugins` option.
*
* @since 3.0.0
*/
includePlugins?: string[];
/**
* Sets WKWebView configuration for limitsNavigationsToAppBoundDomains.
*
* If the Info.plist file includes `WKAppBoundDomains` key, it's recommended to
* set this option to true, otherwise some features won't work.
* But as side effect, it blocks navigation outside the domains in the
* `WKAppBoundDomains` list.
* `localhost` (or the value configured as `server.hostname`) also needs to be
* added to the `WKAppBoundDomains` list.
*
* @since 3.1.0
* @default false
*/
limitsNavigationsToAppBoundDomains?: boolean;
/**
* The content mode for the web view to use when it loads and renders web content.
*
* - 'recommended': The content mode that is appropriate for the current device.
* - 'desktop': The content mode that represents a desktop experience.
* - 'mobile': The content mode that represents a mobile experience.
*
* @since 4.0.0
* @default recommended
*/
preferredContentMode?: 'recommended' | 'desktop' | 'mobile';
/**
* Configure if Capacitor will handle local/push notifications.
* Set to false if you want to use your own UNUserNotificationCenter to handle notifications.
*
* @since 4.5.0
* @default true
*/
handleApplicationNotifications?: boolean;
/**
* Using Xcode 14.3, on iOS 16.4 and greater, enable debuggable web content for release builds.
*
* If not set, it's `true` for development builds.
*
* @since 4.8.0
* @default false
*/
webContentsDebuggingEnabled?: boolean;
};
server?: {
/**
* Configure the local hostname of the device.
*
* It is recommended to keep this as `localhost` as it allows the use of
* Web APIs that would otherwise require a [secure
* context](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts)
* such as
* [`navigator.geolocation`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/geolocation)
* and
* [`MediaDevices.getUserMedia`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia).
*
* @since 1.0.0
* @default localhost
*/
hostname?: string;
/**
* Configure the local scheme on iOS.
*
* [Can't be set to schemes that the WKWebView already handles, such as http or https](https://developer.apple.com/documentation/webkit/wkwebviewconfiguration/2875766-seturlschemehandler)
* This can be useful when migrating from
* [`cordova-plugin-ionic-webview`](https://github.com/ionic-team/cordova-plugin-ionic-webview),
* where the default scheme on iOS is `ionic`.
*
* @since 1.2.0
* @default capacitor
*/
iosScheme?: string;
/**
* Configure the local scheme on Android.
*
* Custom schemes on Android are unable to change the URL path as of Webview 117. Changing this value from anything other than `http` or `https` can result in your
* application unable to resolve routing. If you must change this for some reason, consider using a hash-based url strategy, but there are no guarentees that this
* will continue to work long term as allowing non-standard schemes to modify query parameters and url fragments is only allowed for compatibility reasons.
* https://ionic.io/blog/capacitor-android-customscheme-issue-with-chrome-117
*
* @since 1.2.0
* @default https
*/
androidScheme?: string;
/**
* Load an external URL in the Web View.
*
* This is intended for use with live-reload servers.
*
* **This is not intended for use in production.**
*
* @since 1.0.0
*/
url?: string;
/**
* Allow cleartext traffic in the Web View.
*
* On Android, all cleartext traffic is disabled by default as of API 28.
*
* This is intended for use with live-reload servers where unencrypted HTTP
* traffic is often used.
*
* **This is not intended for use in production.**
*
* @since 1.5.0
* @default false
*/
cleartext?: boolean;
/**
* Set additional URLs the Web View can navigate to.
*
* By default, all external URLs are opened in the external browser (not
* the Web View).
*
* **This is not intended for use in production.**
*
* @since 1.0.0
* @default []
*/
allowNavigation?: string[];
/**
* Specify path to a local html page to display in case of errors.
* On Android the html file won't have access to Capacitor plugins.
*
* @since 4.0.0
* @default null
*/
errorPath?: string;
};
cordova?: {
/**
* Populates <access> tags in the config.xml with the origin set to
* the values entered here.
* If not provided, a single <access origin="*" /> tag gets included.
* It only has effect on a few Cordova plugins that respect the whitelist.
*
* @since 3.3.0
*/
accessOrigins?: string[];
/**
* Configure Cordova preferences.
*
* @since 1.3.0
*/
preferences?: {
[key: string]: string | undefined;
};
/**
* List of Cordova plugins that need to be static but are not
* already in the static plugin list.
*
* It's deprecated and will be removed in Capacitor 7
*
* @since 3.3.0
* @deprecated 6.1.1
*/
staticPlugins?: string[];
};
/**
* Configure plugins.
*
* This is an object with configuration values specified by plugin class
* name.
*
* @since 1.0.0
*/
plugins?: PluginsConfig;
/**
* Allowlist of plugins to include during `npx cap sync`.
*
* This should be an array of strings representing the npm package name of
* plugins to include when running `npx cap sync`. If unset, Capacitor will
* inspect `package.json` for a list of potential plugins.
*
* @since 3.0.0
*/
includePlugins?: string[];
}
export interface PluginsConfig {
/**
* Plugin configuration by class name.
*
* @since 1.0.0
*/
[key: string]: {
[key: string]: any;
} | undefined;
/**
* Capacitor Cookies plugin configuration
*
* @since 4.3.0
*/
CapacitorCookies?: {
/**
* Enable CapacitorCookies to override the global `document.cookie` on native.
*
* @default false
*/
enabled?: boolean;
};
/**
* Capacitor Http plugin configuration
*
* @since 4.3.0
*/
CapacitorHttp?: {
/**
* Enable CapacitorHttp to override the global `fetch` and `XMLHttpRequest` on native.
*
* @default false
*/
enabled?: boolean;
};
}

2
@capacitor/cli/dist/declarations.js vendored Normal file
View file

@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

2
@capacitor/cli/dist/definitions.js vendored Normal file
View file

@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

27
@capacitor/cli/dist/errors.js vendored Normal file
View file

@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isFatal = exports.fatal = exports.FatalException = exports.BaseException = void 0;
class BaseException extends Error {
constructor(message, code) {
super(message);
this.message = message;
this.code = code;
}
}
exports.BaseException = BaseException;
class FatalException extends BaseException {
constructor(message, exitCode = 1) {
super(message, 'FATAL');
this.message = message;
this.exitCode = exitCode;
}
}
exports.FatalException = FatalException;
function fatal(message) {
throw new FatalException(message);
}
exports.fatal = fatal;
function isFatal(e) {
return e && e instanceof FatalException;
}
exports.isFatal = isFatal;

109
@capacitor/cli/dist/framework-configs.js vendored Normal file
View file

@ -0,0 +1,109 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.detectFramework = void 0;
const FRAMEWORK_CONFIGS = [
{
name: 'Angular',
isMatch: config => hasDependency(config, '@angular/cli'),
webDir: 'dist',
priority: 3,
},
{
name: 'Create React App',
isMatch: config => hasDependency(config, 'react-scripts'),
webDir: 'build',
priority: 3,
},
{
name: 'Ember',
isMatch: config => hasDependency(config, 'ember-cli'),
webDir: 'dist',
priority: 3,
},
{
name: 'Gatsby',
isMatch: config => hasDependency(config, 'gatsby'),
webDir: 'public',
priority: 2,
},
{
name: 'Ionic Angular',
isMatch: config => hasDependency(config, '@ionic/angular'),
webDir: 'www',
priority: 1,
},
{
name: 'Ionic React',
isMatch: config => hasDependency(config, '@ionic/react'),
webDir: 'build',
priority: 1,
},
{
name: 'Ionic Vue',
isMatch: config => hasDependency(config, '@ionic/vue'),
webDir: 'public',
priority: 1,
},
{
name: 'Next',
isMatch: config => hasDependency(config, 'next'),
webDir: 'public',
priority: 2,
},
{
name: 'Preact',
isMatch: config => hasDependency(config, 'preact-cli'),
webDir: 'build',
priority: 3,
},
{
name: 'Stencil',
isMatch: config => hasDependency(config, '@stencil/core'),
webDir: 'www',
priority: 3,
},
{
name: 'Svelte',
isMatch: config => hasDependency(config, 'svelte') && hasDependency(config, 'sirv-cli'),
webDir: 'public',
priority: 3,
},
{
name: 'Vite',
isMatch: config => hasDependency(config, 'vite'),
webDir: 'dist',
priority: 2,
},
{
name: 'Vue',
isMatch: config => hasDependency(config, '@vue/cli-service'),
webDir: 'dist',
priority: 3,
},
];
function detectFramework(config) {
const frameworks = FRAMEWORK_CONFIGS.filter(f => f.isMatch(config)).sort((a, b) => {
if (a.priority < b.priority)
return -1;
if (a.priority > b.priority)
return 1;
return 0;
});
return frameworks[0];
}
exports.detectFramework = detectFramework;
function hasDependency(config, depName) {
const deps = getDependencies(config);
return deps.includes(depName);
}
function getDependencies(config) {
var _a, _b, _c, _d;
const deps = [];
if ((_b = (_a = config === null || config === void 0 ? void 0 : config.app) === null || _a === void 0 ? void 0 : _a.package) === null || _b === void 0 ? void 0 : _b.dependencies) {
deps.push(...Object.keys(config.app.package.dependencies));
}
if ((_d = (_c = config === null || config === void 0 ? void 0 : config.app) === null || _c === void 0 ? void 0 : _c.package) === null || _d === void 0 ? void 0 : _d.devDependencies) {
deps.push(...Object.keys(config.app.package.devDependencies));
}
return deps;
}

224
@capacitor/cli/dist/index.js vendored Normal file
View file

@ -0,0 +1,224 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.runProgram = exports.run = void 0;
const tslib_1 = require("tslib");
const commander_1 = require("commander");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("./colors"));
const config_1 = require("./config");
const errors_1 = require("./errors");
const ipc_1 = require("./ipc");
const log_1 = require("./log");
const telemetry_1 = require("./telemetry");
const cli_1 = require("./util/cli");
const emoji_1 = require("./util/emoji");
process.on('unhandledRejection', error => {
console.error(colors_1.default.failure('[fatal]'), error);
});
process.on('message', ipc_1.receive);
async function run() {
try {
const config = await (0, config_1.loadConfig)();
runProgram(config);
}
catch (e) {
process.exitCode = (0, errors_1.isFatal)(e) ? e.exitCode : 1;
log_1.logger.error(e.message ? e.message : String(e));
}
}
exports.run = run;
function runProgram(config) {
commander_1.program.version(config.cli.package.version);
commander_1.program
.command('config', { hidden: true })
.description(`print evaluated Capacitor config`)
.option('--json', 'Print in JSON format')
.action((0, cli_1.wrapAction)(async ({ json }) => {
const { configCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/config')));
await configCommand(config, json);
}));
commander_1.program
.command('create [directory] [name] [id]', { hidden: true })
.description('Creates a new Capacitor project')
.action((0, cli_1.wrapAction)(async () => {
const { createCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/create')));
await createCommand();
}));
commander_1.program
.command('init [appName] [appId]')
.description(`Initialize Capacitor configuration`)
.option('--web-dir <value>', 'Optional: Directory of your projects built web assets')
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (appName, appId, { webDir }) => {
const { initCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/init')));
await initCommand(config, appName, appId, webDir);
})));
commander_1.program
.command('serve', { hidden: true })
.description('Serves a Capacitor Progressive Web App in the browser')
.action((0, cli_1.wrapAction)(async () => {
const { serveCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/serve')));
await serveCommand();
}));
commander_1.program
.command('sync [platform]')
.description(`${colors_1.default.input('copy')} + ${colors_1.default.input('update')}`)
.option('--deployment', 'Optional: if provided, pod install will use --deployment option')
.option('--inline', 'Optional: if true, all source maps will be inlined for easier debugging on mobile devices', false)
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { deployment, inline }) => {
(0, config_1.checkExternalConfig)(config.app);
const { syncCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/sync')));
await syncCommand(config, platform, deployment, inline);
})));
commander_1.program
.command('update [platform]')
.description(`updates the native plugins and dependencies based on ${colors_1.default.strong('package.json')}`)
.option('--deployment', 'Optional: if provided, pod install will use --deployment option')
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { deployment }) => {
(0, config_1.checkExternalConfig)(config.app);
const { updateCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/update')));
await updateCommand(config, platform, deployment);
})));
commander_1.program
.command('copy [platform]')
.description('copies the web app build into the native app')
.option('--inline', 'Optional: if true, all source maps will be inlined for easier debugging on mobile devices', false)
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { inline }) => {
(0, config_1.checkExternalConfig)(config.app);
const { copyCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/copy')));
await copyCommand(config, platform, inline);
})));
commander_1.program
.command('build <platform>')
.description('builds the release version of the selected platform')
.option('--scheme <schemeToBuild>', 'iOS Scheme to build')
.option('--flavor <flavorToBuild>', 'Android Flavor to build')
.option('--keystorepath <keystorePath>', 'Path to the keystore')
.option('--keystorepass <keystorePass>', 'Password to the keystore')
.option('--keystorealias <keystoreAlias>', 'Key Alias in the keystore')
.option('--configuration <name>', 'Configuration name of the iOS Scheme')
.option('--keystorealiaspass <keystoreAliasPass>', 'Password for the Key Alias')
.addOption(new commander_1.Option('--androidreleasetype <androidreleasetype>', 'Android release type; APK or AAB').choices(['AAB', 'APK']))
.addOption(new commander_1.Option('--signing-type <signingtype>', 'Program used to sign apps (default: jarsigner)').choices(['apksigner', 'jarsigner']))
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { scheme, flavor, keystorepath, keystorepass, keystorealias, keystorealiaspass, androidreleasetype, signingType, configuration, }) => {
const { buildCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/build')));
await buildCommand(config, platform, {
scheme,
flavor,
keystorepath,
keystorepass,
keystorealias,
keystorealiaspass,
androidreleasetype,
signingtype: signingType,
configuration,
});
})));
commander_1.program
.command(`run [platform]`)
.description(`runs ${colors_1.default.input('sync')}, then builds and deploys the native app`)
.option('--scheme <schemeName>', 'set the scheme of the iOS project')
.option('--flavor <flavorName>', 'set the flavor of the Android project (flavor dimensions not yet supported)')
.option('--list', 'list targets, then quit')
// TODO: remove once --json is a hidden option (https://github.com/tj/commander.js/issues/1106)
.allowUnknownOption(true)
.option('--target <id>', 'use a specific target')
.option('--no-sync', `do not run ${colors_1.default.input('sync')}`)
.option('--forwardPorts <port:port>', 'Automatically run "adb reverse" for better live-reloading support')
.option('-l, --live-reload', 'Enable Live Reload')
.option('--host <host>', 'Host used for live reload')
.option('--port <port>', 'Port used for live reload')
.option('--configuration <name>', 'Configuration name of the iOS Scheme')
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { scheme, flavor, list, target, sync, forwardPorts, liveReload, host, port, configuration, }) => {
const { runCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/run')));
await runCommand(config, platform, {
scheme,
flavor,
list,
target,
sync,
forwardPorts,
liveReload,
host,
port,
configuration,
});
})));
commander_1.program
.command('open [platform]')
.description('opens the native project workspace (Xcode for iOS)')
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform) => {
const { openCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/open')));
await openCommand(config, platform);
})));
commander_1.program
.command('add [platform]')
.description('add a native platform project')
.option('--packagemanager <packageManager>', 'The package manager to use for dependency installs (Cocoapods, SPM **experimental**)')
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { packagemanager }) => {
(0, config_1.checkExternalConfig)(config.app);
const { addCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/add')));
const configWritable = config;
if (packagemanager === 'SPM') {
configWritable.cli.assets.ios.platformTemplateArchive =
'ios-spm-template.tar.gz';
configWritable.cli.assets.ios.platformTemplateArchiveAbs = (0, path_1.resolve)(configWritable.cli.assetsDirAbs, configWritable.cli.assets.ios.platformTemplateArchive);
}
await addCommand(configWritable, platform);
})));
commander_1.program
.command('ls [platform]')
.description('list installed Cordova and Capacitor plugins')
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform) => {
(0, config_1.checkExternalConfig)(config.app);
const { listCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/list')));
await listCommand(config, platform);
})));
commander_1.program
.command('doctor [platform]')
.description('checks the current setup for common errors')
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform) => {
(0, config_1.checkExternalConfig)(config.app);
const { doctorCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/doctor')));
await doctorCommand(config, platform);
})));
commander_1.program
.command('telemetry [on|off]', { hidden: true })
.description('enable or disable telemetry')
.action((0, cli_1.wrapAction)(async (onOrOff) => {
const { telemetryCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/telemetry')));
await telemetryCommand(onOrOff);
}));
commander_1.program
.command('📡', { hidden: true })
.description('IPC receiver command')
.action(() => {
// no-op: IPC messages are received via `process.on('message')`
});
commander_1.program
.command('plugin:generate', { hidden: true })
.description('start a new Capacitor plugin')
.action((0, cli_1.wrapAction)(async () => {
const { newPluginCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/new-plugin')));
await newPluginCommand();
}));
commander_1.program
.command('migrate')
.option('--noprompt', 'do not prompt for confirmation')
.option('--packagemanager <packageManager>', 'The package manager to use for dependency installs (npm, pnpm, yarn)')
.description('Migrate your current Capacitor app to the latest major version of Capacitor.')
.action((0, cli_1.wrapAction)(async ({ noprompt, packagemanager }) => {
const { migrateCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/migrate')));
await migrateCommand(config, noprompt, packagemanager);
}));
commander_1.program.arguments('[command]').action((0, cli_1.wrapAction)(async (cmd) => {
if (typeof cmd === 'undefined') {
log_1.output.write(`\n ${(0, emoji_1.emoji)('⚡️', '--')} ${colors_1.default.strong('Capacitor - Cross-Platform apps with JavaScript and the Web')} ${(0, emoji_1.emoji)('⚡️', '--')}\n\n`);
commander_1.program.outputHelp();
}
else {
(0, errors_1.fatal)(`Unknown command: ${colors_1.default.input(cmd)}`);
}
}));
commander_1.program.parse(process.argv);
}
exports.runProgram = runProgram;

13
@capacitor/cli/dist/ios/add.js vendored Normal file
View file

@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.addIOS = void 0;
const tslib_1 = require("tslib");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
const template_1 = require("../util/template");
async function addIOS(config) {
await (0, common_1.runTask)(`Adding native Xcode project in ${colors_1.default.strong(config.ios.platformDir)}`, () => {
return (0, template_1.extractTemplate)(config.cli.assets.ios.platformTemplateArchiveAbs, config.ios.platformDirAbs);
});
}
exports.addIOS = addIOS;

70
@capacitor/cli/dist/ios/build.js vendored Normal file
View file

@ -0,0 +1,70 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildiOS = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const path_1 = require("path");
const rimraf_1 = tslib_1.__importDefault(require("rimraf"));
const common_1 = require("../common");
const log_1 = require("../log");
const spm_1 = require("../util/spm");
const subprocess_1 = require("../util/subprocess");
async function buildiOS(config, buildOptions) {
var _a;
const theScheme = (_a = buildOptions.scheme) !== null && _a !== void 0 ? _a : 'App';
const packageManager = await (0, spm_1.checkPackageManager)(config);
let typeOfBuild;
let projectName;
if (packageManager == 'Cocoapods') {
typeOfBuild = '-workspace';
projectName = (0, path_1.basename)(await config.ios.nativeXcodeWorkspaceDirAbs);
}
else {
typeOfBuild = '-project';
projectName = (0, path_1.basename)(await config.ios.nativeXcodeProjDirAbs);
}
await (0, common_1.runTask)('Building xArchive', async () => (0, subprocess_1.runCommand)('xcodebuild', [
typeOfBuild,
projectName,
'-scheme',
`${theScheme}`,
'-destination',
`generic/platform=iOS`,
'-archivePath',
`${theScheme}.xcarchive`,
'archive',
], {
cwd: config.ios.nativeProjectDirAbs,
}));
const archivePlistContents = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>app-store</string>
</dict>
</plist>`;
const archivePlistPath = (0, path_1.join)(`${config.ios.nativeProjectDirAbs}`, 'archive.plist');
(0, utils_fs_1.writeFileSync)(archivePlistPath, archivePlistContents);
await (0, common_1.runTask)('Building IPA', async () => (0, subprocess_1.runCommand)('xcodebuild', [
'archive',
'-archivePath',
`${theScheme}.xcarchive`,
'-exportArchive',
'-exportOptionsPlist',
'archive.plist',
'-exportPath',
'output',
'-allowProvisioningUpdates',
'-configuration',
buildOptions.configuration,
], {
cwd: config.ios.nativeProjectDirAbs,
}));
await (0, common_1.runTask)('Cleaning up', async () => {
(0, utils_fs_1.unlinkSync)(archivePlistPath);
rimraf_1.default.sync((0, path_1.join)(config.ios.nativeProjectDirAbs, `${theScheme}.xcarchive`));
});
(0, log_1.logSuccess)(`Successfully generated an IPA at: ${(0, path_1.join)(config.ios.nativeProjectDirAbs, 'output')}`);
}
exports.buildiOS = buildiOS;

103
@capacitor/cli/dist/ios/common.js vendored Normal file
View file

@ -0,0 +1,103 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.editProjectSettingsIOS = exports.resolvePlugin = exports.getIOSPlugins = exports.checkCocoaPods = exports.checkBundler = exports.checkIOSPackage = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const child_process_1 = require("child_process");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
const cordova_1 = require("../cordova");
const log_1 = require("../log");
const plugin_1 = require("../plugin");
const subprocess_1 = require("../util/subprocess");
async function checkIOSPackage(config) {
return (0, common_1.checkCapacitorPlatform)(config, 'ios');
}
exports.checkIOSPackage = checkIOSPackage;
function execBundler() {
try {
const bundleOutput = (0, child_process_1.execSync)('bundle &> /dev/null ; echo $?');
return parseInt(bundleOutput.toString());
}
catch (e) {
return -1;
}
}
async function checkBundler(config) {
if (config.cli.os === "mac" /* OS.Mac */) {
let bundlerResult = execBundler();
if (bundlerResult === 1) {
// Bundler version is outdated
log_1.logger.info(`Using ${colors_1.default.strong('Gemfile')}: Bundler update needed...`);
await (0, subprocess_1.runCommand)('gem', ['install', 'bundler']);
bundlerResult = execBundler();
}
if (bundlerResult === 0) {
// Bundler in use, all gems current
log_1.logger.info(`Using ${colors_1.default.strong('Gemfile')}: RubyGems bundle installed`);
}
}
return null;
}
exports.checkBundler = checkBundler;
async function checkCocoaPods(config) {
if (!(await (0, subprocess_1.isInstalled)(await config.ios.podPath)) &&
config.cli.os === "mac" /* OS.Mac */) {
return (`CocoaPods is not installed.\n` +
`See this install guide: ${colors_1.default.strong('https://capacitorjs.com/docs/getting-started/environment-setup#homebrew')}`);
}
return null;
}
exports.checkCocoaPods = checkCocoaPods;
async function getIOSPlugins(allPlugins) {
const resolved = await Promise.all(allPlugins.map(async (plugin) => await resolvePlugin(plugin)));
return resolved.filter((plugin) => !!plugin);
}
exports.getIOSPlugins = getIOSPlugins;
async function resolvePlugin(plugin) {
var _a, _b;
const platform = 'ios';
if ((_a = plugin.manifest) === null || _a === void 0 ? void 0 : _a.ios) {
plugin.ios = {
name: plugin.name,
type: 0 /* PluginType.Core */,
path: (_b = plugin.manifest.ios.src) !== null && _b !== void 0 ? _b : platform,
};
}
else if (plugin.xml) {
plugin.ios = {
name: plugin.name,
type: 1 /* PluginType.Cordova */,
path: 'src/' + platform,
};
if ((0, cordova_1.getIncompatibleCordovaPlugins)(platform).includes(plugin.id) ||
!(0, plugin_1.getPluginPlatform)(plugin, platform)) {
plugin.ios.type = 2 /* PluginType.Incompatible */;
}
}
else {
return null;
}
return plugin;
}
exports.resolvePlugin = resolvePlugin;
/**
* Update the native project files with the desired app id and app name
*/
async function editProjectSettingsIOS(config) {
const appId = config.app.appId;
const appName = config.app.appName
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
const pbxPath = `${config.ios.nativeXcodeProjDirAbs}/project.pbxproj`;
const plistPath = (0, path_1.resolve)(config.ios.nativeTargetDirAbs, 'Info.plist');
let plistContent = await (0, utils_fs_1.readFile)(plistPath, { encoding: 'utf-8' });
plistContent = plistContent.replace(/<key>CFBundleDisplayName<\/key>[\s\S]?\s+<string>([^<]*)<\/string>/, `<key>CFBundleDisplayName</key>\n <string>${appName}</string>`);
let pbxContent = await (0, utils_fs_1.readFile)(pbxPath, { encoding: 'utf-8' });
pbxContent = pbxContent.replace(/PRODUCT_BUNDLE_IDENTIFIER = ([^;]+)/g, `PRODUCT_BUNDLE_IDENTIFIER = ${appId}`);
await (0, utils_fs_1.writeFile)(plistPath, plistContent, { encoding: 'utf-8' });
await (0, utils_fs_1.writeFile)(pbxPath, pbxContent, { encoding: 'utf-8' });
}
exports.editProjectSettingsIOS = editProjectSettingsIOS;

49
@capacitor/cli/dist/ios/doctor.js vendored Normal file
View file

@ -0,0 +1,49 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.doctorIOS = void 0;
const common_1 = require("../common");
const errors_1 = require("../errors");
const log_1 = require("../log");
const subprocess_1 = require("../util/subprocess");
const common_2 = require("./common");
async function doctorIOS(config) {
var _a;
// DOCTOR ideas for iOS:
// plugin specific warnings
// check cocoapods installed
// check projects exist
// check content in www === ios/www
// check CLI versions
// check plugins versions
// check native project deps are up-to-date === npm install
// check if npm install was updated
// check online datebase of common errors
// check if www folder is empty (index.html does not exist)
try {
await (0, common_1.check)([
() => (0, common_2.checkBundler)(config) || (0, common_2.checkCocoaPods)(config),
() => (0, common_1.checkWebDir)(config),
checkXcode,
]);
(0, log_1.logSuccess)('iOS looking great! 👌');
}
catch (e) {
(0, errors_1.fatal)((_a = e.stack) !== null && _a !== void 0 ? _a : e);
}
}
exports.doctorIOS = doctorIOS;
async function checkXcode() {
if (!(await (0, subprocess_1.isInstalled)('xcodebuild'))) {
return `Xcode is not installed`;
}
// const matches = output.match(/^Xcode (.*)/);
// if (matches && matches.length === 2) {
// const minVersion = '9.0.0';
// const semver = await import('semver');
// console.log(matches[1]);
// if (semver.gt(minVersion, matches[1])) {
// return `Xcode version is too old, ${minVersion} is required`;
// }
// }
return null;
}

17
@capacitor/cli/dist/ios/open.js vendored Normal file
View file

@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.openIOS = void 0;
const tslib_1 = require("tslib");
const open_1 = tslib_1.__importDefault(require("open"));
const common_1 = require("../common");
const spm_1 = require("../util/spm");
async function openIOS(config) {
if ((await (0, spm_1.checkPackageManager)(config)) == 'SPM') {
await (0, open_1.default)(config.ios.nativeXcodeProjDirAbs, { wait: false });
}
else {
await (0, open_1.default)(await config.ios.nativeXcodeWorkspaceDirAbs, { wait: false });
}
await (0, common_1.wait)(3000);
}
exports.openIOS = openIOS;

53
@capacitor/cli/dist/ios/run.js vendored Normal file
View file

@ -0,0 +1,53 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.runIOS = void 0;
const tslib_1 = require("tslib");
const debug_1 = tslib_1.__importDefault(require("debug"));
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
const native_run_1 = require("../util/native-run");
const spm_1 = require("../util/spm");
const subprocess_1 = require("../util/subprocess");
const debug = (0, debug_1.default)('capacitor:ios:run');
async function runIOS(config, { target: selectedTarget, scheme: selectedScheme, configuration: selectedConfiguration, }) {
const target = await (0, common_1.promptForPlatformTarget)(await (0, native_run_1.getPlatformTargets)('ios'), selectedTarget);
const runScheme = selectedScheme || config.ios.scheme;
const configuration = selectedConfiguration || 'Debug';
const derivedDataPath = (0, path_1.resolve)(config.ios.platformDirAbs, 'DerivedData', target.id);
const packageManager = await (0, spm_1.checkPackageManager)(config);
let typeOfBuild;
let projectName;
if (packageManager == 'Cocoapods') {
typeOfBuild = '-workspace';
projectName = (0, path_1.basename)(await config.ios.nativeXcodeWorkspaceDirAbs);
}
else {
typeOfBuild = '-project';
projectName = (0, path_1.basename)(await config.ios.nativeXcodeProjDirAbs);
}
const xcodebuildArgs = [
typeOfBuild,
projectName,
'-scheme',
runScheme,
'-configuration',
configuration,
'-destination',
`id=${target.id}`,
'-derivedDataPath',
derivedDataPath,
];
debug('Invoking xcodebuild with args: %O', xcodebuildArgs);
await (0, common_1.runTask)('Running xcodebuild', async () => (0, subprocess_1.runCommand)('xcrun', ['xcodebuild', ...xcodebuildArgs], {
cwd: config.ios.nativeProjectDirAbs,
}));
const appName = `${runScheme}.app`;
const appPath = (0, path_1.resolve)(derivedDataPath, 'Build/Products', target.virtual
? `${configuration}-iphonesimulator`
: `${configuration}-iphoneos`, appName);
const nativeRunArgs = ['ios', '--app', appPath, '--target', target.id];
debug('Invoking native-run with args: %O', nativeRunArgs);
await (0, common_1.runTask)(`Deploying ${colors_1.default.strong(appName)} to ${colors_1.default.input(target.id)}`, async () => (0, native_run_1.runNativeRun)(nativeRunArgs));
}
exports.runIOS = runIOS;

417
@capacitor/cli/dist/ios/update.js vendored Normal file
View file

@ -0,0 +1,417 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.installCocoaPodsPlugins = exports.updateIOS = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
const cordova_1 = require("../cordova");
const errors_1 = require("../errors");
const log_1 = require("../log");
const plugin_1 = require("../plugin");
const copy_1 = require("../tasks/copy");
const fs_1 = require("../util/fs");
const iosplugin_1 = require("../util/iosplugin");
const node_1 = require("../util/node");
const spm_1 = require("../util/spm");
const subprocess_1 = require("../util/subprocess");
const template_1 = require("../util/template");
const common_2 = require("./common");
const platform = 'ios';
async function updateIOS(config, deployment) {
const plugins = await getPluginsTask(config);
const capacitorPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 0 /* PluginType.Core */);
if ((await (0, spm_1.checkPackageManager)(config)) === 'SPM') {
await (0, spm_1.generatePackageFile)(config, capacitorPlugins);
}
else {
await updateIOSCocoaPods(config, plugins, deployment);
}
(0, iosplugin_1.generateIOSPackageJSON)(config, plugins);
(0, plugin_1.printPlugins)(capacitorPlugins, 'ios');
}
exports.updateIOS = updateIOS;
async function updateIOSCocoaPods(config, plugins, deployment) {
await removePluginsNativeFiles(config);
const cordovaPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
if (cordovaPlugins.length > 0) {
await copyPluginsNativeFiles(config, cordovaPlugins);
}
if (!(await (0, utils_fs_1.pathExists)(await config.ios.webDirAbs))) {
await (0, copy_1.copy)(config, platform);
}
await (0, cordova_1.handleCordovaPluginsJS)(cordovaPlugins, config, platform);
await (0, cordova_1.checkPluginDependencies)(plugins, platform);
await generateCordovaPodspecs(cordovaPlugins, config);
await installCocoaPodsPlugins(config, plugins, deployment);
await (0, cordova_1.logCordovaManualSteps)(cordovaPlugins, config, platform);
const incompatibleCordovaPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 2 /* PluginType.Incompatible */);
(0, plugin_1.printPlugins)(incompatibleCordovaPlugins, platform, 'incompatible');
await (0, common_1.checkPlatformVersions)(config, platform);
}
async function installCocoaPodsPlugins(config, plugins, deployment) {
await (0, common_1.runTask)(`Updating iOS native dependencies with ${colors_1.default.input(`${await config.ios.podPath} install`)}`, () => {
return updatePodfile(config, plugins, deployment);
});
}
exports.installCocoaPodsPlugins = installCocoaPodsPlugins;
async function updatePodfile(config, plugins, deployment) {
const dependenciesContent = await generatePodFile(config, plugins);
const relativeCapacitoriOSPath = await getRelativeCapacitoriOSPath(config);
const podfilePath = (0, path_1.join)(config.ios.nativeProjectDirAbs, 'Podfile');
let podfileContent = await (0, utils_fs_1.readFile)(podfilePath, { encoding: 'utf-8' });
podfileContent = podfileContent.replace(/(def capacitor_pods)[\s\S]+?(\nend)/, `$1${dependenciesContent}$2`);
podfileContent = podfileContent.replace(/(require_relative)[\s\S]+?(@capacitor\/ios\/scripts\/pods_helpers')/, `require_relative '${relativeCapacitoriOSPath}/scripts/pods_helpers'`);
podfileContent = podfileContent.replace(`def assertDeploymentTarget(installer)
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
# ensure IPHONEOS_DEPLOYMENT_TARGET is at least 13.0
deployment_target = config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'].to_f
should_upgrade = deployment_target < 13.0 && deployment_target != 0.0
if should_upgrade
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
end
end
end
end`, `require_relative '${relativeCapacitoriOSPath}/scripts/pods_helpers'`);
await (0, utils_fs_1.writeFile)(podfilePath, podfileContent, { encoding: 'utf-8' });
const podPath = await config.ios.podPath;
const useBundler = podPath.startsWith('bundle');
const podCommandExists = await (0, subprocess_1.isInstalled)('pod');
if (useBundler || podCommandExists) {
if (useBundler) {
await (0, subprocess_1.runCommand)('bundle', ['exec', 'pod', 'install', ...(deployment ? ['--deployment'] : [])], { cwd: config.ios.nativeProjectDirAbs });
}
else {
await (0, subprocess_1.runCommand)(podPath, ['install', ...(deployment ? ['--deployment'] : [])], { cwd: config.ios.nativeProjectDirAbs });
}
}
else {
log_1.logger.warn('Skipping pod install because CocoaPods is not installed');
}
const isXcodebuildAvailable = await (0, subprocess_1.isInstalled)('xcodebuild');
if (isXcodebuildAvailable) {
await (0, subprocess_1.runCommand)('xcodebuild', ['-project', (0, path_1.basename)(`${config.ios.nativeXcodeProjDirAbs}`), 'clean'], {
cwd: config.ios.nativeProjectDirAbs,
});
}
else {
log_1.logger.warn('Unable to find "xcodebuild". Skipping xcodebuild clean step...');
}
}
async function getRelativeCapacitoriOSPath(config) {
const capacitoriOSPath = (0, node_1.resolveNode)(config.app.rootDir, '@capacitor/ios', 'package.json');
if (!capacitoriOSPath) {
(0, errors_1.fatal)(`Unable to find ${colors_1.default.strong('node_modules/@capacitor/ios')}.\n` +
`Are you sure ${colors_1.default.strong('@capacitor/ios')} is installed?`);
}
return (0, fs_1.convertToUnixPath)((0, path_1.relative)(config.ios.nativeProjectDirAbs, await (0, utils_fs_1.realpath)((0, path_1.dirname)(capacitoriOSPath))));
}
async function generatePodFile(config, plugins) {
const relativeCapacitoriOSPath = await getRelativeCapacitoriOSPath(config);
const capacitorPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 0 /* PluginType.Core */);
const pods = await Promise.all(capacitorPlugins.map(async (p) => {
if (!p.ios) {
return '';
}
return ` pod '${p.ios.name}', :path => '${(0, fs_1.convertToUnixPath)((0, path_1.relative)(config.ios.nativeProjectDirAbs, await (0, utils_fs_1.realpath)(p.rootPath)))}'\n`;
}));
const cordovaPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
cordovaPlugins.map(async (p) => {
const podspecs = (0, plugin_1.getPlatformElement)(p, platform, 'podspec');
podspecs.map((podspec) => {
podspec.pods.map((pPods) => {
pPods.pod.map((pod) => {
if (pod.$.git) {
let gitRef = '';
if (pod.$.tag) {
gitRef = `, :tag => '${pod.$.tag}'`;
}
else if (pod.$.branch) {
gitRef = `, :branch => '${pod.$.branch}'`;
}
else if (pod.$.commit) {
gitRef = `, :commit => '${pod.$.commit}'`;
}
pods.push(` pod '${pod.$.name}', :git => '${pod.$.git}'${gitRef}\n`);
}
});
});
});
});
const staticPlugins = cordovaPlugins.filter(p => (0, cordova_1.needsStaticPod)(p, config));
const noStaticPlugins = cordovaPlugins.filter(el => !staticPlugins.includes(el));
if (noStaticPlugins.length > 0) {
pods.push(` pod 'CordovaPlugins', :path => '../capacitor-cordova-ios-plugins'\n`);
}
if (staticPlugins.length > 0) {
pods.push(` pod 'CordovaPluginsStatic', :path => '../capacitor-cordova-ios-plugins'\n`);
}
const resourcesPlugins = cordovaPlugins.filter(filterResources);
if (resourcesPlugins.length > 0) {
pods.push(` pod 'CordovaPluginsResources', :path => '../capacitor-cordova-ios-plugins'\n`);
}
return `
pod 'Capacitor', :path => '${relativeCapacitoriOSPath}'
pod 'CapacitorCordova', :path => '${relativeCapacitoriOSPath}'
${pods.join('').trimRight()}`;
}
function getFrameworkName(framework) {
if (isFramework(framework)) {
if (framework.$.custom && framework.$.custom === 'true') {
return framework.$.src;
}
return framework.$.src.substr(0, framework.$.src.indexOf('.'));
}
return framework.$.src
.substr(0, framework.$.src.indexOf('.'))
.replace('lib', '');
}
function isFramework(framework) {
return framework.$.src.split('.').pop().includes('framework');
}
async function generateCordovaPodspecs(cordovaPlugins, config) {
const staticPlugins = cordovaPlugins.filter(p => (0, cordova_1.needsStaticPod)(p, config));
const noStaticPlugins = cordovaPlugins.filter(el => !staticPlugins.includes(el));
generateCordovaPodspec(noStaticPlugins, config, false);
generateCordovaPodspec(staticPlugins, config, true);
}
async function generateCordovaPodspec(cordovaPlugins, config, isStatic) {
const weakFrameworks = [];
const linkedFrameworks = [];
const customFrameworks = [];
const systemLibraries = [];
const sourceFrameworks = [];
const frameworkDeps = [];
const compilerFlags = [];
let prefsArray = [];
let name = 'CordovaPlugins';
let sourcesFolderName = 'sources';
if (isStatic) {
name += 'Static';
frameworkDeps.push('s.static_framework = true');
sourcesFolderName += 'static';
}
cordovaPlugins.map((plugin) => {
const frameworks = (0, plugin_1.getPlatformElement)(plugin, platform, 'framework');
frameworks.map((framework) => {
if (!framework.$.type) {
const name = getFrameworkName(framework);
if (isFramework(framework)) {
if (framework.$.weak && framework.$.weak === 'true') {
if (!weakFrameworks.includes(name)) {
weakFrameworks.push(name);
}
}
else if (framework.$.custom && framework.$.custom === 'true') {
const frameworktPath = (0, path_1.join)(sourcesFolderName, plugin.name, name);
if (!customFrameworks.includes(frameworktPath)) {
customFrameworks.push(frameworktPath);
}
}
else {
if (!linkedFrameworks.includes(name)) {
linkedFrameworks.push(name);
}
}
}
else {
if (!systemLibraries.includes(name)) {
systemLibraries.push(name);
}
}
}
else if (framework.$.type && framework.$.type === 'podspec') {
let depString = `s.dependency '${framework.$.src}'`;
if (framework.$.spec && framework.$.spec !== '') {
depString += `, '${framework.$.spec}'`;
}
if (!frameworkDeps.includes(depString)) {
frameworkDeps.push(depString);
}
}
});
prefsArray = prefsArray.concat((0, plugin_1.getAllElements)(plugin, platform, 'preference'));
const podspecs = (0, plugin_1.getPlatformElement)(plugin, platform, 'podspec');
podspecs.map((podspec) => {
podspec.pods.map((pods) => {
pods.pod.map((pod) => {
let depString = `s.dependency '${pod.$.name}'`;
if (pod.$.spec && pod.$.spec !== '') {
depString += `, '${pod.$.spec}'`;
}
if (!frameworkDeps.includes(depString)) {
frameworkDeps.push(depString);
}
});
});
});
const sourceFiles = (0, plugin_1.getPlatformElement)(plugin, platform, 'source-file');
sourceFiles.map((sourceFile) => {
if (sourceFile.$.framework && sourceFile.$.framework === 'true') {
let fileName = sourceFile.$.src.split('/').pop();
if (!fileName.startsWith('lib')) {
fileName = 'lib' + fileName;
}
const frameworktPath = (0, path_1.join)(sourcesFolderName, plugin.name, fileName);
if (!sourceFrameworks.includes(frameworktPath)) {
sourceFrameworks.push(frameworktPath);
}
}
else if (sourceFile.$['compiler-flags']) {
const cFlag = sourceFile.$['compiler-flags'];
if (!compilerFlags.includes(cFlag)) {
compilerFlags.push(cFlag);
}
}
});
});
const onlySystemLibraries = systemLibraries.filter(library => removeNoSystem(library, sourceFrameworks));
if (weakFrameworks.length > 0) {
frameworkDeps.push(`s.weak_frameworks = '${weakFrameworks.join(`', '`)}'`);
}
if (linkedFrameworks.length > 0) {
frameworkDeps.push(`s.frameworks = '${linkedFrameworks.join(`', '`)}'`);
}
if (onlySystemLibraries.length > 0) {
frameworkDeps.push(`s.libraries = '${onlySystemLibraries.join(`', '`)}'`);
}
if (customFrameworks.length > 0) {
frameworkDeps.push(`s.vendored_frameworks = '${customFrameworks.join(`', '`)}'`);
frameworkDeps.push(`s.exclude_files = 'sources/**/*.framework/Headers/*.h', 'sources/**/*.framework/PrivateHeaders/*.h'`);
}
if (sourceFrameworks.length > 0) {
frameworkDeps.push(`s.vendored_libraries = '${sourceFrameworks.join(`', '`)}'`);
}
if (compilerFlags.length > 0) {
frameworkDeps.push(`s.compiler_flags = '${compilerFlags.join(' ')}'`);
}
const arcPlugins = cordovaPlugins.filter(filterARCFiles);
if (arcPlugins.length > 0) {
frameworkDeps.push(`s.subspec 'noarc' do |sna|
sna.requires_arc = false
sna.source_files = 'noarc/**/*.{swift,h,m,c,cc,mm,cpp}'
end`);
}
let frameworksString = frameworkDeps.join('\n ');
frameworksString = await replaceFrameworkVariables(config, prefsArray, frameworksString);
const content = `
Pod::Spec.new do |s|
s.name = '${name}'
s.version = '${config.cli.package.version}'
s.summary = 'Autogenerated spec'
s.license = 'Unknown'
s.homepage = 'https://example.com'
s.authors = { 'Capacitor Generator' => 'hi@example.com' }
s.source = { :git => 'https://github.com/ionic-team/does-not-exist.git', :tag => '${config.cli.package.version}' }
s.source_files = '${sourcesFolderName}/**/*.{swift,h,m,c,cc,mm,cpp}'
s.ios.deployment_target = '${config.ios.minVersion}'
s.xcconfig = {'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1 WK_WEB_VIEW_ONLY=1' }
s.dependency 'CapacitorCordova'${getLinkerFlags(config)}
s.swift_version = '5.1'
${frameworksString}
end`;
await (0, utils_fs_1.writeFile)((0, path_1.join)(config.ios.cordovaPluginsDirAbs, `${name}.podspec`), content);
}
function getLinkerFlags(config) {
var _a;
if ((_a = config.app.extConfig.ios) === null || _a === void 0 ? void 0 : _a.cordovaLinkerFlags) {
return `\n s.pod_target_xcconfig = { 'OTHER_LDFLAGS' => '${config.app.extConfig.ios.cordovaLinkerFlags.join(' ')}' }`;
}
return '';
}
async function copyPluginsNativeFiles(config, cordovaPlugins) {
for (const p of cordovaPlugins) {
const sourceFiles = (0, plugin_1.getPlatformElement)(p, platform, 'source-file');
const headerFiles = (0, plugin_1.getPlatformElement)(p, platform, 'header-file');
const codeFiles = sourceFiles.concat(headerFiles);
const frameworks = (0, plugin_1.getPlatformElement)(p, platform, 'framework');
let sourcesFolderName = 'sources';
if ((0, cordova_1.needsStaticPod)(p, config)) {
sourcesFolderName += 'static';
}
const sourcesFolder = (0, path_1.join)(config.ios.cordovaPluginsDirAbs, sourcesFolderName, p.name);
for (const codeFile of codeFiles) {
let fileName = codeFile.$.src.split('/').pop();
const fileExt = codeFile.$.src.split('.').pop();
if (fileExt === 'a' && !fileName.startsWith('lib')) {
fileName = 'lib' + fileName;
}
let destFolder = sourcesFolderName;
if (codeFile.$['compiler-flags'] &&
codeFile.$['compiler-flags'] === '-fno-objc-arc') {
destFolder = 'noarc';
}
const filePath = (0, plugin_1.getFilePath)(config, p, codeFile.$.src);
const fileDest = (0, path_1.join)(config.ios.cordovaPluginsDirAbs, destFolder, p.name, fileName);
await (0, utils_fs_1.copy)(filePath, fileDest);
if (!codeFile.$.framework) {
let fileContent = await (0, utils_fs_1.readFile)(fileDest, { encoding: 'utf-8' });
if (fileExt === 'swift') {
fileContent = 'import Cordova\n' + fileContent;
await (0, utils_fs_1.writeFile)(fileDest, fileContent, { encoding: 'utf-8' });
}
else {
if (fileContent.includes('@import Firebase;')) {
fileContent = fileContent.replace('@import Firebase;', '#import <Firebase/Firebase.h>');
await (0, utils_fs_1.writeFile)(fileDest, fileContent, { encoding: 'utf-8' });
}
if (fileContent.includes('[NSBundle bundleForClass:[self class]]') ||
fileContent.includes('[NSBundle bundleForClass:[CDVCapture class]]')) {
fileContent = fileContent.replace('[NSBundle bundleForClass:[self class]]', '[NSBundle mainBundle]');
fileContent = fileContent.replace('[NSBundle bundleForClass:[CDVCapture class]]', '[NSBundle mainBundle]');
await (0, utils_fs_1.writeFile)(fileDest, fileContent, { encoding: 'utf-8' });
}
if (fileContent.includes('[self.webView superview]') ||
fileContent.includes('self.webView.superview')) {
fileContent = fileContent.replace(/\[self.webView superview\]/g, 'self.viewController.view');
fileContent = fileContent.replace(/self.webView.superview/g, 'self.viewController.view');
await (0, utils_fs_1.writeFile)(fileDest, fileContent, { encoding: 'utf-8' });
}
}
}
}
const resourceFiles = (0, plugin_1.getPlatformElement)(p, platform, 'resource-file');
for (const resourceFile of resourceFiles) {
const fileName = resourceFile.$.src.split('/').pop();
await (0, utils_fs_1.copy)((0, plugin_1.getFilePath)(config, p, resourceFile.$.src), (0, path_1.join)(config.ios.cordovaPluginsDirAbs, 'resources', fileName));
}
for (const framework of frameworks) {
if (framework.$.custom && framework.$.custom === 'true') {
await (0, utils_fs_1.copy)((0, plugin_1.getFilePath)(config, p, framework.$.src), (0, path_1.join)(sourcesFolder, framework.$.src));
}
}
}
}
async function removePluginsNativeFiles(config) {
await (0, utils_fs_1.remove)(config.ios.cordovaPluginsDirAbs);
await (0, template_1.extractTemplate)(config.cli.assets.ios.cordovaPluginsTemplateArchiveAbs, config.ios.cordovaPluginsDirAbs);
}
function filterResources(plugin) {
const resources = (0, plugin_1.getPlatformElement)(plugin, platform, 'resource-file');
return resources.length > 0;
}
function filterARCFiles(plugin) {
const sources = (0, plugin_1.getPlatformElement)(plugin, platform, 'source-file');
const sourcesARC = sources.filter((sourceFile) => sourceFile.$['compiler-flags'] &&
sourceFile.$['compiler-flags'] === '-fno-objc-arc');
return sourcesARC.length > 0;
}
function removeNoSystem(library, sourceFrameworks) {
const libraries = sourceFrameworks.filter(framework => framework.includes(library));
return libraries.length === 0;
}
async function getPluginsTask(config) {
return await (0, common_1.runTask)('Updating iOS plugins', async () => {
const allPlugins = await (0, plugin_1.getPlugins)(config, 'ios');
const iosPlugins = await (0, common_2.getIOSPlugins)(allPlugins);
return iosPlugins;
});
}
async function replaceFrameworkVariables(config, prefsArray, frameworkString) {
prefsArray.map((preference) => {
frameworkString = frameworkString.replace(new RegExp(('$' + preference.$.name).replace('$', '\\$&'), 'g'), preference.$.default);
});
return frameworkString;
}

61
@capacitor/cli/dist/ipc.js vendored Normal file
View file

@ -0,0 +1,61 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.receive = exports.send = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const utils_subprocess_1 = require("@ionic/utils-subprocess");
const debug_1 = tslib_1.__importDefault(require("debug"));
const https_1 = require("https");
const path_1 = require("path");
const cli_1 = require("./util/cli");
const debug = (0, debug_1.default)('capacitor:ipc');
/**
* Send an IPC message to a forked process.
*/
async function send(msg) {
const dir = cli_1.ENV_PATHS.log;
await (0, utils_fs_1.mkdirp)(dir);
const logPath = (0, path_1.resolve)(dir, 'ipc.log');
debug('Sending %O IPC message to forked process (logs: %O)', msg.type, logPath);
const fd = await (0, utils_fs_1.open)(logPath, 'a');
const p = (0, utils_subprocess_1.fork)(process.argv[1], ['📡'], { stdio: ['ignore', fd, fd, 'ipc'] });
p.send(msg);
p.disconnect();
p.unref();
}
exports.send = send;
/**
* Receive and handle an IPC message.
*
* Assume minimal context and keep external dependencies to a minimum.
*/
async function receive(msg) {
debug('Received %O IPC message', msg.type);
if (msg.type === 'telemetry') {
const now = new Date().toISOString();
const { data } = msg;
// This request is only made if telemetry is on.
const req = (0, https_1.request)({
hostname: 'api.ionicjs.com',
port: 443,
path: '/events/metrics',
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
}, response => {
debug('Sent %O metric to events service (status: %O)', data.name, response.statusCode);
if (response.statusCode !== 204) {
response.on('data', chunk => {
debug('Bad response from events service. Request body: %O', chunk.toString());
});
}
});
const body = {
metrics: [data],
sent_at: now,
};
req.end(JSON.stringify(body));
}
}
exports.receive = receive;

41
@capacitor/cli/dist/log.js vendored Normal file
View file

@ -0,0 +1,41 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.logSuccess = exports.logPrompt = exports.logger = exports.output = void 0;
const tslib_1 = require("tslib");
const cli_framework_output_1 = require("@ionic/cli-framework-output");
const colors_1 = tslib_1.__importDefault(require("./colors"));
const term_1 = require("./util/term");
const options = {
colors: colors_1.default,
stream: process.argv.includes('--json') ? process.stderr : process.stdout,
};
exports.output = (0, term_1.isInteractive)()
? new cli_framework_output_1.TTYOutputStrategy(options)
: new cli_framework_output_1.StreamOutputStrategy(options);
exports.logger = (0, cli_framework_output_1.createDefaultLogger)({
output: exports.output,
formatterOptions: {
titleize: false,
tags: new Map([
[cli_framework_output_1.LOGGER_LEVELS.DEBUG, colors_1.default.log.DEBUG('[debug]')],
[cli_framework_output_1.LOGGER_LEVELS.INFO, colors_1.default.log.INFO('[info]')],
[cli_framework_output_1.LOGGER_LEVELS.WARN, colors_1.default.log.WARN('[warn]')],
[cli_framework_output_1.LOGGER_LEVELS.ERROR, colors_1.default.log.ERROR('[error]')],
]),
},
});
async function logPrompt(msg, promptObject) {
const { wordWrap } = await Promise.resolve().then(() => tslib_1.__importStar(require('@ionic/cli-framework-output')));
const { prompt } = await Promise.resolve().then(() => tslib_1.__importStar(require('prompts')));
exports.logger.log({
msg: `${colors_1.default.input('[?]')} ${wordWrap(msg, { indentation: 4 })}`,
logger: exports.logger,
format: false,
});
return prompt(promptObject, { onCancel: () => process.exit(1) });
}
exports.logPrompt = logPrompt;
function logSuccess(msg) {
exports.logger.msg(`${colors_1.default.success('[success]')} ${msg}`);
}
exports.logSuccess = logSuccess;

186
@capacitor/cli/dist/plugin.js vendored Normal file
View file

@ -0,0 +1,186 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAllElements = exports.getFilePath = exports.getAssets = exports.getJSModules = exports.getPluginType = exports.getPlatformElement = exports.getPluginPlatform = exports.printPlugins = exports.fixName = exports.getDependencies = exports.resolvePlugin = exports.getPlugins = exports.getIncludedPluginPackages = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("./colors"));
const errors_1 = require("./errors");
const log_1 = require("./log");
const node_1 = require("./util/node");
const xml_1 = require("./util/xml");
function getIncludedPluginPackages(config, platform) {
var _a, _b, _c, _d;
const { extConfig } = config.app;
switch (platform) {
case 'android':
return (_b = (_a = extConfig.android) === null || _a === void 0 ? void 0 : _a.includePlugins) !== null && _b !== void 0 ? _b : extConfig.includePlugins;
case 'ios':
return (_d = (_c = extConfig.ios) === null || _c === void 0 ? void 0 : _c.includePlugins) !== null && _d !== void 0 ? _d : extConfig.includePlugins;
}
}
exports.getIncludedPluginPackages = getIncludedPluginPackages;
async function getPlugins(config, platform) {
var _a;
const possiblePlugins = (_a = getIncludedPluginPackages(config, platform)) !== null && _a !== void 0 ? _a : getDependencies(config);
const resolvedPlugins = await Promise.all(possiblePlugins.map(async (p) => resolvePlugin(config, p)));
return resolvedPlugins.filter((p) => !!p);
}
exports.getPlugins = getPlugins;
async function resolvePlugin(config, name) {
try {
const packagePath = (0, node_1.resolveNode)(config.app.rootDir, name, 'package.json');
if (!packagePath) {
(0, errors_1.fatal)(`Unable to find ${colors_1.default.strong(`node_modules/${name}`)}.\n` +
`Are you sure ${colors_1.default.strong(name)} is installed?`);
}
const rootPath = (0, path_1.dirname)(packagePath);
const meta = await (0, utils_fs_1.readJSON)(packagePath);
if (!meta) {
return null;
}
if (meta.capacitor) {
return {
id: name,
name: fixName(name),
version: meta.version,
rootPath,
repository: meta.repository,
manifest: meta.capacitor,
};
}
const pluginXMLPath = (0, path_1.join)(rootPath, 'plugin.xml');
const xmlMeta = await (0, xml_1.readXML)(pluginXMLPath);
return {
id: name,
name: fixName(name),
version: meta.version,
rootPath: rootPath,
repository: meta.repository,
xml: xmlMeta.plugin,
};
}
catch (e) {
// ignore
}
return null;
}
exports.resolvePlugin = resolvePlugin;
function getDependencies(config) {
var _a, _b;
return [
...Object.keys((_a = config.app.package.dependencies) !== null && _a !== void 0 ? _a : {}),
...Object.keys((_b = config.app.package.devDependencies) !== null && _b !== void 0 ? _b : {}),
];
}
exports.getDependencies = getDependencies;
function fixName(name) {
name = name
.replace(/\//g, '_')
.replace(/-/g, '_')
.replace(/@/g, '')
.replace(/_\w/g, m => m[1].toUpperCase());
return name.charAt(0).toUpperCase() + name.slice(1);
}
exports.fixName = fixName;
function printPlugins(plugins, platform, type = 'capacitor') {
if (plugins.length === 0) {
return;
}
let msg;
const plural = plugins.length === 1 ? '' : 's';
switch (type) {
case 'cordova':
msg = `Found ${plugins.length} Cordova plugin${plural} for ${colors_1.default.strong(platform)}:\n`;
break;
case 'incompatible':
msg = `Found ${plugins.length} incompatible Cordova plugin${plural} for ${colors_1.default.strong(platform)}, skipped install:\n`;
break;
case 'capacitor':
msg = `Found ${plugins.length} Capacitor plugin${plural} for ${colors_1.default.strong(platform)}:\n`;
break;
}
msg += plugins.map(p => `${p.id}${colors_1.default.weak(`@${p.version}`)}`).join('\n');
log_1.logger.info(msg);
}
exports.printPlugins = printPlugins;
function getPluginPlatform(p, platform) {
const platforms = p.xml.platform;
if (platforms) {
const platforms = p.xml.platform.filter(function (item) {
return item.$.name === platform;
});
return platforms[0];
}
return [];
}
exports.getPluginPlatform = getPluginPlatform;
function getPlatformElement(p, platform, elementName) {
const platformTag = getPluginPlatform(p, platform);
if (platformTag) {
const element = platformTag[elementName];
if (element) {
return element;
}
}
return [];
}
exports.getPlatformElement = getPlatformElement;
function getPluginType(p, platform) {
var _a, _b, _c, _d;
switch (platform) {
case 'ios':
return (_b = (_a = p.ios) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : 0 /* PluginType.Core */;
case 'android':
return (_d = (_c = p.android) === null || _c === void 0 ? void 0 : _c.type) !== null && _d !== void 0 ? _d : 0 /* PluginType.Core */;
}
return 0 /* PluginType.Core */;
}
exports.getPluginType = getPluginType;
/**
* Get each JavaScript Module for the given plugin
*/
function getJSModules(p, platform) {
return getAllElements(p, platform, 'js-module');
}
exports.getJSModules = getJSModules;
/**
* Get each asset tag for the given plugin
*/
function getAssets(p, platform) {
return getAllElements(p, platform, 'asset');
}
exports.getAssets = getAssets;
function getFilePath(config, plugin, path) {
if (path.startsWith('node_modules')) {
let pathSegments = path.split('/').slice(1);
if (pathSegments[0].startsWith('@')) {
pathSegments = [
pathSegments[0] + '/' + pathSegments[1],
...pathSegments.slice(2),
];
}
const filePath = (0, node_1.resolveNode)(config.app.rootDir, ...pathSegments);
if (!filePath) {
throw new Error(`Can't resolve module ${pathSegments[0]}`);
}
return filePath;
}
return (0, path_1.join)(plugin.rootPath, path);
}
exports.getFilePath = getFilePath;
/**
* For a given plugin, return all the plugin.xml elements with elementName, checking root and specified platform
*/
function getAllElements(p, platform, elementName) {
let modules = [];
if (p.xml[elementName]) {
modules = modules.concat(p.xml[elementName]);
}
const platformModules = getPluginPlatform(p, platform);
if (platformModules === null || platformModules === void 0 ? void 0 : platformModules[elementName]) {
modules = modules.concat(platformModules[elementName]);
}
return modules;
}
exports.getAllElements = getAllElements;

35
@capacitor/cli/dist/sysconfig.js vendored Normal file
View file

@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.writeConfig = exports.readConfig = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const debug_1 = tslib_1.__importDefault(require("debug"));
const path_1 = require("path");
const cli_1 = require("./util/cli");
const uuid_1 = require("./util/uuid");
const debug = (0, debug_1.default)('capacitor:sysconfig');
const SYSCONFIG_FILE = 'sysconfig.json';
const SYSCONFIG_PATH = (0, path_1.resolve)(cli_1.ENV_PATHS.config, SYSCONFIG_FILE);
async function readConfig() {
debug('Reading from %O', SYSCONFIG_PATH);
try {
return await (0, utils_fs_1.readJSON)(SYSCONFIG_PATH);
}
catch (e) {
if (e.code !== 'ENOENT') {
throw e;
}
const sysconfig = {
machine: (0, uuid_1.uuidv4)(),
};
await writeConfig(sysconfig);
return sysconfig;
}
}
exports.readConfig = readConfig;
async function writeConfig(sysconfig) {
debug('Writing to %O', SYSCONFIG_PATH);
await (0, utils_fs_1.mkdirp)((0, path_1.dirname)(SYSCONFIG_PATH));
await (0, utils_fs_1.writeJSON)(SYSCONFIG_PATH, sysconfig, { spaces: '\t' });
}
exports.writeConfig = writeConfig;

122
@capacitor/cli/dist/tasks/add.js vendored Normal file
View file

@ -0,0 +1,122 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.addCommand = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const utils_terminal_1 = require("@ionic/utils-terminal");
const add_1 = require("../android/add");
const common_1 = require("../android/common");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_2 = require("../common");
const errors_1 = require("../errors");
const add_2 = require("../ios/add");
const common_3 = require("../ios/common");
const log_1 = require("../log");
const sync_1 = require("./sync");
async function addCommand(config, selectedPlatformName) {
var _a;
if (selectedPlatformName && !(await (0, common_2.isValidPlatform)(selectedPlatformName))) {
const platformDir = (0, common_2.resolvePlatform)(config, selectedPlatformName);
if (platformDir) {
await (0, common_2.runPlatformHook)(config, selectedPlatformName, platformDir, 'capacitor:add');
}
else {
let msg = `Platform ${colors_1.default.input(selectedPlatformName)} not found.`;
if (await (0, common_2.isValidCommunityPlatform)(selectedPlatformName)) {
msg += `\nTry installing ${colors_1.default.strong(`@capacitor-community/${selectedPlatformName}`)} and adding the platform again.`;
}
if (await (0, common_2.isValidEnterprisePlatform)(selectedPlatformName)) {
msg +=
`\nThis is an enterprise platform and @ionic-enterprise/capacitor-${selectedPlatformName} is not installed.\n` +
`To learn how to use this platform, visit https://ionic.io/docs/${selectedPlatformName}`;
}
log_1.logger.error(msg);
}
}
else {
const knownPlatforms = await (0, common_2.getKnownPlatforms)();
const platformName = await (0, common_2.promptForPlatform)(knownPlatforms, `Please choose a platform to add:`, selectedPlatformName);
if (platformName === config.web.name) {
webWarning();
return;
}
const existingPlatformDir = await (0, common_2.getProjectPlatformDirectory)(config, platformName);
if (existingPlatformDir) {
(0, errors_1.fatal)(`${colors_1.default.input(platformName)} platform already exists.\n` +
`To re-add this platform, first remove ${colors_1.default.strong((0, utils_terminal_1.prettyPath)(existingPlatformDir))}, then run this command again.\n` +
`${colors_1.default.strong('WARNING')}: Your native project will be completely removed.`);
}
try {
await (0, common_2.check)([
() => (0, common_2.checkPackage)(),
() => (0, common_2.checkAppConfig)(config),
...addChecks(config, platformName),
]);
await doAdd(config, platformName);
await editPlatforms(config, platformName);
if (await (0, utils_fs_1.pathExists)(config.app.webDirAbs)) {
await (0, sync_1.sync)(config, platformName, false, false);
if (platformName === config.android.name) {
await (0, common_2.runTask)('Syncing Gradle', async () => {
return (0, add_1.createLocalProperties)(config.android.platformDirAbs);
});
}
}
else {
log_1.logger.warn(`${colors_1.default.success(colors_1.default.strong('sync'))} could not run--missing ${colors_1.default.strong(config.app.webDir)} directory.`);
}
printNextSteps(platformName);
}
catch (e) {
if (!(0, errors_1.isFatal)(e)) {
(0, errors_1.fatal)((_a = e.stack) !== null && _a !== void 0 ? _a : e);
}
throw e;
}
}
}
exports.addCommand = addCommand;
function printNextSteps(platformName) {
(0, log_1.logSuccess)(`${colors_1.default.strong(platformName)} platform added!`);
log_1.output.write(`Follow the Developer Workflow guide to get building:\n${colors_1.default.strong(`https://capacitorjs.com/docs/basics/workflow`)}\n`);
}
function addChecks(config, platformName) {
if (platformName === config.ios.name) {
return [
() => (0, common_3.checkIOSPackage)(config),
() => (0, common_3.checkBundler)(config) || (0, common_3.checkCocoaPods)(config),
];
}
else if (platformName === config.android.name) {
return [() => (0, common_1.checkAndroidPackage)(config)];
}
else if (platformName === config.web.name) {
return [];
}
else {
throw `Platform ${platformName} is not valid.`;
}
}
async function doAdd(config, platformName) {
await (0, common_2.runTask)(colors_1.default.success(colors_1.default.strong('add')), async () => {
if (platformName === config.ios.name) {
await (0, add_2.addIOS)(config);
}
else if (platformName === config.android.name) {
await (0, add_1.addAndroid)(config);
}
});
}
async function editPlatforms(config, platformName) {
if (platformName === config.ios.name) {
await (0, common_3.editProjectSettingsIOS)(config);
}
else if (platformName === config.android.name) {
await (0, common_1.editProjectSettingsAndroid)(config);
}
}
function webWarning() {
log_1.logger.error(`Not adding platform ${colors_1.default.strong('web')}.\n` +
`In Capacitor, the web platform is just your web app! For example, if you have a React or Angular project, the web platform is that project.\n` +
`To add Capacitor functionality to your web app, follow the Web Getting Started Guide: ${colors_1.default.strong('https://capacitorjs.com/docs/web')}`);
}

62
@capacitor/cli/dist/tasks/build.js vendored Normal file
View file

@ -0,0 +1,62 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.build = exports.buildCommand = void 0;
const build_1 = require("../android/build");
const common_1 = require("../common");
const errors_1 = require("../errors");
const build_2 = require("../ios/build");
async function buildCommand(config, selectedPlatformName, buildOptions) {
var _a;
const platforms = await (0, common_1.selectPlatforms)(config, selectedPlatformName);
let platformName;
if (platforms.length === 1) {
platformName = platforms[0];
}
else {
platformName = await (0, common_1.promptForPlatform)(platforms.filter(createBuildablePlatformFilter(config)), `Please choose a platform to build for:`);
}
const buildCommandOptions = {
scheme: buildOptions.scheme || config.ios.scheme,
flavor: buildOptions.flavor || config.android.flavor,
keystorepath: buildOptions.keystorepath || config.android.buildOptions.keystorePath,
keystorepass: buildOptions.keystorepass || config.android.buildOptions.keystorePassword,
keystorealias: buildOptions.keystorealias || config.android.buildOptions.keystoreAlias,
keystorealiaspass: buildOptions.keystorealiaspass ||
config.android.buildOptions.keystoreAliasPassword,
androidreleasetype: buildOptions.androidreleasetype ||
config.android.buildOptions.releaseType ||
'AAB',
signingtype: buildOptions.signingtype ||
config.android.buildOptions.signingType ||
'jarsigner',
configuration: buildOptions.configuration || 'Release',
};
try {
await build(config, platformName, buildCommandOptions);
}
catch (e) {
if (!(0, errors_1.isFatal)(e)) {
(0, errors_1.fatal)((_a = e.stack) !== null && _a !== void 0 ? _a : e);
}
throw e;
}
}
exports.buildCommand = buildCommand;
async function build(config, platformName, buildOptions) {
if (platformName == config.ios.name) {
await (0, build_2.buildiOS)(config, buildOptions);
}
else if (platformName === config.android.name) {
await (0, build_1.buildAndroid)(config, buildOptions);
}
else if (platformName === config.web.name) {
throw `Platform "${platformName}" is not available in the build command.`;
}
else {
throw `Platform "${platformName}" is not valid.`;
}
}
exports.build = build;
function createBuildablePlatformFilter(config) {
return platform => platform === config.ios.name || platform === config.android.name;
}

31
@capacitor/cli/dist/tasks/config.js vendored Normal file
View file

@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.configCommand = void 0;
const tslib_1 = require("tslib");
const util_1 = tslib_1.__importDefault(require("util"));
const log_1 = require("../log");
async function configCommand(config, json) {
const evaluatedConfig = await deepAwait(config);
if (json) {
process.stdout.write(`${JSON.stringify(evaluatedConfig)}\n`);
}
else {
log_1.output.write(`${util_1.default.inspect(evaluatedConfig, { depth: Infinity, colors: true })}\n`);
}
}
exports.configCommand = configCommand;
async function deepAwait(obj) {
if (obj &&
!Array.isArray(obj) &&
typeof obj === 'object' &&
obj.constructor === Object) {
const o = {};
for (const [k, v] of Object.entries(obj)) {
o[k] = await deepAwait(v);
}
return o;
}
else {
return await obj;
}
}

216
@capacitor/cli/dist/tasks/copy.js vendored Normal file
View file

@ -0,0 +1,216 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.copy = exports.copyCommand = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
const cordova_1 = require("../cordova");
const errors_1 = require("../errors");
const common_2 = require("../ios/common");
const log_1 = require("../log");
const plugin_1 = require("../plugin");
const iosplugin_1 = require("../util/iosplugin");
const promise_1 = require("../util/promise");
const copy_1 = require("../web/copy");
const sourcemaps_1 = require("./sourcemaps");
async function copyCommand(config, selectedPlatformName, inline = false) {
var _a;
if (selectedPlatformName && !(await (0, common_1.isValidPlatform)(selectedPlatformName))) {
const platformDir = (0, common_1.resolvePlatform)(config, selectedPlatformName);
if (platformDir) {
await (0, common_1.runPlatformHook)(config, selectedPlatformName, platformDir, 'capacitor:copy');
}
else {
log_1.logger.error(`Platform ${colors_1.default.input(selectedPlatformName)} not found.`);
}
}
else {
const platforms = await (0, common_1.selectPlatforms)(config, selectedPlatformName);
try {
await (0, promise_1.allSerial)(platforms.map(platformName => () => copy(config, platformName, inline)));
}
catch (e) {
if ((0, errors_1.isFatal)(e)) {
throw e;
}
log_1.logger.error((_a = e.stack) !== null && _a !== void 0 ? _a : e);
}
}
}
exports.copyCommand = copyCommand;
async function copy(config, platformName, inline = false) {
await (0, common_1.runTask)(colors_1.default.success(colors_1.default.strong(`copy ${platformName}`)), async () => {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
const result = await (0, common_1.checkWebDir)(config);
if (result) {
throw result;
}
await (0, common_1.runHooks)(config, platformName, config.app.rootDir, 'capacitor:copy:before');
const allPlugins = await (0, plugin_1.getPlugins)(config, platformName);
let usesFederatedCapacitor = false;
if (allPlugins.filter(plugin => plugin.id === '@ionic-enterprise/federated-capacitor').length > 0) {
usesFederatedCapacitor = true;
}
let usesLiveUpdates = false;
if (allPlugins.filter(plugin => plugin.id === '@capacitor/live-updates')
.length > 0) {
usesLiveUpdates = true;
}
let usesSSLPinning = false;
if (allPlugins.filter(plugin => plugin.id === '@ionic-enterprise/ssl-pinning')
.length > 0) {
usesSSLPinning = true;
}
if (platformName === config.ios.name) {
if (usesFederatedCapacitor) {
await copyFederatedWebDirs(config, await config.ios.webDirAbs);
if ((_c = (_b = (_a = config.app.extConfig) === null || _a === void 0 ? void 0 : _a.plugins) === null || _b === void 0 ? void 0 : _b.FederatedCapacitor) === null || _c === void 0 ? void 0 : _c.liveUpdatesKey) {
await copySecureLiveUpdatesKey(config.app.extConfig.plugins.FederatedCapacitor.liveUpdatesKey, config.app.rootDir, config.ios.nativeTargetDirAbs);
}
}
else {
await copyWebDir(config, await config.ios.webDirAbs, config.app.webDirAbs);
}
if (usesLiveUpdates && ((_f = (_e = (_d = config.app.extConfig) === null || _d === void 0 ? void 0 : _d.plugins) === null || _e === void 0 ? void 0 : _e.LiveUpdates) === null || _f === void 0 ? void 0 : _f.key)) {
await copySecureLiveUpdatesKey(config.app.extConfig.plugins.LiveUpdates.key, config.app.rootDir, config.ios.nativeTargetDirAbs);
}
if (usesSSLPinning && ((_j = (_h = (_g = config.app.extConfig) === null || _g === void 0 ? void 0 : _g.plugins) === null || _h === void 0 ? void 0 : _h.SSLPinning) === null || _j === void 0 ? void 0 : _j.certs)) {
await copySSLCert((_k = config.app.extConfig.plugins.SSLPinning) === null || _k === void 0 ? void 0 : _k.certs, config.app.rootDir, await config.ios.webDirAbs);
}
await copyCapacitorConfig(config, config.ios.nativeTargetDirAbs);
const cordovaPlugins = await (0, cordova_1.getCordovaPlugins)(config, platformName);
await (0, cordova_1.handleCordovaPluginsJS)(cordovaPlugins, config, platformName);
const iosPlugins = await (0, common_2.getIOSPlugins)(allPlugins);
await (0, iosplugin_1.generateIOSPackageJSON)(config, iosPlugins);
}
else if (platformName === config.android.name) {
if (usesFederatedCapacitor) {
await copyFederatedWebDirs(config, config.android.webDirAbs);
if ((_o = (_m = (_l = config.app.extConfig) === null || _l === void 0 ? void 0 : _l.plugins) === null || _m === void 0 ? void 0 : _m.FederatedCapacitor) === null || _o === void 0 ? void 0 : _o.liveUpdatesKey) {
await copySecureLiveUpdatesKey(config.app.extConfig.plugins.FederatedCapacitor.liveUpdatesKey, config.app.rootDir, config.android.assetsDirAbs);
}
}
else {
await copyWebDir(config, config.android.webDirAbs, config.app.webDirAbs);
}
if (usesLiveUpdates && ((_r = (_q = (_p = config.app.extConfig) === null || _p === void 0 ? void 0 : _p.plugins) === null || _q === void 0 ? void 0 : _q.LiveUpdates) === null || _r === void 0 ? void 0 : _r.key)) {
await copySecureLiveUpdatesKey(config.app.extConfig.plugins.LiveUpdates.key, config.app.rootDir, config.android.assetsDirAbs);
}
if (usesSSLPinning && ((_u = (_t = (_s = config.app.extConfig) === null || _s === void 0 ? void 0 : _s.plugins) === null || _t === void 0 ? void 0 : _t.SSLPinning) === null || _u === void 0 ? void 0 : _u.certs)) {
await copySSLCert((_v = config.app.extConfig.plugins.SSLPinning) === null || _v === void 0 ? void 0 : _v.certs, config.app.rootDir, config.android.assetsDirAbs);
}
await copyCapacitorConfig(config, config.android.assetsDirAbs);
const cordovaPlugins = await (0, cordova_1.getCordovaPlugins)(config, platformName);
await (0, cordova_1.handleCordovaPluginsJS)(cordovaPlugins, config, platformName);
await (0, cordova_1.writeCordovaAndroidManifest)(cordovaPlugins, config, platformName);
}
else if (platformName === config.web.name) {
if (usesFederatedCapacitor) {
log_1.logger.info('FederatedCapacitor Plugin installed, skipping web bundling...');
}
else {
await (0, copy_1.copyWeb)(config);
}
}
else {
throw `Platform ${platformName} is not valid.`;
}
if (inline) {
await (0, sourcemaps_1.inlineSourceMaps)(config, platformName);
}
});
await (0, common_1.runHooks)(config, platformName, config.app.rootDir, 'capacitor:copy:after');
}
exports.copy = copy;
async function copyCapacitorConfig(config, nativeAbsDir) {
const nativeRelDir = (0, path_1.relative)(config.app.rootDir, nativeAbsDir);
const nativeConfigFile = 'capacitor.config.json';
const nativeConfigFilePath = (0, path_1.join)(nativeAbsDir, nativeConfigFile);
await (0, common_1.runTask)(`Creating ${colors_1.default.strong(nativeConfigFile)} in ${nativeRelDir}`, async () => {
var _a;
(_a = config.app.extConfig.android) === null || _a === void 0 ? true : delete _a.buildOptions;
await (0, utils_fs_1.writeJSON)(nativeConfigFilePath, config.app.extConfig, {
spaces: '\t',
});
});
}
async function copyWebDir(config, nativeAbsDir, webAbsDir) {
var _a;
const webRelDir = (0, path_1.basename)(webAbsDir);
const nativeRelDir = (0, path_1.relative)(config.app.rootDir, nativeAbsDir);
if (((_a = config.app.extConfig.server) === null || _a === void 0 ? void 0 : _a.url) && !(await (0, utils_fs_1.pathExists)(webAbsDir))) {
log_1.logger.warn(`Cannot copy web assets from ${colors_1.default.strong(webRelDir)} to ${nativeRelDir}\n` +
`Web asset directory specified by ${colors_1.default.input('webDir')} does not exist. This is not an error because ${colors_1.default.input('server.url')} is set in config.`);
return;
}
await (0, common_1.runTask)(`Copying web assets from ${colors_1.default.strong(webRelDir)} to ${nativeRelDir}`, async () => {
await (0, utils_fs_1.remove)(nativeAbsDir);
return (0, utils_fs_1.copy)(webAbsDir, nativeAbsDir);
});
}
async function copyFederatedWebDirs(config, nativeAbsDir) {
var _a, _b;
log_1.logger.info('FederatedCapacitor Plugin Loaded - Copying Web Assets');
if (!((_b = (_a = config.app.extConfig) === null || _a === void 0 ? void 0 : _a.plugins) === null || _b === void 0 ? void 0 : _b.FederatedCapacitor)) {
throw `FederatedCapacitor plugin is present but no valid config is defined.`;
}
const federatedConfig = config.app.extConfig.plugins.FederatedCapacitor;
if (federatedConfig) {
if (federatedConfig.shell.name === undefined) {
throw `FederatedCapacitor plugin is present but no valid Shell application is defined in the config.`;
}
if (!federatedConfig.apps.every(isFederatedApp)) {
throw `FederatedCapacitor plugin is present but there is a problem with the apps defined in the config.`;
}
const copyApps = () => {
return federatedConfig.apps.map(app => {
const appDir = (0, path_1.resolve)(config.app.rootDir, app.webDir);
return copyWebDir(config, (0, path_1.resolve)(nativeAbsDir, app.name), appDir);
});
};
const copyShell = () => {
return copyWebDir(config, (0, path_1.resolve)(nativeAbsDir, federatedConfig.shell.name), config.app.webDirAbs);
};
await Promise.all([...copyApps(), copyShell()]);
}
}
function isFederatedApp(config) {
return (config.webDir !== undefined &&
config.name !== undefined);
}
async function copySecureLiveUpdatesKey(secureLiveUpdatesKeyFile, rootDir, nativeAbsDir) {
const keyAbsFromPath = (0, path_1.join)(rootDir, secureLiveUpdatesKeyFile);
const keyAbsToPath = (0, path_1.join)(nativeAbsDir, (0, path_1.basename)(keyAbsFromPath));
const keyRelToDir = (0, path_1.relative)(rootDir, nativeAbsDir);
if (!(await (0, utils_fs_1.pathExists)(keyAbsFromPath))) {
log_1.logger.warn(`Cannot copy Secure Live Updates signature file from ${colors_1.default.strong(keyAbsFromPath)} to ${keyRelToDir}\n` +
`Signature file does not exist at specified key path.`);
return;
}
await (0, common_1.runTask)(`Copying Secure Live Updates key from ${colors_1.default.strong(secureLiveUpdatesKeyFile)} to ${keyRelToDir}`, async () => {
return (0, utils_fs_1.copy)(keyAbsFromPath, keyAbsToPath);
});
}
async function copySSLCert(sslCertPaths, rootDir, targetDir) {
const validCertPaths = [];
for (const sslCertPath of sslCertPaths) {
const certAbsFromPath = (0, path_1.join)(rootDir, sslCertPath);
if (!(await (0, utils_fs_1.pathExists)(certAbsFromPath))) {
log_1.logger.warn(`Cannot copy SSL Certificate file from ${colors_1.default.strong(certAbsFromPath)}\n` +
`SSL Certificate does not exist at specified path.`);
return;
}
validCertPaths.push(certAbsFromPath);
}
const certsDirAbsToPath = (0, path_1.join)(targetDir, 'certs');
const certsDirRelToDir = (0, path_1.relative)(rootDir, targetDir);
await (0, common_1.runTask)(`Copying SSL Certificates from to ${certsDirRelToDir}`, async () => {
const promises = [];
for (const certPath of validCertPaths) {
promises.push((0, utils_fs_1.copy)(certPath, (0, path_1.join)(certsDirAbsToPath, (0, path_1.basename)(certPath))));
}
return Promise.all(promises);
});
}

11
@capacitor/cli/dist/tasks/create.js vendored Normal file
View file

@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createCommand = void 0;
const tslib_1 = require("tslib");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const errors_1 = require("../errors");
async function createCommand() {
(0, errors_1.fatal)(`The create command has been removed.\n` +
`Use ${colors_1.default.input('npm init @capacitor/app')}`);
}
exports.createCommand = createCommand;

73
@capacitor/cli/dist/tasks/doctor.js vendored Normal file
View file

@ -0,0 +1,73 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.doctor = exports.doctorCore = exports.doctorCommand = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const doctor_1 = require("../android/doctor");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
const doctor_2 = require("../ios/doctor");
const log_1 = require("../log");
const emoji_1 = require("../util/emoji");
const node_1 = require("../util/node");
const subprocess_1 = require("../util/subprocess");
async function doctorCommand(config, selectedPlatformName) {
log_1.output.write(`${(0, emoji_1.emoji)('💊', '')} ${colors_1.default.strong('Capacitor Doctor')} ${(0, emoji_1.emoji)('💊', '')} \n\n`);
await doctorCore(config);
const platforms = await (0, common_1.selectPlatforms)(config, selectedPlatformName);
await Promise.all(platforms.map(platformName => {
return doctor(config, platformName);
}));
}
exports.doctorCommand = doctorCommand;
async function doctorCore(config) {
const [cliVersion, coreVersion, androidVersion, iosVersion] = await Promise.all([
(0, subprocess_1.getCommandOutput)('npm', ['info', '@capacitor/cli', 'version']),
(0, subprocess_1.getCommandOutput)('npm', ['info', '@capacitor/core', 'version']),
(0, subprocess_1.getCommandOutput)('npm', ['info', '@capacitor/android', 'version']),
(0, subprocess_1.getCommandOutput)('npm', ['info', '@capacitor/ios', 'version']),
]);
log_1.output.write(`${colors_1.default.strong('Latest Dependencies:')}\n\n` +
` @capacitor/cli: ${colors_1.default.weak(cliVersion !== null && cliVersion !== void 0 ? cliVersion : 'unknown')}\n` +
` @capacitor/core: ${colors_1.default.weak(coreVersion !== null && coreVersion !== void 0 ? coreVersion : 'unknown')}\n` +
` @capacitor/android: ${colors_1.default.weak(androidVersion !== null && androidVersion !== void 0 ? androidVersion : 'unknown')}\n` +
` @capacitor/ios: ${colors_1.default.weak(iosVersion !== null && iosVersion !== void 0 ? iosVersion : 'unknown')}\n\n` +
`${colors_1.default.strong('Installed Dependencies:')}\n\n`);
await printInstalledPackages(config);
log_1.output.write('\n');
}
exports.doctorCore = doctorCore;
async function printInstalledPackages(config) {
const packageNames = [
'@capacitor/cli',
'@capacitor/core',
'@capacitor/android',
'@capacitor/ios',
];
await Promise.all(packageNames.map(async (packageName) => {
const packagePath = (0, node_1.resolveNode)(config.app.rootDir, packageName, 'package.json');
await printPackageVersion(packageName, packagePath);
}));
}
async function printPackageVersion(packageName, packagePath) {
let version;
if (packagePath) {
version = (await (0, utils_fs_1.readJSON)(packagePath)).version;
}
log_1.output.write(` ${packageName}: ${colors_1.default.weak(version || 'not installed')}\n`);
}
async function doctor(config, platformName) {
if (platformName === config.ios.name) {
await (0, doctor_2.doctorIOS)(config);
}
else if (platformName === config.android.name) {
await (0, doctor_1.doctorAndroid)(config);
}
else if (platformName === config.web.name) {
return Promise.resolve();
}
else {
throw `Platform ${platformName} is not valid.`;
}
}
exports.doctor = doctor;

139
@capacitor/cli/dist/tasks/init.js vendored Normal file
View file

@ -0,0 +1,139 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.initCommand = void 0;
const tslib_1 = require("tslib");
const open_1 = tslib_1.__importDefault(require("open"));
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
const config_1 = require("../config");
const cordova_1 = require("../cordova");
const errors_1 = require("../errors");
const framework_configs_1 = require("../framework-configs");
const log_1 = require("../log");
const sysconfig_1 = require("../sysconfig");
const node_1 = require("../util/node");
const term_1 = require("../util/term");
async function initCommand(config, name, id, webDirFromCLI) {
var _a, _b;
try {
if (!(0, term_1.checkInteractive)(name, id)) {
return;
}
if (config.app.extConfigType !== 'json') {
(0, errors_1.fatal)(`Cannot run ${colors_1.default.input('init')} for a project using a non-JSON configuration file.\n` +
`Delete ${colors_1.default.strong(config.app.extConfigName)} and try again.`);
}
const isNewConfig = Object.keys(config.app.extConfig).length === 0;
const tsInstalled = !!(0, node_1.resolveNode)(config.app.rootDir, 'typescript');
const appName = await getName(config, name);
const appId = await getAppId(config, id);
const webDir = (0, term_1.isInteractive)()
? await getWebDir(config, webDirFromCLI)
: (_a = webDirFromCLI !== null && webDirFromCLI !== void 0 ? webDirFromCLI : config.app.extConfig.webDir) !== null && _a !== void 0 ? _a : 'www';
await (0, common_1.check)([
() => (0, common_1.checkAppName)(config, appName),
() => (0, common_1.checkAppId)(config, appId),
]);
const cordova = await (0, cordova_1.getCordovaPreferences)(config);
await runMergeConfig(config, {
appId,
appName,
webDir,
cordova,
}, isNewConfig && tsInstalled ? 'ts' : 'json');
}
catch (e) {
if (!(0, errors_1.isFatal)(e)) {
log_1.output.write('Usage: npx cap init appName appId\n' +
'Example: npx cap init "My App" "com.example.myapp"\n\n');
(0, errors_1.fatal)((_b = e.stack) !== null && _b !== void 0 ? _b : e);
}
throw e;
}
}
exports.initCommand = initCommand;
async function getName(config, name) {
var _a;
if (!name) {
const answers = await (0, log_1.logPrompt)(`${colors_1.default.strong(`What is the name of your app?`)}\n` +
`This should be a human-friendly app name, like what you'd see in the App Store.`, {
type: 'text',
name: 'name',
message: `Name`,
initial: config.app.appName
? config.app.appName
: (_a = config.app.package.name) !== null && _a !== void 0 ? _a : 'App',
});
return answers.name;
}
return name;
}
async function getAppId(config, id) {
if (!id) {
const answers = await (0, log_1.logPrompt)(`${colors_1.default.strong(`What should be the Package ID for your app?`)}\n` +
`Package IDs (aka Bundle ID in iOS and Application ID in Android) are unique identifiers for apps. They must be in reverse domain name notation, generally representing a domain name that you or your company owns.`, {
type: 'text',
name: 'id',
message: `Package ID`,
initial: config.app.appId ? config.app.appId : 'com.example.app',
});
return answers.id;
}
return id;
}
async function getWebDir(config, webDir) {
if (!webDir) {
const framework = (0, framework_configs_1.detectFramework)(config);
if (framework === null || framework === void 0 ? void 0 : framework.webDir) {
return framework.webDir;
}
const answers = await (0, log_1.logPrompt)(`${colors_1.default.strong(`What is the web asset directory for your app?`)}\n` +
`This directory should contain the final ${colors_1.default.strong('index.html')} of your app.`, {
type: 'text',
name: 'webDir',
message: `Web asset directory`,
initial: config.app.webDir ? config.app.webDir : 'www',
});
return answers.webDir;
}
return webDir;
}
async function runMergeConfig(config, extConfig, type) {
const configDirectory = (0, path_1.dirname)(config.app.extConfigFilePath);
const newConfigPath = (0, path_1.resolve)(configDirectory, type === 'ts' ? config_1.CONFIG_FILE_NAME_TS : config_1.CONFIG_FILE_NAME_JSON);
await (0, common_1.runTask)(`Creating ${colors_1.default.strong((0, path_1.basename)(newConfigPath))} in ${colors_1.default.input(config.app.rootDir)}`, async () => {
await mergeConfig(config, extConfig, newConfigPath);
});
printNextSteps((0, path_1.basename)(newConfigPath));
if ((0, term_1.isInteractive)()) {
let sysconfig = await (0, sysconfig_1.readConfig)();
if (typeof sysconfig.signup === 'undefined') {
const signup = await promptToSignup();
sysconfig = { ...sysconfig, signup };
await (0, sysconfig_1.writeConfig)(sysconfig);
}
}
}
async function mergeConfig(config, extConfig, newConfigPath) {
const oldConfig = { ...config.app.extConfig };
const newConfig = { ...oldConfig, ...extConfig };
await (0, config_1.writeConfig)(newConfig, newConfigPath);
}
function printNextSteps(newConfigName) {
(0, log_1.logSuccess)(`${colors_1.default.strong(newConfigName)} created!`);
log_1.output.write(`\nNext steps: \n${colors_1.default.strong(`https://capacitorjs.com/docs/getting-started#where-to-go-next`)}\n`);
}
async function promptToSignup() {
const answers = await (0, log_1.logPrompt)(`Join the Ionic Community! 💙\n` +
`Connect with millions of developers on the Ionic Forum and get access to live events, news updates, and more.`, {
type: 'confirm',
name: 'create',
message: `Create free Ionic account?`,
initial: true,
});
if (answers.create) {
(0, open_1.default)(`http://ionicframework.com/signup?source=capacitor`);
}
return answers.create;
}

50
@capacitor/cli/dist/tasks/list.js vendored Normal file
View file

@ -0,0 +1,50 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.list = exports.listCommand = void 0;
const tslib_1 = require("tslib");
const common_1 = require("../android/common");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_2 = require("../common");
const errors_1 = require("../errors");
const common_3 = require("../ios/common");
const log_1 = require("../log");
const plugin_1 = require("../plugin");
const promise_1 = require("../util/promise");
async function listCommand(config, selectedPlatformName) {
var _a;
const platforms = await (0, common_2.selectPlatforms)(config, selectedPlatformName);
try {
await (0, promise_1.allSerial)(platforms.map(platformName => () => list(config, platformName)));
}
catch (e) {
if ((0, errors_1.isFatal)(e)) {
throw e;
}
log_1.logger.error((_a = e.stack) !== null && _a !== void 0 ? _a : e);
}
}
exports.listCommand = listCommand;
async function list(config, platform) {
const allPlugins = await (0, plugin_1.getPlugins)(config, platform);
let plugins = [];
if (platform === config.ios.name) {
plugins = await (0, common_3.getIOSPlugins)(allPlugins);
}
else if (platform === config.android.name) {
plugins = await (0, common_1.getAndroidPlugins)(allPlugins);
}
else if (platform === config.web.name) {
log_1.logger.info(`Listing plugins for ${colors_1.default.input(platform)} is not possible.`);
return;
}
else {
throw `Platform ${colors_1.default.input(platform)} is not valid.`;
}
const capacitorPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 0 /* PluginType.Core */);
(0, plugin_1.printPlugins)(capacitorPlugins, platform);
const cordovaPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
(0, plugin_1.printPlugins)(cordovaPlugins, platform, 'cordova');
const incompatibleCordovaPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 2 /* PluginType.Incompatible */);
(0, plugin_1.printPlugins)(incompatibleCordovaPlugins, platform, 'incompatible');
}
exports.list = list;

575
@capacitor/cli/dist/tasks/migrate.js vendored Normal file
View file

@ -0,0 +1,575 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.patchOldCapacitorPlugins = exports.migrateCommand = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const path_1 = require("path");
const rimraf_1 = tslib_1.__importDefault(require("rimraf"));
const semver_1 = require("semver");
const common_1 = require("../android/common");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_2 = require("../common");
const errors_1 = require("../errors");
const log_1 = require("../log");
const plugin_1 = require("../plugin");
const fs_1 = require("../util/fs");
const node_1 = require("../util/node");
const subprocess_1 = require("../util/subprocess");
const template_1 = require("../util/template");
// eslint-disable-next-line prefer-const
let allDependencies = {};
const libs = [
'@capacitor/core',
'@capacitor/cli',
'@capacitor/ios',
'@capacitor/android',
];
const plugins = [
'@capacitor/action-sheet',
'@capacitor/app',
'@capacitor/app-launcher',
'@capacitor/browser',
'@capacitor/camera',
'@capacitor/clipboard',
'@capacitor/device',
'@capacitor/dialog',
'@capacitor/filesystem',
'@capacitor/geolocation',
'@capacitor/haptics',
'@capacitor/keyboard',
'@capacitor/local-notifications',
'@capacitor/motion',
'@capacitor/network',
'@capacitor/preferences',
'@capacitor/push-notifications',
'@capacitor/screen-reader',
'@capacitor/screen-orientation',
'@capacitor/share',
'@capacitor/splash-screen',
'@capacitor/status-bar',
'@capacitor/text-zoom',
'@capacitor/toast',
];
const coreVersion = '^6.0.0';
const pluginVersion = '^6.0.0';
const gradleVersion = '8.2.1';
let installFailed = false;
async function migrateCommand(config, noprompt, packagemanager) {
if (config === null) {
(0, errors_1.fatal)('Config data missing');
}
const capMajor = await checkCapacitorMajorVersion(config);
if (capMajor < 5) {
(0, errors_1.fatal)('Migrate can only be used on capacitor 5 and above, please use the CLI in Capacitor 5 to upgrade to 5 first');
}
const jdkMajor = await (0, common_2.checkJDKMajorVersion)();
if (jdkMajor < 17) {
log_1.logger.warn('Capacitor 6 requires JDK 17 or higher. Some steps may fail.');
}
const variablesAndClasspaths = await getAndroidVariablesAndClasspaths(config);
if (!variablesAndClasspaths) {
(0, errors_1.fatal)('Variable and Classpath info could not be read.');
}
allDependencies = {
...config.app.package.dependencies,
...config.app.package.devDependencies,
};
const monorepoWarning = 'Please note this tool is not intended for use in a mono-repo environment, please check out the Ionic vscode extension for this functionality.';
log_1.logger.info(monorepoWarning);
const { migrateconfirm } = noprompt
? { migrateconfirm: 'y' }
: await (0, log_1.logPrompt)(`Capacitor 6 sets a deployment target of iOS 13 and Android 14 (SDK 34). \n`, {
type: 'text',
name: 'migrateconfirm',
message: `Are you sure you want to migrate? (Y/n)`,
initial: 'y',
});
if (typeof migrateconfirm === 'string' &&
migrateconfirm.toLowerCase() === 'y') {
try {
const { depInstallConfirm } = noprompt
? { depInstallConfirm: 'y' }
: await (0, log_1.logPrompt)(`Would you like the migrator to run npm, yarn, pnpm, or bun install to install the latest versions of capacitor packages? (Those using other package managers should answer N)`, {
type: 'text',
name: 'depInstallConfirm',
message: `Run Dependency Install? (Y/n)`,
initial: 'y',
});
const runNpmInstall = typeof depInstallConfirm === 'string' &&
depInstallConfirm.toLowerCase() === 'y';
let installerType = 'npm';
if (runNpmInstall) {
const { manager } = packagemanager
? { manager: packagemanager }
: await (0, log_1.logPrompt)('What dependency manager do you use?', {
type: 'select',
name: 'manager',
message: `Dependency Management Tool`,
choices: [
{ title: 'NPM', value: 'npm' },
{ title: 'Yarn', value: 'yarn' },
{ title: 'PNPM', value: 'pnpm' },
{ title: 'Bun', value: 'bun' },
],
initial: 0,
});
installerType = manager;
}
try {
await (0, common_2.runTask)(`Installing Latest Modules using ${installerType}.`, () => {
return installLatestLibs(installerType, runNpmInstall, config);
});
}
catch (ex) {
log_1.logger.error(`${installerType} install failed. Try deleting node_modules folder and running ${colors_1.default.input(`${installerType} install --force`)} manually.`);
installFailed = true;
}
// Update iOS Projects
if (allDependencies['@capacitor/ios'] &&
(0, utils_fs_1.existsSync)(config.ios.platformDirAbs)) {
// ios template changes
// Remove NSLocationAlwaysUsageDescription
await (0, common_2.runTask)(`Migrating Info.plist by removing NSLocationAlwaysUsageDescription key.`, () => {
return removeKey((0, path_1.join)(config.ios.nativeTargetDirAbs, 'Info.plist'), 'NSLocationAlwaysUsageDescription');
});
}
if (!installFailed) {
await (0, common_2.runTask)(`Running cap sync.`, () => {
return (0, subprocess_1.runCommand)('npx', ['cap', 'sync']);
});
}
else {
log_1.logger.warn('Skipped Running cap sync.');
}
if (allDependencies['@capacitor/android'] &&
(0, utils_fs_1.existsSync)(config.android.platformDirAbs)) {
const gradleWrapperVersion = getGradleWrapperVersion((0, path_1.join)(config.android.platformDirAbs, 'gradle', 'wrapper', 'gradle-wrapper.properties'));
if (!installFailed && (0, semver_1.gt)(gradleVersion, gradleWrapperVersion)) {
try {
await (0, common_2.runTask)(`Upgrading gradle wrapper files`, () => {
return updateGradleWrapperFiles(config.android.platformDirAbs);
});
}
catch (e) {
if (e.includes('EACCES')) {
log_1.logger.error(`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.input(`chmod +x ./${config.android.platformDir}/gradlew`)} and ${colors_1.default.input(`cd ${config.android.platformDir} && ./gradlew wrapper --distribution-type all --gradle-version ${gradleVersion} --warning-mode all`)} to update the files manually`);
}
else {
log_1.logger.error(`gradle wrapper files were not updated`);
}
}
}
else {
log_1.logger.warn('Skipped upgrading gradle wrapper files');
}
await (0, common_2.runTask)(`Migrating build.gradle file.`, () => {
return updateBuildGradle((0, path_1.join)(config.android.platformDirAbs, 'build.gradle'), variablesAndClasspaths);
});
// Replace deprecated compileSdkVersion
await (0, common_2.runTask)('Replacing deprecated compileSdkVersion from build.gradle', () => {
return (async () => {
const buildGradleFilename = (0, path_1.join)(config.android.platformDirAbs, 'app', 'build.gradle');
const buildGradleText = readFile(buildGradleFilename);
if (!buildGradleText) {
log_1.logger.error(`Could not read ${buildGradleFilename}. Check its permissions and if it exists.`);
return;
}
const compileSdk = `compileSdkVersion rootProject.ext.compileSdkVersion`;
if (buildGradleText.includes(compileSdk)) {
const buildGradleReplaced = buildGradleText.replace(compileSdk, `compileSdk rootProject.ext.compileSdkVersion`);
(0, utils_fs_1.writeFileSync)(buildGradleFilename, buildGradleReplaced, 'utf-8');
}
})();
});
// Variables gradle
await (0, common_2.runTask)(`Migrating variables.gradle file.`, () => {
return (async () => {
const variablesPath = (0, path_1.join)(config.android.platformDirAbs, 'variables.gradle');
let txt = readFile(variablesPath);
if (!txt) {
return;
}
txt = txt.replace(/= {2}'/g, `= '`);
(0, utils_fs_1.writeFileSync)(variablesPath, txt, { encoding: 'utf-8' });
for (const variable of Object.keys(variablesAndClasspaths.variables)) {
let replaceStart = `${variable} = '`;
let replaceEnd = `'\n`;
if (typeof variablesAndClasspaths.variables[variable] === 'number') {
replaceStart = `${variable} = `;
replaceEnd = `\n`;
}
if (txt.includes(replaceStart)) {
const first = txt.indexOf(replaceStart) + replaceStart.length;
const value = txt.substring(first, txt.indexOf(replaceEnd, first));
if ((typeof variablesAndClasspaths.variables[variable] ===
'number' &&
value <= variablesAndClasspaths.variables[variable]) ||
(typeof variablesAndClasspaths.variables[variable] ===
'string' &&
(0, semver_1.lt)(value, variablesAndClasspaths.variables[variable]))) {
await updateFile(config, variablesPath, replaceStart, replaceEnd, variablesAndClasspaths.variables[variable].toString(), true);
}
}
else {
let file = readFile(variablesPath);
if (file) {
file = file.replace('}', ` ${replaceStart}${variablesAndClasspaths.variables[variable].toString()}${replaceEnd}}`);
(0, utils_fs_1.writeFileSync)(variablesPath, file);
}
}
}
const pluginVariables = {
firebaseMessagingVersion: '23.3.1',
playServicesLocationVersion: '21.1.0',
androidxBrowserVersion: '1.7.0',
androidxMaterialVersion: '1.10.0',
androidxExifInterfaceVersion: '1.3.6',
androidxCoreKTXVersion: '1.12.0',
googleMapsPlayServicesVersion: '18.2.0',
googleMapsUtilsVersion: '3.8.2',
googleMapsKtxVersion: '5.0.0',
googleMapsUtilsKtxVersion: '5.0.0',
kotlinxCoroutinesVersion: '1.7.3',
coreSplashScreenVersion: '1.0.1',
};
for (const variable of Object.keys(pluginVariables)) {
await updateFile(config, variablesPath, `${variable} = '`, `'`, pluginVariables[variable], true);
}
})();
});
rimraf_1.default.sync((0, path_1.join)(config.android.appDirAbs, 'build'));
if (!installFailed) {
await (0, common_2.runTask)('Migrating package from Manifest to build.gradle in Capacitor plugins', () => {
return patchOldCapacitorPlugins(config);
});
}
else {
log_1.logger.warn('Skipped migrating package from Manifest to build.gradle in Capacitor plugins');
}
}
// Write all breaking changes
await (0, common_2.runTask)(`Writing breaking changes.`, () => {
return writeBreakingChanges();
});
if (!installFailed) {
(0, log_1.logSuccess)(`Migration to Capacitor ${coreVersion} is complete. Run and test your app!`);
}
else {
log_1.logger.warn(`Migration to Capacitor ${coreVersion} is incomplete. Check the log messages for more information.`);
}
}
catch (err) {
(0, errors_1.fatal)(`Failed to migrate: ${err}`);
}
}
else {
(0, errors_1.fatal)(`User canceled migration.`);
}
}
exports.migrateCommand = migrateCommand;
async function checkCapacitorMajorVersion(config) {
var _a;
const capacitorVersion = await (0, common_2.getCoreVersion)(config);
const versionArray = (_a = capacitorVersion.match(/([0-9]+)\.([0-9]+)\.([0-9]+)/)) !== null && _a !== void 0 ? _a : [];
const majorVersion = parseInt(versionArray[1]);
return majorVersion;
}
async function installLatestLibs(dependencyManager, runInstall, config) {
const pkgJsonPath = (0, path_1.join)(config.app.rootDir, 'package.json');
const pkgJsonFile = readFile(pkgJsonPath);
if (!pkgJsonFile) {
return;
}
const pkgJson = JSON.parse(pkgJsonFile);
for (const devDepKey of Object.keys(pkgJson['devDependencies'] || {})) {
if (libs.includes(devDepKey)) {
pkgJson['devDependencies'][devDepKey] = coreVersion;
}
else if (plugins.includes(devDepKey)) {
pkgJson['devDependencies'][devDepKey] = pluginVersion;
}
}
for (const depKey of Object.keys(pkgJson['dependencies'] || {})) {
if (libs.includes(depKey)) {
pkgJson['dependencies'][depKey] = coreVersion;
}
else if (plugins.includes(depKey)) {
pkgJson['dependencies'][depKey] = pluginVersion;
}
}
(0, utils_fs_1.writeFileSync)(pkgJsonPath, JSON.stringify(pkgJson, null, 2), {
encoding: 'utf-8',
});
if (runInstall) {
rimraf_1.default.sync((0, path_1.join)(config.app.rootDir, 'node_modules/@capacitor/!(cli)'));
await (0, subprocess_1.runCommand)(dependencyManager, ['install']);
if (dependencyManager == 'yarn') {
await (0, subprocess_1.runCommand)(dependencyManager, ['upgrade']);
}
else {
await (0, subprocess_1.runCommand)(dependencyManager, ['update']);
}
}
else {
log_1.logger.info(`Please run an install command with your package manager of choice. (ex: yarn install)`);
}
}
async function writeBreakingChanges() {
const breaking = [
'@capacitor/camera',
'@capacitor/filesystem',
'@capacitor/geolocation',
'@capacitor/google-maps',
'@capacitor/local-notifications',
];
const broken = [];
for (const lib of breaking) {
if (allDependencies[lib]) {
broken.push(lib);
}
}
if (broken.length > 0) {
log_1.logger.info(`IMPORTANT: Review https://capacitorjs.com/docs/next/updating/6-0#plugins for breaking changes in these plugins that you use: ${broken.join(', ')}.`);
}
}
async function getAndroidVariablesAndClasspaths(config) {
const tempAndroidTemplateFolder = (0, path_1.join)(config.cli.assetsDirAbs, 'tempAndroidTemplate');
await (0, template_1.extractTemplate)(config.cli.assets.android.platformTemplateArchiveAbs, tempAndroidTemplateFolder);
const variablesGradleFile = readFile((0, path_1.join)(tempAndroidTemplateFolder, 'variables.gradle'));
const buildGradleFile = readFile((0, path_1.join)(tempAndroidTemplateFolder, 'build.gradle'));
if (!variablesGradleFile || !buildGradleFile) {
return;
}
(0, fs_1.deleteFolderRecursive)(tempAndroidTemplateFolder);
const firstIndxOfCATBGV = buildGradleFile.indexOf(`classpath 'com.android.tools.build:gradle:`) + 42;
const firstIndxOfCGGGS = buildGradleFile.indexOf(`com.google.gms:google-services:`) + 31;
const comAndroidToolsBuildGradleVersion = '' +
buildGradleFile.substring(firstIndxOfCATBGV, buildGradleFile.indexOf("'", firstIndxOfCATBGV));
const comGoogleGmsGoogleServices = '' +
buildGradleFile.substring(firstIndxOfCGGGS, buildGradleFile.indexOf("'", firstIndxOfCGGGS));
const variablesGradleAsJSON = JSON.parse(variablesGradleFile
.replace('ext ', '')
.replace(/=/g, ':')
.replace(/\n/g, ',')
.replace(/,([^:]+):/g, function (_k, p1) {
return `,"${p1}":`;
})
.replace('{,', '{')
.replace(',}', '}')
.replace(/\s/g, '')
.replace(/'/g, '"'));
return {
'variables': variablesGradleAsJSON,
'com.android.tools.build:gradle': comAndroidToolsBuildGradleVersion,
'com.google.gms:google-services': comGoogleGmsGoogleServices,
};
}
function readFile(filename) {
try {
if (!(0, utils_fs_1.existsSync)(filename)) {
log_1.logger.error(`Unable to find ${filename}. Try updating it manually`);
return;
}
return (0, utils_fs_1.readFileSync)(filename, 'utf-8');
}
catch (err) {
log_1.logger.error(`Unable to read ${filename}. Verify it is not already open. ${err}`);
}
}
function getGradleWrapperVersion(filename) {
var _a;
const txt = readFile(filename);
if (!txt) {
return '0.0.0';
}
const version = txt.substring(txt.indexOf('gradle-') + 7, txt.indexOf('-all.zip'));
const semverVersion = (_a = (0, semver_1.coerce)(version)) === null || _a === void 0 ? void 0 : _a.version;
return semverVersion ? semverVersion : '0.0.0';
}
async function updateGradleWrapperFiles(platformDir) {
await (0, subprocess_1.runCommand)(`./gradlew`, [
'wrapper',
'--distribution-type',
'all',
'--gradle-version',
gradleVersion,
'--warning-mode',
'all',
], {
cwd: platformDir,
});
}
async function movePackageFromManifestToBuildGradle(manifestFilename, buildGradleFilename) {
const manifestText = readFile(manifestFilename);
const buildGradleText = readFile(buildGradleFilename);
if (!manifestText) {
log_1.logger.error(`Could not read ${manifestFilename}. Check its permissions and if it exists.`);
return;
}
if (!buildGradleText) {
log_1.logger.error(`Could not read ${buildGradleFilename}. Check its permissions and if it exists.`);
return;
}
const namespaceExists = new RegExp(/\s+namespace\s+/).test(buildGradleText);
if (namespaceExists) {
log_1.logger.error('Found namespace in build.gradle already, skipping migration');
return;
}
let packageName;
const manifestRegEx = new RegExp(/package="([^"]+)"/);
const manifestResults = manifestRegEx.exec(manifestText);
if (manifestResults === null) {
log_1.logger.error(`Unable to update Android Manifest. Package not found.`);
return;
}
else {
packageName = manifestResults[1];
}
let manifestReplaced = manifestText;
manifestReplaced = manifestReplaced.replace(manifestRegEx, '');
if (manifestText == manifestReplaced) {
log_1.logger.error(`Unable to update Android Manifest: no changes were detected in Android Manifest file`);
return;
}
let buildGradleReplaced = buildGradleText;
buildGradleReplaced = setAllStringIn(buildGradleText, 'android {', '\n', `\n namespace "${packageName}"`);
if (buildGradleText == buildGradleReplaced) {
log_1.logger.error(`Unable to update buildGradleText: no changes were detected in Android Manifest file`);
return;
}
(0, utils_fs_1.writeFileSync)(manifestFilename, manifestReplaced, 'utf-8');
(0, utils_fs_1.writeFileSync)(buildGradleFilename, buildGradleReplaced, 'utf-8');
}
async function updateBuildGradle(filename, variablesAndClasspaths) {
const txt = readFile(filename);
if (!txt) {
return;
}
const neededDeps = {
'com.android.tools.build:gradle': variablesAndClasspaths['com.android.tools.build:gradle'],
'com.google.gms:google-services': variablesAndClasspaths['com.google.gms:google-services'],
};
let replaced = txt;
for (const dep of Object.keys(neededDeps)) {
if (replaced.includes(`classpath '${dep}`)) {
const firstIndex = replaced.indexOf(dep) + dep.length + 1;
const existingVersion = '' + replaced.substring(firstIndex, replaced.indexOf("'", firstIndex));
if ((0, semver_1.gte)(neededDeps[dep], existingVersion)) {
replaced = setAllStringIn(replaced, `classpath '${dep}:`, `'`, neededDeps[dep]);
log_1.logger.info(`Set ${dep} = ${neededDeps[dep]}.`);
}
}
}
(0, utils_fs_1.writeFileSync)(filename, replaced, 'utf-8');
}
async function updateFile(config, filename, textStart, textEnd, replacement, skipIfNotFound) {
if (config === null) {
return false;
}
const path = filename;
let txt = readFile(path);
if (!txt) {
return false;
}
if (txt.includes(textStart)) {
if (replacement) {
txt = setAllStringIn(txt, textStart, textEnd, replacement);
(0, utils_fs_1.writeFileSync)(path, txt, { encoding: 'utf-8' });
}
else {
// Replacing in code so we need to count the number of brackets to find the end of the function in swift
const lines = txt.split('\n');
let replaced = '';
let keep = true;
let brackets = 0;
for (const line of lines) {
if (line.includes(textStart)) {
keep = false;
}
if (!keep) {
brackets += (line.match(/{/g) || []).length;
brackets -= (line.match(/}/g) || []).length;
if (brackets == 0) {
keep = true;
}
}
else {
replaced += line + '\n';
}
}
(0, utils_fs_1.writeFileSync)(path, replaced, { encoding: 'utf-8' });
}
return true;
}
else if (!skipIfNotFound) {
log_1.logger.error(`Unable to find "${textStart}" in ${filename}. Try updating it manually`);
}
return false;
}
function setAllStringIn(data, start, end, replacement) {
let position = 0;
let result = data;
let replaced = true;
while (replaced) {
const foundIdx = result.indexOf(start, position);
if (foundIdx == -1) {
replaced = false;
}
else {
const idx = foundIdx + start.length;
position = idx + replacement.length;
result =
result.substring(0, idx) +
replacement +
result.substring(result.indexOf(end, idx));
}
}
return result;
}
async function patchOldCapacitorPlugins(config) {
const allPlugins = await (0, plugin_1.getPlugins)(config, 'android');
const androidPlugins = await (0, common_1.getAndroidPlugins)(allPlugins);
return await Promise.all(androidPlugins.map(async (p) => {
var _a, _b;
if ((_b = (_a = p.manifest) === null || _a === void 0 ? void 0 : _a.android) === null || _b === void 0 ? void 0 : _b.src) {
const buildGradlePath = (0, node_1.resolveNode)(config.app.rootDir, p.id, p.manifest.android.src, 'build.gradle');
const manifestPath = (0, node_1.resolveNode)(config.app.rootDir, p.id, p.manifest.android.src, 'src', 'main', 'AndroidManifest.xml');
if (buildGradlePath && manifestPath) {
const gradleContent = readFile(buildGradlePath);
if (!(gradleContent === null || gradleContent === void 0 ? void 0 : gradleContent.includes('namespace'))) {
if (plugins.includes(p.id)) {
log_1.logger.warn(`You are using an outdated version of ${p.id}, update the plugin to version ${pluginVersion}`);
}
else {
log_1.logger.warn(`${p.id}@${p.version} doesn't officially support Capacitor ${coreVersion} yet, doing our best moving it's package to build.gradle so it builds`);
}
movePackageFromManifestToBuildGradle(manifestPath, buildGradlePath);
}
}
}
}));
}
exports.patchOldCapacitorPlugins = patchOldCapacitorPlugins;
async function removeKey(filename, key) {
const txt = readFile(filename);
if (!txt) {
return;
}
let lines = txt.split('\n');
let removed = false;
let removing = false;
lines = lines.filter(line => {
if (removing && line.includes('</string>')) {
removing = false;
return false;
}
if (line.includes(`<key>${key}</key`)) {
removing = true;
removed = true;
}
return !removing;
});
if (removed) {
(0, utils_fs_1.writeFileSync)(filename, lines.join('\n'), 'utf-8');
}
}

11
@capacitor/cli/dist/tasks/new-plugin.js vendored Normal file
View file

@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.newPluginCommand = void 0;
const tslib_1 = require("tslib");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const errors_1 = require("../errors");
async function newPluginCommand() {
(0, errors_1.fatal)(`The plugin:generate command has been removed.\n` +
`Use ${colors_1.default.input('npm init @capacitor/plugin')}`);
}
exports.newPluginCommand = newPluginCommand;

62
@capacitor/cli/dist/tasks/open.js vendored Normal file
View file

@ -0,0 +1,62 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.open = exports.openCommand = void 0;
const tslib_1 = require("tslib");
const open_1 = require("../android/open");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
const errors_1 = require("../errors");
const open_2 = require("../ios/open");
const log_1 = require("../log");
async function openCommand(config, selectedPlatformName) {
var _a;
if (selectedPlatformName && !(await (0, common_1.isValidPlatform)(selectedPlatformName))) {
const platformDir = (0, common_1.resolvePlatform)(config, selectedPlatformName);
if (platformDir) {
await (0, common_1.runPlatformHook)(config, selectedPlatformName, platformDir, 'capacitor:open');
}
else {
log_1.logger.error(`Platform ${colors_1.default.input(selectedPlatformName)} not found.`);
}
}
else {
const platforms = await (0, common_1.selectPlatforms)(config, selectedPlatformName);
let platformName;
if (platforms.length === 1) {
platformName = platforms[0];
}
else {
platformName = await (0, common_1.promptForPlatform)(platforms.filter(createOpenablePlatformFilter(config)), `Please choose a platform to open:`);
}
try {
await open(config, platformName);
}
catch (e) {
if (!(0, errors_1.isFatal)(e)) {
(0, errors_1.fatal)((_a = e.stack) !== null && _a !== void 0 ? _a : e);
}
throw e;
}
}
}
exports.openCommand = openCommand;
function createOpenablePlatformFilter(config) {
return platform => platform === config.ios.name || platform === config.android.name;
}
async function open(config, platformName) {
if (platformName === config.ios.name) {
await (0, common_1.runTask)('Opening the Xcode workspace...', () => {
return (0, open_2.openIOS)(config);
});
}
else if (platformName === config.android.name) {
return (0, open_1.openAndroid)(config);
}
else if (platformName === config.web.name) {
return Promise.resolve();
}
else {
throw `Platform ${platformName} is not valid.`;
}
}
exports.open = open;

114
@capacitor/cli/dist/tasks/run.js vendored Normal file
View file

@ -0,0 +1,114 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = exports.runCommand = void 0;
const tslib_1 = require("tslib");
const utils_process_1 = require("@ionic/utils-process");
const utils_terminal_1 = require("@ionic/utils-terminal");
const run_1 = require("../android/run");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
const cordova_1 = require("../cordova");
const errors_1 = require("../errors");
const run_2 = require("../ios/run");
const log_1 = require("../log");
const livereload_1 = require("../util/livereload");
const native_run_1 = require("../util/native-run");
const sync_1 = require("./sync");
async function runCommand(config, selectedPlatformName, options) {
var _a, _b, _c, _d;
options.host =
(_b = (_a = options.host) !== null && _a !== void 0 ? _a : livereload_1.CapLiveReloadHelper.getIpAddress()) !== null && _b !== void 0 ? _b : 'localhost';
options.port = (_c = options.port) !== null && _c !== void 0 ? _c : '3000';
if (selectedPlatformName && !(await (0, common_1.isValidPlatform)(selectedPlatformName))) {
const platformDir = (0, common_1.resolvePlatform)(config, selectedPlatformName);
if (platformDir) {
await (0, common_1.runPlatformHook)(config, selectedPlatformName, platformDir, 'capacitor:run');
}
else {
log_1.logger.error(`Platform ${colors_1.default.input(selectedPlatformName)} not found.`);
}
}
else {
const platforms = await (0, common_1.selectPlatforms)(config, selectedPlatformName);
let platformName;
if (platforms.length === 1) {
platformName = platforms[0];
}
else {
platformName = await (0, common_1.promptForPlatform)(platforms.filter(createRunnablePlatformFilter(config)), `Please choose a platform to run:`);
}
if (options.list) {
const targets = await (0, native_run_1.getPlatformTargets)(platformName);
const outputTargets = targets.map(t => {
var _a;
return ({
name: (0, common_1.getPlatformTargetName)(t),
api: `${t.platform === 'ios' ? 'iOS' : 'API'} ${t.sdkVersion}`,
id: (_a = t.id) !== null && _a !== void 0 ? _a : '?',
});
});
// TODO: make hidden commander option (https://github.com/tj/commander.js/issues/1106)
if (process.argv.includes('--json')) {
process.stdout.write(`${JSON.stringify(outputTargets)}\n`);
}
else {
const rows = outputTargets.map(t => [t.name, t.api, t.id]);
log_1.output.write(`${(0, utils_terminal_1.columnar)(rows, {
headers: ['Name', 'API', 'Target ID'],
vsep: ' ',
})}\n`);
}
return;
}
try {
if (options.sync) {
await (0, sync_1.sync)(config, platformName, false, true);
}
const cordovaPlugins = await (0, cordova_1.getCordovaPlugins)(config, platformName);
if (options.liveReload) {
await livereload_1.CapLiveReloadHelper.editCapConfigForLiveReload(config, platformName, options);
if (platformName === config.android.name) {
await await (0, cordova_1.writeCordovaAndroidManifest)(cordovaPlugins, config, platformName, true);
}
}
await run(config, platformName, options);
if (options.liveReload) {
new Promise(resolve => process.on('SIGINT', resolve))
.then(async () => {
await livereload_1.CapLiveReloadHelper.revertCapConfigForLiveReload();
if (platformName === config.android.name) {
await (0, cordova_1.writeCordovaAndroidManifest)(cordovaPlugins, config, platformName, false);
}
})
.then(() => process.exit());
log_1.logger.info(`App running with live reload listing for: http://${options.host}:${options.port}. Press Ctrl+C to quit.`);
await (0, utils_process_1.sleepForever)();
}
}
catch (e) {
if (!(0, errors_1.isFatal)(e)) {
(0, errors_1.fatal)((_d = e.stack) !== null && _d !== void 0 ? _d : e);
}
throw e;
}
}
}
exports.runCommand = runCommand;
async function run(config, platformName, options) {
if (platformName == config.ios.name) {
await (0, run_2.runIOS)(config, options);
}
else if (platformName === config.android.name) {
await (0, run_1.runAndroid)(config, options);
}
else if (platformName === config.web.name) {
return;
}
else {
throw `Platform ${platformName} is not valid.`;
}
}
exports.run = run;
function createRunnablePlatformFilter(config) {
return platform => platform === config.ios.name || platform === config.android.name;
}

11
@capacitor/cli/dist/tasks/serve.js vendored Normal file
View file

@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.serveCommand = void 0;
const tslib_1 = require("tslib");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const errors_1 = require("../errors");
async function serveCommand() {
(0, errors_1.fatal)(`The serve command has been removed.\n` +
`Use a third-party tool for serving single page apps, such as ${colors_1.default.strong('serve')}: ${colors_1.default.strong('https://www.npmjs.com/package/serve')}`);
}
exports.serveCommand = serveCommand;

40
@capacitor/cli/dist/tasks/sourcemaps.js vendored Normal file
View file

@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.inlineSourceMaps = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const path_1 = require("path");
const log_1 = require("../log");
function walkDirectory(dirPath) {
const files = (0, utils_fs_1.readdirSync)(dirPath);
files.forEach(file => {
const targetFile = (0, path_1.join)(dirPath, file);
if ((0, utils_fs_1.existsSync)(targetFile) && (0, utils_fs_1.lstatSync)(targetFile).isDirectory()) {
walkDirectory(targetFile);
}
else {
const mapFile = (0, path_1.join)(dirPath, `${file}.map`);
if ((0, path_1.extname)(file) === '.js' && (0, utils_fs_1.existsSync)(mapFile)) {
const bufMap = (0, utils_fs_1.readFileSync)(mapFile).toString('base64');
const bufFile = (0, utils_fs_1.readFileSync)(targetFile, 'utf8');
const result = bufFile.replace(`sourceMappingURL=${file}.map`, 'sourceMappingURL=data:application/json;charset=utf-8;base64,' +
bufMap);
(0, utils_fs_1.writeFileSync)(targetFile, result);
(0, utils_fs_1.unlinkSync)(mapFile);
}
}
});
}
async function inlineSourceMaps(config, platformName) {
let buildDir = '';
if (platformName == config.ios.name) {
buildDir = await config.ios.webDirAbs;
}
if (platformName == config.android.name) {
buildDir = await config.android.webDirAbs;
}
if (buildDir) {
log_1.logger.info('Inlining sourcemaps');
walkDirectory(buildDir);
}
}
exports.inlineSourceMaps = inlineSourceMaps;

59
@capacitor/cli/dist/tasks/sync.js vendored Normal file
View file

@ -0,0 +1,59 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sync = exports.syncCommand = void 0;
const common_1 = require("../common");
const errors_1 = require("../errors");
const log_1 = require("../log");
const promise_1 = require("../util/promise");
const copy_1 = require("./copy");
const update_1 = require("./update");
/**
* Sync is a copy and an update in one.
*/
async function syncCommand(config, selectedPlatformName, deployment, inline = false) {
var _a, _b;
if (selectedPlatformName && !(await (0, common_1.isValidPlatform)(selectedPlatformName))) {
try {
await (0, copy_1.copyCommand)(config, selectedPlatformName, inline);
}
catch (e) {
log_1.logger.error((_a = e.stack) !== null && _a !== void 0 ? _a : e);
}
await (0, update_1.updateCommand)(config, selectedPlatformName, deployment);
}
else {
const then = +new Date();
const platforms = await (0, common_1.selectPlatforms)(config, selectedPlatformName);
try {
await (0, common_1.check)([
() => (0, common_1.checkPackage)(),
() => (0, common_1.checkWebDir)(config),
...(0, update_1.updateChecks)(config, platforms),
]);
await (0, promise_1.allSerial)(platforms.map(platformName => () => sync(config, platformName, deployment, inline)));
const now = +new Date();
const diff = (now - then) / 1000;
log_1.logger.info(`Sync finished in ${diff}s`);
}
catch (e) {
if (!(0, errors_1.isFatal)(e)) {
(0, errors_1.fatal)((_b = e.stack) !== null && _b !== void 0 ? _b : e);
}
throw e;
}
}
}
exports.syncCommand = syncCommand;
async function sync(config, platformName, deployment, inline = false) {
var _a;
await (0, common_1.runHooks)(config, platformName, config.app.rootDir, 'capacitor:sync:before');
try {
await (0, copy_1.copy)(config, platformName, inline);
}
catch (e) {
log_1.logger.error((_a = e.stack) !== null && _a !== void 0 ? _a : e);
}
await (0, update_1.update)(config, platformName, deployment);
await (0, common_1.runHooks)(config, platformName, config.app.rootDir, 'capacitor:sync:after');
}
exports.sync = sync;

40
@capacitor/cli/dist/tasks/telemetry.js vendored Normal file
View file

@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.telemetryCommand = void 0;
const tslib_1 = require("tslib");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const errors_1 = require("../errors");
const log_1 = require("../log");
const sysconfig_1 = require("../sysconfig");
const telemetry_1 = require("../telemetry");
async function telemetryCommand(onOrOff) {
const sysconfig = await (0, sysconfig_1.readConfig)();
const enabled = interpretEnabled(onOrOff);
if (typeof enabled === 'boolean') {
if (sysconfig.telemetry === enabled) {
log_1.logger.info(`Telemetry is already ${colors_1.default.strong(enabled ? 'on' : 'off')}`);
}
else {
await (0, sysconfig_1.writeConfig)({ ...sysconfig, telemetry: enabled });
(0, log_1.logSuccess)(`You have ${colors_1.default.strong(`opted ${enabled ? 'in' : 'out'}`)} ${enabled ? 'for' : 'of'} telemetry on this machine.`);
if (enabled) {
log_1.output.write(telemetry_1.THANK_YOU);
}
}
}
else {
log_1.logger.info(`Telemetry is ${colors_1.default.strong(sysconfig.telemetry ? 'on' : 'off')}`);
}
}
exports.telemetryCommand = telemetryCommand;
function interpretEnabled(onOrOff) {
switch (onOrOff) {
case 'on':
return true;
case 'off':
return false;
case undefined:
return undefined;
}
(0, errors_1.fatal)(`Argument must be ${colors_1.default.strong('on')} or ${colors_1.default.strong('off')} (or left unspecified)`);
}

74
@capacitor/cli/dist/tasks/update.js vendored Normal file
View file

@ -0,0 +1,74 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.update = exports.updateChecks = exports.updateCommand = void 0;
const tslib_1 = require("tslib");
const update_1 = require("../android/update");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
const errors_1 = require("../errors");
const common_2 = require("../ios/common");
const update_2 = require("../ios/update");
const log_1 = require("../log");
const promise_1 = require("../util/promise");
async function updateCommand(config, selectedPlatformName, deployment) {
var _a;
if (selectedPlatformName && !(await (0, common_1.isValidPlatform)(selectedPlatformName))) {
const platformDir = (0, common_1.resolvePlatform)(config, selectedPlatformName);
if (platformDir) {
await (0, common_1.runPlatformHook)(config, selectedPlatformName, platformDir, 'capacitor:update');
}
else {
log_1.logger.error(`Platform ${colors_1.default.input(selectedPlatformName)} not found.`);
}
}
else {
const then = +new Date();
const platforms = await (0, common_1.selectPlatforms)(config, selectedPlatformName);
try {
await (0, common_1.check)([() => (0, common_1.checkPackage)(), ...updateChecks(config, platforms)]);
await (0, promise_1.allSerial)(platforms.map(platformName => async () => await update(config, platformName, deployment)));
const now = +new Date();
const diff = (now - then) / 1000;
log_1.logger.info(`Update finished in ${diff}s`);
}
catch (e) {
if (!(0, errors_1.isFatal)(e)) {
(0, errors_1.fatal)((_a = e.stack) !== null && _a !== void 0 ? _a : e);
}
throw e;
}
}
}
exports.updateCommand = updateCommand;
function updateChecks(config, platforms) {
const checks = [];
for (const platformName of platforms) {
if (platformName === config.ios.name) {
checks.push(() => (0, common_2.checkBundler)(config) || (0, common_2.checkCocoaPods)(config));
}
else if (platformName === config.android.name) {
continue;
}
else if (platformName === config.web.name) {
continue;
}
else {
throw `Platform ${platformName} is not valid.`;
}
}
return checks;
}
exports.updateChecks = updateChecks;
async function update(config, platformName, deployment) {
await (0, common_1.runTask)(colors_1.default.success(colors_1.default.strong(`update ${platformName}`)), async () => {
await (0, common_1.runHooks)(config, platformName, config.app.rootDir, 'capacitor:update:before');
if (platformName === config.ios.name) {
await (0, update_2.updateIOS)(config, deployment);
}
else if (platformName === config.android.name) {
await (0, update_1.updateAndroid)(config);
}
await (0, common_1.runHooks)(config, platformName, config.app.rootDir, 'capacitor:update:after');
});
}
exports.update = update;

130
@capacitor/cli/dist/telemetry.js vendored Normal file
View file

@ -0,0 +1,130 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sendMetric = exports.telemetryAction = exports.THANK_YOU = void 0;
const tslib_1 = require("tslib");
const commander_1 = require("commander");
const debug_1 = tslib_1.__importDefault(require("debug"));
const colors_1 = tslib_1.__importDefault(require("./colors"));
const ipc_1 = require("./ipc");
const log_1 = require("./log");
const sysconfig_1 = require("./sysconfig");
const subprocess_1 = require("./util/subprocess");
const term_1 = require("./util/term");
const debug = (0, debug_1.default)('capacitor:telemetry');
exports.THANK_YOU = `\nThank you for helping to make Capacitor better! 💖` +
`\nInformation about the data we collect is available on our website: ${colors_1.default.strong('https://capacitorjs.com/telemetry')}\n`;
function telemetryAction(config, action) {
return async (...actionArgs) => {
const start = new Date();
// This is how commanderjs works--the command object is either the last
// element or second to last if there are additional options (via `.allowUnknownOption()`)
const lastArg = actionArgs[actionArgs.length - 1];
const cmd = lastArg instanceof commander_1.Command ? lastArg : actionArgs[actionArgs.length - 2];
const command = getFullCommandName(cmd);
let error;
try {
await action(...actionArgs);
}
catch (e) {
error = e;
}
const end = new Date();
const duration = end.getTime() - start.getTime();
const packages = Object.entries({
...config.app.package.devDependencies,
...config.app.package.dependencies,
});
// Only collect packages in the capacitor org:
// https://www.npmjs.com/org/capacitor
const capacitorPackages = packages.filter(([k]) => k.startsWith('@capacitor/'));
const versions = capacitorPackages.map(([k, v]) => [
`${k.replace(/^@capacitor\//, '').replace(/-/g, '_')}_version`,
v,
]);
const data = {
app_id: await getAppIdentifier(config),
command,
arguments: cmd.args.join(' '),
options: JSON.stringify(cmd.opts()),
duration,
error: error ? (error.message ? error.message : String(error)) : null,
node_version: process.version,
os: config.cli.os,
...Object.fromEntries(versions),
};
if ((0, term_1.isInteractive)()) {
let sysconfig = await (0, sysconfig_1.readConfig)();
if (!error && typeof sysconfig.telemetry === 'undefined') {
const confirm = await promptForTelemetry();
sysconfig = { ...sysconfig, telemetry: confirm };
await (0, sysconfig_1.writeConfig)(sysconfig);
}
await sendMetric(sysconfig, 'capacitor_cli_command', data);
}
if (error) {
throw error;
}
};
}
exports.telemetryAction = telemetryAction;
/**
* If telemetry is enabled, send a metric via IPC to a forked process for uploading.
*/
async function sendMetric(sysconfig, name, data) {
if (sysconfig.telemetry && (0, term_1.isInteractive)()) {
const message = {
name,
timestamp: new Date().toISOString(),
session_id: sysconfig.machine,
source: 'capacitor_cli',
value: data,
};
await (0, ipc_1.send)({ type: 'telemetry', data: message });
}
else {
debug('Telemetry is off (user choice, non-interactive terminal, or CI)--not sending metric');
}
}
exports.sendMetric = sendMetric;
async function promptForTelemetry() {
const { confirm } = await (0, log_1.logPrompt)(`${colors_1.default.strong('Would you like to help improve Capacitor by sharing anonymous usage data? 💖')}\n` +
`Read more about what is being collected and why here: ${colors_1.default.strong('https://capacitorjs.com/telemetry')}. You can change your mind at any time by using the ${colors_1.default.input('npx cap telemetry')} command.`, {
type: 'confirm',
name: 'confirm',
message: 'Share anonymous usage data?',
initial: true,
});
if (confirm) {
log_1.output.write(exports.THANK_YOU);
}
return confirm;
}
/**
* Get a unique anonymous identifier for this app.
*/
async function getAppIdentifier(config) {
const { createHash } = await Promise.resolve().then(() => tslib_1.__importStar(require('crypto')));
// get the first commit hash, which should be universally unique
const output = await (0, subprocess_1.getCommandOutput)('git', ['rev-list', '--max-parents=0', 'HEAD'], { cwd: config.app.rootDir });
const firstLine = output === null || output === void 0 ? void 0 : output.split('\n')[0];
if (!firstLine) {
debug('Could not obtain unique app identifier');
return null;
}
// use sha1 to create a one-way hash to anonymize
const id = createHash('sha1').update(firstLine).digest('hex');
return id;
}
/**
* Walk through the command's parent tree and construct a space-separated name.
*
* Probably overkill because we don't have nested commands, but whatever.
*/
function getFullCommandName(cmd) {
const names = [];
while (cmd.parent !== null) {
names.push(cmd.name());
cmd = cmd.parent;
}
return names.reverse().join(' ');
}

25
@capacitor/cli/dist/util/cli.js vendored Normal file
View file

@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.wrapAction = exports.ENV_PATHS = void 0;
const tslib_1 = require("tslib");
const env_paths_1 = tslib_1.__importDefault(require("env-paths"));
const errors_1 = require("../errors");
const log_1 = require("../log");
exports.ENV_PATHS = (0, env_paths_1.default)('capacitor', { suffix: '' });
function wrapAction(action) {
return async (...args) => {
try {
await action(...args);
}
catch (e) {
if ((0, errors_1.isFatal)(e)) {
process.exitCode = e.exitCode;
log_1.logger.error(e.message);
}
else {
throw e;
}
}
};
}
exports.wrapAction = wrapAction;

13
@capacitor/cli/dist/util/emoji.js vendored Normal file
View file

@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.emoji = void 0;
// Emoji falback, right now just uses fallback on windows,
// but could expand to be more sophisticated to allow emoji
// on Hyper term on windows, for example.
const emoji = (x, fallback) => {
if (process.platform === 'win32') {
return fallback;
}
return x;
};
exports.emoji = emoji;

13
@capacitor/cli/dist/util/fn.js vendored Normal file
View file

@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.tryFn = void 0;
const tryFn = async (fn, ...args) => {
try {
return await fn(...args);
}
catch {
// ignore
}
return null;
};
exports.tryFn = tryFn;

24
@capacitor/cli/dist/util/fs.js vendored Normal file
View file

@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.deleteFolderRecursive = exports.convertToUnixPath = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const path_1 = require("path");
const convertToUnixPath = (path) => {
return path.replace(/\\/g, '/');
};
exports.convertToUnixPath = convertToUnixPath;
const deleteFolderRecursive = (directoryPath) => {
if ((0, utils_fs_1.existsSync)(directoryPath)) {
(0, utils_fs_1.readdirSync)(directoryPath).forEach(file => {
const curPath = (0, path_1.join)(directoryPath, file);
if ((0, utils_fs_1.lstatSync)(curPath).isDirectory()) {
(0, exports.deleteFolderRecursive)(curPath);
}
else {
(0, utils_fs_1.unlinkSync)(curPath);
}
});
(0, utils_fs_1.rmdirSync)(directoryPath);
}
};
exports.deleteFolderRecursive = deleteFolderRecursive;

66
@capacitor/cli/dist/util/iosplugin.js vendored Normal file
View file

@ -0,0 +1,66 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateIOSPackageJSON = exports.writePluginJSON = exports.findPluginClasses = exports.getPluginFiles = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const path_1 = require("path");
const cordova_1 = require("../cordova");
const plugin_1 = require("../plugin");
async function getPluginFiles(plugins) {
var _a;
let filenameList = [];
const options = {
filter: item => {
if (item.stats.isFile() &&
(item.path.endsWith('.swift') || item.path.endsWith('.m'))) {
return true;
}
else {
return false;
}
},
};
for (const plugin of plugins) {
if (plugin.ios && (0, plugin_1.getPluginType)(plugin, 'ios') === 0 /* PluginType.Core */) {
const pluginPath = (0, path_1.resolve)(plugin.rootPath, (_a = plugin.ios) === null || _a === void 0 ? void 0 : _a.path);
const filenames = await (0, utils_fs_1.readdirp)(pluginPath, options);
filenameList = filenameList.concat(filenames);
}
}
return filenameList;
}
exports.getPluginFiles = getPluginFiles;
async function findPluginClasses(files) {
const classList = [];
for (const file of files) {
const fileData = (0, utils_fs_1.readFileSync)(file, 'utf-8');
const swiftPluginRegex = RegExp(/@objc\(([A-Za-z0-9_-]+)\)/);
const objcPluginRegex = RegExp(/CAP_PLUGIN\(([A-Za-z0-9_-]+)/);
const swiftMatches = swiftPluginRegex.exec(fileData);
if ((swiftMatches === null || swiftMatches === void 0 ? void 0 : swiftMatches[1]) && !classList.includes(swiftMatches[1])) {
classList.push(swiftMatches[1]);
}
const objcMatches = objcPluginRegex.exec(fileData);
if ((objcMatches === null || objcMatches === void 0 ? void 0 : objcMatches[1]) && !classList.includes(objcMatches[1])) {
classList.push(objcMatches[1]);
}
}
return classList;
}
exports.findPluginClasses = findPluginClasses;
async function writePluginJSON(config, classList) {
const capJSONFile = (0, path_1.resolve)(config.ios.nativeTargetDirAbs, 'capacitor.config.json');
const capJSON = (0, utils_fs_1.readJSONSync)(capJSONFile);
capJSON['packageClassList'] = classList;
(0, utils_fs_1.writeJSONSync)(capJSONFile, capJSON, { spaces: '\t' });
}
exports.writePluginJSON = writePluginJSON;
async function generateIOSPackageJSON(config, plugins) {
const fileList = await getPluginFiles(plugins);
const classList = await findPluginClasses(fileList);
const cordovaPlugins = await (0, cordova_1.getCordovaPlugins)(config, 'ios');
if (cordovaPlugins.length > 0) {
classList.push('CDVPlugin');
}
writePluginJSON(config, classList);
}
exports.generateIOSPackageJSON = generateIOSPackageJSON;

21
@capacitor/cli/dist/util/js.js vendored Normal file
View file

@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.formatJSObject = void 0;
const tslib_1 = require("tslib");
const util_1 = tslib_1.__importDefault(require("util"));
function formatJSObject(o) {
try {
o = JSON.parse(JSON.stringify(o));
}
catch (e) {
throw new Error(`Cannot parse object as JSON: ${e.stack ? e.stack : e}`);
}
return util_1.default.inspect(o, {
compact: false,
breakLength: Infinity,
depth: Infinity,
maxArrayLength: Infinity,
maxStringLength: Infinity,
});
}
exports.formatJSObject = formatJSObject;

151
@capacitor/cli/dist/util/livereload.js vendored Normal file
View file

@ -0,0 +1,151 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CapLiveReloadHelper = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const os_1 = require("os");
const path_1 = require("path");
class CapLiveReload {
constructor() {
this.configJsonToRevertTo = {
json: null,
platformPath: null,
};
// nothing to do
}
getIpAddress(name, family) {
var _a;
const interfaces = (_a = (0, os_1.networkInterfaces)()) !== null && _a !== void 0 ? _a : {};
const _normalizeFamily = (family) => {
if (family === 4) {
return 'ipv4';
}
if (family === 6) {
return 'ipv6';
}
return family ? family.toLowerCase() : 'ipv4';
};
const isLoopback = (addr) => {
return (/^(::f{4}:)?127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/.test(addr) ||
/^fe80::1$/.test(addr) ||
/^::1$/.test(addr) ||
/^::$/.test(addr));
};
const isPrivate = (addr) => {
return (/^(::f{4}:)?10\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) ||
/^(::f{4}:)?192\.168\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) ||
/^(::f{4}:)?172\.(1[6-9]|2\d|30|31)\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) ||
/^(::f{4}:)?127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) ||
/^(::f{4}:)?169\.254\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) ||
/^f[cd][0-9a-f]{2}:/i.test(addr) ||
/^fe80:/i.test(addr) ||
/^::1$/.test(addr) ||
/^::$/.test(addr));
};
const isPublic = (addr) => {
return !isPrivate(addr);
};
const loopback = (family) => {
//
// Default to `ipv4`
//
family = _normalizeFamily(family);
if (family !== 'ipv4' && family !== 'ipv6') {
throw new Error('family must be ipv4 or ipv6');
}
return family === 'ipv4' ? '127.0.0.1' : 'fe80::1';
};
//
// Default to `ipv4`
//
family = _normalizeFamily(family);
//
// If a specific network interface has been named,
// return the address.
//
if (name && name !== 'private' && name !== 'public') {
const res = interfaces[name].filter((details) => {
const itemFamily = _normalizeFamily(details.family);
return itemFamily === family;
});
if (res.length === 0) {
return undefined;
}
return res[0].address;
}
const all = Object.keys(interfaces)
.map(nic => {
//
// Note: name will only be `public` or `private`
// when this is called.
//
const addresses = interfaces[nic].filter((details) => {
details.family = _normalizeFamily(details.family);
if (details.family !== family || isLoopback(details.address)) {
return false;
}
if (!name) {
return true;
}
return name === 'public'
? isPrivate(details.address)
: isPublic(details.address);
});
return addresses.length ? addresses[0].address : undefined;
})
.filter(Boolean);
return !all.length ? loopback(family) : all[0];
}
// TODO remove on next major as it's unused
async editExtConfigForLiveReload(config, platformName, options, rootConfigChange = false) {
const platformAbsPath = platformName == config.ios.name
? config.ios.nativeTargetDirAbs
: platformName == config.android.name
? config.android.assetsDirAbs
: null;
if (platformAbsPath == null)
throw new Error('Platform not found.');
const capConfigPath = rootConfigChange
? config.app.extConfigFilePath
: (0, path_1.join)(platformAbsPath, 'capacitor.config.json');
const configJson = { ...config.app.extConfig };
this.configJsonToRevertTo.json = JSON.stringify(configJson, null, 2);
this.configJsonToRevertTo.platformPath = capConfigPath;
const url = `http://${options.host}:${options.port}`;
configJson.server = {
url,
};
return configJson;
}
// TODO remove rootConfigChange param on next major as it's unused
async editCapConfigForLiveReload(config, platformName, options, rootConfigChange = false) {
const platformAbsPath = platformName == config.ios.name
? config.ios.nativeTargetDirAbs
: platformName == config.android.name
? config.android.assetsDirAbs
: null;
if (platformAbsPath == null)
throw new Error('Platform not found.');
const capConfigPath = rootConfigChange
? config.app.extConfigFilePath
: (0, path_1.join)(platformAbsPath, 'capacitor.config.json');
const configJson = (0, utils_fs_1.readJSONSync)(capConfigPath);
this.configJsonToRevertTo.json = JSON.stringify(configJson, null, 2);
this.configJsonToRevertTo.platformPath = capConfigPath;
const url = `http://${options.host}:${options.port}`;
configJson.server = {
url,
};
(0, utils_fs_1.writeJSONSync)(capConfigPath, configJson, { spaces: '\t' });
}
async revertCapConfigForLiveReload() {
if (this.configJsonToRevertTo.json == null ||
this.configJsonToRevertTo.platformPath == null)
return;
const capConfigPath = this.configJsonToRevertTo.platformPath;
const configJson = this.configJsonToRevertTo.json;
(0, utils_fs_1.writeJSONSync)(capConfigPath, JSON.parse(configJson), { spaces: '\t' });
this.configJsonToRevertTo.json = null;
this.configJsonToRevertTo.platformPath = null;
}
}
exports.CapLiveReloadHelper = new CapLiveReload();

View file

@ -0,0 +1,110 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isNXMonorepo = exports.isMonorepo = exports.findPackageRelativePathInMonorepo = exports.findPackagePath = exports.findNXMonorepoRoot = exports.findMonorepoRoot = void 0;
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
/**
* Finds the monorepo root from the given path.
* @param currentPath - The current path to start searching from.
* @returns The path to the monorepo root.
* @throws An error if the monorepo root is not found.
*/
function findMonorepoRoot(currentPath) {
const packageJsonPath = (0, node_path_1.join)(currentPath, 'package.json');
const pnpmWorkspacePath = (0, node_path_1.join)(currentPath, 'pnpm-workspace.yaml');
if ((0, node_fs_1.existsSync)(pnpmWorkspacePath) ||
((0, node_fs_1.existsSync)(packageJsonPath) &&
JSON.parse((0, node_fs_1.readFileSync)(packageJsonPath, 'utf-8')).workspaces)) {
return currentPath;
}
const parentPath = (0, node_path_1.dirname)(currentPath);
if (parentPath === currentPath) {
throw new Error('Monorepo root not found');
}
return findMonorepoRoot(parentPath);
}
exports.findMonorepoRoot = findMonorepoRoot;
/**
* Finds the NX monorepo root from the given path.
* @param currentPath - The current path to start searching from.
* @returns The path to the monorepo root.
* @throws An error if the monorepo root is not found.
*/
function findNXMonorepoRoot(currentPath) {
const nxJsonPath = (0, node_path_1.join)(currentPath, 'nx.json');
if ((0, node_fs_1.existsSync)(nxJsonPath)) {
return currentPath;
}
const parentPath = (0, node_path_1.dirname)(currentPath);
if (parentPath === currentPath) {
throw new Error('Monorepo root not found');
}
return findNXMonorepoRoot(parentPath);
}
exports.findNXMonorepoRoot = findNXMonorepoRoot;
/**
* Finds the path to a package within the node_modules folder,
* searching up the directory hierarchy until the last possible directory is reached.
* @param packageName - The name of the package to find.
* @param currentPath - The current path to start searching from.
* @param lastPossibleDirectory - The last possible directory to search for the package.
* @returns The path to the package, or null if not found.
*/
function findPackagePath(packageName, currentPath, lastPossibleDirectory) {
const nodeModulesPath = (0, node_path_1.join)(currentPath, 'node_modules', packageName);
if ((0, node_fs_1.existsSync)(nodeModulesPath)) {
return nodeModulesPath;
}
if (currentPath === lastPossibleDirectory) {
return null;
}
const parentPath = (0, node_path_1.dirname)(currentPath);
return findPackagePath(packageName, parentPath, lastPossibleDirectory);
}
exports.findPackagePath = findPackagePath;
/**
* Finds the relative path to a package from the current directory,
* using the monorepo root as the last possible directory.
* @param packageName - The name of the package to find.
* @param currentPath - The current path to start searching from.
* @returns The relative path to the package, or null if not found.
*/
function findPackageRelativePathInMonorepo(packageName, currentPath) {
const monorepoRoot = findMonorepoRoot(currentPath);
const packagePath = findPackagePath(packageName, currentPath, monorepoRoot);
if (packagePath) {
return (0, node_path_1.relative)(currentPath, packagePath);
}
return null;
}
exports.findPackageRelativePathInMonorepo = findPackageRelativePathInMonorepo;
/**
* Detects if the current directory is part of a monorepo (npm, yarn, pnpm).
* @param currentPath - The current path to start searching from.
* @returns True if the current directory is part of a monorepo, false otherwise.
*/
function isMonorepo(currentPath) {
try {
findMonorepoRoot(currentPath);
return true;
}
catch (error) {
return false;
}
}
exports.isMonorepo = isMonorepo;
/**
* Detects if the current directory is part of a nx integrated monorepo.
* @param currentPath - The current path to start searching from.
* @returns True if the current directory is part of a monorepo, false otherwise.
*/
function isNXMonorepo(currentPath) {
try {
findNXMonorepoRoot(currentPath);
return true;
}
catch (error) {
return false;
}
}
exports.isNXMonorepo = isNXMonorepo;

53
@capacitor/cli/dist/util/native-run.js vendored Normal file
View file

@ -0,0 +1,53 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getPlatformTargets = exports.runNativeRun = void 0;
const tslib_1 = require("tslib");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const errors_1 = require("../errors");
const node_1 = require("./node");
const subprocess_1 = require("./subprocess");
async function runNativeRun(args, options = {}) {
const p = (0, node_1.resolveNode)(__dirname, (0, path_1.dirname)('native-run/package'), 'bin/native-run');
if (!p) {
(0, errors_1.fatal)(`${colors_1.default.input('native-run')} not found.`);
}
return await (0, subprocess_1.runCommand)(p, args, options);
}
exports.runNativeRun = runNativeRun;
async function getPlatformTargets(platformName) {
const errors = [];
try {
const output = await runNativeRun([platformName, '--list', '--json']);
const parsedOutput = JSON.parse(output);
if (parsedOutput.devices.length || parsedOutput.virtualDevices.length) {
return [
...parsedOutput.devices.map((t) => ({ ...t, virtual: false })),
...parsedOutput.virtualDevices.map((t) => ({
...t,
virtual: true,
})),
];
}
else {
parsedOutput.errors.map((e) => {
errors.push(e);
});
}
}
catch (e) {
const err = JSON.parse(e);
errors.push(err);
}
const plural = errors.length > 1 ? 's' : '';
const errMsg = `${colors_1.default.strong('native-run')} failed with error${plural}\n
${errors
.map((e) => {
return `\t${colors_1.default.strong(e.code)}: ${e.error}`;
})
.join('\n')}
\n\tMore details for this error${plural} may be available online: ${colors_1.default.strong('https://github.com/ionic-team/native-run/wiki/Android-Errors')}
`;
throw errMsg;
}
exports.getPlatformTargets = getPlatformTargets;

54
@capacitor/cli/dist/util/node.js vendored Normal file
View file

@ -0,0 +1,54 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveNode = exports.requireTS = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const fs_1 = require("fs");
const path_1 = require("path");
/**
* @see https://github.com/ionic-team/stencil/blob/HEAD/src/compiler/sys/node-require.ts
*/
const requireTS = (ts, p) => {
const id = (0, path_1.resolve)(p);
delete require.cache[id];
require.extensions['.ts'] = (module, fileName) => {
var _a;
let sourceText = (0, utils_fs_1.readFileSync)(fileName, 'utf8');
if (fileName.endsWith('.ts')) {
const tsResults = ts.transpileModule(sourceText, {
fileName,
compilerOptions: {
module: ts.ModuleKind.CommonJS,
moduleResolution: ts.ModuleResolutionKind.NodeJs,
esModuleInterop: true,
strict: true,
target: ts.ScriptTarget.ES2017,
},
reportDiagnostics: true,
});
sourceText = tsResults.outputText;
}
else {
// quick hack to turn a modern es module
// into and old school commonjs module
sourceText = sourceText.replace(/export\s+\w+\s+(\w+)/gm, 'exports.$1');
}
(_a = module._compile) === null || _a === void 0 ? void 0 : _a.call(module, sourceText, fileName);
};
const m = require(id); // eslint-disable-line @typescript-eslint/no-var-requires
delete require.extensions['.ts'];
return m;
};
exports.requireTS = requireTS;
function resolveNode(root, ...pathSegments) {
try {
return require.resolve(pathSegments.join('/'), { paths: [root] });
}
catch (e) {
const path = [root, 'node_modules', ...pathSegments].join('/');
if ((0, fs_1.existsSync)(path)) {
return path;
}
return null;
}
}
exports.resolveNode = resolveNode;

35
@capacitor/cli/dist/util/promise.js vendored Normal file
View file

@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.lazy = exports.LazyPromise = exports.allSerial = void 0;
function allSerial(funcs) {
return funcs.reduce((promise, func) => promise.then(result => func().then(x => result.concat(x))), Promise.resolve([]));
}
exports.allSerial = allSerial;
class LazyPromise extends Promise {
constructor(executor) {
super(() => {
/* ignore */
});
this._executor = executor;
}
then(onfulfilled, onrejected) {
this._promise = this._promise || new Promise(this._executor);
return this._promise.then(onfulfilled, onrejected);
}
catch(onrejected) {
this._promise = this._promise || new Promise(this._executor);
return this._promise.catch(onrejected);
}
}
exports.LazyPromise = LazyPromise;
function lazy(fn) {
return new LazyPromise(async (resolve, reject) => {
try {
resolve(await fn());
}
catch (e) {
reject(e);
}
});
}
exports.lazy = lazy;

73
@capacitor/cli/dist/util/spm.js vendored Normal file
View file

@ -0,0 +1,73 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generatePackageFile = exports.findPackageSwiftFile = exports.checkPackageManager = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const path_1 = require("path");
const log_1 = require("../log");
async function checkPackageManager(config) {
const iosDirectory = config.ios.nativeProjectDirAbs;
if ((0, utils_fs_1.existsSync)((0, path_1.resolve)(iosDirectory, 'CapApp-SPM'))) {
return 'SPM';
}
return 'Cocoapods';
}
exports.checkPackageManager = checkPackageManager;
async function findPackageSwiftFile(config) {
const packageDirectory = (0, path_1.resolve)(config.ios.nativeProjectDirAbs, 'CapApp-SPM');
return (0, path_1.resolve)(packageDirectory, 'Package.swift');
}
exports.findPackageSwiftFile = findPackageSwiftFile;
async function generatePackageFile(config, plugins) {
const packageSwiftFile = await findPackageSwiftFile(config);
try {
log_1.logger.warn('SPM Support is still experimental');
const textToWrite = generatePackageText(config, plugins);
(0, utils_fs_1.writeFileSync)(packageSwiftFile, textToWrite);
}
catch (err) {
log_1.logger.error(`Unable to write to ${packageSwiftFile}. Verify it is not already open. \n Error: ${err}`);
}
}
exports.generatePackageFile = generatePackageFile;
function generatePackageText(config, plugins) {
var _a, _b, _c;
const pbx = (0, utils_fs_1.readFileSync)((0, path_1.join)(config.ios.nativeXcodeProjDirAbs, 'project.pbxproj'), 'utf-8');
const searchString = 'IPHONEOS_DEPLOYMENT_TARGET = ';
const iosVersion = pbx.substring(pbx.indexOf(searchString) + searchString.length, pbx.indexOf(searchString) + searchString.length + 2);
let packageSwiftText = `// swift-tools-version: 5.9
import PackageDescription
// DO NOT MODIFY THIS FILE - managed by Capacitor CLI commands
let package = Package(
name: "CapApp-SPM",
platforms: [.iOS(.v${iosVersion})],
products: [
.library(
name: "CapApp-SPM",
targets: ["CapApp-SPM"])
],
dependencies: [
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", branch: "main")`;
for (const plugin of plugins) {
const relPath = (0, path_1.relative)(config.ios.nativeXcodeProjDirAbs, plugin.rootPath);
packageSwiftText += `,\n .package(name: "${(_a = plugin.ios) === null || _a === void 0 ? void 0 : _a.name}", path: "${relPath}")`;
}
packageSwiftText += `
],
targets: [
.target(
name: "CapApp-SPM",
dependencies: [
.product(name: "Capacitor", package: "capacitor-swift-pm"),
.product(name: "Cordova", package: "capacitor-swift-pm")`;
for (const plugin of plugins) {
packageSwiftText += `,\n .product(name: "${(_b = plugin.ios) === null || _b === void 0 ? void 0 : _b.name}", package: "${(_c = plugin.ios) === null || _c === void 0 ? void 0 : _c.name}")`;
}
packageSwiftText += `
]
)
]
)
`;
return packageSwiftText;
}

43
@capacitor/cli/dist/util/subprocess.js vendored Normal file
View file

@ -0,0 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isInstalled = exports.getCommandOutput = exports.runCommand = void 0;
const utils_subprocess_1 = require("@ionic/utils-subprocess");
async function runCommand(command, args, options = {}) {
const p = new utils_subprocess_1.Subprocess(command, args, options);
try {
return await p.output();
}
catch (e) {
if (e instanceof utils_subprocess_1.SubprocessError) {
// old behavior of just throwing the stdout/stderr strings
throw e.output
? e.output
: e.code
? e.code
: e.error
? e.error.message
: 'Unknown error';
}
throw e;
}
}
exports.runCommand = runCommand;
async function getCommandOutput(command, args, options = {}) {
try {
return (await runCommand(command, args, options)).trim();
}
catch (e) {
return null;
}
}
exports.getCommandOutput = getCommandOutput;
async function isInstalled(command) {
try {
await (0, utils_subprocess_1.which)(command);
}
catch (e) {
return false;
}
return true;
}
exports.isInstalled = isInstalled;

11
@capacitor/cli/dist/util/template.js vendored Normal file
View file

@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractTemplate = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const tar_1 = tslib_1.__importDefault(require("tar"));
async function extractTemplate(src, dir) {
await (0, utils_fs_1.mkdirp)(dir);
await tar_1.default.extract({ file: src, cwd: dir });
}
exports.extractTemplate = extractTemplate;

30
@capacitor/cli/dist/util/term.js vendored Normal file
View file

@ -0,0 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isInteractive = exports.checkInteractive = void 0;
const tslib_1 = require("tslib");
const utils_terminal_1 = require("@ionic/utils-terminal");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const log_1 = require("../log");
// Given input variables to a command, make sure all are provided if the terminal
// is not interactive (because we won't be able to prompt the user)
const checkInteractive = (...args) => {
if ((0, exports.isInteractive)()) {
return true;
}
// Fail if no args are provided, treat this as just a check of whether the term is
// interactive or not.
if (!args.length) {
return false;
}
// Make sure none of the provided args are empty, otherwise print the interactive
// warning and return false
if (args.filter(arg => !arg).length) {
log_1.logger.error(`Non-interactive shell detected.\n` +
`Run the command with ${colors_1.default.input('--help')} to see a list of arguments that must be provided.`);
return false;
}
return true;
};
exports.checkInteractive = checkInteractive;
const isInteractive = () => utils_terminal_1.TERMINAL_INFO.tty && !utils_terminal_1.TERMINAL_INFO.ci;
exports.isInteractive = isInteractive;

11
@capacitor/cli/dist/util/uuid.js vendored Normal file
View file

@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.uuidv4 = void 0;
function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
const r = (Math.random() * 16) | 0;
const v = c == 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
exports.uuidv4 = uuidv4;

57
@capacitor/cli/dist/util/xml.js vendored Normal file
View file

@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildXmlElement = exports.writeXML = exports.parseXML = exports.readXML = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const xml2js_1 = tslib_1.__importDefault(require("xml2js"));
async function readXML(path) {
var _a;
try {
const xmlStr = await (0, utils_fs_1.readFile)(path, { encoding: 'utf-8' });
try {
return await xml2js_1.default.parseStringPromise(xmlStr);
}
catch (e) {
throw `Error parsing: ${path}, ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`;
}
}
catch (e) {
throw `Unable to read: ${path}`;
}
}
exports.readXML = readXML;
function parseXML(xmlStr, options) {
const parser = options !== undefined
? new xml2js_1.default.Parser({ ...options })
: new xml2js_1.default.Parser();
let xmlObj;
parser.parseString(xmlStr, (err, result) => {
if (!err) {
xmlObj = result;
}
});
return xmlObj;
}
exports.parseXML = parseXML;
async function writeXML(object) {
return new Promise(resolve => {
const builder = new xml2js_1.default.Builder({
headless: true,
explicitRoot: false,
rootName: 'deleteme',
});
let xml = builder.buildObject(object);
xml = xml.replace('<deleteme>', '').replace('</deleteme>', '');
resolve(xml);
});
}
exports.writeXML = writeXML;
function buildXmlElement(configElement, rootName) {
const builder = new xml2js_1.default.Builder({
headless: true,
explicitRoot: false,
rootName: rootName,
});
return builder.buildObject(configElement);
}
exports.buildXmlElement = buildXmlElement;

22
@capacitor/cli/dist/web/copy.js vendored Normal file
View file

@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.copyWeb = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
const errors_1 = require("../errors");
const node_1 = require("../util/node");
async function copyWeb(config) {
if (config.app.bundledWebRuntime) {
const runtimePath = (0, node_1.resolveNode)(config.app.rootDir, '@capacitor/core', 'dist', 'capacitor.js');
if (!runtimePath) {
(0, errors_1.fatal)(`Unable to find ${colors_1.default.strong('node_modules/@capacitor/core/dist/capacitor.js')}.\n` + `Are you sure ${colors_1.default.strong('@capacitor/core')} is installed?`);
}
return (0, common_1.runTask)(`Copying ${colors_1.default.strong('capacitor.js')} to web dir`, () => {
return (0, utils_fs_1.copy)(runtimePath, (0, path_1.join)(config.app.webDirAbs, 'capacitor.js'));
});
}
}
exports.copyWeb = copyWeb;