catalyst-core 1.1.0 → 1.2.0-canary.2
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/bin/catalyst.js +54 -6
- package/changelog.md +27 -1
- package/dist/errors/registry.js +306 -18
- package/dist/errors-index.json +273 -70
- package/dist/native/androidProject/app/build.gradle.kts +53 -79
- package/dist/native/androidProject/app/src/main/AndroidManifest.xml +1 -1
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/CatalystConstants.kt +3 -1
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/MainActivity.kt +32 -4
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/KeyboardUtil.kt +5 -1
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/ConfigMappingTest.kt +25 -0
- package/dist/native/androidSetup.js +76 -170
- package/dist/native/androidToolchain.js +642 -0
- package/dist/native/appIcon.js +100 -0
- package/dist/native/buildAndroid/assets.js +29 -5
- package/dist/native/buildAndroid/build.js +110 -223
- package/dist/native/buildAndroid/config.js +57 -65
- package/dist/native/buildAndroid/devices.js +176 -0
- package/dist/native/buildAndroid/index.js +271 -46
- package/dist/native/buildAndroid/output.js +43 -0
- package/dist/native/buildAndroid/signing.js +456 -0
- package/dist/native/buildAppAndroid.js +27 -7
- package/dist/native/buildAppIos.js +139 -20
- package/dist/native/buildIos/assets.js +76 -4
- package/dist/native/buildIos/build.js +31 -181
- package/dist/native/buildIos/config.js +126 -11
- package/dist/native/buildIos/index.js +354 -34
- package/dist/native/buildIos/localhostCert.js +87 -0
- package/dist/native/buildIos/output.js +28 -0
- package/dist/native/buildIos/signing.js +596 -0
- package/dist/native/credentials.js +309 -0
- package/dist/native/exportCredentials.js +51 -0
- package/dist/native/iosToolchain.js +583 -0
- package/dist/native/iosnativeWebView/Configurations/Shared.xcconfig +1 -3
- package/dist/native/iosnativeWebView/iosnativeWebView/Info-Release.plist +2 -0
- package/dist/native/iosnativeWebView/iosnativeWebView/PrivacyInfo.xcprivacy +40 -0
- package/dist/native/iosnativeWebView/iosnativeWebView/iosnativeWebView.entitlements +0 -2
- package/dist/native/iosnativeWebView/iosnativeWebView.xcodeproj/project.pbxproj +4 -4
- package/dist/native/localState.js +148 -0
- package/dist/native/nativeConfig.js +621 -0
- package/dist/native/releaseOutput.js +53 -0
- package/dist/native/renameAndroidProject.js +154 -369
- package/dist/native/setupEmulatorIos.js +58 -275
- package/dist/native/setupServer.js +520 -124
- package/dist/native/utils.js +418 -115
- package/dist/vite/resolveDevServerConfig.js +21 -0
- package/mcp_v2/knowledge-base.json +13 -11
- package/mcp_v2/test/config.test.ts +40 -0
- package/mcp_v2/tools/build.js +80 -104
- package/mcp_v2/tools/config.js +181 -174
- package/package.json +1 -1
- package/test/cli/nativeFlags.test.ts +97 -0
- package/test/native/androidDevices.test.ts +230 -0
- package/test/native/androidElfAlignment.test.ts +148 -0
- package/test/native/androidSigning.test.ts +646 -0
- package/test/native/androidToolchain.test.ts +766 -0
- package/test/native/appIcon.test.ts +124 -0
- package/test/native/credentials.test.ts +241 -0
- package/test/native/interaction.test.ts +179 -0
- package/test/native/iosConfigPhase.test.ts +611 -0
- package/test/native/iosSigning.test.ts +1060 -0
- package/test/native/iosToolchain.test.ts +821 -0
- package/test/native/localState.test.ts +80 -0
- package/test/native/nativeConfig.test.ts +602 -0
- package/test/native/setupServer.test.ts +529 -0
- package/test/native/utils.test.ts +102 -127
- package/test/vite/resolveDevServerConfig.test.js +25 -0
- package/dist/native/androidProject/keystore/Untitled +0 -0
- package/dist/native/androidProject/keystore/release-key.jks +0 -0
- package/dist/native/iosnativeWebView/iosnativeWebView/localhost.p12 +0 -0
|
@@ -1,315 +1,98 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var _child_process = require("child_process");
|
|
4
3
|
var _fs = _interopRequireDefault(require("fs"));
|
|
4
|
+
var _path = _interopRequireDefault(require("path"));
|
|
5
5
|
var _utils = require("./utils.js");
|
|
6
|
+
var _iosToolchain = require("./iosToolchain.js");
|
|
7
|
+
var _localState = require("./localState.js");
|
|
6
8
|
var _terminalProgress = _interopRequireDefault(require("./terminalProgress.js"));
|
|
9
|
+
var _diagnostic = require("../cli/diagnostic.js");
|
|
7
10
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
// `catalyst setupEmulator:ios`: install what an iOS debug build needs on this
|
|
12
|
+
// Mac (Xcode's licence and first-launch components, a simulator runtime, the
|
|
13
|
+
// simulator) and nothing else. It reads ios.simulatorName from config.json
|
|
14
|
+
// but never writes config.json, and starts no server. buildApp:ios runs the
|
|
15
|
+
// same checks itself, so this is only for setting a machine up ahead of time.
|
|
16
|
+
|
|
13
17
|
const steps = {
|
|
14
18
|
platform: "Check platform compatibility",
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
saveConfig: "Save configuration",
|
|
19
|
-
setupServer: "Set up server"
|
|
19
|
+
xcode: "Check Xcode",
|
|
20
|
+
runtime: "Check iOS simulator runtime",
|
|
21
|
+
simulator: "Check iOS simulator"
|
|
20
22
|
};
|
|
21
23
|
const progress = new _terminalProgress.default(steps, "catalyst setupEmulator", {
|
|
22
24
|
subject: "ios"
|
|
23
25
|
});
|
|
24
|
-
|
|
25
|
-
const configFile = _fs.default.readFileSync(configPath, "utf8");
|
|
26
|
-
const config = JSON.parse(configFile);
|
|
27
|
-
const {
|
|
28
|
-
WEBVIEW_CONFIG
|
|
29
|
-
} = config;
|
|
30
|
-
if (!WEBVIEW_CONFIG || Object.keys(WEBVIEW_CONFIG).length === 0) {
|
|
31
|
-
progress.log("WebView Config missing in " + configPath, "error");
|
|
32
|
-
process.exit(1);
|
|
33
|
-
}
|
|
34
|
-
if (!WEBVIEW_CONFIG.ios) {
|
|
35
|
-
WEBVIEW_CONFIG.ios = {};
|
|
36
|
-
}
|
|
37
|
-
return {
|
|
38
|
-
WEBVIEW_CONFIG
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
async function saveConfig(newConfig) {
|
|
42
|
-
try {
|
|
43
|
-
// Read the existing config
|
|
44
|
-
const existingConfigFile = _fs.default.readFileSync(configPath, "utf8");
|
|
45
|
-
const existingConfig = JSON.parse(existingConfigFile);
|
|
46
|
-
|
|
47
|
-
// Merge the new WEBVIEW_CONFIG with existing config
|
|
48
|
-
const updatedConfig = {
|
|
49
|
-
...existingConfig,
|
|
50
|
-
// Preserve all existing keys
|
|
51
|
-
WEBVIEW_CONFIG: {
|
|
52
|
-
...existingConfig.WEBVIEW_CONFIG,
|
|
53
|
-
ios: newConfig.WEBVIEW_CONFIG.ios
|
|
54
|
-
} // Update only WEBVIEW_CONFIG
|
|
55
|
-
};
|
|
26
|
+
const log = (message, type = "info") => progress.log(message, type);
|
|
56
27
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
28
|
+
/** ios.simulatorName from config/config.json, when the app sets one. */
|
|
29
|
+
function configuredSimulatorName(cwd = process.cwd()) {
|
|
30
|
+
try {
|
|
31
|
+
// nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal - cwd is the app root; the file name is fixed.
|
|
32
|
+
const config = JSON.parse(_fs.default.readFileSync(_path.default.join(cwd, "config", "config.json"), "utf8"));
|
|
33
|
+
const name = config?.WEBVIEW_CONFIG?.ios?.simulatorName;
|
|
34
|
+
return typeof name === "string" && name.trim() ? name.trim() : null;
|
|
60
35
|
} catch (error) {
|
|
61
|
-
|
|
62
|
-
process.exit(1);
|
|
36
|
+
return null;
|
|
63
37
|
}
|
|
64
38
|
}
|
|
65
39
|
async function setupIOSEnvironment() {
|
|
66
40
|
try {
|
|
41
|
+
const flags = (0, _utils.parseNativeArgs)(process.argv.slice(2));
|
|
67
42
|
progress.start("platform");
|
|
68
43
|
if (process.platform !== "darwin") {
|
|
69
44
|
progress.log("iOS Simulator is only available on macOS.", "error");
|
|
70
45
|
process.exit(1);
|
|
71
46
|
}
|
|
72
47
|
progress.complete("platform");
|
|
73
|
-
progress.start("
|
|
74
|
-
const {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
48
|
+
progress.start("xcode");
|
|
49
|
+
const developerDir = await (0, _iosToolchain.ensureXcodeReady)({
|
|
50
|
+
flags,
|
|
51
|
+
log
|
|
52
|
+
});
|
|
53
|
+
progress.log(`Using ${developerDir}`, "info");
|
|
54
|
+
progress.complete("xcode");
|
|
55
|
+
progress.start("runtime");
|
|
56
|
+
const runtime = await (0, _iosToolchain.ensureIosRuntime)({
|
|
57
|
+
flags,
|
|
58
|
+
log
|
|
59
|
+
});
|
|
60
|
+
progress.log(`Runtime ${runtime.name}`, "info");
|
|
61
|
+
progress.complete("runtime");
|
|
78
62
|
progress.start("simulator");
|
|
79
|
-
await
|
|
63
|
+
const simulator = await (0, _iosToolchain.ensureSimulator)({
|
|
64
|
+
runtime,
|
|
65
|
+
name: configuredSimulatorName() || undefined,
|
|
66
|
+
last: (0, _localState.getLastTarget)("ios"),
|
|
67
|
+
flags,
|
|
68
|
+
log
|
|
69
|
+
});
|
|
70
|
+
if (!simulator.created) progress.log(`Simulator "${simulator.name}" is ready`, "info");
|
|
80
71
|
progress.complete("simulator");
|
|
81
|
-
progress.
|
|
82
|
-
|
|
83
|
-
progress.complete("launch");
|
|
84
|
-
progress.start("saveConfig");
|
|
85
|
-
const config = await (0, _utils.validateAndCompleteConfig)("ios", configPath);
|
|
86
|
-
progress.complete("saveConfig");
|
|
87
|
-
progress.start("setupServer");
|
|
88
|
-
await setupServer(configPath, message => progress.log(message, "info"));
|
|
89
|
-
progress.complete("setupServer");
|
|
90
|
-
const iosCfg = config.ios || {};
|
|
91
|
-
progress.printTreeContent("Config config/config.json", [{
|
|
92
|
-
text: `port ${config.port ?? ""}`,
|
|
72
|
+
progress.printTreeContent("iOS", [{
|
|
73
|
+
text: `xcode ${developerDir}`,
|
|
93
74
|
color: "gray"
|
|
94
75
|
}, {
|
|
95
|
-
text: `
|
|
76
|
+
text: `runtime ${runtime.name}`,
|
|
96
77
|
color: "gray"
|
|
97
78
|
}, {
|
|
98
|
-
text: `
|
|
79
|
+
text: `simulator ${simulator.name}`,
|
|
99
80
|
color: "gray"
|
|
100
81
|
}]);
|
|
101
|
-
progress.summary("Ready", "Run catalyst buildApp:ios to install the app");
|
|
82
|
+
progress.summary("Ready", "Run catalyst buildApp:ios to build and install the app");
|
|
102
83
|
process.exit(0);
|
|
103
84
|
} catch (error) {
|
|
85
|
+
// A coded error (IOS-003, NATIVE-005, ...) gets the full diagnostic:
|
|
86
|
+
// code, hint and doc link. Anything else keeps the one-line failure.
|
|
87
|
+
const coded = /^[A-Z]+-\d{3}$/.test(String(error?.code || ""));
|
|
104
88
|
if (progress.currentStep) {
|
|
105
|
-
progress.fail(progress.currentStep.id, error.message);
|
|
106
|
-
}
|
|
107
|
-
progress.hint(error.hint);
|
|
108
|
-
process.exit(1);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
async function displayPaginatedList(items, startIndex) {
|
|
112
|
-
const endIndex = Math.min(startIndex + ITEMS_PER_PAGE, items.length);
|
|
113
|
-
for (let i = startIndex; i < endIndex; i++) {
|
|
114
|
-
console.log(`${i + 1}. ${items[i]}`);
|
|
115
|
-
}
|
|
116
|
-
if (endIndex < items.length) {
|
|
117
|
-
console.log(`\nShowing ${startIndex + 1}-${endIndex} of ${items.length} items`);
|
|
118
|
-
console.log('Type "more" to see more items, or enter your selection: ');
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
|
-
return false;
|
|
122
|
-
}
|
|
123
|
-
async function getRuntime() {
|
|
124
|
-
const runtimesOutput = (0, _child_process.execSync)("xcrun simctl list runtimes -j").toString();
|
|
125
|
-
const parsedRuntimes = JSON.parse(runtimesOutput).runtimes;
|
|
126
|
-
const availableRuntime = parsedRuntimes.find(runtime => runtime.isAvailable || runtime.availability === "(available)" || runtime.availability === "available");
|
|
127
|
-
if (!availableRuntime) {
|
|
128
|
-
const runningSimulators = (0, _child_process.execSync)("xcrun simctl list devices booted").toString();
|
|
129
|
-
if (runningSimulators.includes("(Booted)") && parsedRuntimes.length > 0) {
|
|
130
|
-
progress.status(`runtime ${parsedRuntimes[0].name}`);
|
|
131
|
-
return parsedRuntimes[0];
|
|
89
|
+
progress.fail(progress.currentStep.id, coded ? undefined : error.message);
|
|
132
90
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return availableRuntime;
|
|
138
|
-
}
|
|
139
|
-
async function configureSimulator(config) {
|
|
140
|
-
// If a simulator is already configured, skip the interactive picker
|
|
141
|
-
if (config.ios.simulatorName) {
|
|
142
|
-
progress.log(`Using configured simulator: ${config.ios.simulatorName}`);
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
progress.pause();
|
|
146
|
-
|
|
147
|
-
// Get the current runtime first
|
|
148
|
-
const runtime = await getRuntime();
|
|
149
|
-
|
|
150
|
-
// Get simulators specifically for this runtime
|
|
151
|
-
const simulatorsJson = JSON.parse((0, _child_process.execSync)("xcrun simctl list devices -j").toString());
|
|
152
|
-
const runtimeSimulators = simulatorsJson.devices[runtime.identifier] || [];
|
|
153
|
-
|
|
154
|
-
// Filter for available simulators only
|
|
155
|
-
const availableSimulators = runtimeSimulators.filter(sim => sim.availability === "(available)" || sim.isAvailable).map(sim => `${sim.name} (${sim.udid})`);
|
|
156
|
-
if (availableSimulators.length === 0) {
|
|
157
|
-
progress.log(`No available simulators found for runtime: ${runtime.name}`, "error");
|
|
158
|
-
progress.resume();
|
|
91
|
+
if (coded) process.stderr.write((0, _diagnostic.buildFailure)({
|
|
92
|
+
error,
|
|
93
|
+
stage: "iOS setup"
|
|
94
|
+
}));else progress.hint(error.hint);
|
|
159
95
|
process.exit(1);
|
|
160
|
-
return;
|
|
161
96
|
}
|
|
162
|
-
let startIndex = 0;
|
|
163
|
-
console.log(`\nAvailable simulators for ${runtime.name} (or type 'new' to create a new one):`);
|
|
164
|
-
|
|
165
|
-
// eslint-disable-next-line no-constant-condition
|
|
166
|
-
while (true) {
|
|
167
|
-
const hasMore = await displayPaginatedList(availableSimulators, startIndex);
|
|
168
|
-
const simulatorChoice = await (0, _utils.promptUser)(hasMore ? "" : "\nEnter selection: ");
|
|
169
|
-
if (simulatorChoice.toLowerCase() === "more" && hasMore) {
|
|
170
|
-
startIndex += ITEMS_PER_PAGE;
|
|
171
|
-
continue;
|
|
172
|
-
}
|
|
173
|
-
if (simulatorChoice.toLowerCase() === "new") {
|
|
174
|
-
const deviceTypes = JSON.parse((0, _child_process.execSync)("xcrun simctl list devicetypes --json").toString()).devicetypes;
|
|
175
|
-
const simulatorName = await (0, _utils.promptUser)("Enter a name for the new simulator: ");
|
|
176
|
-
|
|
177
|
-
// Use iPhone 15 Pro as default device type
|
|
178
|
-
const defaultDevice = deviceTypes.find(dt => dt.name.includes("iPhone 15 Pro")) || deviceTypes[0];
|
|
179
|
-
try {
|
|
180
|
-
(0, _utils.runCommand)(`xcrun simctl create "${simulatorName}" "${defaultDevice.identifier}" "${runtime.identifier}"`);
|
|
181
|
-
console.log(`Simulator "${simulatorName}" created successfully.`);
|
|
182
|
-
config.ios.simulatorName = simulatorName;
|
|
183
|
-
} catch (error) {
|
|
184
|
-
console.log(`Failed to create simulator "${simulatorName}". Error: ${error.message}`);
|
|
185
|
-
process.exit(1);
|
|
186
|
-
}
|
|
187
|
-
break;
|
|
188
|
-
} else {
|
|
189
|
-
const index = parseInt(simulatorChoice) - 1;
|
|
190
|
-
if (index >= 0 && index < availableSimulators.length) {
|
|
191
|
-
const selectedSimulator = availableSimulators[index];
|
|
192
|
-
// Extract only the simulator name without ID and state
|
|
193
|
-
const simulatorName = selectedSimulator.split(" (")[0];
|
|
194
|
-
config.ios.simulatorName = simulatorName;
|
|
195
|
-
break;
|
|
196
|
-
} else {
|
|
197
|
-
console.log("Invalid selection. Please try again.");
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
progress.resume();
|
|
202
|
-
await saveConfig({
|
|
203
|
-
WEBVIEW_CONFIG: config
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// async function createDefaultSimulator(config, runtime) {
|
|
208
|
-
// const deviceTypes = JSON.parse(execSync("xcrun simctl list devicetypes --json").toString()).devicetypes
|
|
209
|
-
// const defaultDevice = deviceTypes.find((dt) => dt.name.includes("iPhone 15 Pro")) || deviceTypes[0]
|
|
210
|
-
// const simulatorName = `Default ${defaultDevice.name.split(" (")[0]}`
|
|
211
|
-
|
|
212
|
-
// try {
|
|
213
|
-
// runCommand(
|
|
214
|
-
// `xcrun simctl create "${simulatorName}" "${defaultDevice.identifier}" "${runtime.identifier}"`
|
|
215
|
-
// )
|
|
216
|
-
// console.log(`Default simulator "${simulatorName}" created successfully.`)
|
|
217
|
-
// config.ios.simulatorName = simulatorName
|
|
218
|
-
// await saveConfig({ WEBVIEW_CONFIG: config })
|
|
219
|
-
// } catch (error) {
|
|
220
|
-
// console.log(`Failed to create default simulator. Error: ${error.message}`)
|
|
221
|
-
// process.exit(1)
|
|
222
|
-
// }
|
|
223
|
-
// }
|
|
224
|
-
|
|
225
|
-
// Xcode 27 replaced the standalone Simulator.app (com.apple.iphonesimulator)
|
|
226
|
-
// with DeviceHub.app (com.apple.dt.Devices); older Xcode installs still ship
|
|
227
|
-
// the former. Resolve whichever is actually installed instead of hardcoding
|
|
228
|
-
// the app name, which no longer resolves via `open -a` on either app.
|
|
229
|
-
function resolveSimulatorAppBundleId() {
|
|
230
|
-
const candidates = ["com.apple.dt.Devices", "com.apple.iphonesimulator"];
|
|
231
|
-
for (const bundleId of candidates) {
|
|
232
|
-
try {
|
|
233
|
-
(0, _child_process.execSync)(`osascript -e 'id of app id "${bundleId}"'`, {
|
|
234
|
-
stdio: "ignore"
|
|
235
|
-
});
|
|
236
|
-
return bundleId;
|
|
237
|
-
} catch {
|
|
238
|
-
// Not installed under this bundle id; try the next candidate.
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
return null;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// Text mirrors errors/registry.js ERROR_DEFINITIONS[IOS-001] (see
|
|
245
|
-
// errors/IOS/IOS-001.md) — this CJS subtree can't import the ESM error
|
|
246
|
-
// registry (see native/buildErrorFormat.js), so the message is duplicated
|
|
247
|
-
// here rather than imported. This condition is recoverable (the simulator
|
|
248
|
-
// can still boot headlessly via simctl) so callers log it as a warning
|
|
249
|
-
// instead of throwing.
|
|
250
|
-
const SIMULATOR_APP_NOT_FOUND_WARNING = "[IOS-001] Could not find an installed iOS Simulator app (checked DeviceHub.app and the legacy Simulator.app). " + "The simulator is booted but its window may not be visible. Suggested action: confirm a full Xcode.app is installed and selected via xcode-select -p, then open it once from Spotlight.";
|
|
251
|
-
async function launchIOSSimulator(simulatorName) {
|
|
252
|
-
progress.status("launching simulator");
|
|
253
|
-
try {
|
|
254
|
-
// Get all simulators including both available and booted ones
|
|
255
|
-
const allSimulatorInfo = (0, _child_process.execSync)("xcrun simctl list devices -j").toString();
|
|
256
|
-
const simulatorsJson = JSON.parse(allSimulatorInfo);
|
|
257
|
-
const runtimesOutput = (0, _child_process.execSync)("xcrun simctl list runtimes -j").toString();
|
|
258
|
-
const availableRuntimeIds = new Set(JSON.parse(runtimesOutput).runtimes.filter(r => r.isAvailable || r.availability === "(available)" || r.availability === "available").map(r => r.identifier));
|
|
259
|
-
|
|
260
|
-
// Search through all runtimes and their devices
|
|
261
|
-
let foundSimulator = null;
|
|
262
|
-
let foundSimulatorId = null;
|
|
263
|
-
let isBooted = false;
|
|
264
|
-
|
|
265
|
-
// Prefer devices under an available runtime; fall back to already-booted ones
|
|
266
|
-
Object.entries(simulatorsJson.devices).forEach(([runtimeId, devices]) => {
|
|
267
|
-
const isAvailableRuntime = availableRuntimeIds.has(runtimeId);
|
|
268
|
-
devices.forEach(device => {
|
|
269
|
-
if (device.name === simulatorName) {
|
|
270
|
-
const alreadyBooted = device.state === "Booted";
|
|
271
|
-
// Take this match if: no match yet, or this runtime is available and current isn't, or device is already booted
|
|
272
|
-
if (!foundSimulator || isAvailableRuntime && !foundSimulator._fromAvailableRuntime || alreadyBooted) {
|
|
273
|
-
foundSimulator = {
|
|
274
|
-
...device,
|
|
275
|
-
_fromAvailableRuntime: isAvailableRuntime
|
|
276
|
-
};
|
|
277
|
-
foundSimulatorId = device.udid;
|
|
278
|
-
isBooted = alreadyBooted;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
});
|
|
282
|
-
});
|
|
283
|
-
if (!foundSimulator) {
|
|
284
|
-
progress.log(`Configured simulator "${simulatorName}" not found`, "warning");
|
|
285
|
-
return;
|
|
286
|
-
}
|
|
287
|
-
if (!isBooted) {
|
|
288
|
-
progress.status(`booting ${simulatorName}`);
|
|
289
|
-
(0, _utils.runCommand)(`xcrun simctl boot ${foundSimulatorId}`);
|
|
290
|
-
} else {
|
|
291
|
-
progress.status("already booted");
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// Open the simulator UI (DeviceHub on Xcode 27+, Simulator.app on older Xcode) and focus it
|
|
295
|
-
const simulatorAppBundleId = resolveSimulatorAppBundleId();
|
|
296
|
-
if (simulatorAppBundleId) {
|
|
297
|
-
progress.status("opening simulator");
|
|
298
|
-
(0, _utils.runCommand)(`open -b ${simulatorAppBundleId}`);
|
|
299
|
-
|
|
300
|
-
// Give the simulator a moment to open/focus
|
|
301
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
302
|
-
|
|
303
|
-
// Activate the simulator UI window to bring it to front
|
|
304
|
-
(0, _utils.runCommand)(`osascript -e 'tell application id "${simulatorAppBundleId}" to activate'`);
|
|
305
|
-
} else {
|
|
306
|
-
progress.log(SIMULATOR_APP_NOT_FOUND_WARNING, "warning");
|
|
307
|
-
}
|
|
308
|
-
} catch (error) {
|
|
309
|
-
progress.log(`Failed to launch iOS Simulator: ${error.message}`, "error");
|
|
310
|
-
}
|
|
311
|
-
// process.exit(0);
|
|
312
97
|
}
|
|
313
|
-
|
|
314
|
-
// Execute the main setup
|
|
315
98
|
setupIOSEnvironment();
|