|
1 | 1 | import { isIosFamily, type DeviceInfo } from '@agent-device/kernel/device'; |
2 | 2 | import { type ExecOptions, type ExecResult } from '@agent-device/host-kit/command'; |
3 | 3 | import { resolveIosSimulatorDeviceSetPath } from '@agent-device/kernel/device-isolation'; |
| 4 | +import type { ScopedSimctlArgs } from '@agent-device/contracts/platform-runtime-host'; |
4 | 5 | import { runXcrun } from './tool-provider.ts'; |
5 | 6 |
|
6 | | -type SimctlArgsOptions = { |
7 | | - simulatorSetPath?: string; |
| 7 | +/** The set of a simctl call that names no device; `undefined` names the default set on purpose. */ |
| 8 | +export type SimulatorSetScope = Readonly<{ simulatorSetPath: string | undefined }>; |
| 9 | + |
| 10 | +declare const simulatorAddress: unique symbol; |
| 11 | +/** A simulator udid with the set that holds it; minted only from a DeviceInfo. */ |
| 12 | +export type SimulatorAddress = Readonly<{ udid: string; simulatorSetPath: string | undefined }> & { |
| 13 | + readonly [simulatorAddress]: true; |
8 | 14 | }; |
9 | 15 |
|
10 | | -/** Arguments that follow the `simctl` tool name, scoped to the simulator set when one is given. */ |
| 16 | +export function simulatorAddressFor(device: DeviceInfo): SimulatorAddress { |
| 17 | + const simulatorSetPath = |
| 18 | + isIosFamily(device) && device.kind === 'simulator' ? device.simulatorSetPath : undefined; |
| 19 | + return Object.freeze({ udid: device.id, simulatorSetPath }) as SimulatorAddress; |
| 20 | +} |
| 21 | + |
| 22 | +/** Arguments that follow the `simctl` tool name for a call that names no device. */ |
11 | 23 | export function scopeSimctlArgs( |
12 | 24 | args: readonly string[], |
13 | | - options: SimctlArgsOptions = {}, |
14 | | -): string[] { |
15 | | - const simulatorSetPath = resolveIosSimulatorDeviceSetPath(options.simulatorSetPath); |
16 | | - if (!simulatorSetPath) return [...args]; |
17 | | - return ['--set', simulatorSetPath, ...args]; |
| 25 | + scope: SimulatorSetScope, |
| 26 | +): ScopedSimctlArgs { |
| 27 | + const simulatorSetPath = resolveIosSimulatorDeviceSetPath(scope.simulatorSetPath); |
| 28 | + const scoped = simulatorSetPath ? ['--set', simulatorSetPath, ...args] : [...args]; |
| 29 | + return Object.freeze(scoped) as ScopedSimctlArgs; |
| 30 | +} |
| 31 | + |
| 32 | +/** Arguments that follow the `simctl` tool name, scoped to the set holding the addressed simulator. */ |
| 33 | +export function scopeSimctlArgsForAddress( |
| 34 | + address: SimulatorAddress, |
| 35 | + args: readonly string[], |
| 36 | +): ScopedSimctlArgs { |
| 37 | + return scopeSimctlArgs(args, { simulatorSetPath: address.simulatorSetPath }); |
18 | 38 | } |
19 | 39 |
|
20 | 40 | /** Arguments that follow the `simctl` tool name, scoped to the simulator set holding the device. */ |
21 | | -export function scopeSimctlArgsForDevice(device: DeviceInfo, args: readonly string[]): string[] { |
22 | | - if (!isIosFamily(device) || device.kind !== 'simulator') return [...args]; |
23 | | - return scopeSimctlArgs(args, { simulatorSetPath: device.simulatorSetPath }); |
| 41 | +export function scopeSimctlArgsForDevice( |
| 42 | + device: DeviceInfo, |
| 43 | + args: readonly string[], |
| 44 | +): ScopedSimctlArgs { |
| 45 | + return scopeSimctlArgsForAddress(simulatorAddressFor(device), args); |
24 | 46 | } |
25 | 47 |
|
26 | | -export function buildSimctlArgs( |
| 48 | +export function buildSimctlArgsForAddress( |
| 49 | + address: SimulatorAddress, |
27 | 50 | args: readonly string[], |
28 | | - options: SimctlArgsOptions = {}, |
29 | 51 | ): string[] { |
30 | | - return ['simctl', ...scopeSimctlArgs(args, options)]; |
| 52 | + return ['simctl', ...scopeSimctlArgsForAddress(address, args)]; |
31 | 53 | } |
32 | 54 |
|
33 | 55 | export function buildSimctlArgsForDevice(device: DeviceInfo, args: readonly string[]): string[] { |
|
0 commit comments