@capacitor/cli 9.0.0-alpha.5 → 9.0.0-alpha.7
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/android/update.js +6 -37
- package/dist/config.js +5 -3
- package/dist/cordova.js +16 -3
- package/dist/declarations.d.ts +70 -4
- package/dist/ios/update.js +21 -7
- package/dist/tasks/migrate-edge-to-edge.js +158 -0
- package/dist/tasks/migrate-swiftui.js +335 -0
- package/dist/tasks/migrate.js +192 -57
- package/dist/util/capacitor-package.js +297 -0
- package/dist/util/cordova-ios.js +144 -12
- package/dist/util/node.js +35 -1
- package/dist/util/spm.js +82 -11
- package/dist/util/xcode.js +48 -0
- package/package.json +4 -2
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findCapacitorDependencyVersion = exports.rewriteCapacitorDependency = exports.renderCapacitorPackage = exports.resolveCapacitorPackage = void 0;
|
|
4
|
+
const fs_extra_1 = require("fs-extra");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const semver_1 = require("semver");
|
|
7
|
+
const common_1 = require("../common");
|
|
8
|
+
const errors_1 = require("../errors");
|
|
9
|
+
const fs_1 = require("./fs");
|
|
10
|
+
/** Capacitor 9 and up builds the iOS platform from source out of the main repo. */
|
|
11
|
+
const SOURCE_PACKAGE_MAJOR = 9;
|
|
12
|
+
const SOURCE_PACKAGE_URL = 'https://github.com/ionic-team/capacitor';
|
|
13
|
+
const SOURCE_PACKAGE_IDENTITY = 'capacitor';
|
|
14
|
+
/** Before Capacitor 9 the platform was consumed as a prebuilt xcframework from a separate repo. */
|
|
15
|
+
const BINARY_PACKAGE_URL = 'https://github.com/ionic-team/capacitor-swift-pm.git';
|
|
16
|
+
const BINARY_PACKAGE_IDENTITY = 'capacitor-swift-pm';
|
|
17
|
+
const ENV_OVERRIDE = 'CAPACITOR_IOS_PACKAGE';
|
|
18
|
+
const REQUIREMENT_KEYS = ['path', 'branch', 'revision', 'exact', 'from'];
|
|
19
|
+
/**
|
|
20
|
+
* Resolves which Capacitor Swift package generated `Package.swift` files should depend on.
|
|
21
|
+
*
|
|
22
|
+
* Precedence, most specific first:
|
|
23
|
+
* 1. the `CAPACITOR_IOS_PACKAGE` environment variable
|
|
24
|
+
* 2. `experimental.ios.spm.capacitorPackage` in the Capacitor config
|
|
25
|
+
* 3. the git tag matching the installed `@capacitor/ios` version
|
|
26
|
+
*
|
|
27
|
+
* The environment variable deliberately outranks the config file so a checkout can be pointed at a
|
|
28
|
+
* local or branch build without editing (and risking committing) the app's configuration.
|
|
29
|
+
*
|
|
30
|
+
* `legacyRequirement` only applies to pre-9 projects, where it preserves each caller's existing
|
|
31
|
+
* requirement style. Source-based projects always pin `exact`, because the app package and any
|
|
32
|
+
* generated plugin packages must agree: a prerelease such as `9.0.0-alpha.6` does not satisfy a
|
|
33
|
+
* `from:` range, so mixing the two styles fails to resolve.
|
|
34
|
+
*/
|
|
35
|
+
async function resolveCapacitorPackage(config, legacyRequirement = 'exact') {
|
|
36
|
+
var _a, _b;
|
|
37
|
+
const version = await (0, common_1.getCapacitorPackageVersion)(config, config.ios.name);
|
|
38
|
+
if ((0, semver_1.major)(version) < SOURCE_PACKAGE_MAJOR) {
|
|
39
|
+
return {
|
|
40
|
+
identity: BINARY_PACKAGE_IDENTITY,
|
|
41
|
+
cordovaProduct: 'Cordova',
|
|
42
|
+
sourceBased: false,
|
|
43
|
+
url: BINARY_PACKAGE_URL,
|
|
44
|
+
requirement: { kind: legacyRequirement, version },
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const override = resolveOverride(config);
|
|
48
|
+
return {
|
|
49
|
+
identity: SOURCE_PACKAGE_IDENTITY,
|
|
50
|
+
cordovaProduct: 'CapacitorCordova',
|
|
51
|
+
sourceBased: true,
|
|
52
|
+
url: (_a = override === null || override === void 0 ? void 0 : override.url) !== null && _a !== void 0 ? _a : SOURCE_PACKAGE_URL,
|
|
53
|
+
requirement: (_b = override === null || override === void 0 ? void 0 : override.requirement) !== null && _b !== void 0 ? _b : { kind: 'exact', version },
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
exports.resolveCapacitorPackage = resolveCapacitorPackage;
|
|
57
|
+
/** Renders the `.package(...)` entry, with any path made relative to the file being written. */
|
|
58
|
+
function renderCapacitorPackage(pkg, fromDir) {
|
|
59
|
+
if (pkg.requirement.kind === 'path') {
|
|
60
|
+
const relPath = (0, fs_1.convertToUnixPath)((0, path_1.relative)(fromDir, pkg.requirement.absolutePath));
|
|
61
|
+
// Pin the identity: for a path dependency SPM would otherwise derive it from the directory
|
|
62
|
+
// name, which breaks `.product(package:)` when the checkout is not named "capacitor".
|
|
63
|
+
return `.package(name: "${pkg.identity}", path: "${relPath}")`;
|
|
64
|
+
}
|
|
65
|
+
return `.package(url: "${pkg.url}", ${renderRequirement(pkg.requirement)})`;
|
|
66
|
+
}
|
|
67
|
+
exports.renderCapacitorPackage = renderCapacitorPackage;
|
|
68
|
+
/**
|
|
69
|
+
* Repoints an existing `Package.swift` at the resolved Capacitor package.
|
|
70
|
+
*
|
|
71
|
+
* Third-party plugins ship a dependency on `capacitor-swift-pm`. From Capacitor 9 the app depends
|
|
72
|
+
* on the source package instead, and SPM treats the two as separate identities that both vend a
|
|
73
|
+
* `Capacitor` product — so a plugin left untouched would either fail to resolve or link a second
|
|
74
|
+
* copy of the framework. Rewriting keeps the whole graph on one identity.
|
|
75
|
+
*/
|
|
76
|
+
function rewriteCapacitorDependency(content, pkg, fromDir) {
|
|
77
|
+
let rewritten = replacePackageCalls(content, renderCapacitorPackage(pkg, fromDir));
|
|
78
|
+
for (const identity of [BINARY_PACKAGE_IDENTITY, SOURCE_PACKAGE_IDENTITY]) {
|
|
79
|
+
rewritten = rewritten.split(`package: "${identity}"`).join(`package: "${pkg.identity}"`);
|
|
80
|
+
}
|
|
81
|
+
return rewritten;
|
|
82
|
+
}
|
|
83
|
+
exports.rewriteCapacitorDependency = rewriteCapacitorDependency;
|
|
84
|
+
/** Reads the version an existing `Package.swift` pins Capacitor to, if it pins one. */
|
|
85
|
+
function findCapacitorDependencyVersion(content) {
|
|
86
|
+
for (const call of findPackageCalls(content)) {
|
|
87
|
+
if (!referencesCapacitor(call.text)) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const match = call.text.match(/(?:from|exact):\s*"([^"]+)"/);
|
|
91
|
+
if (match) {
|
|
92
|
+
return match[1];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
exports.findCapacitorDependencyVersion = findCapacitorDependencyVersion;
|
|
98
|
+
function referencesCapacitor(call) {
|
|
99
|
+
return call.includes(BINARY_PACKAGE_IDENTITY) || call.includes(`${SOURCE_PACKAGE_URL}`);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Locates `.package(...)` calls in code, skipping any inside a comment or string literal.
|
|
103
|
+
*
|
|
104
|
+
* Commented-out calls have to be skipped rather than merely tolerated: `replacePackageCalls`
|
|
105
|
+
* keeps the first match and drops the rest, so a commented dependency above the real one would
|
|
106
|
+
* otherwise be the entry that survives.
|
|
107
|
+
*/
|
|
108
|
+
function findPackageCalls(content) {
|
|
109
|
+
const marker = '.package(';
|
|
110
|
+
const calls = [];
|
|
111
|
+
for (let index = 0; index < content.length; index++) {
|
|
112
|
+
if (content[index] === '"') {
|
|
113
|
+
index = skipString(content, index);
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (content.startsWith('//', index)) {
|
|
117
|
+
const newline = content.indexOf('\n', index);
|
|
118
|
+
if (newline === -1) {
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
index = newline;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (content.startsWith('/*', index)) {
|
|
125
|
+
const close = content.indexOf('*/', index + 2);
|
|
126
|
+
if (close === -1) {
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
index = close + 1;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
if (!content.startsWith(marker, index)) {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
const end = findCallEnd(content, index + marker.length - 1);
|
|
136
|
+
if (end === -1) {
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
calls.push({ start: index, end, text: content.slice(index, end) });
|
|
140
|
+
index = end - 1;
|
|
141
|
+
}
|
|
142
|
+
return calls;
|
|
143
|
+
}
|
|
144
|
+
/** Walks from an opening paren to its match, tracking depth so nested calls don't terminate it. */
|
|
145
|
+
function findCallEnd(content, openParen) {
|
|
146
|
+
let depth = 0;
|
|
147
|
+
for (let cursor = openParen; cursor < content.length; cursor++) {
|
|
148
|
+
const char = content[cursor];
|
|
149
|
+
if (char === '"') {
|
|
150
|
+
cursor = skipString(content, cursor);
|
|
151
|
+
}
|
|
152
|
+
else if (char === '(') {
|
|
153
|
+
depth++;
|
|
154
|
+
}
|
|
155
|
+
else if (char === ')') {
|
|
156
|
+
depth--;
|
|
157
|
+
if (depth === 0) {
|
|
158
|
+
return cursor + 1;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return -1;
|
|
163
|
+
}
|
|
164
|
+
/** Returns the index of the closing quote of the string literal opening at `open`. */
|
|
165
|
+
function skipString(content, open) {
|
|
166
|
+
for (let cursor = open + 1; cursor < content.length; cursor++) {
|
|
167
|
+
if (content[cursor] === '\\') {
|
|
168
|
+
cursor++;
|
|
169
|
+
}
|
|
170
|
+
else if (content[cursor] === '"') {
|
|
171
|
+
return cursor;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return content.length;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Points every Capacitor dependency at `rendered`, collapsing them to a single entry.
|
|
178
|
+
*
|
|
179
|
+
* A manifest supporting both Capacitor 8 and 9 can declare the prebuilt and source packages side
|
|
180
|
+
* by side. Both rewrite to the same text, and SPM rejects a manifest that declares one dependency
|
|
181
|
+
* twice, so the extra entries are removed rather than replaced.
|
|
182
|
+
*/
|
|
183
|
+
function replacePackageCalls(content, rendered) {
|
|
184
|
+
const matches = findPackageCalls(content).filter((call) => referencesCapacitor(call.text));
|
|
185
|
+
if (matches.length === 0) {
|
|
186
|
+
return content;
|
|
187
|
+
}
|
|
188
|
+
const [survivor, ...duplicates] = matches;
|
|
189
|
+
let result = content;
|
|
190
|
+
// Every duplicate sits after the survivor, so splicing them out backwards leaves its offsets
|
|
191
|
+
// valid and guarantees each one is preceded by the comma separating it from an earlier entry.
|
|
192
|
+
for (const call of duplicates.reverse()) {
|
|
193
|
+
result = result.slice(0, startOfEntry(content, call.start)) + result.slice(call.end);
|
|
194
|
+
}
|
|
195
|
+
return result.slice(0, survivor.start) + rendered + result.slice(survivor.end);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Extends a deletion back over the comma separating an entry from the previous one. Swift allows a
|
|
199
|
+
* trailing comma in an array literal but not a leading one, so the preceding comma is the one to
|
|
200
|
+
* take.
|
|
201
|
+
*/
|
|
202
|
+
function startOfEntry(content, start) {
|
|
203
|
+
let cursor = start - 1;
|
|
204
|
+
while (cursor >= 0 && /\s/.test(content[cursor])) {
|
|
205
|
+
cursor--;
|
|
206
|
+
}
|
|
207
|
+
return content[cursor] === ',' ? cursor : start;
|
|
208
|
+
}
|
|
209
|
+
function renderRequirement(requirement) {
|
|
210
|
+
switch (requirement.kind) {
|
|
211
|
+
case 'branch':
|
|
212
|
+
return `branch: "${requirement.branch}"`;
|
|
213
|
+
case 'revision':
|
|
214
|
+
return `revision: "${requirement.revision}"`;
|
|
215
|
+
case 'exact':
|
|
216
|
+
return `exact: "${requirement.version}"`;
|
|
217
|
+
case 'from':
|
|
218
|
+
return `from: "${requirement.version}"`;
|
|
219
|
+
case 'path':
|
|
220
|
+
throw new Error('path requirements are rendered by renderCapacitorPackage');
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
function resolveOverride(config) {
|
|
224
|
+
var _a, _b, _c, _d;
|
|
225
|
+
const baseDir = config.app.rootDir;
|
|
226
|
+
const fromEnv = (_a = process.env[ENV_OVERRIDE]) === null || _a === void 0 ? void 0 : _a.trim();
|
|
227
|
+
if (fromEnv) {
|
|
228
|
+
return { requirement: parseRequirementSpec(fromEnv, baseDir) };
|
|
229
|
+
}
|
|
230
|
+
const fromConfig = (_d = (_c = (_b = config.app.extConfig.experimental) === null || _b === void 0 ? void 0 : _b.ios) === null || _c === void 0 ? void 0 : _c.spm) === null || _d === void 0 ? void 0 : _d.capacitorPackage;
|
|
231
|
+
if (!fromConfig) {
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
const provided = REQUIREMENT_KEYS.filter((key) => fromConfig[key] !== undefined);
|
|
235
|
+
if (provided.length === 0) {
|
|
236
|
+
(0, errors_1.fatal)(`experimental.ios.spm.capacitorPackage must set one of: ${REQUIREMENT_KEYS.join(', ')}.\n` +
|
|
237
|
+
`Remove the entry to use the version matching the installed @capacitor/ios.`);
|
|
238
|
+
}
|
|
239
|
+
if (provided.length > 1) {
|
|
240
|
+
(0, errors_1.fatal)(`experimental.ios.spm.capacitorPackage sets more than one of: ${provided.join(', ')}.\n` + `Only one may be set.`);
|
|
241
|
+
}
|
|
242
|
+
const key = provided[0];
|
|
243
|
+
const value = String(fromConfig[key]);
|
|
244
|
+
if (key === 'path') {
|
|
245
|
+
if (fromConfig.url !== undefined) {
|
|
246
|
+
(0, errors_1.fatal)(`experimental.ios.spm.capacitorPackage cannot set both "url" and "path".`);
|
|
247
|
+
}
|
|
248
|
+
return { requirement: pathRequirement(value, baseDir) };
|
|
249
|
+
}
|
|
250
|
+
return { url: fromConfig.url, requirement: { kind: key, ...requirementValue(key, value) } };
|
|
251
|
+
}
|
|
252
|
+
function requirementValue(key, value) {
|
|
253
|
+
switch (key) {
|
|
254
|
+
case 'branch':
|
|
255
|
+
return { branch: value };
|
|
256
|
+
case 'revision':
|
|
257
|
+
return { revision: value };
|
|
258
|
+
default:
|
|
259
|
+
return { version: value };
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Parses a `CAPACITOR_IOS_PACKAGE` value. Accepts an explicit `kind:value` form, or infers `path`
|
|
264
|
+
* for anything path-shaped and `exact` for a bare version.
|
|
265
|
+
*/
|
|
266
|
+
function parseRequirementSpec(spec, baseDir) {
|
|
267
|
+
const separator = spec.indexOf(':');
|
|
268
|
+
if (separator > 0) {
|
|
269
|
+
const key = spec.slice(0, separator);
|
|
270
|
+
const value = spec.slice(separator + 1);
|
|
271
|
+
if (REQUIREMENT_KEYS.includes(key)) {
|
|
272
|
+
if (key === 'path') {
|
|
273
|
+
return pathRequirement(value, baseDir);
|
|
274
|
+
}
|
|
275
|
+
return {
|
|
276
|
+
kind: key,
|
|
277
|
+
...requirementValue(key, value),
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (spec.startsWith('.') || (0, path_1.isAbsolute)(spec)) {
|
|
282
|
+
return pathRequirement(spec, baseDir);
|
|
283
|
+
}
|
|
284
|
+
if ((0, semver_1.valid)(spec)) {
|
|
285
|
+
return { kind: 'exact', version: spec };
|
|
286
|
+
}
|
|
287
|
+
return (0, errors_1.fatal)(`Could not understand ${ENV_OVERRIDE}="${spec}".\n` +
|
|
288
|
+
`Expected one of ${REQUIREMENT_KEYS.map((k) => `${k}:<value>`).join(', ')}, a path, or a version.`);
|
|
289
|
+
}
|
|
290
|
+
function pathRequirement(value, baseDir) {
|
|
291
|
+
const absolutePath = (0, path_1.resolve)(baseDir, value);
|
|
292
|
+
if (!(0, fs_extra_1.existsSync)((0, path_1.resolve)(absolutePath, 'Package.swift'))) {
|
|
293
|
+
(0, errors_1.fatal)(`No Package.swift found at ${absolutePath}.\n` +
|
|
294
|
+
`A local Capacitor package must point at the repository root, not the ios directory.`);
|
|
295
|
+
}
|
|
296
|
+
return { kind: 'path', absolutePath };
|
|
297
|
+
}
|
package/dist/util/cordova-ios.js
CHANGED
|
@@ -3,11 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.generateCordovaPackageFile = exports.generateCordovaPackageFiles = exports.cordovaPodfileLines = exports.filterARCFiles = exports.removePluginsNativeFiles = exports.copyPluginsNativeFiles = exports.generateCordovaPodspecs = void 0;
|
|
4
4
|
const fs_extra_1 = require("fs-extra");
|
|
5
5
|
const path_1 = require("path");
|
|
6
|
-
const common_1 = require("../common");
|
|
7
6
|
const cordova_1 = require("../cordova");
|
|
8
|
-
const
|
|
7
|
+
const common_1 = require("../ios/common");
|
|
8
|
+
const log_1 = require("../log");
|
|
9
9
|
const plugin_1 = require("../plugin");
|
|
10
|
-
const
|
|
10
|
+
const capacitor_package_1 = require("../util/capacitor-package");
|
|
11
11
|
const template_1 = require("../util/template");
|
|
12
12
|
const platform = 'ios';
|
|
13
13
|
async function generateCordovaPodspecs(cordovaPlugins, config) {
|
|
@@ -321,10 +321,122 @@ async function generateCordovaPackageFiles(cordovaPlugins, config) {
|
|
|
321
321
|
});
|
|
322
322
|
}
|
|
323
323
|
exports.generateCordovaPackageFiles = generateCordovaPackageFiles;
|
|
324
|
+
function buildBinaryTargetEntries(p, frameworks) {
|
|
325
|
+
const customXcframeworks = frameworks.filter((f) => f.$.custom === 'true' && f.$.src.endsWith('.xcframework'));
|
|
326
|
+
const customFrameworks = frameworks.filter((f) => f.$.custom === 'true' && f.$.src.endsWith('.framework'));
|
|
327
|
+
if (customFrameworks.length > 0) {
|
|
328
|
+
customFrameworks.forEach((f) => {
|
|
329
|
+
log_1.logger.warn(`${p.id}: custom .framework files are not supported as binaryTarget in SPM (${f.$.src}). Convert to .xcframework for SPM compatibility.`);
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
const binaryTargetsText = customXcframeworks
|
|
333
|
+
.map((f) => {
|
|
334
|
+
const name = f.$.src.split('/').pop().replace('.xcframework', '');
|
|
335
|
+
return `,
|
|
336
|
+
.binaryTarget(
|
|
337
|
+
name: "${name}",
|
|
338
|
+
path: "${f.$.src}"
|
|
339
|
+
)`;
|
|
340
|
+
})
|
|
341
|
+
.join('');
|
|
342
|
+
const binaryDepsText = customXcframeworks
|
|
343
|
+
.map((f) => {
|
|
344
|
+
const name = f.$.src.split('/').pop().replace('.xcframework', '');
|
|
345
|
+
return `,\n .target(name: "${name}")`;
|
|
346
|
+
})
|
|
347
|
+
.join('');
|
|
348
|
+
return { binaryTargetsText, binaryDepsText };
|
|
349
|
+
}
|
|
350
|
+
function buildResourcesText(resources) {
|
|
351
|
+
const resourceEntry = [];
|
|
352
|
+
for (const resource of resources) {
|
|
353
|
+
resourceEntry.push(`.copy("resources/${resource.$.src.split('/').pop()}")`);
|
|
354
|
+
}
|
|
355
|
+
return resources.length > 0
|
|
356
|
+
? `,
|
|
357
|
+
resources: [
|
|
358
|
+
${resourceEntry.join(',\n ')}
|
|
359
|
+
]`
|
|
360
|
+
: '';
|
|
361
|
+
}
|
|
362
|
+
async function buildDependencyTexts(p, config) {
|
|
363
|
+
let allDependencies = (0, plugin_1.getPlatformElement)(p, platform, 'dependency');
|
|
364
|
+
if (p.xml['dependency']) {
|
|
365
|
+
allDependencies = allDependencies.concat(p.xml['dependency']);
|
|
366
|
+
}
|
|
367
|
+
let packageText = '';
|
|
368
|
+
let productText = '';
|
|
369
|
+
await Promise.all(allDependencies.map(async (dep) => {
|
|
370
|
+
let plugin = dep.$.id;
|
|
371
|
+
if (plugin.includes('@') && plugin.indexOf('@') !== 0) {
|
|
372
|
+
[plugin] = plugin.split('@');
|
|
373
|
+
}
|
|
374
|
+
const depPlugin = await (0, plugin_1.resolvePlugin)(config, plugin);
|
|
375
|
+
if (depPlugin) {
|
|
376
|
+
const headerFiles = (0, plugin_1.getPlatformElement)(depPlugin, platform, 'header-file');
|
|
377
|
+
const resources = (0, plugin_1.getPlatformElement)(depPlugin, platform, 'resource-file');
|
|
378
|
+
const sourceFiles = (0, plugin_1.getPlatformElement)(depPlugin, platform, 'source-file');
|
|
379
|
+
if (sourceFiles.length === 0 && headerFiles.length === 0 && resources.length === 0) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
packageText += `,\n .package(name: "${depPlugin.name}", path: "../${depPlugin.name}")`;
|
|
383
|
+
productText += `,\n .product(name: "${depPlugin.name}", package: "${depPlugin.name}")`;
|
|
384
|
+
}
|
|
385
|
+
}));
|
|
386
|
+
return { packageText, productText };
|
|
387
|
+
}
|
|
388
|
+
function buildCSettingsText(p, sourceFiles) {
|
|
389
|
+
var _a;
|
|
390
|
+
const pluginId = p.id;
|
|
391
|
+
const allFlags = new Set();
|
|
392
|
+
for (const sourceFile of sourceFiles) {
|
|
393
|
+
const flags = (_a = sourceFile.$) === null || _a === void 0 ? void 0 : _a['compiler-flags'];
|
|
394
|
+
if (flags) {
|
|
395
|
+
flags
|
|
396
|
+
.split(/\s+/)
|
|
397
|
+
.map((f) => f.trim())
|
|
398
|
+
.filter((f) => f.length > 0)
|
|
399
|
+
.forEach((f) => allFlags.add(f));
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
if (allFlags.size === 0) {
|
|
403
|
+
return '';
|
|
404
|
+
}
|
|
405
|
+
const entries = [];
|
|
406
|
+
const unsupportedFlags = [];
|
|
407
|
+
for (const flag of allFlags) {
|
|
408
|
+
if (flag.startsWith('-D')) {
|
|
409
|
+
const definition = flag.slice(2);
|
|
410
|
+
const eqIndex = definition.indexOf('=');
|
|
411
|
+
if (eqIndex !== -1) {
|
|
412
|
+
const name = definition.slice(0, eqIndex);
|
|
413
|
+
const value = definition.slice(eqIndex + 1);
|
|
414
|
+
entries.push(` .define("${name}", to: "${value}")`);
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
entries.push(` .define("${definition}")`);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
unsupportedFlags.push(flag);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
if (unsupportedFlags.length > 0) {
|
|
425
|
+
log_1.logger.warn(`${pluginId}: the following compiler flags are not supported in SPM and were ignored: ${unsupportedFlags.join(', ')}. ` +
|
|
426
|
+
`This might cause the plugin to fail to compile.`);
|
|
427
|
+
}
|
|
428
|
+
if (entries.length === 0) {
|
|
429
|
+
return '';
|
|
430
|
+
}
|
|
431
|
+
return `,
|
|
432
|
+
cSettings: [
|
|
433
|
+
${entries.join(',\n')}
|
|
434
|
+
]`;
|
|
435
|
+
}
|
|
324
436
|
async function generateCordovaPackageFile(p, config) {
|
|
325
437
|
var _a;
|
|
326
|
-
const
|
|
327
|
-
const iosVersion = (0,
|
|
438
|
+
const capacitorPackage = await (0, capacitor_package_1.resolveCapacitorPackage)(config, 'from');
|
|
439
|
+
const iosVersion = (0, common_1.getMajoriOSVersion)(config);
|
|
328
440
|
const headerFiles = (0, plugin_1.getPlatformElement)(p, platform, 'header-file');
|
|
329
441
|
let headersText = '';
|
|
330
442
|
if (headerFiles.length > 0) {
|
|
@@ -335,11 +447,31 @@ async function generateCordovaPackageFile(p, config) {
|
|
|
335
447
|
if ((_a = platformTag.$) === null || _a === void 0 ? void 0 : _a.package) {
|
|
336
448
|
const packageSwiftPath = (0, path_1.join)(p.rootPath, 'Package.swift');
|
|
337
449
|
let content = await (0, fs_extra_1.readFile)(packageSwiftPath, { encoding: 'utf-8' });
|
|
338
|
-
content = content.replace(`apache`, `ionic-team`).replaceAll(`cordova-ios`,
|
|
339
|
-
content = (0,
|
|
450
|
+
content = content.replace(`apache`, `ionic-team`).replaceAll(`cordova-ios`, capacitorPackage.identity);
|
|
451
|
+
content = (0, capacitor_package_1.rewriteCapacitorDependency)(content, capacitorPackage, p.rootPath);
|
|
340
452
|
await (0, fs_extra_1.writeFile)(packageSwiftPath, content);
|
|
341
453
|
}
|
|
342
454
|
else {
|
|
455
|
+
const resources = (0, plugin_1.getPlatformElement)(p, platform, 'resource-file');
|
|
456
|
+
const sourceFiles = (0, plugin_1.getPlatformElement)(p, platform, 'source-file');
|
|
457
|
+
if (sourceFiles.length === 0 && headerFiles.length === 0 && resources.length === 0) {
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
const frameworks = (0, plugin_1.getPlatformElement)(p, platform, 'framework');
|
|
461
|
+
const { binaryTargetsText, binaryDepsText } = buildBinaryTargetEntries(p, frameworks);
|
|
462
|
+
const cSettingsText = buildCSettingsText(p, sourceFiles);
|
|
463
|
+
const systemFrameworks = frameworks.filter((f) => !f.$.custom && f.$.src.endsWith('.framework'));
|
|
464
|
+
const hasWeakFrameworks = systemFrameworks.some((f) => f.$.weak === 'true');
|
|
465
|
+
const requiredSystemFrameworks = systemFrameworks.filter((f) => f.$.weak !== 'true');
|
|
466
|
+
const resourcesText = buildResourcesText(resources);
|
|
467
|
+
const libraryTypeText = hasWeakFrameworks ? `\n type: .dynamic,` : '';
|
|
468
|
+
const linkerSettingsText = requiredSystemFrameworks.length > 0
|
|
469
|
+
? `,
|
|
470
|
+
linkerSettings: [
|
|
471
|
+
${requiredSystemFrameworks.map((f) => ` .linkedFramework("${f.$.src.replace('.framework', '')}")`).join(',\n')}
|
|
472
|
+
]`
|
|
473
|
+
: '';
|
|
474
|
+
const { packageText, productText } = await buildDependencyTexts(p, config);
|
|
343
475
|
const content = `// swift-tools-version: 5.9
|
|
344
476
|
|
|
345
477
|
import PackageDescription
|
|
@@ -349,21 +481,21 @@ let package = Package(
|
|
|
349
481
|
platforms: [.iOS(.v${iosVersion})],
|
|
350
482
|
products: [
|
|
351
483
|
.library(
|
|
352
|
-
name: "${p.name}"
|
|
484
|
+
name: "${p.name}",${libraryTypeText}
|
|
353
485
|
targets: ["${p.name}"]
|
|
354
486
|
)
|
|
355
487
|
],
|
|
356
488
|
dependencies: [
|
|
357
|
-
.
|
|
489
|
+
${(0, capacitor_package_1.renderCapacitorPackage)(capacitorPackage, (0, path_1.join)(config.ios.cordovaPluginsDirAbs, 'sources', p.name))}${packageText}
|
|
358
490
|
],
|
|
359
491
|
targets: [
|
|
360
492
|
.target(
|
|
361
493
|
name: "${p.name}",
|
|
362
494
|
dependencies: [
|
|
363
|
-
.product(name: "Cordova", package: "
|
|
495
|
+
.product(name: "Cordova", package: "${capacitorPackage.identity}")${binaryDepsText}${productText}
|
|
364
496
|
],
|
|
365
|
-
path: "."${headersText}
|
|
366
|
-
)
|
|
497
|
+
path: "."${resourcesText}${headersText}${cSettingsText}${linkerSettingsText}
|
|
498
|
+
)${binaryTargetsText}
|
|
367
499
|
]
|
|
368
500
|
)`;
|
|
369
501
|
await (0, fs_extra_1.writeFile)((0, path_1.join)(config.ios.cordovaPluginsDirAbs, 'sources', p.name, 'Package.swift'), content);
|
package/dist/util/node.js
CHANGED
|
@@ -4,11 +4,45 @@ 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)');
|
|
7
25
|
/**
|
|
8
26
|
* @see https://github.com/ionic-team/stencil/blob/HEAD/src/compiler/sys/node-require.ts
|
|
9
27
|
*/
|
|
10
|
-
const requireTS = (ts, p) => {
|
|
28
|
+
const requireTS = async (ts, p) => {
|
|
11
29
|
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
|
+
}
|
|
12
46
|
delete require.cache[id];
|
|
13
47
|
require.extensions['.ts'] = (module, fileName) => {
|
|
14
48
|
var _a;
|