xref: /expo/tools/src/IOSSimulator.ts (revision a272999e)
1*a272999eSBartosz Kaszubowskiimport spawnAsync from '@expo/spawn-async';
2eeffdb10STomasz Sapetaimport { spawn } from 'child_process';
3eeffdb10STomasz Sapetaimport { Transform, TransformCallback, TransformOptions } from 'stream';
4eeffdb10STomasz Sapeta
5eeffdb10STomasz Sapeta/**
6eeffdb10STomasz Sapeta * Starts an arbitrary iOS simulator so that simctl can reference a "booted" simulator.
7eeffdb10STomasz Sapeta */
8eeffdb10STomasz Sapetaexport async function startSimulatorAsync(): Promise<void> {
9eeffdb10STomasz Sapeta  try {
10eeffdb10STomasz Sapeta    await spawnAsync('xcrun', ['instruments', '-w', 'iPhone X (11.2) [']);
11eeffdb10STomasz Sapeta  } catch (e) {
12eeffdb10STomasz Sapeta    // Instruments exits with an expected error
13eeffdb10STomasz Sapeta    if (!e.stderr.includes('Instruments Usage Error')) {
14eeffdb10STomasz Sapeta      throw e;
15eeffdb10STomasz Sapeta    }
16eeffdb10STomasz Sapeta  }
17eeffdb10STomasz Sapeta}
18eeffdb10STomasz Sapeta
19eeffdb10STomasz Sapetaexport async function installSimulatorAppAsync(
20eeffdb10STomasz Sapeta  simulatorId: string,
21eeffdb10STomasz Sapeta  archivePath: string
22eeffdb10STomasz Sapeta): Promise<void> {
23eeffdb10STomasz Sapeta  try {
24eeffdb10STomasz Sapeta    await spawnAsync('xcrun', ['simctl', 'install', simulatorId, archivePath]);
25eeffdb10STomasz Sapeta  } catch (e) {
26*a272999eSBartosz Kaszubowski    const error = new Error(e.stderr);
27eeffdb10STomasz Sapeta    (error as any).status = e.status;
28eeffdb10STomasz Sapeta    throw error;
29eeffdb10STomasz Sapeta  }
30eeffdb10STomasz Sapeta}
31eeffdb10STomasz Sapeta
32eeffdb10STomasz Sapetaexport async function launchSimulatorAppAsync(
33eeffdb10STomasz Sapeta  simulatorId: string,
34eeffdb10STomasz Sapeta  bundleIdentifier: string
35eeffdb10STomasz Sapeta): Promise<void> {
36eeffdb10STomasz Sapeta  try {
37eeffdb10STomasz Sapeta    await spawnAsync('xcrun', ['simctl', 'launch', simulatorId, bundleIdentifier]);
38eeffdb10STomasz Sapeta  } catch (e) {
39*a272999eSBartosz Kaszubowski    const error = new Error(e.stderr);
40eeffdb10STomasz Sapeta    (error as any).status = e.status;
41eeffdb10STomasz Sapeta    throw error;
42eeffdb10STomasz Sapeta  }
43eeffdb10STomasz Sapeta}
44eeffdb10STomasz Sapeta
45eeffdb10STomasz Sapetaexport function getSimulatorLogProcess(simulatorId: string, predicate?: string) {
46eeffdb10STomasz Sapeta  return spawn(
47eeffdb10STomasz Sapeta    'xcrun',
48eeffdb10STomasz Sapeta    [
49eeffdb10STomasz Sapeta      'simctl',
50eeffdb10STomasz Sapeta      'spawn',
51eeffdb10STomasz Sapeta      simulatorId,
52eeffdb10STomasz Sapeta      'log',
53eeffdb10STomasz Sapeta      'stream',
54eeffdb10STomasz Sapeta      '--style',
55eeffdb10STomasz Sapeta      'json',
56eeffdb10STomasz Sapeta      ...(predicate ? ['--predicate', predicate] : []),
57eeffdb10STomasz Sapeta    ],
58eeffdb10STomasz Sapeta    {
59eeffdb10STomasz Sapeta      stdio: ['ignore', 'pipe', 'inherit'],
60eeffdb10STomasz Sapeta    }
61eeffdb10STomasz Sapeta  );
62eeffdb10STomasz Sapeta}
63eeffdb10STomasz Sapeta
64eeffdb10STomasz Sapetaexport class IOSLogStream extends Transform {
65eeffdb10STomasz Sapeta  constructor(options?: TransformOptions) {
66eeffdb10STomasz Sapeta    super({ ...options, objectMode: true });
67eeffdb10STomasz Sapeta  }
68eeffdb10STomasz Sapeta
69eeffdb10STomasz Sapeta  _transform(data: Buffer, encoding: string, callback: TransformCallback): void {
70eeffdb10STomasz Sapeta    // In practice, we receive each log entry as a separate chunk and can test if they are valid,
71eeffdb10STomasz Sapeta    // JSON-formatted log entries
72eeffdb10STomasz Sapeta    let entry;
73eeffdb10STomasz Sapeta    try {
74eeffdb10STomasz Sapeta      entry = JSON.parse(data.toString('utf8'));
75*a272999eSBartosz Kaszubowski    } catch {}
76eeffdb10STomasz Sapeta
77eeffdb10STomasz Sapeta    if (entry?.eventMessage) {
78eeffdb10STomasz Sapeta      this.push(entry);
79eeffdb10STomasz Sapeta    }
80eeffdb10STomasz Sapeta    callback();
81eeffdb10STomasz Sapeta  }
82eeffdb10STomasz Sapeta}
83