Update capacitor version

This commit is contained in:
Pieter Vander Vennet 2025-07-06 20:20:48 +02:00
parent 91155bce0a
commit f3b3a86b32
610 changed files with 28718 additions and 7101 deletions

View file

@ -2,28 +2,25 @@
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 fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const rimraf_1 = tslib_1.__importDefault(require("rimraf"));
const rimraf_1 = 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 common_3 = require("../ios/common");
const log_1 = require("../log");
const plugin_1 = require("../plugin");
const fs_1 = require("../util/fs");
const node_1 = require("../util/node");
const spm_1 = require("../util/spm");
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 libs = ['@capacitor/core', '@capacitor/cli', '@capacitor/ios', '@capacitor/android'];
const plugins = [
'@capacitor/action-sheet',
'@capacitor/app',
@ -50,21 +47,22 @@ const plugins = [
'@capacitor/text-zoom',
'@capacitor/toast',
];
const coreVersion = '^6.0.0';
const pluginVersion = '^6.0.0';
const gradleVersion = '8.2.1';
const coreVersion = '^7.0.0';
const pluginVersion = '^7.0.0';
const gradleVersion = '8.11.1';
const iOSVersion = '14';
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');
if (capMajor < 6) {
(0, errors_1.fatal)('Migrate can only be used on Capacitor 6, please use the CLI in Capacitor 6 to upgrade to 6 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.');
if (jdkMajor < 21) {
log_1.logger.warn('Capacitor 7 requires JDK 21 or higher. Some steps may fail.');
}
const variablesAndClasspaths = await getAndroidVariablesAndClasspaths(config);
if (!variablesAndClasspaths) {
@ -78,14 +76,13 @@ async function migrateCommand(config, noprompt, packagemanager) {
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`, {
: await (0, log_1.logPrompt)(`Capacitor 7 sets a deployment target of iOS ${iOSVersion} and Android 15 (SDK 35). \n`, {
type: 'text',
name: 'migrateconfirm',
message: `Are you sure you want to migrate? (Y/n)`,
initial: 'y',
});
if (typeof migrateconfirm === 'string' &&
migrateconfirm.toLowerCase() === 'y') {
if (typeof migrateconfirm === 'string' && migrateconfirm.toLowerCase() === 'y') {
try {
const { depInstallConfirm } = noprompt
? { depInstallConfirm: 'y' }
@ -95,8 +92,7 @@ async function migrateCommand(config, noprompt, packagemanager) {
message: `Run Dependency Install? (Y/n)`,
initial: 'y',
});
const runNpmInstall = typeof depInstallConfirm === 'string' &&
depInstallConfirm.toLowerCase() === 'y';
const runNpmInstall = typeof depInstallConfirm === 'string' && depInstallConfirm.toLowerCase() === 'y';
let installerType = 'npm';
if (runNpmInstall) {
const { manager } = packagemanager
@ -125,13 +121,23 @@ async function migrateCommand(config, noprompt, packagemanager) {
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 (allDependencies['@capacitor/ios'] && (0, fs_extra_1.existsSync)(config.ios.platformDirAbs)) {
const currentiOSVersion = (0, common_3.getMajoriOSVersion)(config);
if (parseInt(currentiOSVersion) < parseInt(iOSVersion)) {
// ios template changes
await (0, common_2.runTask)(`Migrating deployment target to ${iOSVersion}.0.`, () => {
return updateFile(config, (0, path_1.join)(config.ios.nativeXcodeProjDirAbs, 'project.pbxproj'), 'IPHONEOS_DEPLOYMENT_TARGET = ', ';', `${iOSVersion}.0`);
});
if ((await (0, spm_1.checkPackageManager)(config)) === 'Cocoapods') {
// Update Podfile
await (0, common_2.runTask)(`Migrating Podfile to ${iOSVersion}.0.`, () => {
return updateFile(config, (0, path_1.join)(config.ios.nativeProjectDirAbs, 'Podfile'), `platform :ios, '`, `'`, `${iOSVersion}.0`);
});
}
}
else {
log_1.logger.warn('Skipped updating deployment target');
}
}
if (!installFailed) {
await (0, common_2.runTask)(`Running cap sync.`, () => {
@ -141,11 +147,18 @@ async function migrateCommand(config, noprompt, packagemanager) {
else {
log_1.logger.warn('Skipped Running cap sync.');
}
if (allDependencies['@capacitor/android'] &&
(0, utils_fs_1.existsSync)(config.android.platformDirAbs)) {
if (allDependencies['@capacitor/android'] && (0, fs_extra_1.existsSync)(config.android.platformDirAbs)) {
// AndroidManifest.xml add navigation"
await (0, common_2.runTask)(`Migrating AndroidManifest.xml by adding navigation to Activity configChanges.`, () => {
return updateAndroidManifest((0, path_1.join)(config.android.srcMainDirAbs, 'AndroidManifest.xml'));
});
const gradleWrapperVersion = getGradleWrapperVersion((0, path_1.join)(config.android.platformDirAbs, 'gradle', 'wrapper', 'gradle-wrapper.properties'));
if (!installFailed && (0, semver_1.gt)(gradleVersion, gradleWrapperVersion)) {
if (!installFailed && (0, semver_1.gte)(gradleVersion, gradleWrapperVersion)) {
try {
await (0, common_2.runTask)(`Upgrading gradle wrapper`, () => {
return updateGradleWrapperFiles(config.android.platformDirAbs);
});
// Run twice as first time it only updates the wrapper properties file
await (0, common_2.runTask)(`Upgrading gradle wrapper files`, () => {
return updateGradleWrapperFiles(config.android.platformDirAbs);
});
@ -165,22 +178,6 @@ async function migrateCommand(config, noprompt, packagemanager) {
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 () => {
@ -190,7 +187,7 @@ async function migrateCommand(config, noprompt, packagemanager) {
return;
}
txt = txt.replace(/= {2}'/g, `= '`);
(0, utils_fs_1.writeFileSync)(variablesPath, txt, { encoding: 'utf-8' });
(0, fs_extra_1.writeFileSync)(variablesPath, txt, { encoding: 'utf-8' });
for (const variable of Object.keys(variablesAndClasspaths.variables)) {
let replaceStart = `${variable} = '`;
let replaceEnd = `'\n`;
@ -201,11 +198,9 @@ async function migrateCommand(config, noprompt, packagemanager) {
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' &&
if ((typeof variablesAndClasspaths.variables[variable] === 'number' &&
value <= variablesAndClasspaths.variables[variable]) ||
(typeof variablesAndClasspaths.variables[variable] ===
'string' &&
(typeof variablesAndClasspaths.variables[variable] === 'string' &&
(0, semver_1.lt)(value, variablesAndClasspaths.variables[variable]))) {
await updateFile(config, variablesPath, replaceStart, replaceEnd, variablesAndClasspaths.variables[variable].toString(), true);
}
@ -214,16 +209,16 @@ async function migrateCommand(config, noprompt, packagemanager) {
let file = readFile(variablesPath);
if (file) {
file = file.replace('}', ` ${replaceStart}${variablesAndClasspaths.variables[variable].toString()}${replaceEnd}}`);
(0, utils_fs_1.writeFileSync)(variablesPath, file);
(0, fs_extra_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',
firebaseMessagingVersion: '24.1.0',
playServicesLocationVersion: '21.3.0',
androidxBrowserVersion: '1.8.0',
androidxMaterialVersion: '1.12.0',
androidxExifInterfaceVersion: '1.3.7',
androidxCoreKTXVersion: '1.12.0',
googleMapsPlayServicesVersion: '18.2.0',
googleMapsUtilsVersion: '3.8.2',
@ -237,7 +232,7 @@ async function migrateCommand(config, noprompt, packagemanager) {
}
})();
});
rimraf_1.default.sync((0, path_1.join)(config.android.appDirAbs, 'build'));
rimraf_1.rimraf.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);
@ -297,11 +292,11 @@ async function installLatestLibs(dependencyManager, runInstall, config) {
pkgJson['dependencies'][depKey] = pluginVersion;
}
}
(0, utils_fs_1.writeFileSync)(pkgJsonPath, JSON.stringify(pkgJson, null, 2), {
(0, fs_extra_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)'));
rimraf_1.rimraf.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']);
@ -316,11 +311,11 @@ async function installLatestLibs(dependencyManager, runInstall, config) {
}
async function writeBreakingChanges() {
const breaking = [
'@capacitor/camera',
'@capacitor/filesystem',
'@capacitor/geolocation',
'@capacitor/google-maps',
'@capacitor/local-notifications',
'@capacitor/app',
'@capacitor/device',
'@capacitor/haptics',
'@capacitor/splash-screen',
'@capacitor/statusbar',
];
const broken = [];
for (const lib of breaking) {
@ -329,7 +324,7 @@ async function writeBreakingChanges() {
}
}
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(', ')}.`);
log_1.logger.info(`IMPORTANT: Review https://capacitorjs.com/docs/next/updating/7-0#plugins for breaking changes in these plugins that you use: ${broken.join(', ')}.`);
}
}
async function getAndroidVariablesAndClasspaths(config) {
@ -343,10 +338,8 @@ async function getAndroidVariablesAndClasspaths(config) {
(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 comAndroidToolsBuildGradleVersion = '' + buildGradleFile.substring(firstIndxOfCATBGV, buildGradleFile.indexOf("'", firstIndxOfCATBGV));
const comGoogleGmsGoogleServices = '' + buildGradleFile.substring(firstIndxOfCGGGS, buildGradleFile.indexOf("'", firstIndxOfCGGGS));
const variablesGradleAsJSON = JSON.parse(variablesGradleFile
.replace('ext ', '')
.replace(/=/g, ':')
@ -359,18 +352,18 @@ async function getAndroidVariablesAndClasspaths(config) {
.replace(/\s/g, '')
.replace(/'/g, '"'));
return {
'variables': variablesGradleAsJSON,
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)) {
if (!(0, fs_extra_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');
return (0, fs_extra_1.readFileSync)(filename, 'utf-8');
}
catch (err) {
log_1.logger.error(`Unable to read ${filename}. Verify it is not already open. ${err}`);
@ -387,15 +380,7 @@ function getGradleWrapperVersion(filename) {
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',
], {
await (0, subprocess_1.runCommand)(`./gradlew`, ['wrapper', '--distribution-type', 'all', '--gradle-version', gradleVersion, '--warning-mode', 'all'], {
cwd: platformDir,
});
}
@ -437,8 +422,8 @@ async function movePackageFromManifestToBuildGradle(manifestFilename, buildGradl
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');
(0, fs_extra_1.writeFileSync)(manifestFilename, manifestReplaced, 'utf-8');
(0, fs_extra_1.writeFileSync)(buildGradleFilename, buildGradleReplaced, 'utf-8');
}
async function updateBuildGradle(filename, variablesAndClasspaths) {
const txt = readFile(filename);
@ -460,7 +445,7 @@ async function updateBuildGradle(filename, variablesAndClasspaths) {
}
}
}
(0, utils_fs_1.writeFileSync)(filename, replaced, 'utf-8');
(0, fs_extra_1.writeFileSync)(filename, replaced, 'utf-8');
}
async function updateFile(config, filename, textStart, textEnd, replacement, skipIfNotFound) {
if (config === null) {
@ -474,7 +459,7 @@ async function updateFile(config, filename, textStart, textEnd, replacement, ski
if (txt.includes(textStart)) {
if (replacement) {
txt = setAllStringIn(txt, textStart, textEnd, replacement);
(0, utils_fs_1.writeFileSync)(path, txt, { encoding: 'utf-8' });
(0, fs_extra_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
@ -497,7 +482,7 @@ async function updateFile(config, filename, textStart, textEnd, replacement, ski
replaced += line + '\n';
}
}
(0, utils_fs_1.writeFileSync)(path, replaced, { encoding: 'utf-8' });
(0, fs_extra_1.writeFileSync)(path, replaced, { encoding: 'utf-8' });
}
return true;
}
@ -518,14 +503,22 @@ function setAllStringIn(data, start, end, replacement) {
else {
const idx = foundIdx + start.length;
position = idx + replacement.length;
result =
result.substring(0, idx) +
replacement +
result.substring(result.indexOf(end, idx));
result = result.substring(0, idx) + replacement + result.substring(result.indexOf(end, idx));
}
}
return result;
}
async function updateAndroidManifest(filename) {
const txt = readFile(filename);
if (!txt) {
return;
}
if (txt.includes('navigation')) {
return; // Probably already updated
}
const replaced = txt.replace('android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"', 'android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode|navigation"');
(0, fs_extra_1.writeFileSync)(filename, replaced, 'utf-8');
}
async function patchOldCapacitorPlugins(config) {
const allPlugins = await (0, plugin_1.getPlugins)(config, 'android');
const androidPlugins = await (0, common_1.getAndroidPlugins)(allPlugins);
@ -550,26 +543,3 @@ async function patchOldCapacitorPlugins(config) {
}));
}
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');
}
}