@capacitor/cli 9.0.0-alpha.7 → 9.0.0-beta.0
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/network-security-config.js +230 -0
- package/dist/android/update.js +5 -1
- package/dist/common.js +1 -1
- package/dist/config.js +4 -3
- package/dist/cordova.js +8 -17
- package/dist/declarations.d.ts +8 -41
- package/dist/index.js +4 -14
- package/dist/ios/common.js +1 -1
- package/dist/ios/update.js +9 -17
- package/dist/ipc.js +51 -11
- package/dist/plugin.js +1 -1
- package/dist/run-context/declared.js +54 -0
- package/dist/run-context/index.js +111 -0
- package/dist/run-context/registry.js +45 -0
- package/dist/run-context/signals.js +115 -0
- package/dist/run-context/types.js +2 -0
- package/dist/run-context/unknown.js +46 -0
- package/dist/run-context/version.js +74 -0
- package/dist/tasks/copy.js +3 -1
- package/dist/tasks/doctor.js +4 -1
- package/dist/tasks/list.js +1 -1
- package/dist/tasks/migrate-debug-xcconfig.js +60 -0
- package/dist/tasks/migrate-spm.js +0 -1
- package/dist/tasks/migrate-swiftui.js +344 -54
- package/dist/tasks/migrate-to-modern-project.js +27 -0
- package/dist/tasks/migrate.js +41 -4
- package/dist/tasks/run.js +8 -3
- package/dist/tasks/telemetry.js +8 -1
- package/dist/telemetry.js +303 -57
- package/dist/util/capacitor-package.js +95 -146
- package/dist/util/cordova-ios.js +13 -8
- package/dist/util/js.js +1 -1
- package/dist/util/monorepotools.js +2 -2
- package/dist/util/node.js +3 -3
- package/dist/util/npm.js +120 -0
- package/dist/util/spm.js +35 -25
- package/dist/util/subprocess.js +2 -2
- package/dist/util/xcode.js +193 -2
- package/dist/util/xml.js +1 -1
- package/package.json +3 -2
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.__testables = exports.removeLegacyCordovaPluginsConfig = exports.setAndroidCleartext = void 0;
|
|
4
|
+
const fs_extra_1 = require("fs-extra");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const log_1 = require("../log");
|
|
7
|
+
/**
|
|
8
|
+
* Handles opting in to cleartext (HTTP) traffic through the app module's `network-security-config.xml`.
|
|
9
|
+
*
|
|
10
|
+
* Whatever the CLI changes is tracked by a marker comment inside the config file itself, so it can be
|
|
11
|
+
* reverted later without touching anything the app owned before:
|
|
12
|
+
*
|
|
13
|
+
* <!-- capacitor:cleartext created ref orig=false -->
|
|
14
|
+
*
|
|
15
|
+
* created the CLI created the file (the revert deletes it)
|
|
16
|
+
* ref the CLI added android:networkSecurityConfig to the app manifest (the revert removes it)
|
|
17
|
+
* orig=... state of <base-config cleartextTrafficPermitted> before the CLI changed it:
|
|
18
|
+
* true | false | absent (attribute not set) | added (the CLI added the whole <base-config>)
|
|
19
|
+
*/
|
|
20
|
+
const DEFAULT_CONFIG_NAME = 'network_security_config';
|
|
21
|
+
const MARKER_NAME = 'capacitor:cleartext';
|
|
22
|
+
const MARKER_REGEX = new RegExp(`[ \\t]*<!--\\s*${MARKER_NAME}([^>]*?)-->[ \\t]*\\r?\\n?`);
|
|
23
|
+
const BASE_CONFIG_REGEX = /<base-config\b[^>]*>/;
|
|
24
|
+
const CLEARTEXT_ATTR_REGEX = /(\bcleartextTrafficPermitted\s*=\s*)(["'])(.*?)\2/;
|
|
25
|
+
const ROOT_REGEX = /<network-security-config\b[^>]*?(\/?)>/;
|
|
26
|
+
const APPLICATION_REGEX = /<application\b/;
|
|
27
|
+
const CONFIG_REF_REGEX = /android:networkSecurityConfig\s*=\s*"@xml\/([^"]+)"/;
|
|
28
|
+
const LEGACY_CORDOVA_PLUGINS_CONFIG = `<?xml version="1.0" encoding="utf-8"?>
|
|
29
|
+
<network-security-config>
|
|
30
|
+
<base-config cleartextTrafficPermitted="true" />
|
|
31
|
+
</network-security-config>
|
|
32
|
+
`;
|
|
33
|
+
function parseMarker(xml) {
|
|
34
|
+
var _a;
|
|
35
|
+
const match = MARKER_REGEX.exec(xml);
|
|
36
|
+
if (!match) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
const tokens = match[1].trim().split(/\s+/);
|
|
40
|
+
const orig = (_a = tokens.find((t) => t.startsWith('orig='))) === null || _a === void 0 ? void 0 : _a.slice('orig='.length);
|
|
41
|
+
return { created: tokens.includes('created'), ref: tokens.includes('ref'), orig };
|
|
42
|
+
}
|
|
43
|
+
function buildMarker(marker) {
|
|
44
|
+
const parts = [MARKER_NAME];
|
|
45
|
+
if (marker.created) {
|
|
46
|
+
parts.push('created');
|
|
47
|
+
}
|
|
48
|
+
if (marker.ref) {
|
|
49
|
+
parts.push('ref');
|
|
50
|
+
}
|
|
51
|
+
if (marker.orig) {
|
|
52
|
+
parts.push(`orig=${marker.orig}`);
|
|
53
|
+
}
|
|
54
|
+
return `<!-- ${parts.join(' ')} -->`;
|
|
55
|
+
}
|
|
56
|
+
function getCleartextValue(tag) {
|
|
57
|
+
var _a;
|
|
58
|
+
return (_a = CLEARTEXT_ATTR_REGEX.exec(tag)) === null || _a === void 0 ? void 0 : _a[3];
|
|
59
|
+
}
|
|
60
|
+
function setCleartextValue(tag, value) {
|
|
61
|
+
const hasAttr = CLEARTEXT_ATTR_REGEX.test(tag);
|
|
62
|
+
if (value === undefined) {
|
|
63
|
+
return hasAttr ? tag.replace(new RegExp(`\\s*${CLEARTEXT_ATTR_REGEX.source}`), '') : tag;
|
|
64
|
+
}
|
|
65
|
+
if (hasAttr) {
|
|
66
|
+
return tag.replace(CLEARTEXT_ATTR_REGEX, `$1$2${value}$2`);
|
|
67
|
+
}
|
|
68
|
+
return tag.replace(/\s*(\/?)>$/, (_, slash) => ` cleartextTrafficPermitted="${value}"${slash ? ' />' : '>'}`);
|
|
69
|
+
}
|
|
70
|
+
function indentOf(xml, index) {
|
|
71
|
+
var _a, _b;
|
|
72
|
+
const lineStart = xml.lastIndexOf('\n', index - 1) + 1;
|
|
73
|
+
return (_b = (_a = /^[ \t]*/.exec(xml.slice(lineStart, index))) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : '';
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Returns the config XML with `cleartextTrafficPermitted="true"` on its `<base-config>`.
|
|
77
|
+
* When `xml` is undefined a minimal config is generated. Nothing else in the file is touched.
|
|
78
|
+
*/
|
|
79
|
+
function enableCleartext(xml, flags) {
|
|
80
|
+
var _a;
|
|
81
|
+
if (xml === undefined) {
|
|
82
|
+
return `<?xml version="1.0" encoding="utf-8"?>
|
|
83
|
+
<network-security-config>
|
|
84
|
+
${buildMarker({ created: true, ref: flags.ref })}
|
|
85
|
+
<base-config cleartextTrafficPermitted="true" />
|
|
86
|
+
</network-security-config>
|
|
87
|
+
`;
|
|
88
|
+
}
|
|
89
|
+
const existing = parseMarker(xml);
|
|
90
|
+
const baseConfig = BASE_CONFIG_REGEX.exec(xml);
|
|
91
|
+
if (existing) {
|
|
92
|
+
// Already enabled by the CLI: only make sure the value is still true.
|
|
93
|
+
return baseConfig ? xml.replace(baseConfig[0], setCleartextValue(baseConfig[0], 'true')) : xml;
|
|
94
|
+
}
|
|
95
|
+
if (baseConfig) {
|
|
96
|
+
const original = (_a = getCleartextValue(baseConfig[0])) !== null && _a !== void 0 ? _a : 'absent';
|
|
97
|
+
const indent = indentOf(xml, baseConfig.index);
|
|
98
|
+
const marker = `${buildMarker({ created: false, ref: flags.ref, orig: original })}\n${indent}`;
|
|
99
|
+
return (xml.slice(0, baseConfig.index) +
|
|
100
|
+
marker +
|
|
101
|
+
setCleartextValue(baseConfig[0], 'true') +
|
|
102
|
+
xml.slice(baseConfig.index + baseConfig[0].length));
|
|
103
|
+
}
|
|
104
|
+
const root = ROOT_REGEX.exec(xml);
|
|
105
|
+
if (!root) {
|
|
106
|
+
throw new Error('missing <network-security-config> root element');
|
|
107
|
+
}
|
|
108
|
+
const marker = buildMarker({ created: false, ref: flags.ref, orig: 'added' });
|
|
109
|
+
const addition = `\n ${marker}\n <base-config cleartextTrafficPermitted="true" />`;
|
|
110
|
+
if (root[1] === '/') {
|
|
111
|
+
const open = root[0].replace(/\s*\/>$/, '>');
|
|
112
|
+
return xml.replace(root[0], `${open}${addition}\n</network-security-config>`);
|
|
113
|
+
}
|
|
114
|
+
const end = root.index + root[0].length;
|
|
115
|
+
return xml.slice(0, end) + addition + (/^\s/.test(xml.slice(end)) ? '' : '\n') + xml.slice(end);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Undoes `enableCleartext`. Returns `null` when the file should be deleted, `undefined` when the CLI
|
|
119
|
+
* never touched it, and the restored XML otherwise.
|
|
120
|
+
*/
|
|
121
|
+
function revertCleartext(xml) {
|
|
122
|
+
const marker = parseMarker(xml);
|
|
123
|
+
if (!marker) {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
if (marker.created) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
const withoutMarker = xml.replace(MARKER_REGEX, '');
|
|
130
|
+
const baseConfig = BASE_CONFIG_REGEX.exec(withoutMarker);
|
|
131
|
+
if (!baseConfig) {
|
|
132
|
+
return withoutMarker;
|
|
133
|
+
}
|
|
134
|
+
if (marker.orig === 'added') {
|
|
135
|
+
const isSelfClosing = baseConfig[0].endsWith('/>');
|
|
136
|
+
if (isSelfClosing) {
|
|
137
|
+
const indent = indentOf(withoutMarker, baseConfig.index);
|
|
138
|
+
return withoutMarker.replace(new RegExp(`${indent}${escapeRegex(baseConfig[0])}[ \\t]*\\r?\\n?`), '');
|
|
139
|
+
}
|
|
140
|
+
return withoutMarker.replace(baseConfig[0], setCleartextValue(baseConfig[0], 'false'));
|
|
141
|
+
}
|
|
142
|
+
const original = marker.orig === 'absent' || marker.orig === undefined ? undefined : marker.orig;
|
|
143
|
+
return withoutMarker.replace(baseConfig[0], setCleartextValue(baseConfig[0], original));
|
|
144
|
+
}
|
|
145
|
+
function escapeRegex(value) {
|
|
146
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
147
|
+
}
|
|
148
|
+
function addManifestRef(manifest) {
|
|
149
|
+
return manifest.replace(APPLICATION_REGEX, `<application android:networkSecurityConfig="@xml/${DEFAULT_CONFIG_NAME}"`);
|
|
150
|
+
}
|
|
151
|
+
function removeManifestRef(manifest) {
|
|
152
|
+
return manifest.replace(new RegExp(`\\s+android:networkSecurityConfig\\s*=\\s*"@xml/${DEFAULT_CONFIG_NAME}"`), '');
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Enables or disables cleartext traffic on the app module (`android/app`), leaving any
|
|
156
|
+
* network-security-config the app already has intact besides `cleartextTrafficPermitted`.
|
|
157
|
+
*/
|
|
158
|
+
async function setAndroidCleartext(config, enabled) {
|
|
159
|
+
var _a;
|
|
160
|
+
const manifestPath = (0, path_1.join)(config.android.srcMainDirAbs, 'AndroidManifest.xml');
|
|
161
|
+
if (!(await (0, fs_extra_1.pathExists)(manifestPath))) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const manifest = await (0, fs_extra_1.readFile)(manifestPath, 'utf-8');
|
|
165
|
+
const referencedName = (_a = CONFIG_REF_REGEX.exec(manifest)) === null || _a === void 0 ? void 0 : _a[1];
|
|
166
|
+
const configPath = (0, path_1.join)(config.android.resDirAbs, 'xml', `${referencedName !== null && referencedName !== void 0 ? referencedName : DEFAULT_CONFIG_NAME}.xml`);
|
|
167
|
+
const configExists = await (0, fs_extra_1.pathExists)(configPath);
|
|
168
|
+
if (enabled) {
|
|
169
|
+
if (referencedName && !configExists) {
|
|
170
|
+
log_1.logger.warn(`Could not enable cleartext traffic: ${manifestPath} references @xml/${referencedName}, but ${configPath} does not exist.`);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const current = configExists ? await (0, fs_extra_1.readFile)(configPath, 'utf-8') : undefined;
|
|
174
|
+
const addRef = !referencedName;
|
|
175
|
+
let updated;
|
|
176
|
+
try {
|
|
177
|
+
updated = enableCleartext(current, { ref: addRef });
|
|
178
|
+
}
|
|
179
|
+
catch (e) {
|
|
180
|
+
log_1.logger.warn(`Could not enable cleartext traffic: ${configPath} is not a valid network security config (${e.message}).`);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
await (0, fs_extra_1.ensureDir)((0, path_1.dirname)(configPath));
|
|
184
|
+
await (0, fs_extra_1.writeFile)(configPath, updated);
|
|
185
|
+
if (addRef) {
|
|
186
|
+
await (0, fs_extra_1.writeFile)(manifestPath, addManifestRef(manifest));
|
|
187
|
+
}
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (!configExists) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const current = await (0, fs_extra_1.readFile)(configPath, 'utf-8');
|
|
194
|
+
const marker = parseMarker(current);
|
|
195
|
+
const reverted = revertCleartext(current);
|
|
196
|
+
if (reverted === undefined) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (reverted === null) {
|
|
200
|
+
await (0, fs_extra_1.remove)(configPath);
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
await (0, fs_extra_1.writeFile)(configPath, reverted);
|
|
204
|
+
}
|
|
205
|
+
if ((marker === null || marker === void 0 ? void 0 : marker.ref) && referencedName === DEFAULT_CONFIG_NAME) {
|
|
206
|
+
await (0, fs_extra_1.writeFile)(manifestPath, removeManifestRef(manifest));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
exports.setAndroidCleartext = setAndroidCleartext;
|
|
210
|
+
/**
|
|
211
|
+
* Cleartext used to be written to the generated `capacitor-cordova-android-plugins` module, where it never
|
|
212
|
+
* reached Capacitor-only apps. Removes the file generated by older CLI versions.
|
|
213
|
+
*/
|
|
214
|
+
async function removeLegacyCordovaPluginsConfig(config) {
|
|
215
|
+
const legacyPath = (0, path_1.join)(config.android.cordovaPluginsDirAbs, 'src', 'main', 'res', 'xml', `${DEFAULT_CONFIG_NAME}.xml`);
|
|
216
|
+
if (!(await (0, fs_extra_1.pathExists)(legacyPath))) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if ((await (0, fs_extra_1.readFile)(legacyPath, 'utf-8')).trim() === LEGACY_CORDOVA_PLUGINS_CONFIG.trim()) {
|
|
220
|
+
await (0, fs_extra_1.remove)(legacyPath);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
exports.removeLegacyCordovaPluginsConfig = removeLegacyCordovaPluginsConfig;
|
|
224
|
+
exports.__testables = {
|
|
225
|
+
enableCleartext,
|
|
226
|
+
revertCleartext,
|
|
227
|
+
addManifestRef,
|
|
228
|
+
removeManifestRef,
|
|
229
|
+
parseMarker,
|
|
230
|
+
};
|
package/dist/android/update.js
CHANGED
|
@@ -16,10 +16,11 @@ const fs_1 = require("../util/fs");
|
|
|
16
16
|
const node_1 = require("../util/node");
|
|
17
17
|
const template_1 = require("../util/template");
|
|
18
18
|
const common_2 = require("./common");
|
|
19
|
+
const network_security_config_1 = require("./network-security-config");
|
|
19
20
|
const platform = 'android';
|
|
20
21
|
const debug = (0, debug_1.default)('capacitor:android:update');
|
|
21
22
|
async function updateAndroid(config) {
|
|
22
|
-
var _a;
|
|
23
|
+
var _a, _b;
|
|
23
24
|
const plugins = await getPluginsTask(config);
|
|
24
25
|
const capacitorPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 0 /* PluginType.Core */);
|
|
25
26
|
(0, plugin_1.printPlugins)(capacitorPlugins, 'android');
|
|
@@ -44,6 +45,9 @@ async function updateAndroid(config) {
|
|
|
44
45
|
await handleCordovaPluginsGradle(config, cordovaPlugins);
|
|
45
46
|
await (0, cordova_1.writeCordovaAndroidManifest)(cordovaPlugins, config, platform);
|
|
46
47
|
}
|
|
48
|
+
else {
|
|
49
|
+
await (0, network_security_config_1.setAndroidCleartext)(config, !!((_b = config.app.extConfig.server) === null || _b === void 0 ? void 0 : _b.cleartext));
|
|
50
|
+
}
|
|
47
51
|
const incompatibleCordovaPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 2 /* PluginType.Incompatible */);
|
|
48
52
|
(0, plugin_1.printPlugins)(incompatibleCordovaPlugins, platform, 'incompatible');
|
|
49
53
|
await (0, common_1.checkPlatformVersions)(config, platform);
|
package/dist/common.js
CHANGED
package/dist/config.js
CHANGED
|
@@ -88,7 +88,7 @@ async function loadExtConfigTS(rootDir, extConfigName, extConfigFilePath) {
|
|
|
88
88
|
(0, errors_1.fatal)('Could not find installation of TypeScript.\n' +
|
|
89
89
|
`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')}`);
|
|
90
90
|
}
|
|
91
|
-
const ts = require(tsPath); // eslint-disable-line @typescript-eslint/no-
|
|
91
|
+
const ts = require(tsPath); // eslint-disable-line @typescript-eslint/no-require-imports
|
|
92
92
|
const extConfigObject = (await (0, node_1.requireTS)(ts, extConfigFilePath));
|
|
93
93
|
const extConfig = extConfigObject.default ? await extConfigObject.default : extConfigObject;
|
|
94
94
|
return {
|
|
@@ -112,6 +112,7 @@ async function loadExtConfigJS(rootDir, extConfigName, extConfigFilePath) {
|
|
|
112
112
|
extConfigType: 'js',
|
|
113
113
|
extConfigName,
|
|
114
114
|
extConfigFilePath: extConfigFilePath,
|
|
115
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
115
116
|
extConfig: await require(extConfigFilePath),
|
|
116
117
|
};
|
|
117
118
|
}
|
|
@@ -302,7 +303,7 @@ async function determineIOSWebDirAbs(nativeProjectDirAbs, nativeTargetDirAbs, na
|
|
|
302
303
|
return (0, path_1.resolve)(nativeProjectDirAbs, 'public');
|
|
303
304
|
}
|
|
304
305
|
}
|
|
305
|
-
catch
|
|
306
|
+
catch {
|
|
306
307
|
// ignore
|
|
307
308
|
}
|
|
308
309
|
return (0, path_1.resolve)(nativeTargetDirAbs, 'public');
|
|
@@ -386,7 +387,7 @@ async function determinePackageManager(rootDir, platformDir, nativeProjectDirAbs
|
|
|
386
387
|
gemfilePath = (0, path_1.resolve)(output, 'Gemfile');
|
|
387
388
|
}
|
|
388
389
|
}
|
|
389
|
-
catch
|
|
390
|
+
catch {
|
|
390
391
|
// Nothing
|
|
391
392
|
}
|
|
392
393
|
}
|
package/dist/cordova.js
CHANGED
|
@@ -7,6 +7,7 @@ const path_1 = require("path");
|
|
|
7
7
|
const plist_1 = tslib_1.__importDefault(require("plist"));
|
|
8
8
|
const prompts_1 = tslib_1.__importDefault(require("prompts"));
|
|
9
9
|
const common_1 = require("./android/common");
|
|
10
|
+
const network_security_config_1 = require("./android/network-security-config");
|
|
10
11
|
const colors_1 = tslib_1.__importDefault(require("./colors"));
|
|
11
12
|
const errors_1 = require("./errors");
|
|
12
13
|
const common_2 = require("./ios/common");
|
|
@@ -754,26 +755,16 @@ async function writeCordovaAndroidManifest(cordovaPlugins, config, platform, cle
|
|
|
754
755
|
});
|
|
755
756
|
});
|
|
756
757
|
const cleartextString = 'android:usesCleartextTraffic="true"';
|
|
757
|
-
const
|
|
758
|
-
?
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
await (0, fs_extra_1.ensureDir)(networkSecurityConfigDir);
|
|
764
|
-
await (0, fs_extra_1.writeFile)(networkSecurityConfigPath, `<?xml version="1.0" encoding="utf-8"?>
|
|
765
|
-
<network-security-config>
|
|
766
|
-
<base-config cleartextTrafficPermitted="true" />
|
|
767
|
-
</network-security-config>
|
|
768
|
-
`);
|
|
769
|
-
}
|
|
770
|
-
else if (await (0, fs_extra_1.pathExists)(networkSecurityConfigPath)) {
|
|
771
|
-
await (0, fs_extra_1.remove)(networkSecurityConfigPath);
|
|
772
|
-
}
|
|
758
|
+
const cleartextEnabled = !!(cleartext ||
|
|
759
|
+
((_a = config.app.extConfig.server) === null || _a === void 0 ? void 0 : _a.cleartext) ||
|
|
760
|
+
applicationXMLAttributes.includes(cleartextString));
|
|
761
|
+
// Cleartext is applied to the app module, since the Cordova plugins module is not linked into Capacitor-only apps
|
|
762
|
+
await (0, network_security_config_1.removeLegacyCordovaPluginsConfig)(config);
|
|
763
|
+
await (0, network_security_config_1.setAndroidCleartext)(config, cleartextEnabled);
|
|
773
764
|
let content = `<?xml version='1.0' encoding='utf-8'?>
|
|
774
765
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
775
766
|
xmlns:amazon="http://schemas.amazon.com/apk/res/android">
|
|
776
|
-
<application ${applicationXMLAttributes.filter((attr) => !attr.includes('android:usesCleartextTraffic')).join('\n')}
|
|
767
|
+
<application ${applicationXMLAttributes.filter((attr) => !attr.includes('android:usesCleartextTraffic')).join('\n')}>
|
|
777
768
|
${applicationXMLEntries.join('\n')}
|
|
778
769
|
</application>
|
|
779
770
|
${rootXMLEntries.join('\n')}
|
package/dist/declarations.d.ts
CHANGED
|
@@ -528,46 +528,6 @@ export interface CapacitorConfig {
|
|
|
528
528
|
packageOptions?: {
|
|
529
529
|
[pluginId: string]: PackageOptions;
|
|
530
530
|
};
|
|
531
|
-
/**
|
|
532
|
-
* Override which Capacitor Swift package the generated `Package.swift` depends on.
|
|
533
|
-
*
|
|
534
|
-
* By default the generated package pins the git tag matching the installed
|
|
535
|
-
* `@capacitor/ios` version, which is correct for both stable and pre-release versions
|
|
536
|
-
* and matches what CocoaPods resolves.
|
|
537
|
-
*
|
|
538
|
-
* Set this only when developing against an unreleased Capacitor, such as a local
|
|
539
|
-
* checkout or a feature branch. Exactly one of `path`, `branch`, `revision`, `exact`,
|
|
540
|
-
* or `from` must be set. `path` points at the repository root (the directory containing
|
|
541
|
-
* `Package.swift`) and may be relative to the app.
|
|
542
|
-
*
|
|
543
|
-
* The `CAPACITOR_IOS_PACKAGE` environment variable takes precedence over this setting,
|
|
544
|
-
* so a checkout can be redirected without editing committed configuration.
|
|
545
|
-
*
|
|
546
|
-
* Note that `branch` and `revision` builds are not reproducible and decouple the native
|
|
547
|
-
* code from the `@capacitor/core` JavaScript bridge it is versioned against.
|
|
548
|
-
*
|
|
549
|
-
* @since 9.0.0
|
|
550
|
-
* @example { "path": "../capacitor" }
|
|
551
|
-
* @example { "branch": "next" }
|
|
552
|
-
*/
|
|
553
|
-
capacitorPackage?: {
|
|
554
|
-
/**
|
|
555
|
-
* Repository to fetch from. Ignored when `path` is set.
|
|
556
|
-
*
|
|
557
|
-
* @default 'https://github.com/ionic-team/capacitor'
|
|
558
|
-
*/
|
|
559
|
-
url?: string;
|
|
560
|
-
/** Path to a local Capacitor repository root. */
|
|
561
|
-
path?: string;
|
|
562
|
-
/** Branch to track. */
|
|
563
|
-
branch?: string;
|
|
564
|
-
/** Exact commit to pin. */
|
|
565
|
-
revision?: string;
|
|
566
|
-
/** Exact version tag to pin. */
|
|
567
|
-
exact?: string;
|
|
568
|
-
/** Minimum version tag, allowing compatible upgrades. */
|
|
569
|
-
from?: string;
|
|
570
|
-
};
|
|
571
531
|
};
|
|
572
532
|
};
|
|
573
533
|
};
|
|
@@ -626,6 +586,13 @@ export interface CapacitorConfig {
|
|
|
626
586
|
*
|
|
627
587
|
* On Android, all cleartext traffic is disabled by default as of API 28.
|
|
628
588
|
*
|
|
589
|
+
* When enabled, the CLI sets `cleartextTrafficPermitted="true"` on the `<base-config>` of the app's
|
|
590
|
+
* `network-security-config.xml` (`android/app/src/main/res/xml/`), creating the file and the
|
|
591
|
+
* `android:networkSecurityConfig` manifest reference if the app has none. If the app already has its own
|
|
592
|
+
* network security config, only that attribute is changed. Other settings, such as a `<domain-config>`
|
|
593
|
+
* that disallows cleartext for specific domains, are left as they are and still apply.
|
|
594
|
+
* The change is reverted when the option is disabled.
|
|
595
|
+
*
|
|
629
596
|
* This is intended for use with live-reload servers where unencrypted HTTP
|
|
630
597
|
* traffic is often used.
|
|
631
598
|
*
|
|
@@ -757,7 +724,7 @@ export interface PluginsConfig {
|
|
|
757
724
|
*
|
|
758
725
|
* This option is only supported on Android.
|
|
759
726
|
*
|
|
760
|
-
* `native` = (recommended) For older Chromium versions (< v140) this embeds the webview with padding and sets the `env(safe-area-inset-*)` variables to `0px`. For newer Chromium versions (>= v140) this makes sure the webview adheres to the `viewport-fit` meta tag. If set to `viewport-fit="cover"` this will make the webview edge-to-edge and the `env(safe-area-inset-*)` variables will contain the correct values. With those values you could set padding for example
|
|
727
|
+
* `native` = (recommended) For older Chromium versions (< v140) this embeds the webview with padding and sets the `env(safe-area-inset-*)` variables to `0px`. For newer Chromium versions (>= v140) this makes sure the webview adheres to the `viewport-fit` meta tag. If set to `viewport-fit="cover"` this will make the webview edge-to-edge and the `env(safe-area-inset-*)` variables will contain the correct values. With those values you could set padding for example to make sure the webview is shown correctly.
|
|
761
728
|
*
|
|
762
729
|
* `css` = This is the same as `native`, but it also injects CSS variables (`--safe-area-inset-*`) containing correct safe area inset values into the webview.
|
|
763
730
|
*
|
package/dist/index.js
CHANGED
|
@@ -105,24 +105,14 @@ function runProgram(config) {
|
|
|
105
105
|
.option('--configuration <name>', 'Configuration name of the iOS Scheme')
|
|
106
106
|
.option('--keystorealiaspass <keystoreAliasPass>', 'Password for the Key Alias')
|
|
107
107
|
.addOption(new commander_1.Option('--androidreleasetype <androidreleasetype>', 'Android release type; APK or AAB').choices([
|
|
108
|
-
|
|
109
|
-
'APK',
|
|
108
|
+
...telemetry_1.TELEMETRY_SAFE_CHOICES.androidreleasetype,
|
|
110
109
|
]))
|
|
111
110
|
.addOption(new commander_1.Option('--signing-type <signingtype>', 'Program used to sign apps (default: jarsigner)').choices([
|
|
112
|
-
|
|
113
|
-
'jarsigner',
|
|
111
|
+
...telemetry_1.TELEMETRY_SAFE_CHOICES.signingType,
|
|
114
112
|
]))
|
|
115
113
|
.addOption(new commander_1.Option('--xcode-team-id <xcodeTeamID>', 'The Developer team to use for building and exporting the archive'))
|
|
116
|
-
.addOption(new commander_1.Option('--xcode-export-method <xcodeExportMethod>', 'Describes how xcodebuild should export the archive (default: app-store-connect)').choices([
|
|
117
|
-
'
|
|
118
|
-
'release-testing',
|
|
119
|
-
'enterprise',
|
|
120
|
-
'debugging',
|
|
121
|
-
'developer-id',
|
|
122
|
-
'mac-application',
|
|
123
|
-
'validation',
|
|
124
|
-
]))
|
|
125
|
-
.addOption(new commander_1.Option('--xcode-signing-style <xcodeSigningStyle>', 'The iOS signing style to use when building the app for distribution (default: automatic)').choices(['automatic', 'manual']))
|
|
114
|
+
.addOption(new commander_1.Option('--xcode-export-method <xcodeExportMethod>', 'Describes how xcodebuild should export the archive (default: app-store-connect)').choices([...telemetry_1.TELEMETRY_SAFE_CHOICES.xcodeExportMethod]))
|
|
115
|
+
.addOption(new commander_1.Option('--xcode-signing-style <xcodeSigningStyle>', 'The iOS signing style to use when building the app for distribution (default: automatic)').choices([...telemetry_1.TELEMETRY_SAFE_CHOICES.xcodeSigningStyle]))
|
|
126
116
|
.addOption(new commander_1.Option('--xcode-signing-certificate <xcodeSigningCertificate>', 'A certificate name, SHA-1 hash, or automatic selector to use for signing for iOS builds'))
|
|
127
117
|
.addOption(new commander_1.Option('--xcode-provisioning-profile <xcodeProvisioningProfile>', 'A provisioning profile name or UUID for iOS builds'))
|
|
128
118
|
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { scheme, flavor, keystorepath, keystorepass, keystorealias, keystorealiaspass, androidreleasetype, signingType, configuration, xcodeTeamId, xcodeExportMethod, xcodeSigningStyle, xcodeSigningCertificate, xcodeProvisioningProfile, }) => {
|
package/dist/ios/common.js
CHANGED
package/dist/ios/update.js
CHANGED
|
@@ -12,7 +12,6 @@ const errors_1 = require("../errors");
|
|
|
12
12
|
const log_1 = require("../log");
|
|
13
13
|
const plugin_1 = require("../plugin");
|
|
14
14
|
const copy_1 = require("../tasks/copy");
|
|
15
|
-
const migrate_1 = require("../tasks/migrate");
|
|
16
15
|
const capacitor_package_1 = require("../util/capacitor-package");
|
|
17
16
|
const cordova_ios_1 = require("../util/cordova-ios");
|
|
18
17
|
const fs_1 = require("../util/fs");
|
|
@@ -55,28 +54,21 @@ async function updatePluginFiles(config, plugins, deployment) {
|
|
|
55
54
|
const validSPMPackages = await (0, spm_1.checkPluginsForPackageSwift)(config, plugins);
|
|
56
55
|
const iosPlatformVersion = await (0, common_1.getCapacitorPackageVersion)(config, config.ios.name);
|
|
57
56
|
const majorCapVersion = (0, semver_1.major)(iosPlatformVersion);
|
|
58
|
-
const
|
|
57
|
+
const capacitorPackagePath = await (0, capacitor_package_1.resolveCapacitorPackagePath)(config);
|
|
58
|
+
const iosVersion = (0, common_2.getMajoriOSVersion)(config);
|
|
59
59
|
await Promise.all(validSPMPackages.map(async (plugin) => {
|
|
60
60
|
const packageSwiftPath = (0, path_1.join)(plugin.rootPath, 'Package.swift');
|
|
61
|
-
|
|
61
|
+
const content = await (0, fs_extra_1.readFile)(packageSwiftPath, { encoding: 'utf-8' });
|
|
62
62
|
const version = (0, capacitor_package_1.findCapacitorDependencyVersion)(content);
|
|
63
63
|
if (version && (0, semver_1.major)(version) != majorCapVersion) {
|
|
64
64
|
log_1.logger.warn(`${plugin.id} is built for Capacitor ${(0, semver_1.major)(version)}, it might cause issues`);
|
|
65
65
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
if (version && (0, semver_1.major)(version) != majorCapVersion) {
|
|
76
|
-
const preCapVersion = (0, semver_1.prerelease)(iosPlatformVersion);
|
|
77
|
-
const forceVersion = preCapVersion ? iosPlatformVersion : `${majorCapVersion}.0.0`;
|
|
78
|
-
content = (0, migrate_1.setAllStringIn)(content, `url: "https://github.com/ionic-team/capacitor-swift-pm.git",`, `)`, ` from: "${forceVersion}"`);
|
|
79
|
-
await (0, fs_extra_1.writeFile)(packageSwiftPath, content);
|
|
66
|
+
// The plugin has to resolve to the same package identity as the app, or SPM ends up with
|
|
67
|
+
// two packages that both vend a Capacitor product.
|
|
68
|
+
let rewritten = (0, capacitor_package_1.rewriteCapacitorDependency)(content, capacitorPackagePath, plugin.rootPath);
|
|
69
|
+
rewritten = (0, capacitor_package_1.patchPackageSwiftDeploymentTarget)(rewritten, iosVersion).content;
|
|
70
|
+
if (rewritten !== content) {
|
|
71
|
+
await (0, fs_extra_1.writeFile)(packageSwiftPath, rewritten);
|
|
80
72
|
}
|
|
81
73
|
}));
|
|
82
74
|
await (0, spm_1.generatePackageFile)(config, validSPMPackages.concat(cordovaPlugins));
|
package/dist/ipc.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.receive = exports.send = void 0;
|
|
3
|
+
exports.deliver = exports.receive = exports.send = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const utils_subprocess_1 = require("@ionic/utils-subprocess");
|
|
6
6
|
const debug_1 = tslib_1.__importDefault(require("debug"));
|
|
@@ -9,6 +9,11 @@ const https_1 = require("https");
|
|
|
9
9
|
const path_1 = require("path");
|
|
10
10
|
const cli_1 = require("./util/cli");
|
|
11
11
|
const debug = (0, debug_1.default)('capacitor:ipc');
|
|
12
|
+
/**
|
|
13
|
+
* How long an awaited delivery may take. Short enough that a developer never
|
|
14
|
+
* notices it, long enough for a request from a cold sandbox.
|
|
15
|
+
*/
|
|
16
|
+
const DELIVERY_TIMEOUT = 3000;
|
|
12
17
|
/**
|
|
13
18
|
* Send an IPC message to a forked process.
|
|
14
19
|
*/
|
|
@@ -32,8 +37,39 @@ exports.send = send;
|
|
|
32
37
|
async function receive(msg) {
|
|
33
38
|
debug('Received %O IPC message', msg.type);
|
|
34
39
|
if (msg.type === 'telemetry') {
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
await deliver(msg.data);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.receive = receive;
|
|
44
|
+
/**
|
|
45
|
+
* POST a metric to the events service.
|
|
46
|
+
*
|
|
47
|
+
* Never rejects and never writes to stderr. Telemetry failing is not something
|
|
48
|
+
* the caller can act on, and it must not change the command's outcome or its
|
|
49
|
+
* exit code — so every ending, including the timeout, resolves.
|
|
50
|
+
*/
|
|
51
|
+
function deliver(data, timeout = DELIVERY_TIMEOUT) {
|
|
52
|
+
return new Promise((resolve) => {
|
|
53
|
+
const body = JSON.stringify({ metrics: [data], sent_at: new Date().toISOString() });
|
|
54
|
+
let settled = false;
|
|
55
|
+
const finish = (reason) => {
|
|
56
|
+
if (settled) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
settled = true;
|
|
60
|
+
clearTimeout(deadline);
|
|
61
|
+
debug('Delivery of %O metric %s', data.name, reason);
|
|
62
|
+
resolve();
|
|
63
|
+
};
|
|
64
|
+
// An overall deadline rather than `req.setTimeout`, which is a socket
|
|
65
|
+
// inactivity timer and only arms once the socket connects — so it never
|
|
66
|
+
// fires against an unroutable host, which is exactly the sandbox this
|
|
67
|
+
// bound exists for. Unref'd so a pending request can't hold the CLI open.
|
|
68
|
+
const deadline = setTimeout(() => {
|
|
69
|
+
req.destroy();
|
|
70
|
+
finish('timed out');
|
|
71
|
+
}, timeout);
|
|
72
|
+
deadline.unref();
|
|
37
73
|
// This request is only made if telemetry is on.
|
|
38
74
|
const req = (0, https_1.request)({
|
|
39
75
|
hostname: 'metrics-capacitor.outsystems.com',
|
|
@@ -45,17 +81,21 @@ async function receive(msg) {
|
|
|
45
81
|
},
|
|
46
82
|
}, (response) => {
|
|
47
83
|
debug('Sent %O metric to events service (status: %O)', data.name, response.statusCode);
|
|
48
|
-
if (response.statusCode
|
|
84
|
+
if (response.statusCode === 202) {
|
|
85
|
+
// Draining is what lets the socket close; without it an awaited
|
|
86
|
+
// delivery sits until the timeout fires.
|
|
87
|
+
response.resume();
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
49
90
|
response.on('data', (chunk) => {
|
|
50
91
|
debug('Bad response from events service. Request body: %O', chunk.toString());
|
|
51
92
|
});
|
|
52
93
|
}
|
|
94
|
+
response.on('end', () => finish('completed'));
|
|
95
|
+
response.on('error', () => finish('failed reading the response'));
|
|
53
96
|
});
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
};
|
|
58
|
-
req.end(JSON.stringify(body));
|
|
59
|
-
}
|
|
97
|
+
req.on('error', (e) => finish(`failed: ${e.message}`));
|
|
98
|
+
req.end(body);
|
|
99
|
+
});
|
|
60
100
|
}
|
|
61
|
-
exports.
|
|
101
|
+
exports.deliver = deliver;
|