serve-sim 0.1.44-beta.98.1 → 0.1.44-beta.99.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,6 +2,18 @@ import Foundation
2
2
  import ObjectiveC
3
3
  import Darwin
4
4
 
5
+ /// Per-event HID logging is gated behind `SERVE_SIM_DEBUG_HID`. These lines fire
6
+ /// on every touch/move/button/key/crown event — a single drag emits a dozen —
7
+ /// so by default they flood stdout (and anything mirroring it) for no benefit.
8
+ /// Failure diagnostics ("returned nil", "unavailable", "not found") stay on
9
+ /// `print` so real problems are always visible.
10
+ private let hidDebugEnabled = ProcessInfo.processInfo.environment["SERVE_SIM_DEBUG_HID"] != nil
11
+
12
+ @inline(__always)
13
+ private func hidLog(_ message: @autoclosure () -> String) {
14
+ if hidDebugEnabled { print(message()) }
15
+ }
16
+
5
17
  /// Injects touch, button, and orientation HID events into the iOS Simulator.
6
18
  ///
7
19
  /// Uses IndigoHIDMessageForMouseNSEvent to create touch messages and
@@ -70,28 +82,28 @@ final class HIDInjector {
70
82
 
71
83
  if let buttonPtr = dlsym(UnsafeMutableRawPointer(bitPattern: -2), "IndigoHIDMessageForButton") {
72
84
  self.buttonFunc = unsafeBitCast(buttonPtr, to: IndigoButtonFunc.self)
73
- print("[hid] IndigoHIDMessageForButton loaded")
85
+ hidLog("[hid] IndigoHIDMessageForButton loaded")
74
86
  } else {
75
87
  print("[hid] Warning: IndigoHIDMessageForButton not found")
76
88
  }
77
89
 
78
90
  if let arbPtr = dlsym(UnsafeMutableRawPointer(bitPattern: -2), "IndigoHIDMessageForHIDArbitrary") {
79
91
  self.hidArbitraryFunc = unsafeBitCast(arbPtr, to: IndigoHIDArbitraryFunc.self)
80
- print("[hid] IndigoHIDMessageForHIDArbitrary loaded")
92
+ hidLog("[hid] IndigoHIDMessageForHIDArbitrary loaded")
81
93
  } else {
82
94
  print("[hid] Warning: IndigoHIDMessageForHIDArbitrary not found")
83
95
  }
84
96
 
85
97
  if let keyboardPtr = dlsym(UnsafeMutableRawPointer(bitPattern: -2), "IndigoHIDMessageForKeyboardArbitrary") {
86
98
  self.keyboardFunc = unsafeBitCast(keyboardPtr, to: IndigoKeyboardFunc.self)
87
- print("[hid] IndigoHIDMessageForKeyboardArbitrary loaded")
99
+ hidLog("[hid] IndigoHIDMessageForKeyboardArbitrary loaded")
88
100
  } else {
89
101
  print("[hid] Warning: IndigoHIDMessageForKeyboardArbitrary not found")
90
102
  }
91
103
 
92
104
  if let crownPtr = dlsym(UnsafeMutableRawPointer(bitPattern: -2), "IndigoHIDMessageForDigitalCrownEvent") {
93
105
  self.digitalCrownFunc = unsafeBitCast(crownPtr, to: IndigoDigitalCrownFunc.self)
94
- print("[hid] IndigoHIDMessageForDigitalCrownEvent loaded")
106
+ hidLog("[hid] IndigoHIDMessageForDigitalCrownEvent loaded")
95
107
  } else {
96
108
  print("[hid] Warning: IndigoHIDMessageForDigitalCrownEvent not found")
97
109
  }
@@ -120,8 +132,8 @@ final class HIDInjector {
120
132
 
121
133
  self.hidClient = clientObj
122
134
  self.sendSel = NSSelectorFromString("sendWithMessage:freeWhenDone:completionQueue:completion:")
123
- print("[hid] SimDeviceLegacyHIDClient created")
124
- print("[hid] IndigoHIDMessageForMouseNSEvent loaded (with edge gesture support)")
135
+ hidLog("[hid] SimDeviceLegacyHIDClient created")
136
+ hidLog("[hid] IndigoHIDMessageForMouseNSEvent loaded (with edge gesture support)")
125
137
  }
126
138
 
127
139
  // IndigoHIDEdge values (x4 param to IndigoHIDMessageForMouseNSEvent).
@@ -175,7 +187,7 @@ final class HIDInjector {
175
187
 
176
188
  func sendTouch(type: String, x: Double, y: Double, screenWidth: Int, screenHeight: Int, edge: UInt32 = 0) {
177
189
  guard let msg = touchMessage(type: type, x: x, y: y, edge: edge) else { return }
178
- print("[hid] Sending \(type) at (\(String(format:"%.3f",x)),\(String(format:"%.3f",y)))\(edge > 0 ? " edge=\(edge)" : "")")
190
+ hidLog("[hid] Sending \(type) at (\(String(format:"%.3f",x)),\(String(format:"%.3f",y)))\(edge > 0 ? " edge=\(edge)" : "")")
179
191
  inputQueue.async { [self] in rawSend(msg) }
180
192
  }
181
193
 
@@ -197,7 +209,7 @@ final class HIDInjector {
197
209
  return
198
210
  }
199
211
 
200
- print("[hid] Multi-touch \(type) f1=(\(String(format:"%.3f",x1)),\(String(format:"%.3f",y1))) f2=(\(String(format:"%.3f",x2)),\(String(format:"%.3f",y2)))")
212
+ hidLog("[hid] Multi-touch \(type) f1=(\(String(format:"%.3f",x1)),\(String(format:"%.3f",y1))) f2=(\(String(format:"%.3f",x2)),\(String(format:"%.3f",y2)))")
201
213
  inputQueue.async { [self] in rawSend(rawMsg) }
202
214
  }
203
215
 
@@ -257,7 +269,7 @@ final class HIDInjector {
257
269
  return
258
270
  }
259
271
 
260
- print("[hid] Key \(type) usage=0x\(String(usage, radix: 16))")
272
+ hidLog("[hid] Key \(type) usage=0x\(String(usage, radix: 16))")
261
273
  inputQueue.async { [self] in rawSend(msg) }
262
274
  }
263
275
 
@@ -277,7 +289,7 @@ final class HIDInjector {
277
289
  return
278
290
  }
279
291
 
280
- print("[hid] Digital Crown delta=\(String(format:"%.4f", delta))")
292
+ hidLog("[hid] Digital Crown delta=\(String(format:"%.4f", delta))")
281
293
  inputQueue.async { [self] in rawSend(msg) }
282
294
  }
283
295
 
@@ -397,7 +409,7 @@ final class HIDInjector {
397
409
  }
398
410
  rawSend(msg)
399
411
  }
400
- print("[hid] HID button page=\(page) usage=\(usage) phase=\(phase)")
412
+ hidLog("[hid] HID button page=\(page) usage=\(usage) phase=\(phase)")
401
413
  inputQueue.async {
402
414
  switch phase {
403
415
  case "down": emit(1)
@@ -411,7 +423,7 @@ final class HIDInjector {
411
423
  }
412
424
 
413
425
  func sendButton(button: String, deviceUDID: String) {
414
- print("[hid] Sending button: \(button)")
426
+ hidLog("[hid] Sending button: \(button)")
415
427
 
416
428
  switch button {
417
429
  case "home":
@@ -490,7 +502,7 @@ final class HIDInjector {
490
502
  let imp = device.method(for: sel)
491
503
  let fn = unsafeBitCast(imp, to: Fn.self)
492
504
  let result = fn(device, sel, name as NSString, ObjCBool(enabled))
493
- print("[sim] setCADebugOption(\(name), \(enabled)) → \(result.boolValue)")
505
+ hidLog("[sim] setCADebugOption(\(name), \(enabled)) → \(result.boolValue)")
494
506
  return result.boolValue
495
507
  }
496
508
 
@@ -523,7 +535,7 @@ final class HIDInjector {
523
535
  return
524
536
  }
525
537
  _ = device.perform(sel)
526
- print("[sim] simulateMemoryWarning dispatched")
538
+ hidLog("[sim] simulateMemoryWarning dispatched")
527
539
  }
528
540
 
529
541
  /// Synthesize a swipe-up-from-bottom gesture (Face ID "go home" gesture).
@@ -629,7 +641,7 @@ final class HIDInjector {
629
641
  fputs("[hid] sendOrientation: mach_msg_send failed (\(kr))\n", stderr)
630
642
  return false
631
643
  } else {
632
- print("[hid] Orientation set to \(orientation)")
644
+ hidLog("[hid] Orientation set to \(orientation)")
633
645
  return true
634
646
  }
635
647
  }
@@ -40,7 +40,7 @@ function __sd_simulate(p){
40
40
  `+_)}function M(X,L,_,P,j,q){if(X.listenerCount("wsClientError")){let S=Error(j);Error.captureStackTrace(S,M),X.emit("wsClientError",S,_,L)}else R(_,P,j,q)}});MJ=YQ(e8(),1),FJ=YQ(J4(),1),NJ=YQ(vQ(),1),LJ=YQ(f5(),1),_J=YQ(b5(),1),RJ=YQ(h5(),1),_9=YQ(Y4(),1),i5=YQ(Q9(),1),k5=_9.default;q9={"Network.setUserAgentOverride":"Page.overrideUserAgent","Network.setCacheDisabled":"Network.setResourceCachingDisabled"},I9={"Network.requestWillBeSent":{walltime:"wallTime"}},x9={hasUserGesture:!1,redirectHasExtraInfo:!1},S9={hasExtraInfo:!1},w9={encodedDataLength:0,shouldReportCorbBlocking:!1},y9={initialPriority:"Medium",referrerPolicy:"origin"},k9={connectionReused:!1,connectionId:0,fromDiskCache:!1,fromServiceWorker:!1,encodedDataLength:0};d9={"media-rule":"mediaRule","media-import-rule":"importRule","media-style-node":"inlineSheet","media-link-node":"linkedSheet"};r9={protocolVersion:"1.3",product:"Safari/inspect-webkit",revision:"605.1.15",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS like Mac OS X) AppleWebKit/605.1.15 Safari/inspect-webkit",jsVersion:""};Y$=["Animation","Autofill","Audits","ServiceWorker","Profiler","HeapProfiler","Storage","Tethering","Tracing","BackgroundService","FedCm","DeviceAccess","WebAuthn","Cast","Database","ApplicationCache","BackgroundFetch","DeviceOrientation","EventBreakpoints","FileSystem","HeadlessExperimental","IndexedDB","Memory","PerformanceTimeline","Performance","Preload","Schema","Security","SystemInfo","WebAudio"],G$={"Network.setAttachDebugStack":{},"Network.emulateNetworkConditionsByRule":{ruleIds:[]},"Network.overrideNetworkState":{},"Network.clearAcceptedEncodingsOverride":{},"Network.setAcceptedEncodings":{},"Network.enableReportingApi":{},"Overlay.setShowHinge":{},"Overlay.setShowViewportSizeOnResize":{},"Overlay.setShowGridOverlays":{},"Overlay.setShowFlexOverlays":{},"Overlay.setShowScrollSnapOverlays":{},"Overlay.setShowContainerQueryOverlays":{},"Overlay.setShowIsolatedElements":{},"Overlay.setPausedInDebuggerMessage":{},"Overlay.setShowAdHighlights":{},"Overlay.setShowDebugBorders":{},"Overlay.setShowFPSCounter":{},"Overlay.setShowLayoutShiftRegions":{},"Overlay.setShowScrollBottleneckRects":{},"Overlay.setShowHitTestBorders":{},"Overlay.setShowWebVitals":{},"CSS.trackComputedStyleUpdates":{},"CSS.takeComputedStyleUpdates":{nodeIds:[]},"CSS.startRuleUsageTracking":{},"CSS.stopRuleUsageTracking":{ruleUsage:[]},"CSS.takeCoverageDelta":{coverage:[],timestamp:0},"Page.setAdBlockingEnabled":{},"Page.removeScriptToEvaluateOnNewDocument":{},"Page.setBypassCSP":{},"Page.setInterceptFileChooserDialog":{},"Page.setPrerenderingAllowed":{},"Page.setRPHRegistrationMode":{},"Page.setSPCTransactionMode":{},"Emulation.setEmulatedVisionDeficiency":{},"Emulation.setFocusEmulationEnabled":{},"Emulation.setAutoDarkModeOverride":{},"Emulation.setAutomationOverride":{},"Emulation.setLocaleOverride":{},"Emulation.setTimezoneOverride":{},"Emulation.setVisibleSize":{},"Emulation.setIdleOverride":{},"Emulation.clearIdleOverride":{},"Emulation.setGeolocationOverride":{},"Emulation.clearGeolocationOverride":{},"Emulation.setSensorOverrideEnabled":{},"Emulation.setSensorOverrideReadings":{},"Emulation.setHardwareConcurrencyOverride":{},"Emulation.setNavigatorOverrides":{},"Emulation.setPageScaleFactor":{},"Emulation.setScrollbarsHidden":{},"Emulation.setDocumentCookieDisabled":{},"DOMDebugger.setBreakOnCSPViolation":{},"Runtime.addBinding":{},"Runtime.removeBinding":{},"Debugger.setReturnValue":{},"Debugger.setBlackboxExecutionContexts":{},"Debugger.setInstrumentationBreakpoint":{},"DOM.markUndoableState":{},"DOM.undo":{},"DOM.redo":{},"DOM.copyTo":{nodeId:0},"DOM.collectClassNamesFromSubtree":{classNames:[]},"Accessibility.enable":{},"Accessibility.disable":{},"Accessibility.getFullAXTree":{nodes:[]},"Accessibility.getRootAXNode":{node:null},"Accessibility.getPartialAXTree":{nodes:[]},"Accessibility.queryAXTree":{nodes:[]},"Accessibility.getAXNodeAndAncestors":{nodes:[]},"Accessibility.getChildAXNodes":{nodes:[]}};X$={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}});import{readdirSync as j$,readFileSync as D$,existsSync as R6,unlinkSync as V6,watch as T$}from"fs";import{execSync as NQ,spawn as P$,exec as q$,execFile as lQ}from"child_process";import{tmpdir as I$}from"os";import{join as _4}from"path";import{createServer as x$}from"net";import{createHash as S$,randomBytes as w$,timingSafeEqual as y$}from"crypto";import{WebSocket as X6}from"ws";var R0="Accessibility unavailable on this simulator.";import{createRequire as p6}from"module";import{dirname as O0,join as U0}from"path";import{existsSync as c6}from"fs";import{fileURLToPath as x4}from"url";var m6=p6(import.meta.url),d6=1,n6=1,i6=2,SQ={portrait:1,portraitUpsideDown:2,landscapeRight:3,landscapeLeft:4};function o6(){let Q=[U0(O0(process.execPath),"native","serve-sim-native.node"),U0(O0(x4(import.meta.url)),"native","serve-sim-native.node"),U0(O0(x4(import.meta.url)),"..","dist","native","serve-sim-native.node")];for(let $ of Q)if(c6($))return $;throw Error(`serve-sim-native.node not found. Looked in:
41
41
  ${Q.join(`
42
42
  `)}
43
- Run \`bun run build.ts\` to build the native addon.`)}var A0;function cQ(){if(!A0)A0=m6(o6());return A0}class C0{handle;constructor(Q){this.handle=new(cQ()).SimHID(Q)}touch(Q,$,Z,J,Y,G=0){this.handle.touch(Q,$,Z,J,Y,G)}multiTouch(Q,$,Z,J,Y,G,V){this.handle.multiTouch(Q,$,Z,J,Y,G,V)}button(Q){this.handle.button(Q)}buttonHid(Q,$,Z="press"){this.handle.buttonHid(Q,$,Z)}key(Q,$){this.handle.key(Q,$)}scroll(Q,$,Z,J,Y,G){this.handle.scroll(Q,$,Y??NaN,G??NaN,Z,J)}digitalCrown(Q){this.handle.digitalCrown(Q)}orientation(Q){return this.handle.orientation(Q)}memoryWarning(){this.handle.memoryWarning()}softwareKeyboard(){this.handle.softwareKeyboard()}caDebug(Q,$){return this.handle.caDebug(Q,$)}}class B0{handle;constructor(Q,$){this.handle=new(cQ()).SimCapture(Q,(Z,J,Y,G,V)=>{$({codec:Z===d6?"avcc":"mjpeg",data:J,width:Y,height:G,isDescription:(V&n6)!==0,isKeyframe:(V&i6)!==0})})}start(){this.handle.start()}setAvccActive(Q){this.handle.setAvccActive(Q)}requestKeyframe(){this.handle.requestKeyframe()}screenSize(){return this.handle.screenSize()}stop(){this.handle.stop()}}function mQ(Q){return cQ().axDescribe(Q)}function dQ(Q){return cQ().axFrontmost(Q)}var E0=500,S4=500,a6=2000,r6=15000;function t6(Q){return Q[0]?.frame??{x:0,y:0,width:1,height:1}}function s6(Q,$){return Math.abs(Q.x-$.x)<0.5&&Math.abs(Q.y-$.y)<0.5&&Math.abs(Q.width-$.width)<0.5&&Math.abs(Q.height-$.height)<0.5}function e6(Q){let $=t6(Q),Z=[],J=(Y,G)=>{if(Z.length>=E0)return;let V=Y.frame;if(!s6(V,$))Z.push({id:Y.AXUniqueId??G,path:G,label:Y.AXLabel??"",value:Y.AXValue??"",role:Y.role_description,type:Y.type,enabled:Y.enabled!==!1,frame:V});for(let K=0;K<Y.children.length&&Z.length<E0;K++)J(Y.children[K],`${G}.${K}`)};for(let Y=0;Y<Q.length&&Z.length<E0;Y++)J(Q[Y],String(Y));return{screen:{width:$.width,height:$.height},elements:Z}}async function Q7(Q){let $;try{$=JSON.parse(await mQ(Q))}catch{return{screen:{width:1,height:1},elements:[],errors:[R0]}}return e6($)}function $7(Q){return Q?.errors?.includes(R0)??!1}function Z7(Q){return Q.elements.length>0&&Q.screen.width>1&&Q.screen.height>1}async function J7(Q){let $=[];try{let Z=await Q7(Q);if(Z.errors?.length)return Z;if(!Z7(Z))throw Error(`native AX returned ${Z.elements.length} elements in ${Z.screen.width}x${Z.screen.height} AX space`);return{...Z,errors:$}}catch(Z){$.push(Z.message||String(Z))}return{screen:{width:1,height:1},elements:[],errors:$}}function Y7(Q){return`data: ${JSON.stringify(Q)}
43
+ Run \`bun run build.ts\` to build the native addon.`)}var A0;function cQ(){if(!A0)A0=m6(o6());return A0}class C0{handle;constructor(Q){this.handle=new(cQ()).SimHID(Q)}guard(Q,$,Z){try{return $()}catch(J){return console.error(`[hid] ${Q} ignored bad input:`,J instanceof Error?J.message:J),Z}}touch(Q,$,Z,J,Y,G=0){this.guard("touch",()=>this.handle.touch(Q,$,Z,J,Y,G),void 0)}multiTouch(Q,$,Z,J,Y,G,V){this.guard("multiTouch",()=>this.handle.multiTouch(Q,$,Z,J,Y,G,V),void 0)}button(Q){this.guard("button",()=>this.handle.button(Q),void 0)}buttonHid(Q,$,Z="press"){this.guard("buttonHid",()=>this.handle.buttonHid(Q,$,Z),void 0)}key(Q,$){this.guard("key",()=>this.handle.key(Q,$),void 0)}scroll(Q,$,Z,J,Y,G){this.guard("scroll",()=>this.handle.scroll(Q,$,Y??NaN,G??NaN,Z,J),void 0)}digitalCrown(Q){this.guard("digitalCrown",()=>this.handle.digitalCrown(Q),void 0)}orientation(Q){return this.guard("orientation",()=>this.handle.orientation(Q),!1)}memoryWarning(){this.guard("memoryWarning",()=>this.handle.memoryWarning(),void 0)}softwareKeyboard(){this.guard("softwareKeyboard",()=>this.handle.softwareKeyboard(),void 0)}caDebug(Q,$){return this.guard("caDebug",()=>this.handle.caDebug(Q,$),!1)}}class B0{handle;constructor(Q,$){this.handle=new(cQ()).SimCapture(Q,(Z,J,Y,G,V)=>{$({codec:Z===d6?"avcc":"mjpeg",data:J,width:Y,height:G,isDescription:(V&n6)!==0,isKeyframe:(V&i6)!==0})})}start(){this.handle.start()}setAvccActive(Q){this.handle.setAvccActive(Q)}requestKeyframe(){this.handle.requestKeyframe()}screenSize(){return this.handle.screenSize()}stop(){this.handle.stop()}}function mQ(Q){return cQ().axDescribe(Q)}function dQ(Q){return cQ().axFrontmost(Q)}var E0=500,S4=500,a6=2000,r6=15000;function t6(Q){return Q[0]?.frame??{x:0,y:0,width:1,height:1}}function s6(Q,$){return Math.abs(Q.x-$.x)<0.5&&Math.abs(Q.y-$.y)<0.5&&Math.abs(Q.width-$.width)<0.5&&Math.abs(Q.height-$.height)<0.5}function e6(Q){let $=t6(Q),Z=[],J=(Y,G)=>{if(Z.length>=E0)return;let V=Y.frame;if(!s6(V,$))Z.push({id:Y.AXUniqueId??G,path:G,label:Y.AXLabel??"",value:Y.AXValue??"",role:Y.role_description,type:Y.type,enabled:Y.enabled!==!1,frame:V});for(let K=0;K<Y.children.length&&Z.length<E0;K++)J(Y.children[K],`${G}.${K}`)};for(let Y=0;Y<Q.length&&Z.length<E0;Y++)J(Q[Y],String(Y));return{screen:{width:$.width,height:$.height},elements:Z}}async function Q7(Q){let $;try{$=JSON.parse(await mQ(Q))}catch{return{screen:{width:1,height:1},elements:[],errors:[R0]}}return e6($)}function $7(Q){return Q?.errors?.includes(R0)??!1}function Z7(Q){return Q.elements.length>0&&Q.screen.width>1&&Q.screen.height>1}async function J7(Q){let $=[];try{let Z=await Q7(Q);if(Z.errors?.length)return Z;if(!Z7(Z))throw Error(`native AX returned ${Z.elements.length} elements in ${Z.screen.width}x${Z.screen.height} AX space`);return{...Z,errors:$}}catch(Z){$.push(Z.message||String(Z))}return{screen:{width:1,height:1},elements:[],errors:$}}function Y7(Q){return`data: ${JSON.stringify(Q)}
44
44
 
45
45
  `}function G7({udid:Q}){let $=new Set,Z=null,J=null,Y=S4,G=!1,V=!1,N=()=>{if(V||$.size===0||Z)return;Z=setTimeout(K,Y)},K=async()=>{if(Z=null,V||G||$.size===0){N();return}G=!0;try{let H=await J7(Q),z=Y7(H);if(z!==J){for(let F of $)F.write(z);Y=S4}else Y=Math.min(Y*2,a6);if(J=z,$7(H))Y=r6}finally{G=!1,N()}};return{addClient(H){if(V)return()=>{};if($.add(H),J)H.write(J);return K(),()=>{if($.delete(H),$.size===0&&Z)clearTimeout(Z),Z=null}},dispose(){if(V)return;if(V=!0,Z)clearTimeout(Z),Z=null;$.clear(),J=null}}}function w4(){let Q=new Map;return{get($){let Z=Q.get($);if(Z)return Z;let J=G7({udid:$});return Q.set($,J),J},prune($){let Z=$ instanceof Set?$:new Set($);for(let[J,Y]of Q)if(!Z.has(J))Y.dispose(),Q.delete(J)},size(){return Q.size}}}var j0={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"Content-Type"},y4=8388608,V7=4,X7=130,W7=Buffer.from(`\r
46
46
  `,"ascii");function k4(Q){return Buffer.from(`--frame\r
Binary file
package/dist/serve-sim.js CHANGED
@@ -49,7 +49,7 @@ Simulator-wide UI options:
49
49
  `).map(($)=>$.trim()).join(" ")};m9.O=function(Q){return this.inspectOpts.colors=this.useColors,w4.inspect(Q,this.inspectOpts)}});var i9=YQ((q3,x6)=>{if(typeof process>"u"||process.type==="renderer"||!1||process.__nwjs)x6.exports=c9();else x6.exports=n9()});var K4,k6,w6,RQ,y4;var S6=GQ(()=>{K4=o8(i9(),1),k6=K4.default("serve-sim:cli"),w6=K4.default("serve-sim:helper"),RQ=K4.default("serve-sim:state"),y4=K4.default("serve-sim:mw")});var y6="Accessibility unavailable on this simulator.";import{createRequire as EZ}from"module";import{dirname as f6,join as b6}from"path";import{existsSync as TZ}from"fs";import{fileURLToPath as o9}from"url";function AZ(){let Q=[b6(f6(process.execPath),"native","serve-sim-native.node"),b6(f6(o9(import.meta.url)),"native","serve-sim-native.node"),b6(f6(o9(import.meta.url)),"..","dist","native","serve-sim-native.node")];for(let $ of Q)if(TZ($))return $;throw Error(`serve-sim-native.node not found. Looked in:
50
50
  ${Q.join(`
51
51
  `)}
52
- Run \`bun run build.ts\` to build the native addon.`)}function f4(){if(!v6)v6=jZ(AZ());return v6}class h6{handle;constructor(Q){this.handle=new(f4()).SimHID(Q)}touch(Q,$,Z,J,Y,G=0){this.handle.touch(Q,$,Z,J,Y,G)}multiTouch(Q,$,Z,J,Y,G,X){this.handle.multiTouch(Q,$,Z,J,Y,G,X)}button(Q){this.handle.button(Q)}buttonHid(Q,$,Z="press"){this.handle.buttonHid(Q,$,Z)}key(Q,$){this.handle.key(Q,$)}scroll(Q,$,Z,J,Y,G){this.handle.scroll(Q,$,Y??NaN,G??NaN,Z,J)}digitalCrown(Q){this.handle.digitalCrown(Q)}orientation(Q){return this.handle.orientation(Q)}memoryWarning(){this.handle.memoryWarning()}softwareKeyboard(){this.handle.softwareKeyboard()}caDebug(Q,$){return this.handle.caDebug(Q,$)}}class u6{handle;constructor(Q,$){this.handle=new(f4()).SimCapture(Q,(Z,J,Y,G,X)=>{$({codec:Z===OZ?"avcc":"mjpeg",data:J,width:Y,height:G,isDescription:(X&qZ)!==0,isKeyframe:(X&DZ)!==0})})}start(){this.handle.start()}setAvccActive(Q){this.handle.setAvccActive(Q)}requestKeyframe(){this.handle.requestKeyframe()}screenSize(){return this.handle.screenSize()}stop(){this.handle.stop()}}function b4(Q){return f4().axDescribe(Q)}function v4(Q){return f4().axFrontmost(Q)}var jZ,OZ=1,qZ=1,DZ=2,W4,v6;var h4=GQ(()=>{jZ=EZ(import.meta.url),W4={portrait:1,portraitUpsideDown:2,landscapeRight:3,landscapeLeft:4}});function IZ(Q){return Q[0]?.frame??{x:0,y:0,width:1,height:1}}function xZ(Q,$){return Math.abs(Q.x-$.x)<0.5&&Math.abs(Q.y-$.y)<0.5&&Math.abs(Q.width-$.width)<0.5&&Math.abs(Q.height-$.height)<0.5}function kZ(Q){let $=IZ(Q),Z=[],J=(Y,G)=>{if(Z.length>=g6)return;let X=Y.frame;if(!xZ(X,$))Z.push({id:Y.AXUniqueId??G,path:G,label:Y.AXLabel??"",value:Y.AXValue??"",role:Y.role_description,type:Y.type,enabled:Y.enabled!==!1,frame:X});for(let W=0;W<Y.children.length&&Z.length<g6;W++)J(Y.children[W],`${G}.${W}`)};for(let Y=0;Y<Q.length&&Z.length<g6;Y++)J(Q[Y],String(Y));return{screen:{width:$.width,height:$.height},elements:Z}}async function wZ(Q){let $;try{$=JSON.parse(await b4(Q))}catch{return{screen:{width:1,height:1},elements:[],errors:[y6]}}return kZ($)}function SZ(Q){return Q?.errors?.includes(y6)??!1}function yZ(Q){return Q.elements.length>0&&Q.screen.width>1&&Q.screen.height>1}async function fZ(Q){let $=[];try{let Z=await wZ(Q);if(Z.errors?.length)return Z;if(!yZ(Z))throw Error(`native AX returned ${Z.elements.length} elements in ${Z.screen.width}x${Z.screen.height} AX space`);return{...Z,errors:$}}catch(Z){$.push(Z.message||String(Z))}return{screen:{width:1,height:1},elements:[],errors:$}}function bZ(Q){return`data: ${JSON.stringify(Q)}
52
+ Run \`bun run build.ts\` to build the native addon.`)}function f4(){if(!v6)v6=jZ(AZ());return v6}class h6{handle;constructor(Q){this.handle=new(f4()).SimHID(Q)}guard(Q,$,Z){try{return $()}catch(J){return console.error(`[hid] ${Q} ignored bad input:`,J instanceof Error?J.message:J),Z}}touch(Q,$,Z,J,Y,G=0){this.guard("touch",()=>this.handle.touch(Q,$,Z,J,Y,G),void 0)}multiTouch(Q,$,Z,J,Y,G,X){this.guard("multiTouch",()=>this.handle.multiTouch(Q,$,Z,J,Y,G,X),void 0)}button(Q){this.guard("button",()=>this.handle.button(Q),void 0)}buttonHid(Q,$,Z="press"){this.guard("buttonHid",()=>this.handle.buttonHid(Q,$,Z),void 0)}key(Q,$){this.guard("key",()=>this.handle.key(Q,$),void 0)}scroll(Q,$,Z,J,Y,G){this.guard("scroll",()=>this.handle.scroll(Q,$,Y??NaN,G??NaN,Z,J),void 0)}digitalCrown(Q){this.guard("digitalCrown",()=>this.handle.digitalCrown(Q),void 0)}orientation(Q){return this.guard("orientation",()=>this.handle.orientation(Q),!1)}memoryWarning(){this.guard("memoryWarning",()=>this.handle.memoryWarning(),void 0)}softwareKeyboard(){this.guard("softwareKeyboard",()=>this.handle.softwareKeyboard(),void 0)}caDebug(Q,$){return this.guard("caDebug",()=>this.handle.caDebug(Q,$),!1)}}class u6{handle;constructor(Q,$){this.handle=new(f4()).SimCapture(Q,(Z,J,Y,G,X)=>{$({codec:Z===OZ?"avcc":"mjpeg",data:J,width:Y,height:G,isDescription:(X&qZ)!==0,isKeyframe:(X&DZ)!==0})})}start(){this.handle.start()}setAvccActive(Q){this.handle.setAvccActive(Q)}requestKeyframe(){this.handle.requestKeyframe()}screenSize(){return this.handle.screenSize()}stop(){this.handle.stop()}}function b4(Q){return f4().axDescribe(Q)}function v4(Q){return f4().axFrontmost(Q)}var jZ,OZ=1,qZ=1,DZ=2,W4,v6;var h4=GQ(()=>{jZ=EZ(import.meta.url),W4={portrait:1,portraitUpsideDown:2,landscapeRight:3,landscapeLeft:4}});function IZ(Q){return Q[0]?.frame??{x:0,y:0,width:1,height:1}}function xZ(Q,$){return Math.abs(Q.x-$.x)<0.5&&Math.abs(Q.y-$.y)<0.5&&Math.abs(Q.width-$.width)<0.5&&Math.abs(Q.height-$.height)<0.5}function kZ(Q){let $=IZ(Q),Z=[],J=(Y,G)=>{if(Z.length>=g6)return;let X=Y.frame;if(!xZ(X,$))Z.push({id:Y.AXUniqueId??G,path:G,label:Y.AXLabel??"",value:Y.AXValue??"",role:Y.role_description,type:Y.type,enabled:Y.enabled!==!1,frame:X});for(let W=0;W<Y.children.length&&Z.length<g6;W++)J(Y.children[W],`${G}.${W}`)};for(let Y=0;Y<Q.length&&Z.length<g6;Y++)J(Q[Y],String(Y));return{screen:{width:$.width,height:$.height},elements:Z}}async function wZ(Q){let $;try{$=JSON.parse(await b4(Q))}catch{return{screen:{width:1,height:1},elements:[],errors:[y6]}}return kZ($)}function SZ(Q){return Q?.errors?.includes(y6)??!1}function yZ(Q){return Q.elements.length>0&&Q.screen.width>1&&Q.screen.height>1}async function fZ(Q){let $=[];try{let Z=await wZ(Q);if(Z.errors?.length)return Z;if(!yZ(Z))throw Error(`native AX returned ${Z.elements.length} elements in ${Z.screen.width}x${Z.screen.height} AX space`);return{...Z,errors:$}}catch(Z){$.push(Z.message||String(Z))}return{screen:{width:1,height:1},elements:[],errors:$}}function bZ(Q){return`data: ${JSON.stringify(Q)}
53
53
 
54
54
  `}function vZ({udid:Q}){let $=new Set,Z=null,J=null,Y=a9,G=!1,X=!1,H=()=>{if(X||$.size===0||Z)return;Z=setTimeout(W,Y)},W=async()=>{if(Z=null,X||G||$.size===0){H();return}G=!0;try{let z=await fZ(Q),K=bZ(z);if(K!==J){for(let M of $)M.write(K);Y=a9}else Y=Math.min(Y*2,CZ);if(J=K,SZ(z))Y=PZ}finally{G=!1,H()}};return{addClient(z){if(X)return()=>{};if($.add(z),J)z.write(J);return W(),()=>{if($.delete(z),$.size===0&&Z)clearTimeout(Z),Z=null}},dispose(){if(X)return;if(X=!0,Z)clearTimeout(Z),Z=null;$.clear(),J=null}}}function r9(){let Q=new Map;return{get($){let Z=Q.get($);if(Z)return Z;let J=vZ({udid:$});return Q.set($,J),J},prune($){let Z=$ instanceof Set?$:new Set($);for(let[J,Y]of Q)if(!Z.has(J))Y.dispose(),Q.delete(J)},size(){return Q.size}}}var g6=500,a9=500,CZ=2000,PZ=15000;var s9=GQ(()=>{h4()});function e9(Q){return Buffer.from(`--frame\r
55
55
  Content-Type: image/jpeg\r
@@ -136,7 +136,7 @@ Usage:
136
136
  serve-sim permissions reset <permission|all> <bundle-id> [-d <udid|name>]
137
137
  serve-sim permissions list [bundle-id] [-d <udid|name>]
138
138
 
139
- Permissions: ${_6().join(", ")}`),process.exit(1);let Y=J.device?o(J.device):$Q();if(!Y)console.error("No booted simulator. Boot one or pass -d <udid|name>."),process.exit(1);if(J.verb==="list"){let X={udid:Y,bundleId:J.bundleId??null,tcc:j7(Y,J.bundleId),location:q7(Y,J.bundleId),notifications:P7(Y,J.bundleId)};console.log(JSON.stringify(X,null,$?0:2)),process.exit(0)}let G=J.bundleId;try{if(J.permission==="all")for(let X of _6())O9(Y,"reset",X,void 0,G);else O9(Y,J.verb,J.permission,J.value,G)}catch(X){console.error(X?.message??String(X)),process.exit(1)}if($)console.log(JSON.stringify({udid:Y,verb:J.verb,permission:J.permission,value:J.value??null,bundleId:G}));else{let X=J.value?` (${J.value})`:"";console.log(`\uD83D\uDD10 ${J.verb} ${J.permission}${X} for ${G} on ${Y}`)}process.exit(0)}P6();S6();var qQ=A4(import.meta.url);function o2(){return"0.1.44-beta.98.1"}function x0(){if(!i(VQ))P8(VQ,{recursive:!0})}function e(Q){if(Q)return A8(Y4(Q));for(let $ of q4()){let Z=A8($);if(Z)return Z}return null}var s4={at:0,booted:null};function a2(){let Q=Date.now();if(s4.booted&&Q-s4.at<1000)return s4.booted;try{let $=t("xcrun simctl list devices booted -j",{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3000}),Z=JSON.parse($),J=new Set;for(let Y of Object.values(Z.devices))for(let G of Y)if(G.state==="Booted")J.add(G.udid);return s4={at:Q,booted:J},J}catch{return null}}function A8(Q){try{if(!i(Q))return RQ("state file missing %s",Q),null;let $=JSON.parse(WQ(Q,"utf-8"));try{process.kill($.pid,0)}catch{return RQ("helper pid %d dead, removing stale state %s",$.pid,Q),rQ(Q),null}let Z=a2();if(Z&&!Z.has($.device)){RQ("helper pid %d bound to non-booted device %s — killing stale helper",$.pid,$.device),console.error(`[serve-sim] Helper pid ${$.pid} is bound to device ${$.device} which is no longer booted — killing stale helper.`);try{process.kill($.pid,"SIGTERM")}catch{}try{rQ(Q)}catch{}return null}return RQ("state ok pid=%d device=%s port=%d",$.pid,$.device,$.port),$}catch($){return RQ("readStateFile threw for %s: %o",Q,$),null}}function F4(){let Q=[];for(let $ of q4()){let Z=A8($);if(Z)Q.push(Z)}return Q}function r2(Q){x0(),k8(Y4(Q.device),JSON.stringify(Q,null,2)),RQ("wrote state pid=%d device=%s port=%d",Q.pid,Q.device,Q.port)}function bQ(Q){if(Q){RQ("clearState device=%s",Q);try{rQ(Y4(Q))}catch{}}else{RQ("clearState (all)");for(let $ of q4())try{rQ($)}catch{}}}function w8(){try{let Q=t("xcrun simctl list devices -j",{encoding:"utf-8"}),$=JSON.parse(Q),Z=Object.keys($.devices).filter((J)=>/SimRuntime\.iOS-/i.test(J)).sort((J,Y)=>{let G=(J.match(/iOS-(\d+)-(\d+)/)??[]).slice(1).map(Number),X=(Y.match(/iOS-(\d+)-(\d+)/)??[]).slice(1).map(Number);return(X[0]??0)-(G[0]??0)||(X[1]??0)-(G[1]??0)});for(let J of Z){let G=($.devices[J]??[]).find((X)=>X.isAvailable!==!1&&/^iPhone\b/i.test(X.name));if(G)return{udid:G.udid,name:G.name}}}catch{}return null}function C0(Q){try{let $=t("xcrun simctl list devices -j",{encoding:"utf-8"}),Z=JSON.parse($);for(let J of Object.values(Z.devices))for(let Y of J)if(Y.udid===Q)return Y.name}catch{}return null}function k0(Q){try{let $=t("xcrun simctl list devices -j",{encoding:"utf-8"}),Z=JSON.parse($);for(let J of Object.values(Z.devices))for(let Y of J)if(Y.udid===Q)return Y.state==="Booted"}catch{}return!1}function e4(Q){try{return process.kill(Q,0),!0}catch{return!1}}function w0(Q){try{process.kill(Q,"SIGTERM")}catch{return}let $=Date.now()+500;while(Date.now()<$)try{process.kill(Q,0),AQ(25)}catch{return}try{process.kill(Q,"SIGKILL")}catch{}let Z=Date.now()+500;while(Date.now()<Z)try{process.kill(Q,0),AQ(25)}catch{return}}function s2(Q){if(!k0(Q))try{t(`xcrun simctl boot ${Q}`,{encoding:"utf-8",stdio:"pipe"})}catch($){let Z=($.stderr??$.message??"").toLowerCase();if(!Z.includes("booted")&&!Z.includes("current state"))throw Error(`Failed to boot device ${Q}: ${$.stderr||$.message}`)}try{t("open -ga Simulator",{encoding:"utf-8",stdio:"pipe",timeout:3000})}catch{}}function t2(){let Q=i2();for(let $ of Object.values(Q))for(let Z of $??[])if(Z.family==="IPv4"&&!Z.internal)return Z.address;return null}async function S0(Q){let $=new Set(F4().map((Z)=>Z.port));for(let Z=Q;Z<Q+100;Z++){if($.has(Z))continue;if(await F9(Z))return Z}throw Error(`No available port found in range ${Q}-${Q+99}`)}async function e2(Q){s2(Q);try{t(`xcrun simctl bootstatus ${Q} -b`,{encoding:"utf-8",stdio:"pipe",timeout:60000})}catch($){if(!k0(Q))console.error(`Device ${Q} failed to reach booted state: ${$.stderr||$.message}`),process.exit(1)}}function QY(Q){if(process.argv[0]&&/(^|\/)serve-sim$/.test(process.argv[0]))return{command:process.argv[0],args:Q};return{command:process.argv[0],args:[process.argv[1],...Q]}}async function $Y(Q,$=150000){let Z=Date.now();while(Date.now()-Z<$){let J=e(Q);if(J)return J;await new Promise((Y)=>setTimeout(Y,200))}return null}async function y0(Q,$,Z){w6("startHelper udid=%s port=%d detach=%s",Q,$,Z.detach);let J="127.0.0.1";x0(),bQ(Q),T9($);let Y=JQ(VQ,`server-${Q}.log`),G=I8(Y,"w"),{command:X,args:H}=QY([Q,"--port",String($),"--host",J]),W=P0(X,H,{detached:Z.detach,stdio:["ignore",G,G]});if(x8(G),Z.detach)W.unref();let z=await $Y(Q);if(!z){if(W.pid)w0(W.pid);let K="";try{K=WQ(Y,"utf-8").trim()}catch{}console.error(K?`Preview server failed:
139
+ Permissions: ${_6().join(", ")}`),process.exit(1);let Y=J.device?o(J.device):$Q();if(!Y)console.error("No booted simulator. Boot one or pass -d <udid|name>."),process.exit(1);if(J.verb==="list"){let X={udid:Y,bundleId:J.bundleId??null,tcc:j7(Y,J.bundleId),location:q7(Y,J.bundleId),notifications:P7(Y,J.bundleId)};console.log(JSON.stringify(X,null,$?0:2)),process.exit(0)}let G=J.bundleId;try{if(J.permission==="all")for(let X of _6())O9(Y,"reset",X,void 0,G);else O9(Y,J.verb,J.permission,J.value,G)}catch(X){console.error(X?.message??String(X)),process.exit(1)}if($)console.log(JSON.stringify({udid:Y,verb:J.verb,permission:J.permission,value:J.value??null,bundleId:G}));else{let X=J.value?` (${J.value})`:"";console.log(`\uD83D\uDD10 ${J.verb} ${J.permission}${X} for ${G} on ${Y}`)}process.exit(0)}P6();S6();var qQ=A4(import.meta.url);function o2(){return"0.1.44-beta.99.3"}function x0(){if(!i(VQ))P8(VQ,{recursive:!0})}function e(Q){if(Q)return A8(Y4(Q));for(let $ of q4()){let Z=A8($);if(Z)return Z}return null}var s4={at:0,booted:null};function a2(){let Q=Date.now();if(s4.booted&&Q-s4.at<1000)return s4.booted;try{let $=t("xcrun simctl list devices booted -j",{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3000}),Z=JSON.parse($),J=new Set;for(let Y of Object.values(Z.devices))for(let G of Y)if(G.state==="Booted")J.add(G.udid);return s4={at:Q,booted:J},J}catch{return null}}function A8(Q){try{if(!i(Q))return RQ("state file missing %s",Q),null;let $=JSON.parse(WQ(Q,"utf-8"));try{process.kill($.pid,0)}catch{return RQ("helper pid %d dead, removing stale state %s",$.pid,Q),rQ(Q),null}let Z=a2();if(Z&&!Z.has($.device)){RQ("helper pid %d bound to non-booted device %s — killing stale helper",$.pid,$.device),console.error(`[serve-sim] Helper pid ${$.pid} is bound to device ${$.device} which is no longer booted — killing stale helper.`);try{process.kill($.pid,"SIGTERM")}catch{}try{rQ(Q)}catch{}return null}return RQ("state ok pid=%d device=%s port=%d",$.pid,$.device,$.port),$}catch($){return RQ("readStateFile threw for %s: %o",Q,$),null}}function F4(){let Q=[];for(let $ of q4()){let Z=A8($);if(Z)Q.push(Z)}return Q}function r2(Q){x0(),k8(Y4(Q.device),JSON.stringify(Q,null,2)),RQ("wrote state pid=%d device=%s port=%d",Q.pid,Q.device,Q.port)}function bQ(Q){if(Q){RQ("clearState device=%s",Q);try{rQ(Y4(Q))}catch{}}else{RQ("clearState (all)");for(let $ of q4())try{rQ($)}catch{}}}function w8(){try{let Q=t("xcrun simctl list devices -j",{encoding:"utf-8"}),$=JSON.parse(Q),Z=Object.keys($.devices).filter((J)=>/SimRuntime\.iOS-/i.test(J)).sort((J,Y)=>{let G=(J.match(/iOS-(\d+)-(\d+)/)??[]).slice(1).map(Number),X=(Y.match(/iOS-(\d+)-(\d+)/)??[]).slice(1).map(Number);return(X[0]??0)-(G[0]??0)||(X[1]??0)-(G[1]??0)});for(let J of Z){let G=($.devices[J]??[]).find((X)=>X.isAvailable!==!1&&/^iPhone\b/i.test(X.name));if(G)return{udid:G.udid,name:G.name}}}catch{}return null}function C0(Q){try{let $=t("xcrun simctl list devices -j",{encoding:"utf-8"}),Z=JSON.parse($);for(let J of Object.values(Z.devices))for(let Y of J)if(Y.udid===Q)return Y.name}catch{}return null}function k0(Q){try{let $=t("xcrun simctl list devices -j",{encoding:"utf-8"}),Z=JSON.parse($);for(let J of Object.values(Z.devices))for(let Y of J)if(Y.udid===Q)return Y.state==="Booted"}catch{}return!1}function e4(Q){try{return process.kill(Q,0),!0}catch{return!1}}function w0(Q){try{process.kill(Q,"SIGTERM")}catch{return}let $=Date.now()+500;while(Date.now()<$)try{process.kill(Q,0),AQ(25)}catch{return}try{process.kill(Q,"SIGKILL")}catch{}let Z=Date.now()+500;while(Date.now()<Z)try{process.kill(Q,0),AQ(25)}catch{return}}function s2(Q){if(!k0(Q))try{t(`xcrun simctl boot ${Q}`,{encoding:"utf-8",stdio:"pipe"})}catch($){let Z=($.stderr??$.message??"").toLowerCase();if(!Z.includes("booted")&&!Z.includes("current state"))throw Error(`Failed to boot device ${Q}: ${$.stderr||$.message}`)}try{t("open -ga Simulator",{encoding:"utf-8",stdio:"pipe",timeout:3000})}catch{}}function t2(){let Q=i2();for(let $ of Object.values(Q))for(let Z of $??[])if(Z.family==="IPv4"&&!Z.internal)return Z.address;return null}async function S0(Q){let $=new Set(F4().map((Z)=>Z.port));for(let Z=Q;Z<Q+100;Z++){if($.has(Z))continue;if(await F9(Z))return Z}throw Error(`No available port found in range ${Q}-${Q+99}`)}async function e2(Q){s2(Q);try{t(`xcrun simctl bootstatus ${Q} -b`,{encoding:"utf-8",stdio:"pipe",timeout:60000})}catch($){if(!k0(Q))console.error(`Device ${Q} failed to reach booted state: ${$.stderr||$.message}`),process.exit(1)}}function QY(Q){if(process.argv[0]&&/(^|\/)serve-sim$/.test(process.argv[0]))return{command:process.argv[0],args:Q};return{command:process.argv[0],args:[process.argv[1],...Q]}}async function $Y(Q,$=150000){let Z=Date.now();while(Date.now()-Z<$){let J=e(Q);if(J)return J;await new Promise((Y)=>setTimeout(Y,200))}return null}async function y0(Q,$,Z){w6("startHelper udid=%s port=%d detach=%s",Q,$,Z.detach);let J="127.0.0.1";x0(),bQ(Q),T9($);let Y=JQ(VQ,`server-${Q}.log`),G=I8(Y,"w"),{command:X,args:H}=QY([Q,"--port",String($),"--host",J]),W=P0(X,H,{detached:Z.detach,stdio:["ignore",G,G]});if(x8(G),Z.detach)W.unref();let z=await $Y(Q);if(!z){if(W.pid)w0(W.pid);let K="";try{K=WQ(Y,"utf-8").trim()}catch{}console.error(K?`Preview server failed:
140
140
  ${K}`:"Preview server failed to start"),process.exit(1)}return Z.detach?{pid:z.pid}:{pid:z.pid,child:W}}async function ZY(Q,$,Z){k6("follow devices=%o startPort=%d",Q,$);let J=Q.length>0?Q.map(o):(()=>{let z=$Q();if(z)return[z];let K=w8();if(!K)console.error("No device specified and no available iOS simulator found."),process.exit(1);if(!Z)console.log(`No booted simulator — booting ${K.name}...`);return[K.udid]})(),Y=new Map,G=[],X=$;for(let z of J){let K=e(z);if(K){if(!Z){let T=C0(z)??z;if(J.length>1)console.log(`
141
141
  ==> ${T} (${z}) <==`);console.log(` Already running on port ${K.port}`),console.log(` Stream: ${K.streamUrl}`),console.log(` WebSocket: ${K.wsUrl}`)}G.push(K);continue}X=await S0(X);let{child:M}=await y0(z,X,{detach:!1});if(M)Y.set(z,M);let L=e(z)??mQ(z,X,"/","127.0.0.1");if(G.push(L),!Z){let T=C0(z)??z;if(J.length>1)console.log(`
142
142
  ==> ${T} (${z}) <==`);console.log(` Stream: ${L.streamUrl}`),console.log(` WebSocket: ${L.wsUrl}`),console.log(` Port: ${X}`)}X++}if(G.length===1){let z=G[0];console.log(JSON.stringify({url:z.url,streamUrl:z.streamUrl,wsUrl:z.wsUrl,port:z.port,device:z.device}))}else console.log(JSON.stringify({devices:G.map((z)=>({url:z.url,streamUrl:z.streamUrl,wsUrl:z.wsUrl,port:z.port,device:z.device}))}));if(Y.size===0)return;let H=!1,W=(z)=>{if(H)return;if(H=!0,!Z)console.log(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "serve-sim",
3
- "version": "0.1.44-beta.98.1",
3
+ "version": "0.1.44-beta.99.3",
4
4
  "type": "module",
5
5
  "author": {
6
6
  "name": "Evan Bacon",
package/src/native.ts CHANGED
@@ -116,49 +116,65 @@ export class NativeHid {
116
116
  this.handle = new (load().SimHID)(udid);
117
117
  }
118
118
 
119
+ // The N-API bindings throw synchronously when a JS value can't be coerced to
120
+ // the native parameter type (e.g. a touch with a non-string `type` →
121
+ // "Could not convert parameter 0 to type String"). HID now runs in-process,
122
+ // so an unhandled throw here crashes the whole server — and if it lands
123
+ // mid-gesture, the guest is left with a stuck finger that wedges input until
124
+ // the sim reboots. The spawned helper used to absorb this in its own process;
125
+ // `guard` restores that isolation by swallowing malformed-input errors.
126
+ private guard<T>(op: string, fn: () => T, fallback: T): T {
127
+ try {
128
+ return fn();
129
+ } catch (err) {
130
+ console.error(`[hid] ${op} ignored bad input:`, err instanceof Error ? err.message : err);
131
+ return fallback;
132
+ }
133
+ }
134
+
119
135
  touch(type: TouchType, x: number, y: number, w: number, h: number, edge = 0): void {
120
- this.handle.touch(type, x, y, w, h, edge);
136
+ this.guard("touch", () => this.handle.touch(type, x, y, w, h, edge), undefined);
121
137
  }
122
138
 
123
139
  multiTouch(type: TouchType, x1: number, y1: number, x2: number, y2: number, w: number, h: number): void {
124
- this.handle.multiTouch(type, x1, y1, x2, y2, w, h);
140
+ this.guard("multiTouch", () => this.handle.multiTouch(type, x1, y1, x2, y2, w, h), undefined);
125
141
  }
126
142
 
127
143
  button(button: string): void {
128
- this.handle.button(button);
144
+ this.guard("button", () => this.handle.button(button), undefined);
129
145
  }
130
146
 
131
147
  buttonHid(page: number, usage: number, phase: ButtonPhase = "press"): void {
132
- this.handle.buttonHid(page, usage, phase);
148
+ this.guard("buttonHid", () => this.handle.buttonHid(page, usage, phase), undefined);
133
149
  }
134
150
 
135
151
  key(type: KeyType, usage: number): void {
136
- this.handle.key(type, usage);
152
+ this.guard("key", () => this.handle.key(type, usage), undefined);
137
153
  }
138
154
 
139
155
  /** anchorX/anchorY default to screen center when omitted. */
140
156
  scroll(dx: number, dy: number, w: number, h: number, anchorX?: number, anchorY?: number): void {
141
- this.handle.scroll(dx, dy, anchorX ?? NaN, anchorY ?? NaN, w, h);
157
+ this.guard("scroll", () => this.handle.scroll(dx, dy, anchorX ?? NaN, anchorY ?? NaN, w, h), undefined);
142
158
  }
143
159
 
144
160
  digitalCrown(delta: number): void {
145
- this.handle.digitalCrown(delta);
161
+ this.guard("digitalCrown", () => this.handle.digitalCrown(delta), undefined);
146
162
  }
147
163
 
148
164
  orientation(orientation: number): boolean {
149
- return this.handle.orientation(orientation);
165
+ return this.guard("orientation", () => this.handle.orientation(orientation), false);
150
166
  }
151
167
 
152
168
  memoryWarning(): void {
153
- this.handle.memoryWarning();
169
+ this.guard("memoryWarning", () => this.handle.memoryWarning(), undefined);
154
170
  }
155
171
 
156
172
  softwareKeyboard(): void {
157
- this.handle.softwareKeyboard();
173
+ this.guard("softwareKeyboard", () => this.handle.softwareKeyboard(), undefined);
158
174
  }
159
175
 
160
176
  caDebug(name: string, enabled: boolean): boolean {
161
- return this.handle.caDebug(name, enabled);
177
+ return this.guard("caDebug", () => this.handle.caDebug(name, enabled), false);
162
178
  }
163
179
  }
164
180