The set of platforms was hand-restated in three places that must agree:
the canonical tuples in src/utils/device.ts, the --platform flag's
enumValues in cli-flags.ts, and the leaf-platform validation in
client-normalizers.ts. The two non-canonical copies could drift.
- Export PLATFORMS from device.ts and add an isPlatform() leaf-platform
type guard derived from it (excludes the `apple` selector).
- Derive the --platform enumValues and usageLabel from PLATFORM_SELECTORS.
- Derive normalizeOpenDevice's leaf-platform check from isPlatform();
per-platform udid/serial identifier shaping is unchanged.
Behaviorless: the derived sets equal the previous hardcoded sets.
What
The set of supported platforms was hand-restated in three places that must agree:
src/utils/device.ts(PLATFORMS/PLATFORM_SELECTORS).--platformflag'senumValuesinsrc/utils/cli-flags.ts.normalizeOpenDeviceinsrc/client-normalizers.ts.This PR makes copies (2) and (3) derive from the canonical source so they cannot drift.
PLATFORMSfromdevice.tsand add anisPlatform()leaf-platform type guard derived from it.isPlatformaccepts exactlyPLATFORMSand rejects theappleselector (which is a routing selector, not a concrete device platform).cli-flags.ts--platform:enumValuesandusageLabelnow derive fromPLATFORM_SELECTORS(the CLI accepts the leaf platforms plus theappleselector).client-normalizers.tsnormalizeOpenDevice: the leaf-platform gate now usesisPlatform(). Per-platformudid/serialidentifier shaping is unchanged.Why
Three independent restatements of the same allow-list invite silent drift when a platform is added or renamed. Deriving the two non-canonical copies from
device.tsmakes the canonical tuples the single source of truth.Behaviorless
The derived sets are identical to the previous hardcoded sets:
--platformenumValues stay['ios','macos','android','linux','web','apple'].normalizeOpenDevicestill accepts exactly['ios','macos','android','linux','web']and rejectsapple/unknown platforms.New tests assert these memberships explicitly so the derivation is pinned.
Validation
node_modules/.bin/tsc -p tsconfig.json --noEmit(exit 0)node ./node_modules/oxfmt/bin/oxfmt --write <changed .ts files>node_modules/.bin/oxlint <changed .ts files> --deny-warnings(exit 0)node_modules/.bin/vitest run cli-flags client-normalizers args device(12 files, 197 tests passed)