@@ -64,7 +64,7 @@ type TypedMaestroReplayState = {
6464type TypedMaestroReplayContext = {
6565 filePath : string ;
6666 program : MaestroProgram ;
67- device : DeviceInfo ;
67+ device ? : DeviceInfo ;
6868 platform : Extract < MaestroPlatform , 'android' | 'ios' > ;
6969 target : string ;
7070 runtimeHints : ReturnType < typeof resolveEffectiveOpenRuntimeHints > ;
@@ -74,6 +74,11 @@ type TypedMaestroReplayContext = {
7474 loadProgram : ReturnType < typeof createMaestroProgramLoader > ;
7575} ;
7676
77+ type MaestroReplayBinding = Pick <
78+ TypedMaestroReplayContext ,
79+ 'device' | 'platform' | 'target' | 'runtimeHints'
80+ > ;
81+
7782export async function runTypedMaestroReplayFile (
7883 params : TypedMaestroReplayParams ,
7984) : Promise < DaemonResponse > {
@@ -177,36 +182,89 @@ async function prepareTypedMaestroReplay(
177182 } ) ;
178183 const session = sessionStore . get ( sessionName ) ;
179184 if ( session ) assertSessionSelectorMatches ( session , req . flags ) ;
180- const device = session ?. device ?? ( await resolveTargetDevice ( req . flags ?? { } ) ) ;
185+ const binding = await resolveMaestroReplayBinding ( { req, sessionStore, sessionName, session } ) ;
186+ return {
187+ filePath,
188+ program,
189+ ...binding ,
190+ defaults : buildTypedMaestroDefaults ( {
191+ req,
192+ sessionName,
193+ filePath,
194+ platform : binding . platform ,
195+ target : binding . target ,
196+ } ) ,
197+ env : buildTypedMaestroEnv ( req ) ,
198+ signal : getRequestSignal ( req . meta ?. requestId ) ,
199+ loadProgram : createMaestroProgramLoader ( path . dirname ( filePath ) ) ,
200+ } ;
201+ }
202+
203+ async function resolveMaestroReplayBinding ( params : {
204+ req : DaemonRequest ;
205+ sessionStore : SessionStore ;
206+ sessionName : string ;
207+ session : ReturnType < SessionStore [ 'get' ] > ;
208+ } ) : Promise < MaestroReplayBinding > {
209+ const { req, sessionStore, sessionName, session } = params ;
210+ const requestedPlatform = req . flags ?. platform ;
211+ const device =
212+ session ?. device ??
213+ ( requestedPlatform === 'android' || requestedPlatform === 'ios'
214+ ? undefined
215+ : await resolveTargetDevice ( req . flags ?? { } ) ) ;
181216 const platform = resolveMaestroPlatform ( req , device ) ;
182- const target = resolveMaestroTarget ( req , device ) ;
183217 const runtimeHints = resolveEffectiveOpenRuntimeHints ( {
184218 req,
185219 sessionStore,
186220 sessionName,
187221 device,
188222 platform,
189223 } ) ;
190- return {
191- filePath,
192- program,
224+ return await completeMaestroRuntimeBinding ( {
225+ req,
226+ sessionStore,
227+ sessionName,
193228 device,
194229 platform,
195- target,
230+ target : resolveMaestroTarget ( req , device ) ,
196231 runtimeHints,
197- defaults : buildTypedMaestroDefaults ( {
198- req,
199- sessionName,
200- filePath,
201- platform,
202- target,
232+ } ) ;
233+ }
234+
235+ async function completeMaestroRuntimeBinding (
236+ params : {
237+ req : DaemonRequest ;
238+ sessionStore : SessionStore ;
239+ sessionName : string ;
240+ } & MaestroReplayBinding ,
241+ ) : Promise < MaestroReplayBinding > {
242+ if ( params . device || ! requiresDeviceRuntimeDefaults ( params . runtimeHints ) ) return params ;
243+ const device = await resolveTargetDevice ( params . req . flags ?? { } ) ;
244+ return {
245+ device,
246+ platform : params . platform ,
247+ target : resolveMaestroTarget ( params . req , device ) ,
248+ runtimeHints : resolveEffectiveOpenRuntimeHints ( {
249+ req : params . req ,
250+ sessionStore : params . sessionStore ,
251+ sessionName : params . sessionName ,
252+ device,
253+ platform : params . platform ,
203254 } ) ,
204- env : buildTypedMaestroEnv ( req ) ,
205- signal : getRequestSignal ( req . meta ?. requestId ) ,
206- loadProgram : createMaestroProgramLoader ( path . dirname ( filePath ) ) ,
207255 } ;
208256}
209257
258+ function requiresDeviceRuntimeDefaults (
259+ runtimeHints : ReturnType < typeof resolveEffectiveOpenRuntimeHints > ,
260+ ) : boolean {
261+ return (
262+ runtimeHints ?. metroPort !== undefined &&
263+ runtimeHints . metroHost === undefined &&
264+ runtimeHints . bundleUrl === undefined
265+ ) ;
266+ }
267+
210268function buildTypedMaestroDefaults ( params : {
211269 req : DaemonRequest ;
212270 sessionName : string ;
@@ -239,7 +297,7 @@ function createMaestroReplayPort(params: {
239297 logPath : string ;
240298 sessionName : string ;
241299 sessionStore : SessionStore ;
242- device : DeviceInfo ;
300+ device : DeviceInfo | undefined ;
243301 platform : Extract < MaestroPlatform , 'android' | 'ios' > ;
244302 runtimeHints : ReturnType < typeof resolveEffectiveOpenRuntimeHints > ;
245303 sourcePath : string ;
@@ -264,7 +322,7 @@ function createMaestroReplayPort(params: {
264322 } = req ;
265323 const baseReq = {
266324 ...requestBase ,
267- flags : maestroRuntimeDeviceFlags ( device , platform ) ,
325+ flags : maestroRuntimeDeviceFlags ( device , platform , req . flags ) ,
268326 ...( runtimeHints === undefined ? { } : { runtime : runtimeHints } ) ,
269327 } ;
270328 return createDaemonMaestroRuntimePort ( {
@@ -292,9 +350,11 @@ function createMaestroReplayPort(params: {
292350}
293351
294352function maestroRuntimeDeviceFlags (
295- device : DeviceInfo ,
353+ device : DeviceInfo | undefined ,
296354 platform : Extract < MaestroPlatform , 'android' | 'ios' > ,
355+ requestedFlags : CommandFlags | undefined ,
297356) : CommandFlags {
357+ if ( ! device ) return unresolvedMaestroRuntimeDeviceFlags ( platform , requestedFlags ) ;
298358 const flags : CommandFlags = {
299359 platform,
300360 target : device . target ,
@@ -308,6 +368,43 @@ function maestroRuntimeDeviceFlags(
308368 } ;
309369}
310370
371+ function unresolvedMaestroRuntimeDeviceFlags (
372+ platform : Extract < MaestroPlatform , 'android' | 'ios' > ,
373+ requestedFlags : CommandFlags | undefined ,
374+ ) : CommandFlags {
375+ const flags : CommandFlags = {
376+ platform,
377+ target : requestedFlags ?. target ?? 'mobile' ,
378+ noRecord : true ,
379+ } ;
380+ if ( requestedFlags ?. device ) flags . device = requestedFlags . device ;
381+ return platform === 'android'
382+ ? unresolvedAndroidMaestroFlags ( flags , requestedFlags )
383+ : unresolvedIosMaestroFlags ( flags , requestedFlags ) ;
384+ }
385+
386+ function unresolvedAndroidMaestroFlags (
387+ flags : CommandFlags ,
388+ requestedFlags : CommandFlags | undefined ,
389+ ) : CommandFlags {
390+ if ( requestedFlags ?. serial ) flags . serial = requestedFlags . serial ;
391+ if ( requestedFlags ?. androidDeviceAllowlist ) {
392+ flags . androidDeviceAllowlist = requestedFlags . androidDeviceAllowlist ;
393+ }
394+ return flags ;
395+ }
396+
397+ function unresolvedIosMaestroFlags (
398+ flags : CommandFlags ,
399+ requestedFlags : CommandFlags | undefined ,
400+ ) : CommandFlags {
401+ if ( requestedFlags ?. udid ) flags . udid = requestedFlags . udid ;
402+ if ( requestedFlags ?. iosSimulatorDeviceSet ) {
403+ flags . iosSimulatorDeviceSet = requestedFlags . iosSimulatorDeviceSet ;
404+ }
405+ return flags ;
406+ }
407+
311408function createMaestroReplayObserver ( params : {
312409 filePath : string ;
313410 tracePath : string | undefined ;
0 commit comments