@capacitor/cli 9.0.0-alpha.8 → 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.
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isAgentDriven = exports.isCI = exports.detectRunContext = exports.CONVENTION_PATTERN = exports.CONVENTION_DENYLIST = void 0;
4
+ const utils_terminal_1 = require("@ionic/utils-terminal");
5
+ const net_1 = require("net");
6
+ const declared_1 = require("./declared");
7
+ const signals_1 = require("./signals");
8
+ const unknown_1 = require("./unknown");
9
+ const version_1 = require("./version");
10
+ var unknown_2 = require("./unknown");
11
+ Object.defineProperty(exports, "CONVENTION_DENYLIST", { enumerable: true, get: function () { return unknown_2.CONVENTION_DENYLIST; } });
12
+ Object.defineProperty(exports, "CONVENTION_PATTERN", { enumerable: true, get: function () { return unknown_2.CONVENTION_PATTERN; } });
13
+ /**
14
+ * Any single signal happens legitimately — a `cat` pager, a missing TTY, a
15
+ * local proxy. Three together, with no terminal anywhere, is what separates a
16
+ * machine-driven run from a developer with an unusual setup.
17
+ */
18
+ const HEURISTIC_THRESHOLD = 3;
19
+ /**
20
+ * Classify this invocation as human, CI, or agent-driven from the environment
21
+ * alone — no process spawn, no filesystem read.
22
+ *
23
+ * Every input is injectable and nothing is captured at module load, so tests
24
+ * can drive the whole thing. This is also why `@ionic/utils-terminal`'s
25
+ * `TERMINAL_INFO` isn't used: it snapshots the real process when the module is
26
+ * first imported and freezes it.
27
+ */
28
+ function detectRunContext(options = {}) {
29
+ var _a, _b, _c, _d;
30
+ const env = (_a = options.env) !== null && _a !== void 0 ? _a : process.env;
31
+ const streams = (_b = options.streams) !== null && _b !== void 0 ? _b : readStreamStates();
32
+ const cwd = (_c = options.cwd) !== null && _c !== void 0 ? _c : process.cwd();
33
+ const execPath = (_d = options.execPath) !== null && _d !== void 0 ? _d : process.execPath;
34
+ const scan = (0, signals_1.scanSignals)(env, streams, cwd, execPath);
35
+ const surface = (0, signals_1.deriveSurface)(env, scan);
36
+ // CI is classified but never delivered, so nothing below needs to run.
37
+ if (isCI(env)) {
38
+ return { report: false, surface, confidence: 'none' };
39
+ }
40
+ const declared = (0, declared_1.detectDeclared)(env);
41
+ if (declared) {
42
+ return {
43
+ report: true,
44
+ agentId: declared.id,
45
+ agentVersion: (0, version_1.detectAgentVersion)(env, declared.id),
46
+ surface,
47
+ confidence: 'declared',
48
+ sessionVar: declared.sessionVar,
49
+ };
50
+ }
51
+ // Neither path below may report a run with a terminal attached, which makes
52
+ // "someone at a terminal is never reported as an agent" a guarantee rather
53
+ // than a likelihood. The convention rule needs the gate most: it matches on
54
+ // the shape of a variable name alone, which desktop sessions and shells also
55
+ // produce, yet returns the stronger `declared` confidence.
56
+ const headless = scan.headless.includes(signals_1.NO_TTY_SIGNAL);
57
+ const detectedBy = headless ? (0, unknown_1.detectUnknownHarness)(env) : undefined;
58
+ if (detectedBy) {
59
+ return {
60
+ report: true,
61
+ agentId: 'unknown',
62
+ agentDetectedBy: detectedBy,
63
+ surface,
64
+ confidence: 'declared',
65
+ };
66
+ }
67
+ // This path exists for harnesses that strip their environment before
68
+ // invoking the CLI.
69
+ const weight = headless ? scan.headless.length + scan.sandbox.length : 0;
70
+ if (weight >= HEURISTIC_THRESHOLD) {
71
+ return {
72
+ report: true,
73
+ agentId: 'unknown',
74
+ surface,
75
+ confidence: 'heuristic',
76
+ };
77
+ }
78
+ return { report: true, surface, confidence: 'none' };
79
+ }
80
+ exports.detectRunContext = detectRunContext;
81
+ /**
82
+ * Whether this is a build server. Reuses the CLI's existing variable list
83
+ * rather than a copy of it, so the gate can't drift from `isInteractive()`.
84
+ */
85
+ function isCI(env) {
86
+ return utils_terminal_1.CI_ENVIRONMENT_VARIABLES.some((name) => Boolean(env[name]));
87
+ }
88
+ exports.isCI = isCI;
89
+ /**
90
+ * Whether something other than a person invoked the CLI. True for an
91
+ * unrecognised harness as well as a named one — both mean there is nobody
92
+ * waiting on the terminal.
93
+ */
94
+ function isAgentDriven(runContext) {
95
+ return Boolean(runContext.agentId);
96
+ }
97
+ exports.isAgentDriven = isAgentDriven;
98
+ function readStreamStates() {
99
+ const { stdin, stdout, stderr } = process;
100
+ return {
101
+ tty: [Boolean(stdin.isTTY), Boolean(stdout.isTTY), Boolean(stderr.isTTY)],
102
+ socket: [isPipe(stdin), isPipe(stdout), isPipe(stderr)],
103
+ };
104
+ }
105
+ /**
106
+ * `tty.ReadStream` extends `net.Socket`, so a real terminal has to be excluded
107
+ * rather than just testing the prototype.
108
+ */
109
+ function isPipe(stream) {
110
+ return stream instanceof net_1.Socket && !stream.isTTY;
111
+ }
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.capacitorAgents = exports.overrideFor = exports.AGENT_OVERRIDES = void 0;
4
+ const agent_cli_detector_1 = require("agent-cli-detector");
5
+ /**
6
+ * Capacitor's additions to the published registry, keyed by the upstream agent
7
+ * id. `agent-cli-detector@0.1.7` matches Codex only through its sandbox
8
+ * markers, knows none of Claude Code's entrypoint or hosted-sandbox variables,
9
+ * and carries no version information for anyone.
10
+ *
11
+ * Keying against the package's own id union means a rename or removal upstream
12
+ * fails to compile instead of silently dropping the entry. It also means this
13
+ * map can only extend a harness the package already lists; a vendor it has
14
+ * never heard of needs an upstream addition first.
15
+ *
16
+ * Re-verify the version variables before every release — vendors rename them
17
+ * between versions.
18
+ *
19
+ * Claude Code's `CLAUDE_CODE_HOST_*_PROXY_PORT` variables are deliberately
20
+ * absent: a wildcard can't be expressed as an `EnvSignal.name`, and they are
21
+ * loopback proxy markers, so `signals.ts` matches them instead.
22
+ */
23
+ exports.AGENT_OVERRIDES = {
24
+ antigravity: { versionVariable: 'ANTIGRAVITY_LS_VERSION' },
25
+ 'claude-code': { env: [{ name: 'CLAUDE_CODE_ENTRYPOINT' }, { name: 'CLAUDE_TMPDIR' }] },
26
+ codex: {
27
+ env: [{ name: 'CODEX_VERSION' }, { name: 'CODEX_SANDBOX' }],
28
+ versionVariable: 'CODEX_VERSION',
29
+ },
30
+ kilocode: { versionVariable: 'KILOCODE_VERSION' },
31
+ muse: { versionVariable: 'MUSE_RELEASE_INFO', versionIsJson: true },
32
+ };
33
+ function overrideFor(agentId) {
34
+ return exports.AGENT_OVERRIDES[agentId];
35
+ }
36
+ exports.overrideFor = overrideFor;
37
+ /**
38
+ * The published registry with Capacitor's additions layered on. Extending a
39
+ * listed harness means editing `AGENT_OVERRIDES` and nothing else.
40
+ */
41
+ exports.capacitorAgents = agent_cli_detector_1.defaultAgents.map((agent) => {
42
+ var _a, _b;
43
+ const extra = (_a = overrideFor(agent.id)) === null || _a === void 0 ? void 0 : _a.env;
44
+ return extra ? { ...agent, env: [...((_b = agent.env) !== null && _b !== void 0 ? _b : []), ...extra] } : agent;
45
+ });
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deriveSurface = exports.scanSignals = exports.NO_TTY_SIGNAL = void 0;
4
+ /**
5
+ * No standard stream is attached to a terminal. The strongest of the headless
6
+ * signals, and the one the heuristic verdict is gated on.
7
+ */
8
+ exports.NO_TTY_SIGNAL = 'no-tty';
9
+ /**
10
+ * Variables whose value is a proxy target. The `_PORT` spelling is how hosted
11
+ * Claude Code sandboxes expose theirs.
12
+ */
13
+ const PROXY_VARIABLE_PATTERN = /_PROXY$|_PROXY_PORT$|^(?:HTTP|HTTPS|ALL)_PROXY$/;
14
+ const LOOPBACK_PATTERN = /(?:^|\/\/|@)(?:127\.0\.0\.1|localhost|\[::1\]|0\.0\.0\.0)(?::\d+)?(?:$|[/?])/i;
15
+ /**
16
+ * Some hosted sandboxes mint an adjective-adjective-surname username per
17
+ * session. Inferred from observed sandboxes, not documented by any vendor —
18
+ * which is why it only ever contributes to a heuristic verdict.
19
+ */
20
+ const GENERATED_USERNAME_PATTERN = /^[a-z]+[-_][a-z]+[-_][a-z]+$/;
21
+ /** A session-scoped mount carries a generated id in its path. Also inferred. */
22
+ const SESSION_MOUNT_PATTERN = /[/\\](?:sessions?|workspaces?)[/\\][0-9a-f][0-9a-f-]{7,}/i;
23
+ const JAVA_AGENT_PATTERN = /-javaagent/i;
24
+ const JETBRAINS_TERMINAL_PATTERN = /jetbrains/i;
25
+ function scanSignals(env, streams, cwd, execPath) {
26
+ return {
27
+ headless: scanHeadless(env, streams),
28
+ sandbox: scanSandbox(env, cwd, execPath),
29
+ };
30
+ }
31
+ exports.scanSignals = scanSignals;
32
+ /**
33
+ * Derive the execution environment, most specific match first. Independent of
34
+ * the agent verdict by design, so a terminal agent and an IDE agent are
35
+ * distinguishable downstream.
36
+ */
37
+ function deriveSurface(env, scan) {
38
+ if (scan.sandbox.length > 0) {
39
+ return 'cloud-sandbox';
40
+ }
41
+ if (isDesktopShell(env)) {
42
+ return 'desktop-app';
43
+ }
44
+ if (isIde(env)) {
45
+ return 'ide';
46
+ }
47
+ return 'terminal';
48
+ }
49
+ exports.deriveSurface = deriveSurface;
50
+ function scanHeadless(env, streams) {
51
+ const signals = [];
52
+ if (!streams.tty.some(Boolean)) {
53
+ signals.push(exports.NO_TTY_SIGNAL);
54
+ }
55
+ if (streams.socket.some(Boolean)) {
56
+ signals.push('stream-socket');
57
+ }
58
+ // A human wouldn't set contradictory color rules; a wrapper assembling an
59
+ // environment from defaults does.
60
+ if (env.NO_COLOR && env.CLICOLOR_FORCE) {
61
+ signals.push('contradictory-color');
62
+ }
63
+ if (env.PAGER === 'cat' || env.GIT_PAGER === 'cat' || env.GIT_EDITOR === 'true') {
64
+ signals.push('pager-disabled');
65
+ }
66
+ if (isDesktopShell(env)) {
67
+ signals.push('gui-bundle-no-term');
68
+ }
69
+ return signals;
70
+ }
71
+ function scanSandbox(env, cwd, execPath) {
72
+ var _a, _b;
73
+ const signals = [];
74
+ if (countLoopbackProxies(env) >= 3) {
75
+ signals.push('loopback-proxies');
76
+ }
77
+ if (env.SANDBOX_RUNTIME) {
78
+ signals.push('sandbox-runtime');
79
+ }
80
+ if (env.JAVA_TOOL_OPTIONS && JAVA_AGENT_PATTERN.test(env.JAVA_TOOL_OPTIONS)) {
81
+ signals.push('java-tool-options-agent');
82
+ }
83
+ if (GENERATED_USERNAME_PATTERN.test((_b = (_a = env.USER) !== null && _a !== void 0 ? _a : env.USERNAME) !== null && _b !== void 0 ? _b : '')) {
84
+ signals.push('generated-username');
85
+ }
86
+ if (SESSION_MOUNT_PATTERN.test(cwd) || SESSION_MOUNT_PATTERN.test(execPath)) {
87
+ signals.push('session-mount');
88
+ }
89
+ return signals;
90
+ }
91
+ function countLoopbackProxies(env) {
92
+ return Object.entries(env).filter(([name, value]) => {
93
+ const normalized = name.toUpperCase();
94
+ if (!value || !PROXY_VARIABLE_PATTERN.test(normalized)) {
95
+ return false;
96
+ }
97
+ // A bare port is only ever a local one, so `*_PROXY_PORT` needs no host.
98
+ return normalized.endsWith('_PORT') ? /^\d+$/.test(value) : LOOPBACK_PATTERN.test(value);
99
+ }).length;
100
+ }
101
+ /**
102
+ * A GUI application spawned a bare shell. Shared by the headless scan and the
103
+ * surface derivation so the two can't drift apart.
104
+ */
105
+ function isDesktopShell(env) {
106
+ return Boolean(env.__CFBundleIdentifier || env.ELECTRON_RUN_AS_NODE) && !env.TERM;
107
+ }
108
+ function isIde(env) {
109
+ var _a;
110
+ return Boolean(env.VSCODE_PID ||
111
+ env.VSCODE_GIT_ASKPASS_NODE ||
112
+ env.JETBRAINS_IDE ||
113
+ env.TERM_PROGRAM === 'vscode' ||
114
+ JETBRAINS_TERMINAL_PATTERN.test((_a = env.TERMINAL_EMULATOR) !== null && _a !== void 0 ? _a : ''));
115
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectUnknownHarness = exports.CONVENTION_DENYLIST = exports.CONVENTION_PATTERN = void 0;
4
+ /**
5
+ * Agent harnesses name their declaring variables consistently, so one missing
6
+ * from the registry can still be noticed by shape alone. A name that shows up
7
+ * across many projects is the signal to register the vendor properly.
8
+ */
9
+ exports.CONVENTION_PATTERN = /^[A-Z0-9_]+_(AGENT|TOOL_USE_ID|SESSION_ID|THREAD_ID|CONVERSATION_ID|TRAJECTORY_ID)$/;
10
+ /**
11
+ * Non-agent tools that follow the same convention. Terminals, SSH and GPG all
12
+ * mint session identifiers of their own. Tested one entry at a time.
13
+ *
14
+ * The caller only consults this rule for a run with no terminal attached, so a
15
+ * name missing here can only affect a headless run.
16
+ */
17
+ exports.CONVENTION_DENYLIST = [
18
+ 'TERM_SESSION_ID',
19
+ 'ITERM_SESSION_ID',
20
+ 'SSH_SESSION_ID',
21
+ 'XDG_SESSION_ID',
22
+ 'USER_AGENT',
23
+ 'HTTP_USER_AGENT',
24
+ 'GPG_AGENT',
25
+ 'SSH_AGENT',
26
+ ];
27
+ /**
28
+ * Return the name of the first variable that looks like an unregistered
29
+ * harness, or undefined. Names are sorted so the result doesn't depend on
30
+ * environment insertion order.
31
+ */
32
+ function detectUnknownHarness(env) {
33
+ for (const name of Object.keys(env).sort()) {
34
+ // Windows environment variables are case-insensitive, so normalize before
35
+ // both tests — otherwise a denylisted name in mixed case slips through.
36
+ const normalized = name.toUpperCase();
37
+ if (exports.CONVENTION_DENYLIST.includes(normalized)) {
38
+ continue;
39
+ }
40
+ if (exports.CONVENTION_PATTERN.test(normalized)) {
41
+ return name;
42
+ }
43
+ }
44
+ return undefined;
45
+ }
46
+ exports.detectUnknownHarness = detectUnknownHarness;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectAgentVersion = void 0;
4
+ const semver_1 = require("semver");
5
+ const registry_1 = require("./registry");
6
+ /**
7
+ * Several harnesses set `AI_AGENT` in a shared `<vendor>_<version>_agent`
8
+ * format, with the version's dots written as dashes. It's the only
9
+ * non-per-vendor source, so a harness adopting the convention is picked up
10
+ * without a registry change.
11
+ */
12
+ const AI_AGENT_PATTERN = /^[A-Za-z0-9-]+_(\d[\d-]*)_agent$/;
13
+ /**
14
+ * Resolve the harness version from the first source that carries one.
15
+ *
16
+ * "First source" means first *present*, not first valid: a harness that sets
17
+ * `AI_AGENT` to something malformed reports `unknown` rather than falling
18
+ * through to a variable it never set.
19
+ *
20
+ * Both sources are environment variables by design. The executable path looks
21
+ * like a third, but it is always the Node binary running the CLI rather than
22
+ * the harness's entrypoint — reading a version out of it reports the user's
23
+ * nvm or Homebrew Node version as the agent's.
24
+ */
25
+ function detectAgentVersion(env, agentId) {
26
+ var _a;
27
+ const raw = (_a = fromAiAgent(env)) !== null && _a !== void 0 ? _a : fromVendorVariable(env, agentId);
28
+ return raw && (0, semver_1.valid)(raw) ? raw : 'unknown';
29
+ }
30
+ exports.detectAgentVersion = detectAgentVersion;
31
+ function fromAiAgent(env) {
32
+ const value = env.AI_AGENT;
33
+ if (!value) {
34
+ return undefined;
35
+ }
36
+ const match = AI_AGENT_PATTERN.exec(value);
37
+ // An unparseable value is still a hit — it gets rejected by semver below.
38
+ return match ? match[1].replace(/-/g, '.') : value;
39
+ }
40
+ function fromVendorVariable(env, agentId) {
41
+ var _a;
42
+ const override = (0, registry_1.overrideFor)(agentId);
43
+ if (!(override === null || override === void 0 ? void 0 : override.versionVariable)) {
44
+ return undefined;
45
+ }
46
+ const value = env[override.versionVariable];
47
+ if (!value) {
48
+ return undefined;
49
+ }
50
+ return override.versionIsJson ? ((_a = fromJson(value)) !== null && _a !== void 0 ? _a : value) : value;
51
+ }
52
+ /**
53
+ * Pull a version out of a JSON-valued vendor variable. The field name isn't
54
+ * documented by any vendor we've seen, so the common spellings are tried and
55
+ * anything else falls through to semver rejection.
56
+ */
57
+ function fromJson(value) {
58
+ try {
59
+ const parsed = JSON.parse(value);
60
+ if (typeof parsed !== 'object' || parsed === null) {
61
+ return undefined;
62
+ }
63
+ const record = parsed;
64
+ for (const field of ['version', 'release', 'tag']) {
65
+ if (typeof record[field] === 'string') {
66
+ return record[field];
67
+ }
68
+ }
69
+ return undefined;
70
+ }
71
+ catch {
72
+ return undefined;
73
+ }
74
+ }
@@ -57,7 +57,9 @@ async function copy(config, platformName, inline = false) {
57
57
  usesLiveUpdates = true;
58
58
  }
59
59
  let usesSSLPinning = false;
60
- if (allPlugins.filter((plugin) => plugin.id === '@ionic-enterprise/ssl-pinning' || plugin.id === '@capacitor/ssl-pinning').length > 0) {
60
+ if (allPlugins.filter((plugin) => plugin.id === '@ionic-enterprise/ssl-pinning' ||
61
+ plugin.id === '@capacitor/ssl-pinning' ||
62
+ plugin.id === '@capacitor-community/ssl-pinning').length > 0) {
61
63
  usesSSLPinning = true;
62
64
  }
63
65
  if (platformName === config.ios.name) {
@@ -10,6 +10,7 @@ const doctor_2 = require("../ios/doctor");
10
10
  const log_1 = require("../log");
11
11
  const emoji_1 = require("../util/emoji");
12
12
  const node_1 = require("../util/node");
13
+ const npm_1 = require("../util/npm");
13
14
  const subprocess_1 = require("../util/subprocess");
14
15
  async function doctorCommand(config, selectedPlatformName) {
15
16
  log_1.output.write(`${(0, emoji_1.emoji)('💊', '')} ${colors_1.default.strong('Capacitor Doctor')} ${(0, emoji_1.emoji)('💊', '')} \n\n`);
@@ -21,11 +22,12 @@ async function doctorCommand(config, selectedPlatformName) {
21
22
  }
22
23
  exports.doctorCommand = doctorCommand;
23
24
  async function doctorCore(config) {
24
- const [cliVersion, coreVersion, androidVersion, iosVersion] = await Promise.all([
25
+ const [cliVersion, coreVersion, androidVersion, iosVersion, blockedInstallScripts] = await Promise.all([
25
26
  (0, subprocess_1.getCommandOutput)('npm', ['info', '@capacitor/cli', 'version']),
26
27
  (0, subprocess_1.getCommandOutput)('npm', ['info', '@capacitor/core', 'version']),
27
28
  (0, subprocess_1.getCommandOutput)('npm', ['info', '@capacitor/android', 'version']),
28
29
  (0, subprocess_1.getCommandOutput)('npm', ['info', '@capacitor/ios', 'version']),
30
+ (0, npm_1.getBlockedInstallScripts)(config.app.rootDir),
29
31
  ]);
30
32
  log_1.output.write(`${colors_1.default.strong('Latest Dependencies:')}\n\n` +
31
33
  ` @capacitor/cli: ${colors_1.default.weak(cliVersion !== null && cliVersion !== void 0 ? cliVersion : 'unknown')}\n` +
@@ -35,6 +37,7 @@ async function doctorCore(config) {
35
37
  `${colors_1.default.strong('Installed Dependencies:')}\n\n`);
36
38
  await printInstalledPackages(config);
37
39
  log_1.output.write('\n');
40
+ (0, npm_1.logBlockedInstallScripts)(blockedInstallScripts);
38
41
  }
39
42
  exports.doctorCore = doctorCore;
40
43
  async function printInstalledPackages(config) {
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.__testables = exports.removeDebugXcconfig = void 0;
4
+ const fs_extra_1 = require("fs-extra");
5
+ const path_1 = require("path");
6
+ const log_1 = require("../log");
7
+ const spm_1 = require("../util/spm");
8
+ const xcode_1 = require("../util/xcode");
9
+ const STOCK_LINE = /^CAPACITOR_DEBUG\s*=\s*true$/;
10
+ async function removeDebugXcconfig(config) {
11
+ if ((await config.ios.packageManager) !== 'SPM') {
12
+ return;
13
+ }
14
+ const xcconfigPath = (0, path_1.join)(config.ios.platformDirAbs, 'debug.xcconfig');
15
+ const state = classifyDebugXcconfig(xcconfigPath);
16
+ if (state === 'customized') {
17
+ log_1.logger.warn(`${xcconfigPath} declares build settings besides CAPACITOR_DEBUG, leaving it in place. ` +
18
+ `Remove the CAPACITOR_DEBUG line yourself — Capacitor 9 no longer reads it.`);
19
+ }
20
+ else if (state === 'stock' && unregisterFromXcodeProject(config)) {
21
+ await (0, fs_extra_1.remove)(xcconfigPath);
22
+ log_1.logger.info(`Removed ${xcconfigPath}.`);
23
+ }
24
+ const result = (0, spm_1.removeInfoPlistDebug)(config);
25
+ if (result.status === 'skipped') {
26
+ log_1.logger.warn(`CAPACITOR_DEBUG not removed from Info.plist: ${result.reason}`);
27
+ }
28
+ }
29
+ exports.removeDebugXcconfig = removeDebugXcconfig;
30
+ /**
31
+ * Deleting the file while the Debug build configuration still points at it fails the
32
+ * Xcode build, so the file only goes once the project has been rewritten.
33
+ */
34
+ function unregisterFromXcodeProject(config) {
35
+ var _a;
36
+ const pbxprojPath = (0, path_1.join)(config.ios.nativeXcodeProjDirAbs, 'project.pbxproj');
37
+ try {
38
+ (0, xcode_1.removeBaseConfigurationFile)(pbxprojPath, 'debug.xcconfig');
39
+ return true;
40
+ }
41
+ catch (err) {
42
+ log_1.logger.warn(`Could not remove the debug.xcconfig reference from ${pbxprojPath}: ${(_a = err === null || err === void 0 ? void 0 : err.message) !== null && _a !== void 0 ? _a : err}. ` +
43
+ `Remove debug.xcconfig from the Xcode project manually.`);
44
+ return false;
45
+ }
46
+ }
47
+ function classifyDebugXcconfig(path) {
48
+ if (!(0, fs_extra_1.existsSync)(path)) {
49
+ return 'absent';
50
+ }
51
+ const settings = (0, fs_extra_1.readFileSync)(path, 'utf-8')
52
+ .split('\n')
53
+ .map((line) => line.trim())
54
+ .filter((line) => line.length > 0 && !line.startsWith('//'));
55
+ return settings.every((line) => STOCK_LINE.test(line)) ? 'stock' : 'customized';
56
+ }
57
+ // Exported for tests.
58
+ exports.__testables = {
59
+ classifyDebugXcconfig,
60
+ };
@@ -15,7 +15,6 @@ async function migrateToSPM(config) {
15
15
  await (0, spm_1.extractSPMPackageDirectory)(config);
16
16
  await (0, spm_1.runCocoapodsDeintegrate)(config);
17
17
  await (0, spm_1.removeCocoapodsFiles)(config);
18
- await (0, spm_1.addInfoPlistDebugIfNeeded)(config);
19
18
  const configWritable = config;
20
19
  configWritable.ios.packageManager = Promise.resolve('SPM');
21
20
  await (0, update_1.update)(configWritable, 'ios', false);