mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
1de7e73e2a
* refactor(types): reuse canonical string-unions across the codebase
Replace inline duplicates of SessionSurface, ClickButton, DeviceRotation,
BackMode, ScrollDirection, Platform/PlatformSelector/DeviceTarget,
AlertAction, and LeaseBackend with imports of the existing canonical types.
Extract BackMode into a core/back-mode.ts leaf (matching click-button.ts /
session-surface.ts) to keep backend.ts dependency-clean. Add 'satisfies
readonly T[]' drift-guards to the runtime enum tuples consumed by enumField.
Pure refactor: single source of truth for these unions, no behavior change.
* refactor(types): consolidate gesture + daemon/network/metro mode unions
- Add SwipePattern to core/scroll-gesture.ts; reuse SwipePreset,
ScrollInputDirection, ScrollDirection at remaining inline sites.
- Move DaemonServerMode / DaemonTransportPreference / SessionIsolationMode /
NetworkIncludeMode to contracts.ts (the client<->daemon boundary); daemon/
config.ts and daemon/network-log.ts re-export them. Drop client-types.ts's
three private alias copies.
- Reuse MetroPrepareKind in metro.ts and remote-config-schema.ts.
- Add satisfies-guards to the runtime enum tuples.
Pure refactor, type-only changes.
* refactor(types): single-source remaining string-literal unions
- ElementSelectorKey (core/interactor-types.ts) for the 'id|label|text|value'
selector-key subset across core/daemon/ios/maestro.
- GESTURE_KINDS + GestureKind (command-catalog.ts), dropping the duplicate
GESTURE_KIND_VALUES.
- AndroidTextInputAction (android/adb-executor.ts); reuse NetworkLogBackend for
the app-log backend union.
- Reuse contracts.ts JsonRpcId / JsonRpcRequestEnvelope in mcp router + server.
- New commands/log-command-contract.ts (LOG_ACTION_VALUES + LogAction),
mirroring perf-command-contract.ts.
- Named Android snapshot helper metadata unions (transport/captureMode/install
reason) shared between helper + backend metadata.
Pure refactor, type-only changes; full unit suite green.
* refactor(types): consolidate geometry shapes
- Reuse canonical Rect (utils/snapshot.ts) for inline {x,y,width,height}
literals (parsing, output, screenshot-diff regions/ocr, atspi-bridge).
- GestureReferenceFrame (core/scroll-gesture.ts) as the single reference-frame
type; TouchReferenceFrame becomes an alias; replace inline
{referenceWidth,referenceHeight} across daemon + maestro + commands.
- New ImageDimensions (screenshot-geometry.ts) and MovementRange
(screenshot-diff-ocr.ts) for repeated {width,height} / {min,max} shapes.
- File-local AndroidRecordingSize in record-trace-android.ts.
Pure refactor, type-only changes. Point literals with normalized-vs-absolute
semantics deliberately left untouched.
* refactor(types): consolidate result/options/resolver shapes (+oxfmt)
- Generic PlatformProviderResolver<T> collapses 6 near-identical resolver
types in request-platform-providers.ts.
- Reuse canonical DaemonError (contracts.ts) / NormalizedError (utils/errors.ts)
for the inline error DTOs in daemon/types.ts and utils/output.ts.
- Single DaemonFailureResponse: FailedDaemonResponse becomes an alias and the
maestro-local redefinition is dropped.
- Extract one shared toBackendResult() into commands/runtime-types.ts, deleting
5 duplicate copies.
- Normalize whitespace with oxfmt across the touched files.
Full unit suite green.
* refactor(types): share TransformGestureParams + RepeatedInput bundles
- TransformGestureParams (core/scroll-gesture.ts) replaces 4 identical inline
transform-gesture param shapes (core interactor, dispatch, android multitouch,
client options).
- Reuse RepeatedInput (commands/command-input.ts) for the tap-modifier bundle in
PressCommandOptions and BackendTapOptions.
Pure refactor, type-only.
* refactor(types): extract BackendResultEnvelope mix-in
Replace the repeated inline { backendResult?: Record<string, unknown>;
message?: string } pair on ~17 single-object command result types with
'& BackendResultEnvelope' (commands/runtime-types.ts). Discriminated-union
variants and single-field result types are intentionally left inline.
Pure refactor, type-only changes; failing files re-verified green in isolation
(full-suite failures were flaky timeouts).
* refactor(types): dedupe runner/replay/selector/exec result shapes
- RunnerSessionOptions = AppleRunnerLifecycleOptions (field-identical).
- Reuse ReplayActionBlockInvoker for the maestro + daemon replay invoker types.
- SelectorSnapshotOptions aliases the canonical SelectorSnapshotInput; annotate
selectorSnapshotOptionsFromFlags.
- Reuse ExecResult for the { stdout; stderr; exitCode } subset in
record-trace-errors and app-log-process.
Pure refactor, type-only.
* refactor(types): make canonical tuples the single source for enum unions
Each string-enum module now exports an 'as const' literal tuple as the single
source and derives its union via (typeof TUPLE)[number]: SESSION_SURFACES,
CLICK_BUTTONS, DEVICE_ROTATIONS, BACK_MODES, SCROLL_DIRECTIONS/SWIPE_PRESETS/
SWIPE_PATTERNS, SCROLL_INPUT_DIRECTIONS, ALERT_ACTIONS, DEVICE_TARGETS. The
command metadata/input files import these tuples instead of redefining local
*_VALUES copies, which also retires 10 now-redundant 'satisfies' drift-guards.
Member order preserved everywhere (enumField error messages unchanged). Platform
tuples intentionally left as-is (command-input vs contracts use different orders).
Net -39 lines; tuple+type dual maintenance eliminated for these unions.
181 lines
4.8 KiB
TypeScript
181 lines
4.8 KiB
TypeScript
export const PUBLIC_COMMANDS = {
|
|
alert: 'alert',
|
|
appState: 'appstate',
|
|
appSwitcher: 'app-switcher',
|
|
apps: 'apps',
|
|
back: 'back',
|
|
batch: 'batch',
|
|
boot: 'boot',
|
|
click: 'click',
|
|
close: 'close',
|
|
clipboard: 'clipboard',
|
|
devices: 'devices',
|
|
diff: 'diff',
|
|
fill: 'fill',
|
|
find: 'find',
|
|
focus: 'focus',
|
|
gesture: 'gesture',
|
|
get: 'get',
|
|
home: 'home',
|
|
install: 'install',
|
|
installFromSource: 'install-from-source',
|
|
is: 'is',
|
|
keyboard: 'keyboard',
|
|
logs: 'logs',
|
|
longPress: 'longpress',
|
|
network: 'network',
|
|
open: 'open',
|
|
perf: 'perf',
|
|
prepare: 'prepare',
|
|
press: 'press',
|
|
push: 'push',
|
|
record: 'record',
|
|
reactNative: 'react-native',
|
|
reinstall: 'reinstall',
|
|
replay: 'replay',
|
|
rotate: 'rotate',
|
|
scroll: 'scroll',
|
|
screenshot: 'screenshot',
|
|
settings: 'settings',
|
|
snapshot: 'snapshot',
|
|
swipe: 'swipe',
|
|
test: 'test',
|
|
trace: 'trace',
|
|
triggerAppEvent: 'trigger-app-event',
|
|
type: 'type',
|
|
wait: 'wait',
|
|
} as const;
|
|
|
|
export const INTERNAL_COMMANDS = {
|
|
installSource: 'install_source',
|
|
leaseAllocate: 'lease_allocate',
|
|
leaseHeartbeat: 'lease_heartbeat',
|
|
leaseRelease: 'lease_release',
|
|
releaseMaterializedPaths: 'release_materialized_paths',
|
|
runtime: 'runtime',
|
|
sessionList: 'session_list',
|
|
} as const;
|
|
|
|
const LOCAL_CLI_COMMANDS = {
|
|
auth: 'auth',
|
|
connect: 'connect',
|
|
connection: 'connection',
|
|
disconnect: 'disconnect',
|
|
mcp: 'mcp',
|
|
metro: 'metro',
|
|
reactDevtools: 'react-devtools',
|
|
session: 'session',
|
|
} as const;
|
|
|
|
export const GESTURE_KINDS = ['pan', 'fling', 'swipe', 'pinch', 'rotate', 'transform'] as const;
|
|
export type GestureKind = (typeof GESTURE_KINDS)[number];
|
|
export const GESTURE_SUBCOMMAND_ERROR = `gesture requires one of: ${GESTURE_KINDS.join(', ')}`;
|
|
|
|
export type PublicCommandName = (typeof PUBLIC_COMMANDS)[keyof typeof PUBLIC_COMMANDS];
|
|
export type LocalCliCommandName = (typeof LOCAL_CLI_COMMANDS)[keyof typeof LOCAL_CLI_COMMANDS];
|
|
export type CliCommandName = PublicCommandName | LocalCliCommandName;
|
|
export type ClientBackedCliCommandName =
|
|
| PublicCommandName
|
|
| typeof LOCAL_CLI_COMMANDS.metro
|
|
| typeof LOCAL_CLI_COMMANDS.session;
|
|
|
|
export const BATCH_COMMAND_NAMES = [
|
|
PUBLIC_COMMANDS.devices,
|
|
PUBLIC_COMMANDS.boot,
|
|
PUBLIC_COMMANDS.apps,
|
|
PUBLIC_COMMANDS.open,
|
|
PUBLIC_COMMANDS.close,
|
|
PUBLIC_COMMANDS.install,
|
|
PUBLIC_COMMANDS.reinstall,
|
|
PUBLIC_COMMANDS.installFromSource,
|
|
PUBLIC_COMMANDS.push,
|
|
PUBLIC_COMMANDS.triggerAppEvent,
|
|
PUBLIC_COMMANDS.snapshot,
|
|
PUBLIC_COMMANDS.screenshot,
|
|
PUBLIC_COMMANDS.diff,
|
|
PUBLIC_COMMANDS.wait,
|
|
PUBLIC_COMMANDS.alert,
|
|
PUBLIC_COMMANDS.settings,
|
|
PUBLIC_COMMANDS.click,
|
|
PUBLIC_COMMANDS.press,
|
|
PUBLIC_COMMANDS.longPress,
|
|
PUBLIC_COMMANDS.swipe,
|
|
PUBLIC_COMMANDS.focus,
|
|
PUBLIC_COMMANDS.type,
|
|
PUBLIC_COMMANDS.fill,
|
|
PUBLIC_COMMANDS.scroll,
|
|
PUBLIC_COMMANDS.get,
|
|
PUBLIC_COMMANDS.gesture,
|
|
PUBLIC_COMMANDS.is,
|
|
PUBLIC_COMMANDS.find,
|
|
PUBLIC_COMMANDS.perf,
|
|
PUBLIC_COMMANDS.logs,
|
|
PUBLIC_COMMANDS.network,
|
|
PUBLIC_COMMANDS.record,
|
|
PUBLIC_COMMANDS.trace,
|
|
PUBLIC_COMMANDS.test,
|
|
PUBLIC_COMMANDS.appState,
|
|
PUBLIC_COMMANDS.back,
|
|
PUBLIC_COMMANDS.home,
|
|
PUBLIC_COMMANDS.rotate,
|
|
PUBLIC_COMMANDS.appSwitcher,
|
|
PUBLIC_COMMANDS.keyboard,
|
|
PUBLIC_COMMANDS.clipboard,
|
|
PUBLIC_COMMANDS.reactNative,
|
|
] as const;
|
|
|
|
const MCP_UNEXPOSED_CLI_COMMANDS = commandSet(
|
|
LOCAL_CLI_COMMANDS.auth,
|
|
LOCAL_CLI_COMMANDS.connect,
|
|
LOCAL_CLI_COMMANDS.connection,
|
|
LOCAL_CLI_COMMANDS.disconnect,
|
|
LOCAL_CLI_COMMANDS.mcp,
|
|
LOCAL_CLI_COMMANDS.reactDevtools,
|
|
PUBLIC_COMMANDS.prepare,
|
|
);
|
|
|
|
const CAPABILITY_EXEMPT_CLI_COMMANDS = commandSet(
|
|
LOCAL_CLI_COMMANDS.auth,
|
|
LOCAL_CLI_COMMANDS.connect,
|
|
LOCAL_CLI_COMMANDS.connection,
|
|
LOCAL_CLI_COMMANDS.disconnect,
|
|
LOCAL_CLI_COMMANDS.mcp,
|
|
LOCAL_CLI_COMMANDS.metro,
|
|
LOCAL_CLI_COMMANDS.reactDevtools,
|
|
LOCAL_CLI_COMMANDS.session,
|
|
PUBLIC_COMMANDS.appState,
|
|
PUBLIC_COMMANDS.prepare,
|
|
PUBLIC_COMMANDS.batch,
|
|
PUBLIC_COMMANDS.devices,
|
|
PUBLIC_COMMANDS.gesture,
|
|
PUBLIC_COMMANDS.replay,
|
|
PUBLIC_COMMANDS.test,
|
|
PUBLIC_COMMANDS.trace,
|
|
);
|
|
|
|
function commandSet(...commands: readonly string[]): ReadonlySet<string> {
|
|
return new Set(commands);
|
|
}
|
|
|
|
export function listCliCommandNames(): CliCommandName[] {
|
|
return [...Object.values(PUBLIC_COMMANDS), ...Object.values(LOCAL_CLI_COMMANDS)].sort();
|
|
}
|
|
|
|
export function isClientBackedCliCommandName(
|
|
command: string,
|
|
): command is ClientBackedCliCommandName {
|
|
return (
|
|
Object.values(PUBLIC_COMMANDS).includes(command as PublicCommandName) ||
|
|
command === LOCAL_CLI_COMMANDS.metro ||
|
|
command === LOCAL_CLI_COMMANDS.session
|
|
);
|
|
}
|
|
|
|
export function listMcpExposedCommandNames(): CliCommandName[] {
|
|
return listCliCommandNames().filter((command) => !MCP_UNEXPOSED_CLI_COMMANDS.has(command));
|
|
}
|
|
|
|
export function listCapabilityCheckedCommandNames(): CliCommandName[] {
|
|
return listCliCommandNames().filter((command) => !CAPABILITY_EXEMPT_CLI_COMMANDS.has(command));
|
|
}
|