( simulatorId: string | undefined, simulatorName: string | undefined, executor: CommandExecutor, )
| 167 | } |
| 168 | |
| 169 | async function inferPlatformFromSimctl( |
| 170 | simulatorId: string | undefined, |
| 171 | simulatorName: string | undefined, |
| 172 | executor: CommandExecutor, |
| 173 | ): Promise<SimulatorPlatform | null> { |
| 174 | if (!simulatorId && !simulatorName) return null; |
| 175 | |
| 176 | const result = await executor( |
| 177 | ['xcrun', 'simctl', 'list', 'devices', 'available', '--json'], |
| 178 | 'Infer Simulator Platform', |
| 179 | true, |
| 180 | ); |
| 181 | |
| 182 | if (!result.success) { |
| 183 | log('warn', `[Platform Inference] simctl failed: ${result.error ?? 'Unknown error'}`); |
| 184 | return null; |
| 185 | } |
| 186 | |
| 187 | let parsed: unknown; |
| 188 | try { |
| 189 | parsed = JSON.parse(result.output); |
| 190 | } catch { |
| 191 | log('warn', `[Platform Inference] Failed to parse simctl JSON output`); |
| 192 | return null; |
| 193 | } |
| 194 | |
| 195 | if (!parsed || typeof parsed !== 'object' || !('devices' in parsed)) { |
| 196 | log('warn', `[Platform Inference] simctl JSON missing devices`); |
| 197 | return null; |
| 198 | } |
| 199 | |
| 200 | const devices = (parsed as { devices: Record<string, unknown[]> }).devices; |
| 201 | for (const runtime of Object.keys(devices)) { |
| 202 | const list = devices[runtime]; |
| 203 | if (!Array.isArray(list)) continue; |
| 204 | |
| 205 | for (const device of list) { |
| 206 | if (!device || typeof device !== 'object') continue; |
| 207 | const current = device as { |
| 208 | udid?: unknown; |
| 209 | name?: unknown; |
| 210 | isAvailable?: unknown; |
| 211 | }; |
| 212 | |
| 213 | if (simulatorId) { |
| 214 | const matchesId = typeof current.udid === 'string' && current.udid === simulatorId; |
| 215 | if (!matchesId) continue; |
| 216 | } else { |
| 217 | const matchesName = typeof current.name === 'string' && current.name === simulatorName; |
| 218 | if (!matchesName) continue; |
| 219 | } |
| 220 | if (typeof current.isAvailable === 'boolean' && !current.isAvailable) continue; |
| 221 | |
| 222 | return inferPlatformFromRuntime(runtime); |
| 223 | } |
| 224 | } |
| 225 | |
| 226 | return null; |
no test coverage detected