Skip to content

Commit 2b8f633

Browse files
committed
refactor: simplify CLI and daemon facades
1 parent 3482627 commit 2b8f633

21 files changed

Lines changed: 761 additions & 787 deletions

src/cli/commands/devices.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
import { printJson } from '../../utils/output.ts';
21
import { serializeDevice } from '../../cli-serializers.ts';
32
import type { AgentDeviceDevice } from '../../client.ts';
4-
import { buildSelectionOptions } from './shared.ts';
3+
import { buildSelectionOptions, writeCommandOutput } from './shared.ts';
54
import type { ClientCommandHandler } from './router.ts';
65

76
export const devicesCommand: ClientCommandHandler = async ({ flags, client }) => {
87
const devices = await client.devices.list(buildSelectionOptions(flags));
98
const data = { devices: devices.map(serializeDevice) };
10-
if (flags.json) printJson({ success: true, data });
11-
else process.stdout.write(`${devices.map(formatDeviceLine).join('\n')}\n`);
9+
writeCommandOutput(flags, data, () => devices.map(formatDeviceLine).join('\n'));
1210
return true;
1311
};
1412

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { printJson } from '../../utils/output.ts';
21
import { AppError } from '../../utils/errors.ts';
32
import { serializeEnsureSimulatorResult } from '../../cli-serializers.ts';
3+
import { writeCommandOutput } from './shared.ts';
44
import type { ClientCommandHandler } from './router.ts';
55

66
export const ensureSimulatorCommand: ClientCommandHandler = async ({ flags, client }) => {
@@ -15,13 +15,12 @@ export const ensureSimulatorCommand: ClientCommandHandler = async ({ flags, clie
1515
iosSimulatorDeviceSet: flags.iosSimulatorDeviceSet,
1616
});
1717
const data = serializeEnsureSimulatorResult(result);
18-
if (flags.json) {
19-
printJson({ success: true, data });
20-
} else {
18+
writeCommandOutput(flags, data, () => {
2119
const action = result.created ? 'Created' : 'Reused';
2220
const bootedSuffix = result.booted ? ' (booted)' : '';
23-
process.stdout.write(`${action}: ${result.device} ${result.udid}${bootedSuffix}\n`);
24-
if (result.runtime) process.stdout.write(`Runtime: ${result.runtime}\n`);
25-
}
21+
return result.runtime
22+
? `${action}: ${result.device} ${result.udid}${bootedSuffix}\nRuntime: ${result.runtime}`
23+
: `${action}: ${result.device} ${result.udid}${bootedSuffix}`;
24+
});
2625
return true;
2726
};

src/cli/commands/install.ts

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,21 @@
1-
import { printJson } from '../../utils/output.ts';
21
import { AppError } from '../../utils/errors.ts';
3-
import {
4-
serializeDeployResult,
5-
serializeInstallFromSourceResult,
6-
} from '../../cli-serializers.ts';
7-
import { readCommandMessage } from '../../utils/success-text.ts';
2+
import { serializeDeployResult, serializeInstallFromSourceResult } from '../../cli-serializers.ts';
83
import type { CliFlags } from '../../utils/command-schema.ts';
94
import type { AgentDeviceClient, AppDeployResult } from '../../client.ts';
10-
import { buildSelectionOptions } from './shared.ts';
5+
import { buildSelectionOptions, writeCommandMessage } from './shared.ts';
116
import type { ClientCommandHandler } from './router.ts';
127

138
export const installCommand: ClientCommandHandler = async ({ positionals, flags, client }) => {
149
const result = await runDeployCommand('install', positionals, flags, client);
1510
const data = serializeDeployResult(result);
16-
if (flags.json) printJson({ success: true, data });
17-
else writeHumanMessage(data);
11+
writeCommandMessage(flags, data);
1812
return true;
1913
};
2014

2115
export const reinstallCommand: ClientCommandHandler = async ({ positionals, flags, client }) => {
2216
const result = await runDeployCommand('reinstall', positionals, flags, client);
2317
const data = serializeDeployResult(result);
24-
if (flags.json) printJson({ success: true, data });
25-
else writeHumanMessage(data);
18+
writeCommandMessage(flags, data);
2619
return true;
2720
};
2821

@@ -33,16 +26,10 @@ export const installFromSourceCommand: ClientCommandHandler = async ({
3326
}) => {
3427
const result = await runInstallFromSourceCommand(positionals, flags, client);
3528
const data = serializeInstallFromSourceResult(result);
36-
if (flags.json) printJson({ success: true, data });
37-
else writeHumanMessage(data);
29+
writeCommandMessage(flags, data);
3830
return true;
3931
};
4032

41-
function writeHumanMessage(data: Record<string, unknown>): void {
42-
const message = readCommandMessage(data);
43-
if (message) process.stdout.write(`${message}\n`);
44-
}
45-
4633
async function runDeployCommand(
4734
command: 'install' | 'reinstall',
4835
positionals: string[],

src/cli/commands/metro.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import { printJson } from '../../utils/output.ts';
21
import { AppError } from '../../utils/errors.ts';
3-
import type { CliFlags } from '../../utils/command-schema.ts';
2+
import { writeCommandOutput } from './shared.ts';
43
import type { ClientCommandHandler } from './router.ts';
54

65
export const metroCommand: ClientCommandHandler = async ({ positionals, flags, client }) => {
@@ -28,14 +27,6 @@ export const metroCommand: ClientCommandHandler = async ({ positionals, flags, c
2827
runtimeFilePath: flags.metroRuntimeFile,
2928
});
3029

31-
writeMetroPrepareResult(result, flags);
30+
writeCommandOutput(flags, result, () => JSON.stringify(result, null, 2));
3231
return true;
3332
};
34-
35-
function writeMetroPrepareResult(result: unknown, flags: CliFlags): void {
36-
if (flags.json) {
37-
printJson({ success: true, data: result });
38-
} else {
39-
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
40-
}
41-
}

src/cli/commands/open.ts

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
import { printJson } from '../../utils/output.ts';
21
import { serializeCloseResult, serializeOpenResult } from '../../cli-serializers.ts';
32
import { resolveRemoteOpenRuntime } from '../../core/remote-open.ts';
4-
import { readCommandMessage } from '../../utils/success-text.ts';
5-
import { buildSelectionOptions } from './shared.ts';
3+
import { buildSelectionOptions, writeCommandMessage } from './shared.ts';
64
import type { ClientCommandHandler } from './router.ts';
75

86
export const openCommand: ClientCommandHandler = async ({ positionals, flags, client }) => {
@@ -13,6 +11,7 @@ export const openCommand: ClientCommandHandler = async ({ positionals, flags, cl
1311
const result = await client.apps.open({
1412
app: positionals[0],
1513
url: positionals[1],
14+
surface: flags.surface,
1615
activity: flags.activity,
1716
relaunch: flags.relaunch,
1817
saveScript: flags.saveScript,
@@ -21,11 +20,7 @@ export const openCommand: ClientCommandHandler = async ({ positionals, flags, cl
2120
...buildSelectionOptions(flags),
2221
});
2322
const data = serializeOpenResult(result);
24-
if (flags.json) printJson({ success: true, data });
25-
else {
26-
const successText = readCommandMessage(data);
27-
if (successText) process.stdout.write(`${successText}\n`);
28-
}
23+
writeCommandMessage(flags, data);
2924
return true;
3025
};
3126

@@ -34,11 +29,6 @@ export const closeCommand: ClientCommandHandler = async ({ positionals, flags, c
3429
? await client.apps.close({ app: positionals[0], shutdown: flags.shutdown })
3530
: await client.sessions.close({ shutdown: flags.shutdown });
3631
const data = serializeCloseResult(result);
37-
if (flags.json) {
38-
printJson({ success: true, data });
39-
} else {
40-
const successText = readCommandMessage(data);
41-
if (successText) process.stdout.write(`${successText}\n`);
42-
}
32+
writeCommandMessage(flags, data);
4333
return true;
4434
};

src/cli/commands/screenshot.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import fs from 'node:fs';
22
import os from 'node:os';
33
import path from 'node:path';
4-
import { formatScreenshotDiffText, printJson } from '../../utils/output.ts';
4+
import { formatScreenshotDiffText } from '../../utils/output.ts';
55
import { AppError } from '../../utils/errors.ts';
66
import { compareScreenshots, type ScreenshotDiffResult } from '../../utils/screenshot-diff.ts';
77
import { resolveUserPath } from '../../utils/path-resolution.ts';
8+
import { writeCommandOutput } from './shared.ts';
89
import type { ClientCommandHandler } from './router.ts';
910

1011
export const screenshotCommand: ClientCommandHandler = async ({ positionals, flags, client }) => {
@@ -16,12 +17,11 @@ export const screenshotCommand: ClientCommandHandler = async ({ positionals, fla
1617
path: result.path,
1718
...(result.overlayRefs ? { overlayRefs: result.overlayRefs } : {}),
1819
};
19-
if (flags.json) printJson({ success: true, data });
20-
else if (result.overlayRefs) {
21-
process.stdout.write(`Annotated ${result.overlayRefs.length} refs onto ${result.path}\n`);
22-
} else {
23-
process.stdout.write(`${result.path}\n`);
24-
}
20+
writeCommandOutput(flags, data, () =>
21+
result.overlayRefs
22+
? `Annotated ${result.overlayRefs.length} refs onto ${result.path}`
23+
: result.path,
24+
);
2525
return true;
2626
};
2727

@@ -64,10 +64,6 @@ export const diffCommand: ClientCommandHandler = async ({ positionals, flags, cl
6464
} catch {}
6565
}
6666

67-
if (flags.json) {
68-
printJson({ success: true, data: result });
69-
} else {
70-
process.stdout.write(formatScreenshotDiffText(result));
71-
}
67+
writeCommandOutput(flags, result, () => formatScreenshotDiffText(result));
7268
return true;
7369
};

src/cli/commands/session.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { printJson } from '../../utils/output.ts';
21
import { AppError } from '../../utils/errors.ts';
32
import { serializeSessionListEntry } from '../../cli-serializers.ts';
3+
import { writeCommandOutput } from './shared.ts';
44
import type { ClientCommandHandler } from './router.ts';
55

66
export const sessionCommand: ClientCommandHandler = async ({ positionals, flags, client }) => {
@@ -10,7 +10,6 @@ export const sessionCommand: ClientCommandHandler = async ({ positionals, flags,
1010
}
1111
const sessions = await client.sessions.list();
1212
const data = { sessions: sessions.map(serializeSessionListEntry) };
13-
if (flags.json) printJson({ success: true, data });
14-
else process.stdout.write(`${JSON.stringify(data, null, 2)}\n`);
13+
writeCommandOutput(flags, data, () => JSON.stringify(data, null, 2));
1514
return true;
1615
};

src/cli/commands/shared.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import type { CliFlags } from '../../utils/command-schema.ts';
2+
import { printJson } from '../../utils/output.ts';
3+
import { readCommandMessage } from '../../utils/success-text.ts';
24

35
export function buildSelectionOptions(flags: CliFlags): {
46
platform?: CliFlags['platform'];
@@ -19,3 +21,24 @@ export function buildSelectionOptions(flags: CliFlags): {
1921
androidDeviceAllowlist: flags.androidDeviceAllowlist,
2022
};
2123
}
24+
25+
export function writeCommandOutput(
26+
flags: CliFlags,
27+
data: unknown,
28+
renderHuman?: () => string | null | undefined,
29+
): void {
30+
if (flags.json) {
31+
printJson({ success: true, data });
32+
return;
33+
}
34+
const text = renderHuman?.();
35+
if (text) writeLine(text);
36+
}
37+
38+
export function writeCommandMessage(flags: CliFlags, data: Record<string, unknown>): void {
39+
writeCommandOutput(flags, data, () => readCommandMessage(data));
40+
}
41+
42+
function writeLine(text: string): void {
43+
process.stdout.write(text.endsWith('\n') ? text : `${text}\n`);
44+
}

src/cli/commands/snapshot.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { formatSnapshotText, printJson } from '../../utils/output.ts';
1+
import { formatSnapshotText } from '../../utils/output.ts';
22
import { serializeSnapshotResult } from '../../cli-serializers.ts';
3-
import { buildSelectionOptions } from './shared.ts';
3+
import { buildSelectionOptions, writeCommandOutput } from './shared.ts';
44
import type { ClientCommandHandler } from './router.ts';
55

66
export const snapshotCommand: ClientCommandHandler = async ({ flags, client }) => {
@@ -13,15 +13,11 @@ export const snapshotCommand: ClientCommandHandler = async ({ flags, client }) =
1313
raw: flags.snapshotRaw,
1414
});
1515
const data = serializeSnapshotResult(result);
16-
if (flags.json) {
17-
printJson({ success: true, data });
18-
} else {
19-
process.stdout.write(
20-
formatSnapshotText(data, {
21-
raw: flags.snapshotRaw,
22-
flatten: flags.snapshotInteractiveOnly,
23-
}),
24-
);
25-
}
16+
writeCommandOutput(flags, data, () =>
17+
formatSnapshotText(data, {
18+
raw: flags.snapshotRaw,
19+
flatten: flags.snapshotInteractiveOnly,
20+
}),
21+
);
2622
return true;
2723
};

src/core/dispatch.ts

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { runIosRunnerCommand } from '../platforms/ios/runner-client.ts';
1414
import {
1515
runMacOsPressAction,
1616
runMacOsReadTextAction,
17-
runMacOsScreenshotAction,
1817
} from '../platforms/ios/macos-helper.ts';
1918
import { pushIosNotification } from '../platforms/ios/index.ts';
2019
import type { SessionSurface } from './session-surface.ts';
@@ -493,18 +492,11 @@ export async function dispatchCommand(
493492
const positionalPath = positionals[0];
494493
const screenshotPath = positionalPath ?? outPath ?? `./screenshot-${Date.now()}.png`;
495494
await fs.mkdir(pathModule.dirname(screenshotPath), { recursive: true });
496-
if (device.platform === 'macos' && context?.surface && context.surface !== 'app') {
497-
await runMacOsScreenshotAction(screenshotPath, {
498-
surface: context.surface,
499-
fullscreen: context.screenshotFullscreen,
500-
});
501-
} else {
502-
await interactor.screenshot(
503-
screenshotPath,
504-
context?.appBundleId,
505-
context?.screenshotFullscreen,
506-
);
507-
}
495+
await interactor.screenshot(screenshotPath, {
496+
appBundleId: context?.appBundleId,
497+
fullscreen: context?.screenshotFullscreen,
498+
surface: context?.surface,
499+
});
508500
return { path: screenshotPath, ...successText(`Saved screenshot: ${screenshotPath}`) };
509501
}
510502
case 'back': {

0 commit comments

Comments
 (0)