@expo/serve-sim 0.4.0 → 0.5.0-canary-20260928-e9c5bcd

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.
package/dist/serve-sim.js CHANGED
@@ -317,7 +317,7 @@ Usage:
317
317
  serve-sim permissions reset <permission|all> <bundle-id> [-d <udid|name>]
318
318
  serve-sim permissions list [bundle-id] [-d <udid|name>]
319
319
 
320
- Permissions: ${W9().join(", ")}`),process.exit(1);let U=Q.device?b$(Q.device):e$();if(!U)console.error("No booted simulator. Boot one or pass -d <udid|name>."),process.exit(1);if(Q.verb==="list"){let Y={udid:U,bundleId:Q.bundleId??null,tcc:_O(U,Q.bundleId),location:JO(U,Q.bundleId),notifications:WO(U,Q.bundleId)};console.log(JSON.stringify(Y,null,_?0:2)),process.exit(0)}let X=Q.bundleId;try{if(Q.permission==="all")for(let Y of W9())xz(U,"reset",Y,void 0,X);else xz(U,Q.verb,Q.permission,Q.value,X)}catch(Y){console.error(Y?.message??String(Y)),process.exit(1)}if(_)console.log(JSON.stringify({udid:U,verb:Q.verb,permission:Q.permission,value:Q.value??null,bundleId:X}));else{let Y=Q.value?` (${Q.value})`:"";console.log(`\uD83D\uDD10 ${Q.verb} ${Q.permission}${Y} for ${X} on ${U}`)}process.exit(0)}g_();n_();function SN($,_={}){let J=new Date($.timestamp),Q=Number.isNaN(J.getTime())?$.timestamp:J.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"}),U=_.deviceLabel??($.device?$.device.slice(0,8):null),X=$.status==="error"?" failed":"";return[Q,U,`${RV($)}${X?` (${X.trim()})`:""}`].filter(Boolean).join(" ")}function RV($){if($.kind==="tap"){let _=m_($.details,"current")??m_($.details,"start");return _?`Tap at ${k9(_)}`:"Tap"}if($.kind==="drag"){let _=m_($.details,"start"),J=m_($.details,"current");if(_&&J)return`Drag from ${k9(_)} to ${k9(J)}`;return"Drag"}if($.kind==="key"){let _=TV($.details,"key")??$.action??"key",J=$.action==="down"?"down":$.action==="up"?"up":$.action;return J?`Key ${J} ${EN(_)}`:`Key ${EN(_)}`}if($.kind==="rotate"){let _=$.action?kN($.action):"";return _?`Rotate ${_}`:"Rotate"}return AV($.msg??$.summary)}function m_($,_){let J=$?.[_];if(!J||typeof J!=="object"||Array.isArray(J))return null;let Q=J;return typeof Q.x==="number"&&typeof Q.y==="number"?{x:Q.x,y:Q.y}:null}function TV($,_){let J=$?.[_];return typeof J==="string"&&J.length>0?J:null}function k9($){return`${qN($.x)}, ${qN($.y)}`}function qN($){if(!Number.isFinite($))return"?";return(Math.round((PV($,0,1)+Number.EPSILON)*100)/100).toFixed(2)}function PV($,_,J){return Math.min(J,Math.max(_,$))}function AV($){return $.replace(/\b[a-z]+(?:_[a-z]+)+\b/g,kN)}function kN($){return $.replace(/[-_]+/g," ")}function EN($){return{MetaLeft:"Left Command",MetaRight:"Right Command",AltLeft:"Left Option",AltRight:"Right Option",ControlLeft:"Left Control",ControlRight:"Right Control",ShiftLeft:"Left Shift",ShiftRight:"Right Shift",ArrowLeft:"Left Arrow",ArrowRight:"Right Arrow",ArrowUp:"Up Arrow",ArrowDown:"Down Arrow"}[$]??$}b9();E0();function x9($,_){let J=$.split(",").map((U)=>U.trim()).filter(Boolean),Q=_==="stun"?/^stuns?:/i:/^turns?:/i;if(J.length===0||J.length>16||J.some((U)=>U.length>2048||!Q.test(U)))throw Error(`Expected one or more comma-separated ${_.toUpperCase()} URLs`);return J}function g9($,_){let J=$??{transport:"http"},Q=_??{transport:"http"};if(J.transport!==Q.transport)return!1;let U=z1(J),X=z1(Q);if(U.mjpegFps!==X.mjpegFps||U.mjpegQuality!==X.mjpegQuality||U.maxDimension!==X.maxDimension||U.h264Bitrate!==X.h264Bitrate||U.h264Fps!==X.h264Fps)return!1;if(J.transport==="http"&&Q.transport==="http")return(J.codec??"auto")===(Q.codec??"auto");if(J.transport!=="webrtc"||Q.transport!=="webrtc")return!1;if(J.codec!==Q.codec)return!1;let Y=J.iceServers??[],W=Q.iceServers??[];if(Y.length!==W.length)return!1;return Y.every((G,I)=>{let z=W[I];return G.username===z.username&&G.credential===z.credential&&G.urls.length===z.urls.length&&G.urls.every((N,K)=>N===z.urls[K])})}function bN($,_){let J=[];for(let Q of $??[])for(let U of Q.urls){let X=U.toLowerCase();if(_.some((Y)=>X.startsWith(Y)))J.push(U)}return J}function CV($){for(let _ of $??[])if(_.urls.some((J)=>/^turns?:/i.test(J)))return _;return null}function wV($){if(!$)return[];let _=[];if(_.push("--transport",$.transport),$.transport==="http"){if($.codec)_.push("--codec",$.codec)}else{_.push("--webrtc-codec",$.codec);let J=bN($.iceServers,["stun:","stuns:"]);if(J.length)_.push("--stun-url",J.join(","));let Q=bN($.iceServers,["turn:","turns:"]);if(Q.length){_.push("--turn-url",Q.join(","));let U=CV($.iceServers);if(U?.username)_.push("--turn-username",U.username);if(U?.credential)_.push("--turn-credential",U.credential)}}if($.mjpegFps!==void 0)_.push("--mjpeg-fps",String($.mjpegFps));if($.mjpegQuality!==void 0)_.push("--mjpeg-quality",String($.mjpegQuality));if($.maxDimension!==void 0)_.push("--max-dimension",String($.maxDimension));if($.h264Bitrate!==void 0)_.push("--video-bitrate",String($.h264Bitrate));if($.h264Fps!==void 0)_.push("--video-fps",String($.h264Fps));return _}function xN($,_,J,Q){return[$,"--port",String(_),"--host",J,...wV(Q)]}E0();H1();H1();import bV from"ws";async function yN($,_,J={}){if(!b4(_))throw Error("Hinge angle must be between 0–180 degrees");return new Promise((Q,U)=>{let X=new bV($,{headers:J.token?{Authorization:`Bearer ${J.token}`}:void 0}),Y=!1,W=(I)=>{if(Y)return;if(Y=!0,clearTimeout(G),X.close(),I)U(I);else Q()},G=setTimeout(()=>W(Error("Timed out waiting for hinge control acknowledgement")),J.timeoutMs??5000);X.on("open",()=>{X.send(Buffer.concat([Buffer.from([15]),Buffer.from(JSON.stringify({angle:_}))]))}),X.on("message",(I)=>{let z=Buffer.from(I);if(z[0]!==143)return;let N;try{N=JSON.parse(z.subarray(1).toString())}catch{W(Error("Invalid hinge control acknowledgement"));return}if(!N||typeof N!=="object"||typeof N.ok!=="boolean"){W(Error("Invalid hinge control acknowledgement"));return}if(!N.ok)W(Error(N.error||"Hinge control is unavailable on this simulator"));else if(N.angle===_)W();else W(Error("Server acknowledged a different hinge angle"))}),X.on("error",(I)=>W(Error(`Hinge control connection failed: ${I.message}`))),X.on("close",()=>W(Error("Connection closed before hinge control acknowledgement")))})}var B6=X1(import.meta.url);function Pw(){return"0.4.0"}function fH(){nG(v$(),{recursive:!0})}function x$($){if($)return uG(B0($));for(let _ of Q1()){let J=uG(_);if(J)return J}return null}var F8={at:0,booted:null};function Aw(){let $=Date.now();if(F8.booted&&$-F8.at<1000)return F8.booted;try{let _=n4("xcrun simctl list devices booted -j",{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3000}),J=JSON.parse(_),Q=new Set;for(let U of Object.values(J.devices))for(let X of U)if(X.state==="Booted")Q.add(X.udid);return F8={at:$,booted:Q},Q}catch{return null}}function uG($){try{if(!h4($))return Z4("state file missing %s",$),null;let _=JSON.parse(e6($,"utf-8"));try{process.kill(_.pid,0)}catch{return Z4("helper pid %d dead, removing stale state %s",_.pid,$),s6($),null}let J=Aw();if(J&&!J.has(_.device)){if(_.pid===process.pid){Z4("dropping own stale state for non-booted device %s",_.device);try{s6($)}catch{}return null}Z4("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{s6($)}catch{}return null}return Z4("state ok pid=%d device=%s port=%d",_.pid,_.device,_.port),_}catch(_){return Z4("readStateFile threw for %s: %o",$,_),null}}function Q_(){let $=[];for(let _ of Q1()){let J=uG(_);if(J)$.push(J)}return $}function qw($){fH(),z_($),Z4("wrote state pid=%d device=%s port=%d",$.pid,$.device,$.port)}function N0($){return new Tw($.wsUrl,$.token?{headers:{Authorization:`Bearer ${$.token}`}}:void 0)}function K0($,_){$.on("close",(J,Q)=>{if(J===1013)_(Error(`Simulator input rejected: ${Q.toString()||"server busy"}. Try again shortly.`))})}function z0($){if($){Z4("clearState device=%s",$);try{s6(B0($))}catch{}}else{Z4("clearState (all)");for(let _ of Q1())try{s6(_)}catch{}}}function iG(){try{let $=n4("xcrun simctl list devices -j",{encoding:"utf-8"}),_=JSON.parse($),J=Object.keys(_.devices).filter((Q)=>/SimRuntime\.iOS-/i.test(Q)).sort((Q,U)=>{let X=(Q.match(/iOS-(\d+)-(\d+)/)??[]).slice(1).map(Number),Y=(U.match(/iOS-(\d+)-(\d+)/)??[]).slice(1).map(Number);return(Y[0]??0)-(X[0]??0)||(Y[1]??0)-(X[1]??0)});for(let Q of J){let X=(_.devices[Q]??[]).find((Y)=>Y.isAvailable!==!1&&/^iPhone\b/i.test(Y.name));if(X)return{udid:X.udid,name:X.name}}}catch{}return null}function bH($){return yH().get($)??null}function yH(){let $=new Map;try{let _=n4("xcrun simctl list devices -j",{encoding:"utf-8"}),J=JSON.parse(_);for(let Q of Object.values(J.devices))for(let U of Q)$.set(U.udid,U.name)}catch{}return $}function uH($){try{let _=n4("xcrun simctl list devices -j",{encoding:"utf-8"}),J=JSON.parse(_);for(let Q of Object.values(J.devices))for(let U of Q)if(U.udid===$)return U.state==="Booted"}catch{}return!1}function hG($){try{return process.kill($,0),!0}catch{return!1}}function O8($){try{process.kill($,"SIGTERM")}catch{return}let _=Date.now()+500;while(Date.now()<_)try{process.kill($,0),F6(25)}catch{return}try{process.kill($,"SIGKILL")}catch{}let J=Date.now()+500;while(Date.now()<J)try{process.kill($,0),F6(25)}catch{return}}function Ew($){if(!uH($))try{n4(`xcrun simctl boot ${$}`,{encoding:"utf-8",stdio:"pipe"})}catch(_){let J=(_.stderr??_.message??"").toLowerCase();if(!J.includes("booted")&&!J.includes("current state"))throw Error(`Failed to boot device ${$}: ${_.stderr||_.message}`)}try{Cz($)}catch{}}function Sw(){let $=Rw();for(let _ of Object.values($))for(let J of _??[])if(J.family==="IPv4"&&!J.internal)return J.address;return null}async function hH($){let _=new Set(Q_().map((J)=>J.port));for(let J=$;J<$+100;J++){if(_.has(J))continue;if(await cI(J))return J}throw Error(`No available port found in range ${$}-${$+99}`)}async function nH($){Ew($);try{n4(`xcrun simctl bootstatus ${$} -b`,{encoding:"utf-8",stdio:"pipe",timeout:60000})}catch(_){if(!uH($))console.error(`Device ${$} failed to reach booted state: ${_.stderr||_.message}`),process.exit(1)}await Rz($)}function mH(){for(let $ of _9())try{Hz($,process.pid,(_)=>{if(_.name==="camera")X_($)})}catch(_){console.error(`Could not clean up capabilities on ${$}: ${_ instanceof Error?_.message:String(_)}`)}}var t6=!1,kw;function cG(){return kw??=(async()=>{await P0();for(let $ of _9())await $9($,process.pid,(_)=>{if(_.name==="camera")X_($)})})()}var lH="SERVE_SIM_STREAM_HELPER";function Cw($){if(process.argv[0]&&/(^|\/)serve-sim$/.test(process.argv[0]))return{command:process.argv[0],args:$};return{command:process.argv[0],args:[process.argv[1],...$]}}async function ww($,_=150000){let J=Date.now();while(Date.now()-J<_){let Q=x$($);if(Q)return Q;await new Promise((U)=>setTimeout(U,200))}return null}async function iH($,_,J){E9("startHelper udid=%s port=%d detach=%s",$,_,J.detach);let Q="127.0.0.1";fH(),Ez(_),z0($);let U=S4(v$(),`server-${$}.log`),X=mG(U,"w"),{command:Y,args:W}=Cw(xN($,_,Q,J.stream)),G=xH(Y,W,{detached:J.detach,stdio:["ignore",X,X],env:{...process.env,[lH]:"1"}});if(lG(X),J.detach)G.unref();let I=await ww($);if(!I){if(G.pid)O8(G.pid);let z="";try{z=e6(U,"utf-8").trim()}catch{}console.error(z?`Preview server failed:
320
+ Permissions: ${W9().join(", ")}`),process.exit(1);let U=Q.device?b$(Q.device):e$();if(!U)console.error("No booted simulator. Boot one or pass -d <udid|name>."),process.exit(1);if(Q.verb==="list"){let Y={udid:U,bundleId:Q.bundleId??null,tcc:_O(U,Q.bundleId),location:JO(U,Q.bundleId),notifications:WO(U,Q.bundleId)};console.log(JSON.stringify(Y,null,_?0:2)),process.exit(0)}let X=Q.bundleId;try{if(Q.permission==="all")for(let Y of W9())xz(U,"reset",Y,void 0,X);else xz(U,Q.verb,Q.permission,Q.value,X)}catch(Y){console.error(Y?.message??String(Y)),process.exit(1)}if(_)console.log(JSON.stringify({udid:U,verb:Q.verb,permission:Q.permission,value:Q.value??null,bundleId:X}));else{let Y=Q.value?` (${Q.value})`:"";console.log(`\uD83D\uDD10 ${Q.verb} ${Q.permission}${Y} for ${X} on ${U}`)}process.exit(0)}g_();n_();function SN($,_={}){let J=new Date($.timestamp),Q=Number.isNaN(J.getTime())?$.timestamp:J.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"}),U=_.deviceLabel??($.device?$.device.slice(0,8):null),X=$.status==="error"?" failed":"";return[Q,U,`${RV($)}${X?` (${X.trim()})`:""}`].filter(Boolean).join(" ")}function RV($){if($.kind==="tap"){let _=m_($.details,"current")??m_($.details,"start");return _?`Tap at ${k9(_)}`:"Tap"}if($.kind==="drag"){let _=m_($.details,"start"),J=m_($.details,"current");if(_&&J)return`Drag from ${k9(_)} to ${k9(J)}`;return"Drag"}if($.kind==="key"){let _=TV($.details,"key")??$.action??"key",J=$.action==="down"?"down":$.action==="up"?"up":$.action;return J?`Key ${J} ${EN(_)}`:`Key ${EN(_)}`}if($.kind==="rotate"){let _=$.action?kN($.action):"";return _?`Rotate ${_}`:"Rotate"}return AV($.msg??$.summary)}function m_($,_){let J=$?.[_];if(!J||typeof J!=="object"||Array.isArray(J))return null;let Q=J;return typeof Q.x==="number"&&typeof Q.y==="number"?{x:Q.x,y:Q.y}:null}function TV($,_){let J=$?.[_];return typeof J==="string"&&J.length>0?J:null}function k9($){return`${qN($.x)}, ${qN($.y)}`}function qN($){if(!Number.isFinite($))return"?";return(Math.round((PV($,0,1)+Number.EPSILON)*100)/100).toFixed(2)}function PV($,_,J){return Math.min(J,Math.max(_,$))}function AV($){return $.replace(/\b[a-z]+(?:_[a-z]+)+\b/g,kN)}function kN($){return $.replace(/[-_]+/g," ")}function EN($){return{MetaLeft:"Left Command",MetaRight:"Right Command",AltLeft:"Left Option",AltRight:"Right Option",ControlLeft:"Left Control",ControlRight:"Right Control",ShiftLeft:"Left Shift",ShiftRight:"Right Shift",ArrowLeft:"Left Arrow",ArrowRight:"Right Arrow",ArrowUp:"Up Arrow",ArrowDown:"Down Arrow"}[$]??$}b9();E0();function x9($,_){let J=$.split(",").map((U)=>U.trim()).filter(Boolean),Q=_==="stun"?/^stuns?:/i:/^turns?:/i;if(J.length===0||J.length>16||J.some((U)=>U.length>2048||!Q.test(U)))throw Error(`Expected one or more comma-separated ${_.toUpperCase()} URLs`);return J}function g9($,_){let J=$??{transport:"http"},Q=_??{transport:"http"};if(J.transport!==Q.transport)return!1;let U=z1(J),X=z1(Q);if(U.mjpegFps!==X.mjpegFps||U.mjpegQuality!==X.mjpegQuality||U.maxDimension!==X.maxDimension||U.h264Bitrate!==X.h264Bitrate||U.h264Fps!==X.h264Fps)return!1;if(J.transport==="http"&&Q.transport==="http")return(J.codec??"auto")===(Q.codec??"auto");if(J.transport!=="webrtc"||Q.transport!=="webrtc")return!1;if(J.codec!==Q.codec)return!1;let Y=J.iceServers??[],W=Q.iceServers??[];if(Y.length!==W.length)return!1;return Y.every((G,I)=>{let z=W[I];return G.username===z.username&&G.credential===z.credential&&G.urls.length===z.urls.length&&G.urls.every((N,K)=>N===z.urls[K])})}function bN($,_){let J=[];for(let Q of $??[])for(let U of Q.urls){let X=U.toLowerCase();if(_.some((Y)=>X.startsWith(Y)))J.push(U)}return J}function CV($){for(let _ of $??[])if(_.urls.some((J)=>/^turns?:/i.test(J)))return _;return null}function wV($){if(!$)return[];let _=[];if(_.push("--transport",$.transport),$.transport==="http"){if($.codec)_.push("--codec",$.codec)}else{_.push("--webrtc-codec",$.codec);let J=bN($.iceServers,["stun:","stuns:"]);if(J.length)_.push("--stun-url",J.join(","));let Q=bN($.iceServers,["turn:","turns:"]);if(Q.length){_.push("--turn-url",Q.join(","));let U=CV($.iceServers);if(U?.username)_.push("--turn-username",U.username);if(U?.credential)_.push("--turn-credential",U.credential)}}if($.mjpegFps!==void 0)_.push("--mjpeg-fps",String($.mjpegFps));if($.mjpegQuality!==void 0)_.push("--mjpeg-quality",String($.mjpegQuality));if($.maxDimension!==void 0)_.push("--max-dimension",String($.maxDimension));if($.h264Bitrate!==void 0)_.push("--video-bitrate",String($.h264Bitrate));if($.h264Fps!==void 0)_.push("--video-fps",String($.h264Fps));return _}function xN($,_,J,Q){return[$,"--port",String(_),"--host",J,...wV(Q)]}E0();H1();H1();import bV from"ws";async function yN($,_,J={}){if(!b4(_))throw Error("Hinge angle must be between 0–180 degrees");return new Promise((Q,U)=>{let X=new bV($,{headers:J.token?{Authorization:`Bearer ${J.token}`}:void 0}),Y=!1,W=(I)=>{if(Y)return;if(Y=!0,clearTimeout(G),X.close(),I)U(I);else Q()},G=setTimeout(()=>W(Error("Timed out waiting for hinge control acknowledgement")),J.timeoutMs??5000);X.on("open",()=>{X.send(Buffer.concat([Buffer.from([15]),Buffer.from(JSON.stringify({angle:_}))]))}),X.on("message",(I)=>{let z=Buffer.from(I);if(z[0]!==143)return;let N;try{N=JSON.parse(z.subarray(1).toString())}catch{W(Error("Invalid hinge control acknowledgement"));return}if(!N||typeof N!=="object"||typeof N.ok!=="boolean"){W(Error("Invalid hinge control acknowledgement"));return}if(!N.ok)W(Error(N.error||"Hinge control is unavailable on this simulator"));else if(N.angle===_)W();else W(Error("Server acknowledged a different hinge angle"))}),X.on("error",(I)=>W(Error(`Hinge control connection failed: ${I.message}`))),X.on("close",()=>W(Error("Connection closed before hinge control acknowledgement")))})}var B6=X1(import.meta.url);function Pw(){return"0.5.0-canary-20260928-e9c5bcd"}function fH(){nG(v$(),{recursive:!0})}function x$($){if($)return uG(B0($));for(let _ of Q1()){let J=uG(_);if(J)return J}return null}var F8={at:0,booted:null};function Aw(){let $=Date.now();if(F8.booted&&$-F8.at<1000)return F8.booted;try{let _=n4("xcrun simctl list devices booted -j",{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3000}),J=JSON.parse(_),Q=new Set;for(let U of Object.values(J.devices))for(let X of U)if(X.state==="Booted")Q.add(X.udid);return F8={at:$,booted:Q},Q}catch{return null}}function uG($){try{if(!h4($))return Z4("state file missing %s",$),null;let _=JSON.parse(e6($,"utf-8"));try{process.kill(_.pid,0)}catch{return Z4("helper pid %d dead, removing stale state %s",_.pid,$),s6($),null}let J=Aw();if(J&&!J.has(_.device)){if(_.pid===process.pid){Z4("dropping own stale state for non-booted device %s",_.device);try{s6($)}catch{}return null}Z4("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{s6($)}catch{}return null}return Z4("state ok pid=%d device=%s port=%d",_.pid,_.device,_.port),_}catch(_){return Z4("readStateFile threw for %s: %o",$,_),null}}function Q_(){let $=[];for(let _ of Q1()){let J=uG(_);if(J)$.push(J)}return $}function qw($){fH(),z_($),Z4("wrote state pid=%d device=%s port=%d",$.pid,$.device,$.port)}function N0($){return new Tw($.wsUrl,$.token?{headers:{Authorization:`Bearer ${$.token}`}}:void 0)}function K0($,_){$.on("close",(J,Q)=>{if(J===1013)_(Error(`Simulator input rejected: ${Q.toString()||"server busy"}. Try again shortly.`))})}function z0($){if($){Z4("clearState device=%s",$);try{s6(B0($))}catch{}}else{Z4("clearState (all)");for(let _ of Q1())try{s6(_)}catch{}}}function iG(){try{let $=n4("xcrun simctl list devices -j",{encoding:"utf-8"}),_=JSON.parse($),J=Object.keys(_.devices).filter((Q)=>/SimRuntime\.iOS-/i.test(Q)).sort((Q,U)=>{let X=(Q.match(/iOS-(\d+)-(\d+)/)??[]).slice(1).map(Number),Y=(U.match(/iOS-(\d+)-(\d+)/)??[]).slice(1).map(Number);return(Y[0]??0)-(X[0]??0)||(Y[1]??0)-(X[1]??0)});for(let Q of J){let X=(_.devices[Q]??[]).find((Y)=>Y.isAvailable!==!1&&/^iPhone\b/i.test(Y.name));if(X)return{udid:X.udid,name:X.name}}}catch{}return null}function bH($){return yH().get($)??null}function yH(){let $=new Map;try{let _=n4("xcrun simctl list devices -j",{encoding:"utf-8"}),J=JSON.parse(_);for(let Q of Object.values(J.devices))for(let U of Q)$.set(U.udid,U.name)}catch{}return $}function uH($){try{let _=n4("xcrun simctl list devices -j",{encoding:"utf-8"}),J=JSON.parse(_);for(let Q of Object.values(J.devices))for(let U of Q)if(U.udid===$)return U.state==="Booted"}catch{}return!1}function hG($){try{return process.kill($,0),!0}catch{return!1}}function O8($){try{process.kill($,"SIGTERM")}catch{return}let _=Date.now()+500;while(Date.now()<_)try{process.kill($,0),F6(25)}catch{return}try{process.kill($,"SIGKILL")}catch{}let J=Date.now()+500;while(Date.now()<J)try{process.kill($,0),F6(25)}catch{return}}function Ew($){if(!uH($))try{n4(`xcrun simctl boot ${$}`,{encoding:"utf-8",stdio:"pipe"})}catch(_){let J=(_.stderr??_.message??"").toLowerCase();if(!J.includes("booted")&&!J.includes("current state"))throw Error(`Failed to boot device ${$}: ${_.stderr||_.message}`)}try{Cz($)}catch{}}function Sw(){let $=Rw();for(let _ of Object.values($))for(let J of _??[])if(J.family==="IPv4"&&!J.internal)return J.address;return null}async function hH($){let _=new Set(Q_().map((J)=>J.port));for(let J=$;J<$+100;J++){if(_.has(J))continue;if(await cI(J))return J}throw Error(`No available port found in range ${$}-${$+99}`)}async function nH($){Ew($);try{n4(`xcrun simctl bootstatus ${$} -b`,{encoding:"utf-8",stdio:"pipe",timeout:60000})}catch(_){if(!uH($))console.error(`Device ${$} failed to reach booted state: ${_.stderr||_.message}`),process.exit(1)}await Rz($)}function mH(){for(let $ of _9())try{Hz($,process.pid,(_)=>{if(_.name==="camera")X_($)})}catch(_){console.error(`Could not clean up capabilities on ${$}: ${_ instanceof Error?_.message:String(_)}`)}}var t6=!1,kw;function cG(){return kw??=(async()=>{await P0();for(let $ of _9())await $9($,process.pid,(_)=>{if(_.name==="camera")X_($)})})()}var lH="SERVE_SIM_STREAM_HELPER";function Cw($){if(process.argv[0]&&/(^|\/)serve-sim$/.test(process.argv[0]))return{command:process.argv[0],args:$};return{command:process.argv[0],args:[process.argv[1],...$]}}async function ww($,_=150000){let J=Date.now();while(Date.now()-J<_){let Q=x$($);if(Q)return Q;await new Promise((U)=>setTimeout(U,200))}return null}async function iH($,_,J){E9("startHelper udid=%s port=%d detach=%s",$,_,J.detach);let Q="127.0.0.1";fH(),Ez(_),z0($);let U=S4(v$(),`server-${$}.log`),X=mG(U,"w"),{command:Y,args:W}=Cw(xN($,_,Q,J.stream)),G=xH(Y,W,{detached:J.detach,stdio:["ignore",X,X],env:{...process.env,[lH]:"1"}});if(lG(X),J.detach)G.unref();let I=await ww($);if(!I){if(G.pid)O8(G.pid);let z="";try{z=e6(U,"utf-8").trim()}catch{}console.error(z?`Preview server failed:
321
321
  ${z}`:"Preview server failed to start"),process.exit(1)}return J.detach?{pid:I.pid}:{pid:I.pid,child:G}}async function bw($,_,J,Q,U=!1){q9("follow devices=%o startPort=%d",$,_);let X=$.length>0?$.map(b$):(()=>{let N=e$();if(N)return[N];let K=iG();if(!K)console.error("No device specified and no available iOS simulator found."),process.exit(1);if(!J)console.log(`No booted simulator — booting ${K.name}...`);return[K.udid]})(),Y=new Map,W=[],G=_;for(let N of X){let K=x$(N);if(K)if(U&&!g9(K.streamSettings,Q))O8(K.pid),z0(N);else{if(!J){let F=bH(N)??N;if(X.length>1)console.log(`
322
322
  ==> ${F} (${N}) <==`);console.log(` Already running on port ${K.port}`),console.log(` Stream: ${K.streamUrl}`),console.log(` WebSocket: ${K.wsUrl}`)}W.push(K);continue}G=await hH(G);let{child:D}=await iH(N,G,{detach:!1,stream:Q});if(D)Y.set(N,D);let j=x$(N)??Z6(N,G,"/","127.0.0.1");if(W.push(j),!J){let F=bH(N)??N;if(X.length>1)console.log(`
323
323
  ==> ${F} (${N}) <==`);console.log(` Stream: ${j.streamUrl}`),console.log(` WebSocket: ${j.wsUrl}`),console.log(` Port: ${G}`)}G++}if(W.length===1){let N=W[0];console.log(JSON.stringify({url:N.url,streamUrl:N.streamUrl,wsUrl:N.wsUrl,port:N.port,device:N.device}))}else console.log(JSON.stringify({devices:W.map((N)=>({url:N.url,streamUrl:N.streamUrl,wsUrl:N.wsUrl,port:N.port,device:N.device}))}));if(Y.size===0)return;let I=!1,z=async(N)=>{if(I)return;if(I=!0,t6=!0,!J)console.log(`
@@ -374,5 +374,5 @@ Examples:
374
374
  serve-sim --launch-app-identifier host.exp.Exponent
375
375
  Launch an installed app, then start the stream`).action(async($,_)=>{if(_.list!==void 0){fw(typeof _.list==="string"?_.list:void 0);return}if(_.kill!==void 0){await yw(typeof _.kill==="string"?_.kill:void 0);return}if(_.transport!=="http"&&_.transport!=="webrtc")console.error("--transport must be one of: http, webrtc."),process.exit(1);let J=(Z)=>u$.getOptionValueSource(Z)==="cli",Q=["webrtcCodec","stunUrl","turnUrl","turnUsername","turnCredential"].some(J);if(_.transport==="http"&&Q)console.error("WebRTC options require --transport webrtc."),process.exit(1);if(_.transport==="webrtc"&&J("codec"))console.error("--codec configures HTTP streaming; use --webrtc-codec with --transport webrtc."),process.exit(1);if(_.turnUsername===void 0!==(_.turnCredential===void 0))console.error("--turn-username and --turn-credential must be provided together."),process.exit(1);if((_.turnUsername!==void 0||_.turnCredential!==void 0)&&!_.turnUrl)console.error("--turn-username and --turn-credential require --turn-url."),process.exit(1);let U=_.stunUrl??[],X=[];if(U.length)X.push({urls:U});if(_.turnUrl)X.push({urls:_.turnUrl,username:_.turnUsername,credential:_.turnCredential});let Y=["mjpegFps","mjpegQuality","maxDimension","videoBitrate","videoFps"],W={...J("mjpegFps")?{mjpegFps:_.mjpegFps}:{},...J("mjpegQuality")?{mjpegQuality:_.mjpegQuality}:{},...J("maxDimension")?{maxDimension:_.maxDimension}:{},...J("videoBitrate")?{h264Bitrate:_.videoBitrate}:{},...J("videoFps")?{h264Fps:_.videoFps}:{}},G=_.transport==="webrtc"?{transport:"webrtc",codec:_.webrtcCodec,...X.length?{iceServers:X}:{},...W}:{transport:"http",codec:_.codec,...W},I=typeof _.launchAppIdentifier==="string"?_.launchAppIdentifier.trim():"";if(_.launchAppIdentifier!==void 0&&!I)console.error("--launch-app-identifier needs an app bundle identifier, such as host.exp.Exponent."),process.exit(1);let z=_.launchArg??[],N=_.openUrl;if(!I&&(z.length>0||N))console.error("--launch-arg and --open-url apply to an app launch. Pass --launch-app-identifier with the app to launch."),process.exit(1);let K={enable:_.enable??[],disable:_.disable??[]};try{aI([...K.enable,...K.disable])}catch(Z){console.error(Z instanceof Error?Z.message:Z),process.exit(1)}let D=Boolean(I)||K.enable.length>0||K.disable.length>0||sI(),j=_.port,F=J("transport")||J("codec")||Q||Y.some(J),R=_.debugStream?.trim();if(_.debugStream!==void 0){let Z=!R?"--debug-stream needs a file path, for example --debug-stream ./stream.ndjson":_.detach||_.preview===!1?"--debug-stream needs the preview server, so drop --detach/--no-preview.":G.transport!=="webrtc"?"--debug-stream records sender statistics, which only exist on --transport webrtc.":null;if(Z!==null)console.error(Z),process.exit(1)}if(_.requireToken&&(_.detach||_.preview===!1))console.error("--require-token needs the preview server, so drop --detach/--no-preview. It gates the network-exposed preview; those modes bind loopback only, where the token does nothing."),process.exit(1);if(_.detach){let Z=[...I?["--launch-app-identifier"]:[],...z.length>0?["--launch-arg"]:[],...N?["--open-url"]:[],...K.enable.length>0?["--enable"]:[],...K.disable.length>0?["--disable"]:[]];if(Z.length>0)console.error(`${Z.join(", ")} ${Z.length===1?"needs":"need"} the foreground session, so drop --detach. A detached helper only streams: it does not arm the capability loader or launch an app.`),process.exit(1)}let O=$;if(!_.detach)try{O=dH($);{process.on("exit",mH);for(let H of["SIGINT","SIGTERM","SIGHUP"])process.on(H,async()=>{if(t6=!0,await cG(),process.listenerCount(H)>1)return;process.exit(0)})}for(let H of O)if(await nH(H),t6)return;let Z=process.env[lH]==="1";if(!Z){for(let H of O)if(await Oz(H),t6)return}for(let H of D&&!Z?O:[]){if(t6)return;if(I)await qz(H,{bundleId:I,launchArgs:z,openUrl:N,capabilities:K});else{let v=await T_(H,null,K),T=K.enable.filter((L)=>!v.includes(L));if(T.length>0)console.error(`Requested ${T.join(", ")} but ${T.length===1?"it":"they"} did not apply on ${H}. See the message above for why.`),process.exit(1)}}}catch(Z){console.error(Z instanceof Error?Z.message:Z),process.exit(1)}if(t6)return;if(_.detach){let Z=await xw(O,j??3100,G,F);gw(Z)}else if(_.preview===!1)await bw(O,j??3100,!!_.quiet,G,F);else await Yb(j??3200,O,j!==void 0,_.host,{stream:G,corsOrigins:_.corsOrigin,frameAncestors:_.frameAncestor,shareUrl:_.shareUrl,debugStreamPath:R,requireToken:!!_.requireToken,quiet:!!_.quiet})});var m4=["-d, --device <udid>","Target a specific simulator (udid or name)"];u$.command("gesture").description("Send a touch gesture").argument("<json>",`Gesture JSON, e.g. '{"type":"begin","x":0.5,"y":0.5}'`).option(...m4).action(($,_)=>mw($,_.device));u$.command("tap").description("Tap at normalized 0..1 coords").argument("<x>","X coord, normalized 0..1").argument("<y>","Y coord, normalized 0..1").option(...m4).action(($,_,J)=>lw($,_,J.device));u$.command("button").description("Send a hardware button press").argument("[name]","Button name","home").option(...m4).action(($,_)=>ow($,_.device));u$.command("type").description("Type text (US keyboard only)").argument("[text...]","Text to type").option(...m4).option("--stdin","Read text from stdin").option("--file <path>","Read text from a file").action(($,_)=>iw($,{device:_.device,stdin:_.stdin,file:_.file}));u$.command("rotate").description("Set device orientation (portrait|portrait_upside_down|landscape_left|landscape_right)").argument("<orientation>").option(...m4).action(($,_)=>pw($,_.device));u$.command("hinge").description("Set a foldable simulator's hinge angle (0° folded, 90° half folded, 180° unfolded)").argument("<position>","fold|half|unfold or an angle from 0 to 180 degrees",($)=>{let _=fN($);if(_===void 0)throw new C4("Expected fold, half, unfold, or an angle from 0 to 180");return _}).option(...m4).action(($,_)=>cw($,_.device));u$.command("ca-debug").description("Toggle a CoreAnimation debug render flag (blended|copies|misaligned|offscreen|slow-animations)").argument("<option>").argument("<state>","on|off").option(...m4).action(($,_,J)=>dw($,_,J.device));u$.command("memory-warning").description("Simulate a memory warning on the device").option(...m4).action(($)=>tw($.device));u$.command("event-log").description("Show recent simulator events").option(...m4).option("-j, --json","Print JSON").option("-n, --limit <count>","Maximum number of events").action(($)=>uw($.device,{json:$.json,limit:$.limit}));u$.command("camera").description("Inject a synthetic camera feed and launch an app (see `camera --help`)").allowUnknownOption(!0).helpOption(!1).argument("[args...]").action(($)=>Xb($));u$.command("permissions").description("Manage app permissions (see `permissions` with no args for usage)").allowUnknownOption(!0).helpOption(!1).argument("[args...]").action(($)=>mz($));u$.command("ui").description("Get or set simulator-wide UI options (see `ui --help`)").allowUnknownOption(!0).helpOption(!1).argument("[args...]").action(($)=>KN($));await u$.parseAsync(process.argv);
376
376
 
377
- //# debugId=02FF72EC2F1CCAF164756E2164756E21
377
+ //# debugId=C05944E12CAE819164756E2164756E21
378
378
  //# sourceMappingURL=serve-sim.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/serve-sim",
3
- "version": "0.4.0",
3
+ "version": "0.5.0-canary-20260928-e9c5bcd",
4
4
  "type": "module",
5
5
  "author": {
6
6
  "name": "Evan Bacon",