@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.
@@ -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
+ }
@@ -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 common_2 = require("../ios/common");
7
+ const common_1 = require("../ios/common");
8
+ const log_1 = require("../log");
9
9
  const plugin_1 = require("../plugin");
10
- const migrate_1 = require("../tasks/migrate");
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 iosPlatformVersion = await (0, common_1.getCapacitorPackageVersion)(config, config.ios.name);
327
- const iosVersion = (0, common_2.getMajoriOSVersion)(config);
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`, `capacitor-swift-pm`);
339
- content = (0, migrate_1.setAllStringIn)(content, `url: "https://github.com/ionic-team/capacitor-swift-pm.git",`, `)`, ` from: "${iosPlatformVersion}"`);
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
- .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "${iosPlatformVersion}")
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: "capacitor-swift-pm")
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;