@capacitor/cli 8.4.3-nightly-20260731T154447.0 → 8.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/android-template.tar.gz +0 -0
- package/assets/capacitor-cordova-android-plugins.tar.gz +0 -0
- package/assets/capacitor-cordova-ios-plugins.tar.gz +0 -0
- package/assets/ios-pods-template.tar.gz +0 -0
- package/assets/ios-spm-template.tar.gz +0 -0
- package/dist/config.js +1 -1
- package/dist/tasks/migrate.js +0 -6
- package/dist/util/node.js +1 -35
- package/dist/util/spm.js +1 -36
- package/package.json +1 -3
- package/dist/tasks/migrate-uiscene.js +0 -273
- package/dist/util/xcode.js +0 -48
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/config.js
CHANGED
|
@@ -87,7 +87,7 @@ async function loadExtConfigTS(rootDir, extConfigName, extConfigFilePath) {
|
|
|
87
87
|
`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')}`);
|
|
88
88
|
}
|
|
89
89
|
const ts = require(tsPath); // eslint-disable-line @typescript-eslint/no-var-requires
|
|
90
|
-
const extConfigObject = (
|
|
90
|
+
const extConfigObject = (0, node_1.requireTS)(ts, extConfigFilePath);
|
|
91
91
|
const extConfig = extConfigObject.default ? await extConfigObject.default : extConfigObject;
|
|
92
92
|
return {
|
|
93
93
|
extConfigType: 'ts',
|
package/dist/tasks/migrate.js
CHANGED
|
@@ -14,7 +14,6 @@ const log_1 = require("../log");
|
|
|
14
14
|
const fs_1 = require("../util/fs");
|
|
15
15
|
const subprocess_1 = require("../util/subprocess");
|
|
16
16
|
const template_1 = require("../util/template");
|
|
17
|
-
const migrate_uiscene_1 = require("./migrate-uiscene");
|
|
18
17
|
// eslint-disable-next-line prefer-const
|
|
19
18
|
let allDependencies = {};
|
|
20
19
|
const libs = ['@capacitor/core', '@capacitor/cli', '@capacitor/ios', '@capacitor/android'];
|
|
@@ -137,7 +136,6 @@ async function migrateCommand(config, noprompt, packagemanager) {
|
|
|
137
136
|
else {
|
|
138
137
|
log_1.logger.warn('Skipped updating deployment target');
|
|
139
138
|
}
|
|
140
|
-
await (0, migrate_uiscene_1.migrateToUIScene)(config);
|
|
141
139
|
}
|
|
142
140
|
if (!installFailed) {
|
|
143
141
|
await (0, common_1.runTask)(`Running cap sync.`, () => {
|
|
@@ -326,10 +324,6 @@ async function writeBreakingChanges() {
|
|
|
326
324
|
if (broken.length > 0) {
|
|
327
325
|
log_1.logger.info(`IMPORTANT: Review https://capacitorjs.com/docs/next/updating/8-0#plugins for breaking changes in these plugins that you use: ${broken.join(', ')}.`);
|
|
328
326
|
}
|
|
329
|
-
if (allDependencies['@capacitor/ios']) {
|
|
330
|
-
log_1.logger.info('IMPORTANT: Capacitor 8.5 adopts UIScene on iOS. ' +
|
|
331
|
-
'See https://capacitorjs.com/docs/updating/8-5 for the full 8.4 → 8.5 migration guide.');
|
|
332
|
-
}
|
|
333
327
|
}
|
|
334
328
|
async function getAndroidVariablesAndClasspaths(config) {
|
|
335
329
|
const tempAndroidTemplateFolder = (0, path_1.join)(config.cli.assetsDirAbs, 'tempAndroidTemplate');
|
package/dist/util/node.js
CHANGED
|
@@ -4,45 +4,11 @@ exports.resolveNode = exports.requireTS = void 0;
|
|
|
4
4
|
const fs_1 = require("fs");
|
|
5
5
|
const fs_extra_1 = require("fs-extra");
|
|
6
6
|
const path_1 = require("path");
|
|
7
|
-
const url_1 = require("url");
|
|
8
|
-
/**
|
|
9
|
-
* TypeScript 7 dropped the classic compiler API (transpileModule, ModuleKind, etc.) from its
|
|
10
|
-
* default export -- `require('typescript')` now only exposes `version`/`versionMajorMinor`.
|
|
11
|
-
* Detect that case so we can fall back to a loading strategy that doesn't depend on it.
|
|
12
|
-
*
|
|
13
|
-
* @see https://github.com/ionic-team/capacitor/issues/8531
|
|
14
|
-
*/
|
|
15
|
-
function hasClassicCompilerAPI(ts) {
|
|
16
|
-
return typeof ts.transpileModule === 'function';
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* A plain `import()` here gets downleveled to a `require()` call by tsc when compiling to
|
|
20
|
-
* CommonJS (our build target), which defeats the purpose -- we specifically need the real ESM
|
|
21
|
-
* loader so Node's native TypeScript stripping kicks in. Constructing the import from a string
|
|
22
|
-
* keeps tsc from touching it.
|
|
23
|
-
*/
|
|
24
|
-
const dynamicImport = new Function('specifier', 'return import(specifier)');
|
|
25
7
|
/**
|
|
26
8
|
* @see https://github.com/ionic-team/stencil/blob/HEAD/src/compiler/sys/node-require.ts
|
|
27
9
|
*/
|
|
28
|
-
const requireTS =
|
|
10
|
+
const requireTS = (ts, p) => {
|
|
29
11
|
const id = (0, path_1.resolve)(p);
|
|
30
|
-
if (!hasClassicCompilerAPI(ts)) {
|
|
31
|
-
// Node has its own built-in TypeScript syntax stripping (stable since Node 23.6, and
|
|
32
|
-
// available behind --experimental-strip-types since Node 22.6), so we can load the file
|
|
33
|
-
// directly via the native ESM loader instead of transpiling it ourselves.
|
|
34
|
-
try {
|
|
35
|
-
return await dynamicImport((0, url_1.pathToFileURL)(id).href);
|
|
36
|
-
}
|
|
37
|
-
catch (e) {
|
|
38
|
-
if ((e === null || e === void 0 ? void 0 : e.code) === 'ERR_UNKNOWN_FILE_EXTENSION') {
|
|
39
|
-
throw new Error(`Your installed version of TypeScript (${ts.version}) no longer provides the compiler API Capacitor previously used to load .ts config files, ` +
|
|
40
|
-
`and your Node.js runtime (${process.version}) doesn't support loading them natively either.\n` +
|
|
41
|
-
'Upgrade to Node.js 22.6+ (running with --experimental-strip-types), or Node.js 23.6+, to continue using capacitor.config.ts.');
|
|
42
|
-
}
|
|
43
|
-
throw e;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
12
|
delete require.cache[id];
|
|
47
13
|
require.extensions['.ts'] = (module, fileName) => {
|
|
48
14
|
var _a;
|
package/dist/util/spm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.checkPackageTraitsRequirements = exports.checkSwiftToolsVersion = exports.
|
|
3
|
+
exports.checkPackageTraitsRequirements = exports.checkSwiftToolsVersion = exports.addInfoPlistDebugIfNeeded = exports.runCocoapodsDeintegrate = exports.generatePackageText = exports.removeCocoapodsFiles = exports.extractSPMPackageDirectory = exports.checkPluginsForPackageSwift = exports.generatePackageFile = exports.findPackageSwiftFile = exports.checkPackageManager = void 0;
|
|
4
4
|
const fs_extra_1 = require("fs-extra");
|
|
5
5
|
const os_1 = require("os");
|
|
6
6
|
const path_1 = require("path");
|
|
@@ -221,41 +221,6 @@ async function addInfoPlistDebugIfNeeded(config) {
|
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
223
|
exports.addInfoPlistDebugIfNeeded = addInfoPlistDebugIfNeeded;
|
|
224
|
-
function hasSceneManifest(config) {
|
|
225
|
-
const infoPlist = (0, path_1.resolve)(config.ios.nativeTargetDirAbs, 'Info.plist');
|
|
226
|
-
if (!(0, fs_extra_1.existsSync)(infoPlist)) {
|
|
227
|
-
return false;
|
|
228
|
-
}
|
|
229
|
-
const entries = (0, plist_1.parse)((0, fs_extra_1.readFileSync)(infoPlist, 'utf-8'));
|
|
230
|
-
return entries['UIApplicationSceneManifest'] !== undefined;
|
|
231
|
-
}
|
|
232
|
-
exports.hasSceneManifest = hasSceneManifest;
|
|
233
|
-
async function addSceneManifestIfNeeded(config) {
|
|
234
|
-
const infoPlist = (0, path_1.resolve)(config.ios.nativeTargetDirAbs, 'Info.plist');
|
|
235
|
-
if (!(0, fs_extra_1.existsSync)(infoPlist)) {
|
|
236
|
-
log_1.logger.warn(infoPlist + ' not found.');
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
const entries = (0, plist_1.parse)((0, fs_extra_1.readFileSync)(infoPlist, 'utf-8'));
|
|
240
|
-
if (entries['UIApplicationSceneManifest'] !== undefined) {
|
|
241
|
-
log_1.logger.warn('Found UIApplicationSceneManifest in ' + infoPlist + ', skipping.');
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
entries['UIApplicationSceneManifest'] = {
|
|
245
|
-
UIApplicationSupportsMultipleScenes: false,
|
|
246
|
-
UISceneConfigurations: {
|
|
247
|
-
UIWindowSceneSessionRoleApplication: [
|
|
248
|
-
{
|
|
249
|
-
UISceneConfigurationName: 'Default Configuration',
|
|
250
|
-
UISceneDelegateClassName: '$(PRODUCT_MODULE_NAME).SceneDelegate',
|
|
251
|
-
UISceneStoryboardFile: 'Main',
|
|
252
|
-
},
|
|
253
|
-
],
|
|
254
|
-
},
|
|
255
|
-
};
|
|
256
|
-
(0, fs_extra_1.writeFileSync)(infoPlist, (0, plist_1.build)(entries));
|
|
257
|
-
}
|
|
258
|
-
exports.addSceneManifestIfNeeded = addSceneManifestIfNeeded;
|
|
259
224
|
async function checkSwiftToolsVersion(config, version) {
|
|
260
225
|
if (!version) {
|
|
261
226
|
return null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capacitor/cli",
|
|
3
|
-
"version": "8.4.3
|
|
3
|
+
"version": "8.4.3",
|
|
4
4
|
"description": "Capacitor: Cross-platform apps with JavaScript and the web",
|
|
5
5
|
"homepage": "https://capacitorjs.com",
|
|
6
6
|
"author": "Ionic Team <hi@ionic.io> (https://ionic.io)",
|
|
@@ -60,7 +60,6 @@
|
|
|
60
60
|
"semver": "^7.6.3",
|
|
61
61
|
"tar": "^7.5.3",
|
|
62
62
|
"tslib": "^2.8.1",
|
|
63
|
-
"xcode": "^3.0.1",
|
|
64
63
|
"xml2js": "^0.6.2"
|
|
65
64
|
},
|
|
66
65
|
"devDependencies": {
|
|
@@ -71,7 +70,6 @@
|
|
|
71
70
|
"@types/prompts": "^2.4.9",
|
|
72
71
|
"@types/semver": "^7.5.8",
|
|
73
72
|
"@types/tmp": "^0.2.6",
|
|
74
|
-
"@types/xcode": "^3.0.0",
|
|
75
73
|
"@types/xml2js": "0.4.5",
|
|
76
74
|
"jest": "^29.7.0",
|
|
77
75
|
"jest-environment-jsdom": "^29.7.0",
|
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.__testables = exports.migrateToUIScene = void 0;
|
|
4
|
-
const fs_extra_1 = require("fs-extra");
|
|
5
|
-
const path_1 = require("path");
|
|
6
|
-
const common_1 = require("../common");
|
|
7
|
-
const log_1 = require("../log");
|
|
8
|
-
const fs_1 = require("../util/fs");
|
|
9
|
-
const spm_1 = require("../util/spm");
|
|
10
|
-
const template_1 = require("../util/template");
|
|
11
|
-
const xcode_1 = require("../util/xcode");
|
|
12
|
-
async function migrateToUIScene(config) {
|
|
13
|
-
const signals = readDetectionSignals(config);
|
|
14
|
-
const state = classify(signals);
|
|
15
|
-
switch (state) {
|
|
16
|
-
case 'already-migrated':
|
|
17
|
-
log_1.logger.info('UIScene migration: project already migrated, skipping.');
|
|
18
|
-
return;
|
|
19
|
-
case 'partial':
|
|
20
|
-
log_1.logger.warn(`UIScene migration: project is in a partial state (${describeSignals(signals)}). ` +
|
|
21
|
-
`Skipping automated migration — finish the migration by hand or reset to a clean 8.4 state first.`);
|
|
22
|
-
return;
|
|
23
|
-
case 'eligible':
|
|
24
|
-
break;
|
|
25
|
-
}
|
|
26
|
-
const assets = await loadTemplateAssets(config);
|
|
27
|
-
if (!assets) {
|
|
28
|
-
log_1.logger.error('UIScene migration: could not read shipped iOS template assets; skipping.');
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
await (0, common_1.runTask)('Adding UIApplicationSceneManifest to Info.plist.', () => (0, spm_1.addSceneManifestIfNeeded)(config));
|
|
32
|
-
await (0, common_1.runTask)('Writing SceneDelegate.swift.', async () => {
|
|
33
|
-
const { written } = writeSceneDelegate(config, assets.sceneDelegate);
|
|
34
|
-
if (!written) {
|
|
35
|
-
log_1.logger.warn('SceneDelegate.swift already exists, skipping.');
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
await (0, common_1.runTask)('Patching AppDelegate.swift with configurationForConnecting.', async () => {
|
|
39
|
-
const { patched, reason } = patchAppDelegate(config, assets.configurationForConnectingSnippet);
|
|
40
|
-
if (!patched && reason) {
|
|
41
|
-
log_1.logger.warn(`AppDelegate.swift not patched: ${reason}`);
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
await (0, common_1.runTask)('Registering SceneDelegate.swift with the Xcode App target.', async () => {
|
|
45
|
-
var _a;
|
|
46
|
-
const pbxprojPath = (0, path_1.join)(config.ios.nativeXcodeProjDirAbs, 'project.pbxproj');
|
|
47
|
-
try {
|
|
48
|
-
const { added } = (0, xcode_1.addSwiftFileToAppTarget)(pbxprojPath, 'App', 'SceneDelegate.swift');
|
|
49
|
-
if (!added) {
|
|
50
|
-
log_1.logger.warn('SceneDelegate.swift is already registered in the App target, skipping.');
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
catch (err) {
|
|
54
|
-
log_1.logger.warn(`Could not register SceneDelegate.swift automatically: ${(_a = err === null || err === void 0 ? void 0 : err.message) !== null && _a !== void 0 ? _a : err}. ` +
|
|
55
|
-
'Add SceneDelegate.swift to the App target in Xcode manually.');
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
await scanAndWarn(config);
|
|
59
|
-
printNextSteps();
|
|
60
|
-
}
|
|
61
|
-
exports.migrateToUIScene = migrateToUIScene;
|
|
62
|
-
async function scanAndWarn(config) {
|
|
63
|
-
const findings = [];
|
|
64
|
-
const swiftFiles = await (0, fs_1.readdirp)(config.ios.platformDirAbs, {
|
|
65
|
-
filter: (item) => {
|
|
66
|
-
if (!item.stats.isFile())
|
|
67
|
-
return false;
|
|
68
|
-
if (!item.path.endsWith('.swift'))
|
|
69
|
-
return false;
|
|
70
|
-
const p = item.path;
|
|
71
|
-
return (!p.includes(`${path_1.sep}Pods${path_1.sep}`) &&
|
|
72
|
-
!p.includes(`${path_1.sep}build${path_1.sep}`) &&
|
|
73
|
-
!p.includes(`${path_1.sep}DerivedData${path_1.sep}`) &&
|
|
74
|
-
!p.includes(`${path_1.sep}.build${path_1.sep}`));
|
|
75
|
-
},
|
|
76
|
-
});
|
|
77
|
-
const tokenPatterns = [
|
|
78
|
-
{ token: /UIApplication\.shared\.applicationState/, label: 'UIApplication.shared.applicationState' },
|
|
79
|
-
{ token: /\btmpWindow\b/, label: 'tmpWindow' },
|
|
80
|
-
{ token: /\bTmpViewController\b/, label: 'TmpViewController' },
|
|
81
|
-
];
|
|
82
|
-
for (const filePath of swiftFiles) {
|
|
83
|
-
const source = (0, fs_extra_1.readFileSync)(filePath, 'utf-8');
|
|
84
|
-
source.split('\n').forEach((line, idx) => {
|
|
85
|
-
for (const { token, label } of tokenPatterns) {
|
|
86
|
-
if (token.test(line)) {
|
|
87
|
-
findings.push(`${filePath}:${idx + 1}: uses ${label}`);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
const appDelegatePath = (0, path_1.join)(config.ios.nativeTargetDirAbs, 'AppDelegate.swift');
|
|
93
|
-
if ((0, fs_extra_1.existsSync)(appDelegatePath)) {
|
|
94
|
-
const source = (0, fs_extra_1.readFileSync)(appDelegatePath, 'utf-8');
|
|
95
|
-
if (hasCustomDelegateBody(source, /func application\([^)]*\bopen url:/)) {
|
|
96
|
-
findings.push(`${appDelegatePath}: custom application(_:open:) body — review for UIScene compatibility`);
|
|
97
|
-
}
|
|
98
|
-
if (hasCustomDelegateBody(source, /func application\([^)]*\bcontinue userActivity:/)) {
|
|
99
|
-
findings.push(`${appDelegatePath}: custom application(_:continue:) body — review for UIScene compatibility`);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
if (findings.length === 0)
|
|
103
|
-
return;
|
|
104
|
-
log_1.logger.warn('UIScene scan found patterns that may need manual review:');
|
|
105
|
-
for (const finding of findings) {
|
|
106
|
-
log_1.logger.warn(` ${finding}`);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
function hasCustomDelegateBody(source, sigRegex) {
|
|
110
|
-
const match = source.match(sigRegex);
|
|
111
|
-
if (!match || match.index === undefined)
|
|
112
|
-
return false;
|
|
113
|
-
const openIdx = source.indexOf('{', match.index);
|
|
114
|
-
if (openIdx === -1)
|
|
115
|
-
return false;
|
|
116
|
-
let depth = 1;
|
|
117
|
-
let i = openIdx + 1;
|
|
118
|
-
while (i < source.length && depth > 0) {
|
|
119
|
-
const ch = source[i];
|
|
120
|
-
if (ch === '{')
|
|
121
|
-
depth++;
|
|
122
|
-
else if (ch === '}')
|
|
123
|
-
depth--;
|
|
124
|
-
i++;
|
|
125
|
-
}
|
|
126
|
-
if (depth !== 0)
|
|
127
|
-
return false;
|
|
128
|
-
const body = source.slice(openIdx + 1, i - 1);
|
|
129
|
-
const codeLines = body
|
|
130
|
-
.split('\n')
|
|
131
|
-
.map((l) => l.trim())
|
|
132
|
-
.filter((l) => l.length > 0 && !l.startsWith('//'));
|
|
133
|
-
if (codeLines.length === 0)
|
|
134
|
-
return false;
|
|
135
|
-
return codeLines.some((l) => !l.includes('ApplicationDelegateProxy.shared'));
|
|
136
|
-
}
|
|
137
|
-
function printNextSteps() {
|
|
138
|
-
log_1.logger.info('');
|
|
139
|
-
log_1.logger.info('UIScene migration next steps:');
|
|
140
|
-
log_1.logger.info(' • Review any warnings above for legacy API usage or custom AppDelegate URL/activity handlers.');
|
|
141
|
-
log_1.logger.info(' • Full guide: https://capacitorjs.com/docs/updating/8-5');
|
|
142
|
-
}
|
|
143
|
-
async function loadTemplateAssets(config) {
|
|
144
|
-
const packageManager = await config.ios.packageManager;
|
|
145
|
-
const archiveName = packageManager === 'SPM' ? 'ios-spm-template.tar.gz' : 'ios-pods-template.tar.gz';
|
|
146
|
-
const archivePath = (0, path_1.join)(config.cli.assetsDirAbs, archiveName);
|
|
147
|
-
const tempDir = (0, path_1.join)(config.cli.assetsDirAbs, 'tempUISceneTemplate');
|
|
148
|
-
try {
|
|
149
|
-
await (0, template_1.extractTemplate)(archivePath, tempDir);
|
|
150
|
-
const sceneDelegatePath = (0, path_1.join)(tempDir, 'App', 'App', 'SceneDelegate.swift');
|
|
151
|
-
const appDelegatePath = (0, path_1.join)(tempDir, 'App', 'App', 'AppDelegate.swift');
|
|
152
|
-
if (!(0, fs_extra_1.existsSync)(sceneDelegatePath) || !(0, fs_extra_1.existsSync)(appDelegatePath)) {
|
|
153
|
-
return null;
|
|
154
|
-
}
|
|
155
|
-
const sceneDelegate = (0, fs_extra_1.readFileSync)(sceneDelegatePath, 'utf-8');
|
|
156
|
-
const appDelegateSource = (0, fs_extra_1.readFileSync)(appDelegatePath, 'utf-8');
|
|
157
|
-
const configurationForConnectingSnippet = extractConfigurationForConnecting(appDelegateSource);
|
|
158
|
-
if (!configurationForConnectingSnippet) {
|
|
159
|
-
return null;
|
|
160
|
-
}
|
|
161
|
-
return { sceneDelegate, configurationForConnectingSnippet };
|
|
162
|
-
}
|
|
163
|
-
finally {
|
|
164
|
-
(0, fs_1.deleteFolderRecursive)(tempDir);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
function writeSceneDelegate(config, contents) {
|
|
168
|
-
const path = (0, path_1.join)(config.ios.nativeTargetDirAbs, 'SceneDelegate.swift');
|
|
169
|
-
if ((0, fs_extra_1.existsSync)(path)) {
|
|
170
|
-
return { written: false };
|
|
171
|
-
}
|
|
172
|
-
(0, fs_extra_1.writeFileSync)(path, contents);
|
|
173
|
-
return { written: true };
|
|
174
|
-
}
|
|
175
|
-
function patchAppDelegate(config, snippet) {
|
|
176
|
-
const path = (0, path_1.join)(config.ios.nativeTargetDirAbs, 'AppDelegate.swift');
|
|
177
|
-
if (!(0, fs_extra_1.existsSync)(path)) {
|
|
178
|
-
return { patched: false, reason: 'AppDelegate.swift not found.' };
|
|
179
|
-
}
|
|
180
|
-
const source = (0, fs_extra_1.readFileSync)(path, 'utf-8');
|
|
181
|
-
if (source.includes('UISceneConfiguration(name:')) {
|
|
182
|
-
return { patched: false, reason: 'configurationForConnecting already present.' };
|
|
183
|
-
}
|
|
184
|
-
const patched = insertBeforeAppDelegateClassEnd(source, snippet);
|
|
185
|
-
if (!patched) {
|
|
186
|
-
return { patched: false, reason: 'could not locate AppDelegate class body.' };
|
|
187
|
-
}
|
|
188
|
-
(0, fs_extra_1.writeFileSync)(path, patched);
|
|
189
|
-
return { patched: true };
|
|
190
|
-
}
|
|
191
|
-
function extractConfigurationForConnecting(appDelegateSource) {
|
|
192
|
-
const sigRegex = /^ {4}func application\(_ application: UIApplication,\n {21}configurationForConnecting\b/m;
|
|
193
|
-
const sigMatch = appDelegateSource.match(sigRegex);
|
|
194
|
-
if (!sigMatch || sigMatch.index === undefined) {
|
|
195
|
-
return null;
|
|
196
|
-
}
|
|
197
|
-
const openIdx = appDelegateSource.indexOf('{', sigMatch.index);
|
|
198
|
-
if (openIdx === -1) {
|
|
199
|
-
return null;
|
|
200
|
-
}
|
|
201
|
-
let depth = 1;
|
|
202
|
-
let i = openIdx + 1;
|
|
203
|
-
while (i < appDelegateSource.length && depth > 0) {
|
|
204
|
-
const ch = appDelegateSource[i];
|
|
205
|
-
if (ch === '{')
|
|
206
|
-
depth++;
|
|
207
|
-
else if (ch === '}')
|
|
208
|
-
depth--;
|
|
209
|
-
i++;
|
|
210
|
-
}
|
|
211
|
-
if (depth !== 0) {
|
|
212
|
-
return null;
|
|
213
|
-
}
|
|
214
|
-
return '\n' + appDelegateSource.slice(sigMatch.index, i) + '\n';
|
|
215
|
-
}
|
|
216
|
-
function insertBeforeAppDelegateClassEnd(source, snippet) {
|
|
217
|
-
const classDeclRegex = /\bclass\s+AppDelegate\b[^{]*\{/;
|
|
218
|
-
const match = source.match(classDeclRegex);
|
|
219
|
-
if (!match || match.index === undefined) {
|
|
220
|
-
return null;
|
|
221
|
-
}
|
|
222
|
-
const openIdx = source.indexOf('{', match.index);
|
|
223
|
-
let depth = 1;
|
|
224
|
-
let i = openIdx + 1;
|
|
225
|
-
while (i < source.length && depth > 0) {
|
|
226
|
-
const ch = source[i];
|
|
227
|
-
if (ch === '{')
|
|
228
|
-
depth++;
|
|
229
|
-
else if (ch === '}')
|
|
230
|
-
depth--;
|
|
231
|
-
i++;
|
|
232
|
-
}
|
|
233
|
-
if (depth !== 0) {
|
|
234
|
-
return null;
|
|
235
|
-
}
|
|
236
|
-
const closeIdx = i - 1;
|
|
237
|
-
return source.slice(0, closeIdx) + snippet + source.slice(closeIdx);
|
|
238
|
-
}
|
|
239
|
-
function readDetectionSignals(config) {
|
|
240
|
-
const sceneDelegatePath = (0, path_1.join)(config.ios.nativeTargetDirAbs, 'SceneDelegate.swift');
|
|
241
|
-
const appDelegatePath = (0, path_1.join)(config.ios.nativeTargetDirAbs, 'AppDelegate.swift');
|
|
242
|
-
return {
|
|
243
|
-
hasManifest: (0, spm_1.hasSceneManifest)(config),
|
|
244
|
-
hasSceneDelegate: (0, fs_extra_1.existsSync)(sceneDelegatePath),
|
|
245
|
-
hasConfigurationForConnecting: (0, fs_extra_1.existsSync)(appDelegatePath) && (0, fs_extra_1.readFileSync)(appDelegatePath, 'utf-8').includes('UISceneConfiguration(name:'),
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
function classify(signals) {
|
|
249
|
-
const { hasManifest, hasSceneDelegate, hasConfigurationForConnecting } = signals;
|
|
250
|
-
const trueCount = [hasManifest, hasSceneDelegate, hasConfigurationForConnecting].filter(Boolean).length;
|
|
251
|
-
if (trueCount === 0)
|
|
252
|
-
return 'eligible';
|
|
253
|
-
if (trueCount === 3)
|
|
254
|
-
return 'already-migrated';
|
|
255
|
-
return 'partial';
|
|
256
|
-
}
|
|
257
|
-
function describeSignals({ hasManifest, hasSceneDelegate, hasConfigurationForConnecting, }) {
|
|
258
|
-
const present = [];
|
|
259
|
-
const missing = [];
|
|
260
|
-
(hasManifest ? present : missing).push('UIApplicationSceneManifest');
|
|
261
|
-
(hasSceneDelegate ? present : missing).push('SceneDelegate.swift');
|
|
262
|
-
(hasConfigurationForConnecting ? present : missing).push('AppDelegate.configurationForConnecting');
|
|
263
|
-
return `present: [${present.join(', ')}]; missing: [${missing.join(', ')}]`;
|
|
264
|
-
}
|
|
265
|
-
// Exported for tests.
|
|
266
|
-
exports.__testables = {
|
|
267
|
-
classify,
|
|
268
|
-
describeSignals,
|
|
269
|
-
insertBeforeAppDelegateClassEnd,
|
|
270
|
-
extractConfigurationForConnecting,
|
|
271
|
-
hasCustomDelegateBody,
|
|
272
|
-
scanAndWarn,
|
|
273
|
-
};
|
package/dist/util/xcode.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.findGroupUuidByComment = exports.addSwiftFileToAppTarget = void 0;
|
|
4
|
-
const fs_extra_1 = require("fs-extra");
|
|
5
|
-
const xcode_1 = require("xcode");
|
|
6
|
-
/**
|
|
7
|
-
* Register a Swift source file with the first native target of an Xcode project.
|
|
8
|
-
*
|
|
9
|
-
* Writes entries in PBXFileReference, PBXBuildFile, the named PBXGroup's children,
|
|
10
|
-
* and the target's Sources build phase. Idempotent: a second call is a no-op.
|
|
11
|
-
*
|
|
12
|
-
* @param pbxprojPath Absolute path to project.pbxproj
|
|
13
|
-
* @param groupName Comment/name of the PBXGroup the file belongs under (e.g. 'App')
|
|
14
|
-
* @param fileRelPath Path of the file relative to the group (e.g. 'SceneDelegate.swift')
|
|
15
|
-
*/
|
|
16
|
-
function addSwiftFileToAppTarget(pbxprojPath, groupName, fileRelPath) {
|
|
17
|
-
const project = (0, xcode_1.project)(pbxprojPath);
|
|
18
|
-
project.parseSync();
|
|
19
|
-
if (project.hasFile(fileRelPath)) {
|
|
20
|
-
return { added: false };
|
|
21
|
-
}
|
|
22
|
-
const groupUuid = findGroupUuidByComment(project, groupName);
|
|
23
|
-
if (!groupUuid) {
|
|
24
|
-
throw new Error(`Could not find PBXGroup with comment "${groupName}" in ${pbxprojPath}`);
|
|
25
|
-
}
|
|
26
|
-
const targetUuid = project.getFirstTarget().uuid;
|
|
27
|
-
const result = project.addSourceFile(fileRelPath, { target: targetUuid }, groupUuid);
|
|
28
|
-
if (!result) {
|
|
29
|
-
throw new Error(`Failed to register ${fileRelPath} in ${pbxprojPath}`);
|
|
30
|
-
}
|
|
31
|
-
(0, fs_extra_1.writeFileSync)(pbxprojPath, project.writeSync(), 'utf-8');
|
|
32
|
-
return { added: true };
|
|
33
|
-
}
|
|
34
|
-
exports.addSwiftFileToAppTarget = addSwiftFileToAppTarget;
|
|
35
|
-
// Exported for tests.
|
|
36
|
-
function findGroupUuidByComment(project, comment) {
|
|
37
|
-
const groups = project.hash.project.objects.PBXGroup;
|
|
38
|
-
const COMMENT_SUFFIX = '_comment';
|
|
39
|
-
for (const key of Object.keys(groups)) {
|
|
40
|
-
if (!key.endsWith(COMMENT_SUFFIX))
|
|
41
|
-
continue;
|
|
42
|
-
if (groups[key] === comment) {
|
|
43
|
-
return key.substring(0, key.length - COMMENT_SUFFIX.length);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
exports.findGroupUuidByComment = findGroupUuidByComment;
|