@expo/serve-sim 0.6.2-canary-20261008-c8a9613 → 0.6.2

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.
@@ -106,7 +106,7 @@ ${X}`});return v.length>0?`${v.join(`
106
106
  `)}
107
107
  `:""}function C0($){let v=BK($.capabilities),J=Buffer.byteLength(v,"utf8");if(J>=mU-1)throw Error(`Capability config is ${J} bytes, over the ${mU} byte limit the capability loader can read. The capability loader would load nothing. Disable capabilities you are not using, or shorten the environment values passed to them.`);return v}function o4($){return HK(Y$(),`capabilities-${$}.conf`)}function yv($,v){zK(Y$(),{recursive:!0});let J=o4($),U=`${J}.${process.pid}.tmp`;jK(U,v),DK(U,J)}function OK($){return HK(Y$(),`capability-inserts-${$}.json`)}function g0($){let v;try{v=VL(OK($),"utf8")}catch(U){if(U.code==="ENOENT")return[];throw U}let J=JSON.parse(v);if(!Array.isArray(J)||!J.every((U)=>typeof U==="string"&&MK(U)&&!U.includes(":")))throw Error(`Invalid startup capability ownership for ${$}. Reboot the simulator before repairing its state.`);return J}function v1($,v){zK(Y$(),{recursive:!0});let J=OK($),U=`${J}.${process.pid}.tmp`;jK(U,JSON.stringify([...new Set(v)])),DK(U,J)}var mU=65536,PL;var lU=Q$(()=>{P4();PL={userApps:"user",allApps:"all"}});import{existsSync as AL,mkdirSync as TL,readFileSync as RL,renameSync as EL,unlinkSync as qL,writeFileSync as SL}from"fs";import{join as kL}from"path";function CL($){return $==="userApps"||$==="allApps"}function iU($){return kL(Y$(),`launch-${$}.json`)}function cU($){if($===null)return!1;try{return process.kill($,0),!1}catch{return!0}}function Z4($,v){let J;try{J=JSON.parse(RL(iU($),"utf-8"))}catch{return null}if(typeof J!=="object"||J===null)return null;let{bundleId:U,launchArgs:_,capabilities:Q,sessionPids:X}=J;return{...typeof U==="string"&&U?{bundleId:U}:{},launchArgs:Array.isArray(_)?_.filter((W)=>typeof W==="string"):[],capabilities:gL(Q,v),...Array.isArray(X)?{sessionPids:X.filter((W)=>Number.isInteger(W)&&W>0&&!cU(W))}:{}}}function gL($,v){if(typeof $!=="object"||$===null)return{};let J={};for(let[U,_]of Object.entries($)){if(typeof _!=="object"||_===null)continue;let{name:Q,dylib:X,scope:W,bundleId:I,ownerPid:Y}=_;if(typeof Q!=="string"||typeof X!=="string"||!CL(W))continue;let G=typeof Y==="number"?Y:null;if(G!==v&&cU(G))continue;J[U]={..._,bundleId:typeof I==="string"?I:null,ownerPid:G}}return J}function pU($){try{qL(iU($))}catch{}}function oU($,v){if(!AL(Y$()))TL(Y$(),{recursive:!0});let J=iU($),U=`${J}.${process.pid}.tmp`;SL(U,JSON.stringify(v)),EL(U,J)}var rU=Q$(()=>{P4()});import{existsSync as tU,readFileSync as VK,rmSync as wL,unlinkSync as bL}from"fs";import{basename as fL,join as PK}from"path";function yL(){return PK(p4(import.meta.url),"..","dist","capability-loader")}function TK(){return[...nv]}function nL($){let v=fL($);return v===AK||v==="libServeSimTrampoline.dylib"}function RK($,v=[]){return $.split(":").map((J)=>J.trim()).filter((J)=>J!==""&&!nL(J)&&!v.includes(J))}async function dU($){return(await x$(["spawn",$,"launchctl","getenv",_1],15000)).trim()}function EK($){return Object.values($).filter((v)=>v.loadPhase==="startup"||v.loadPhase==="startupAndDeferred").map((v)=>v.dylib)}async function uL($,v,J=Z4($)?.capabilities??{},U=g0($)){let _=EK(J),Q=RK(await dU($),U),X=[...new Set([...Q,v,..._])].join(":");v1($,[...U,..._]),await x$(["spawn",$,"launchctl","setenv",w0,o4($)],15000),await x$(["spawn",$,"launchctl","setenv",_1,X],15000),v1($,_),nv.add($)}async function hL($){let v=null;try{v=VK(o4($),"utf8")}catch(Q){if(Q.code!=="ENOENT")throw Q}let J=g0($),U=await dU($),_=(await x$(["spawn",$,"launchctl","getenv",w0],15000)).trim();return{config:v,configPath:_,insert:U,startupDylibs:J}}async function LK($,v,J){await x$(["spawn",$,"launchctl",...J?["setenv",v,J]:["unsetenv",v]],15000)}async function mL($,v,J){if(v1($,[...v.startupDylibs,...J]),v.config===null)wL(o4($),{force:!0});else yv($,v.config);await LK($,w0,v.configPath),await LK($,_1,v.insert),v1($,v.startupDylibs)}function lL($){for(let v of $)if(!tU(v))throw Error(`Startup capability not built: ${v}. Rebuild the native artifacts before enabling it.`)}async function uv($,v){let J=C0(v),U=EK(v.capabilities);lL(U);let _=await hL($),Q=Z4($)?.capabilities??{},X=Object.fromEntries(Object.entries(v.capabilities).filter(([I,Y])=>JSON.stringify(Q[I])===JSON.stringify(Y))),W=C0({...v,capabilities:X});try{if(yv($,W),await uL($,hv(),v.capabilities,_.startupDylibs),J!==W)yv($,J);oU($,v)}catch(I){try{await mL($,_,U)}catch(Y){throw new x0([I,Y],`Could not restore capability launch state on ${$}. Retry cleanup before launching apps.`)}throw I}}function hv(){return PK(yL(),AK)}async function qK($){let v=hv();if(!tU(v))throw Error(`Capability loader not found at ${v}, so capabilities on ${$} cannot be restored. Rebuild serve-sim's native artifacts and try again.`);nv.add($),await vU($,async()=>{let J=Z4($)??{launchArgs:[],capabilities:{}};await uv($,{...J,sessionPids:[...new Set([...J.sessionPids??[],process.pid])]})})}async function iL($){await x$(["spawn",$,"launchctl","unsetenv",w0],15000).catch(()=>{return});let v=RK(await dU($),g0($)).join(":");await x$(v===""?["spawn",$,"launchctl","unsetenv",_1]:["spawn",$,"launchctl","setenv",_1,v],15000),v1($,[]);try{bL(o4($))}catch{}nv.delete($)}function SK($,v,J){if(!v.exclusive)return!1;let U=Z4($)?.capabilities[v.name];return U!==void 0&&U.ownerPid!==J}function cL($,v,J){if(SK($,v,J))throw Error(`Capability ${v.name} on ${$} belongs to another session. Stop that session before enabling it here.`)}async function kK($,v,{bundleId:J=null,options:U={},enabled:_,relaunch:Q=!0,ownerPid:X=process.pid}){let W={udid:$,bundleId:J,options:U,enabled:_};await vU($,async()=>{if(!_){if(!SK($,v,X))await dL($,J,v.name,{relaunch:!1});await v.setEnabled(W);return}cL($,v,X);let I=await NK(v,W);if(!I)throw Error(`Capability ${v.name} declined to start on ${$}. Check its configuration and retry.`);if(await pL($,J,[I],X),Q){let Y=Z4($);if(Y)await aU($,J,Y)}})}async function pL($,v,J,U=process.pid){let _=Z4($);try{let Q=J.map(({capability:X})=>X);await oL($,v,Q,{relaunch:!1,ownerPid:U})}catch(Q){let X=nU(J,Q);if(Q instanceof x0){if(X.length>0)throw new x0([Q,...X],Q.message);throw Q}throw await uU($,J,Q,X),Q}try{for(let{resources:Q}of J)Q.committed?.()}catch(Q){let X=nU(J,Q);try{if(_)await uv($,_);else await iL($),pU($)}catch(W){throw new x0([Q,W,...X],`Could not withdraw a failed capability on ${$}; its resources were kept. Retry cleanup before launching apps.`)}throw await uU($,J,Q,X),Q}}async function oL($,v,J,{relaunch:U=!0,ownerPid:_=process.pid}={}){if(J.length===0)return;let Q=hv();if(!tU(Q))throw Error(`Capability loader not built: ${Q} is missing. Run \`bun run packages/serve-sim/build.ts\` to build the native artifacts, then retry.`);let X=Z4($),W=Object.fromEntries(J.map((Y)=>[Y.name,{...Y,bundleId:v,ownerPid:_}])),I={...X??{launchArgs:[],capabilities:{}},capabilities:{...X?.capabilities,...W}};if(await uv($,I),U)await aU($,v,I)}async function rL($,v){let J=await x$(["spawn",$,"launchctl","list"],15000).catch(()=>null);if(J===null)return null;return J.includes(`UIKitApplication:${v}`)}async function tL($,v){try{await x$(["terminate",$,v],ZK);return}catch{}let J=await rL($,v);if(J===!1)return;throw Error(J===null?`Could not stop ${v} on ${$}, and could not check whether it is still running. Relaunching now would do nothing if it is. Check the simulator and retry.`:`Could not stop ${v} on ${$}, so it cannot be relaunched with its capabilities loaded. simctl terminate did not take effect within ${ZK/1000}s. Stop the app yourself and retry.`)}async function aU($,v,J){let U=v??J.bundleId;if(!U)return;let _=U===J.bundleId?J.launchArgs:[];await tL($,U),await x$(["launch",$,U,..._])}async function FK($,v){try{return await uv($,v),!0}catch(J){if(!fv(J))throw J;return oU($,v),!1}}async function dL($,v,J,{relaunch:U=!0}={}){let _=Z4($);if(!_||!(J in _.capabilities)){if(g0($).length>0)await FK($,_??{launchArgs:[],capabilities:{}});return}let Q=Object.fromEntries(Object.entries(_.capabilities).filter(([I])=>I!==J)),X={..._,capabilities:Q},W=await FK($,X);if(U&&W)await aU($,v,X)}async function CK($,v,J={},U=x$){let _=Z4($)?.capabilities[v];if(!_||Object.entries(J).some(([K,N])=>_.env?.[K]!==N))return!1;let Q=o4($);if((await U(["spawn",$,"launchctl","getenv",w0])).trim()!==Q)return!1;let X;try{X=VK(Q,"utf8")}catch(K){if(K.code==="ENOENT")return!1;throw K}let W=C0({launchArgs:[],capabilities:{[v]:_}}).trimEnd().split(`
108
108
  `),I=new Set(X.split(`
109
- `));if(!W.every((K)=>I.has(K)))return!1;let Y=(await U(["spawn",$,"launchctl","getenv",_1])).trim().split(":"),G=_.loadPhase==="startup"||_.loadPhase==="startupAndDeferred";return Y.includes(hv())&&(!G||Y.includes(_.dylib))}var AK="libServeSimCapabilityLoader.dylib",_1="DYLD_INSERT_LIBRARIES",w0="SERVE_SIM_CAPABILITIES_CONFIG",ZK=15000,nv,x0;var mv=Q$(()=>{KK();lU();rU();zv();k0();Z0();bv();rU();lU();zv();nv=new Set;x0=class x0 extends AggregateError{}});import{existsSync as aL,mkdtempSync as eL,readFileSync as sL,rmSync as $F,writeFileSync as vF}from"node:fs";import{tmpdir as _F}from"node:os";import{join as b0}from"node:path";async function gK($,v){let J=eL(b0(_F(),"serve-sim-ca-")),U=b0(J,"capture-root.crt");try{vF(U,v),await x$(["keychain",$,"add-root-cert",U])}finally{$F(J,{recursive:!0,force:!0})}}function JF(){return[b0(eU,"simnet",sU),b0(eU,"..","dist","simnet",sU),b0(eU,"..","..","dist","simnet",sU)]}function xK(){return JF().find(($)=>aL($))??null}async function wK($,v,J={}){let U;try{U=Number(sL(v,"utf8").trim())}catch(_){if(_.code==="ENOENT")return!1;throw _}if(!Number.isInteger(U)||U<1||U>65535||J.expectedPort!==void 0&&U!==J.expectedPort)return!1;return CK($,"networkCapture",{SIMNET_PROXY_PORT_FILE:v},J.read)}var eU,sU="libSimNetProxy.dylib";var bK=Q$(()=>{mv();Z0();bv();eU=p4(import.meta.url)});import{readFileSync as UF}from"node:fs";import{dirname as QF,join as XF}from"node:path";import{fileURLToPath as WF}from"node:url";function lv(){return"0.6.2-canary-20261008-c8a9613"}var $9=()=>{};class yK{#$=new Map;enqueue($,v){let J=this.#$.get($),U=J?J.then(v):v(),_=U.then(()=>{},()=>{});return this.#$.set($,_),_.then(()=>{if(this.#$.get($)===_)this.#$.delete($)}),U}devices(){return this.#$.keys()}}function iv($,v){return{schemaVersion:R0,udid:$,proxyAddress:null,attachment:"not-enabled",attachError:null,droppedOversizedBodies:0,fields:[...v]}}function nK($,v){return{...iv($,v),attachment:"failed",attachError:"Capture was turned off while it was waiting to start. Enable it again to retry."}}function J1($,v){if(v.cancelled)throw new f4(nK($,v.fields))}function KF($){if(uK.add($),fK)return;fK=!0,process.on("exit",NF)}function NF(){for(let $ of uK)$()}function v9($={}){let v=$.fields??P6,J=$.startProxy??((Z,T)=>WK(Z,T)),U=$.trustCa??gK,_=$.configure??kK,Q=$.dylib??xK,X=$.isInjected??((Z,T,k)=>wK(Z,T,{expectedPort:Number(new URL(`http://${k}`).port)})),W=$.checkIntervalMs??IF,I=$.writeDiskArtifacts!==!1,Y=$.creatorVersion??"0.0.0",G=new Map,K=()=>{for(let Z of G.values())try{Z.disk?.discardSync()}catch{}},N=new Map,z=new yK,j=new Map,L=null,P=new Map,V=new Map,O=(Z,T)=>{for(let k of P.get(Z)??[])try{k(T)}catch{}},F=(Z)=>G.get(Z)?.meta??V.get(Z)??iv(Z,v),A=(Z,T)=>{if(!I)return{disk:null,stopDisk:null};if(!$.captureDirFor)zU([...G.keys(),Z]);let k=$.captureDirFor?{dir:$.captureDirFor(Z),networkCapturePath:void 0,harPath:void 0}:Vv(Z),g=new V6({dir:k.dir,networkCapturePath:k.networkCapturePath,harPath:k.harPath,creatorVersion:Y,flushIntervalMs:$.flushIntervalMs,harRebuildIntervalMs:GF});return KF(K),{disk:g,stopDisk:g.attach(T)}},R=async(Z,T)=>{if(T.cleanup??=(async()=>{await T.proxy?.close(),T.proxy=null,T.meta.proxyAddress=null,await T.stopDisk?.(),T.stopDisk=null,T.disk=null})().catch((k)=>{throw T.cleanup=void 0,console.warn(`Network capture: cleanup for ${Z} failed:`,k),k}),await T.cleanup,G.get(Z)===T)G.delete(Z)},B=async(Z,T)=>{if(L)throw Error(L);if(T)J1(Z,T);let k=G.get(Z);if(k?.proxy){if(k.meta.attachment==="failed")throw Error("The previous capture session failed. Disable capture before retrying so its launch configuration can be removed safely.");return{dylib:M(),env:{SIMNET_PROXY_PORT_FILE:k.proxy.portFile}}}let g=M(),u=[...T?.fields??v],m=new E0,h={schemaVersion:R0,udid:Z,proxyAddress:null,attachment:"starting",attachError:null,droppedOversizedBodies:0,fields:u},n={store:m,meta:h,proxy:null,...A(Z,m)};m.subscribe((l)=>{if(G.get(Z)===n)O(Z,l)}),V.delete(Z),G.set(Z,n),O(Z,{type:"cleared"}),O(Z,{type:"meta",meta:h});try{let l=await J(m,{fields:u,onUnexpectedExit:(t)=>{if(G.get(Z)!==n)return;h.attachment="failed",h.attachError=`${t}
109
+ `));if(!W.every((K)=>I.has(K)))return!1;let Y=(await U(["spawn",$,"launchctl","getenv",_1])).trim().split(":"),G=_.loadPhase==="startup"||_.loadPhase==="startupAndDeferred";return Y.includes(hv())&&(!G||Y.includes(_.dylib))}var AK="libServeSimCapabilityLoader.dylib",_1="DYLD_INSERT_LIBRARIES",w0="SERVE_SIM_CAPABILITIES_CONFIG",ZK=15000,nv,x0;var mv=Q$(()=>{KK();lU();rU();zv();k0();Z0();bv();rU();lU();zv();nv=new Set;x0=class x0 extends AggregateError{}});import{existsSync as aL,mkdtempSync as eL,readFileSync as sL,rmSync as $F,writeFileSync as vF}from"node:fs";import{tmpdir as _F}from"node:os";import{join as b0}from"node:path";async function gK($,v){let J=eL(b0(_F(),"serve-sim-ca-")),U=b0(J,"capture-root.crt");try{vF(U,v),await x$(["keychain",$,"add-root-cert",U])}finally{$F(J,{recursive:!0,force:!0})}}function JF(){return[b0(eU,"simnet",sU),b0(eU,"..","dist","simnet",sU),b0(eU,"..","..","dist","simnet",sU)]}function xK(){return JF().find(($)=>aL($))??null}async function wK($,v,J={}){let U;try{U=Number(sL(v,"utf8").trim())}catch(_){if(_.code==="ENOENT")return!1;throw _}if(!Number.isInteger(U)||U<1||U>65535||J.expectedPort!==void 0&&U!==J.expectedPort)return!1;return CK($,"networkCapture",{SIMNET_PROXY_PORT_FILE:v},J.read)}var eU,sU="libSimNetProxy.dylib";var bK=Q$(()=>{mv();Z0();bv();eU=p4(import.meta.url)});import{readFileSync as UF}from"node:fs";import{dirname as QF,join as XF}from"node:path";import{fileURLToPath as WF}from"node:url";function lv(){return"0.6.2"}var $9=()=>{};class yK{#$=new Map;enqueue($,v){let J=this.#$.get($),U=J?J.then(v):v(),_=U.then(()=>{},()=>{});return this.#$.set($,_),_.then(()=>{if(this.#$.get($)===_)this.#$.delete($)}),U}devices(){return this.#$.keys()}}function iv($,v){return{schemaVersion:R0,udid:$,proxyAddress:null,attachment:"not-enabled",attachError:null,droppedOversizedBodies:0,fields:[...v]}}function nK($,v){return{...iv($,v),attachment:"failed",attachError:"Capture was turned off while it was waiting to start. Enable it again to retry."}}function J1($,v){if(v.cancelled)throw new f4(nK($,v.fields))}function KF($){if(uK.add($),fK)return;fK=!0,process.on("exit",NF)}function NF(){for(let $ of uK)$()}function v9($={}){let v=$.fields??P6,J=$.startProxy??((Z,T)=>WK(Z,T)),U=$.trustCa??gK,_=$.configure??kK,Q=$.dylib??xK,X=$.isInjected??((Z,T,k)=>wK(Z,T,{expectedPort:Number(new URL(`http://${k}`).port)})),W=$.checkIntervalMs??IF,I=$.writeDiskArtifacts!==!1,Y=$.creatorVersion??"0.0.0",G=new Map,K=()=>{for(let Z of G.values())try{Z.disk?.discardSync()}catch{}},N=new Map,z=new yK,j=new Map,L=null,P=new Map,V=new Map,O=(Z,T)=>{for(let k of P.get(Z)??[])try{k(T)}catch{}},F=(Z)=>G.get(Z)?.meta??V.get(Z)??iv(Z,v),A=(Z,T)=>{if(!I)return{disk:null,stopDisk:null};if(!$.captureDirFor)zU([...G.keys(),Z]);let k=$.captureDirFor?{dir:$.captureDirFor(Z),networkCapturePath:void 0,harPath:void 0}:Vv(Z),g=new V6({dir:k.dir,networkCapturePath:k.networkCapturePath,harPath:k.harPath,creatorVersion:Y,flushIntervalMs:$.flushIntervalMs,harRebuildIntervalMs:GF});return KF(K),{disk:g,stopDisk:g.attach(T)}},R=async(Z,T)=>{if(T.cleanup??=(async()=>{await T.proxy?.close(),T.proxy=null,T.meta.proxyAddress=null,await T.stopDisk?.(),T.stopDisk=null,T.disk=null})().catch((k)=>{throw T.cleanup=void 0,console.warn(`Network capture: cleanup for ${Z} failed:`,k),k}),await T.cleanup,G.get(Z)===T)G.delete(Z)},B=async(Z,T)=>{if(L)throw Error(L);if(T)J1(Z,T);let k=G.get(Z);if(k?.proxy){if(k.meta.attachment==="failed")throw Error("The previous capture session failed. Disable capture before retrying so its launch configuration can be removed safely.");return{dylib:M(),env:{SIMNET_PROXY_PORT_FILE:k.proxy.portFile}}}let g=M(),u=[...T?.fields??v],m=new E0,h={schemaVersion:R0,udid:Z,proxyAddress:null,attachment:"starting",attachError:null,droppedOversizedBodies:0,fields:u},n={store:m,meta:h,proxy:null,...A(Z,m)};m.subscribe((l)=>{if(G.get(Z)===n)O(Z,l)}),V.delete(Z),G.set(Z,n),O(Z,{type:"cleared"}),O(Z,{type:"meta",meta:h});try{let l=await J(m,{fields:u,onUnexpectedExit:(t)=>{if(G.get(Z)!==n)return;h.attachment="failed",h.attachError=`${t}
110
110
 
111
111
  Relaunch apps after restarting capture; their existing sessions may still point at the stopped proxy.`,m.publishMeta(h)},onOversizedControlBody:()=>{if(G.get(Z)!==n)return;h.droppedOversizedBodies+=1,m.publishMeta(h)}});if(n.proxy=l,h.proxyAddress=l.address,T)J1(Z,T);if(await U(Z,await l.caPem()),T)J1(Z,T);if(h.attachment==="failed")throw Error(h.attachError??"The capture proxy stopped during startup.");return{dylib:g,env:{SIMNET_PROXY_PORT_FILE:l.portFile},committed(){if(h.attachment==="failed")throw Error(h.attachError??"The capture proxy stopped during startup.");h.attachment="capturing",m.publishMeta(h)},failed(t){h.attachment="failed",h.attachError=t instanceof Error?t.message:String(t),m.publishMeta(h)},async rollback(){if(T)T.failed=!0;await R(Z,n),G.set(Z,n)}}}catch(l){if(T)T.failed=!0;throw h.attachment="failed",h.attachError=l instanceof Error?l.message:String(l),await R(Z,n),G.set(Z,n),m.publishMeta(h),l}};function M(){let Z=Q();if(!Z)throw Error("Network capture library is missing. Rebuild serve-sim's native artifacts before enabling capture.");return Z}let H={name:"networkCapture",exclusive:!0,scope:"userApps",loadPhase:"startupAndDeferred",defaultEnabled:!1,async setEnabled({udid:Z,enabled:T}){if(T)return B(Z);let k=G.get(Z);if(k)await R(Z,k);if(V.delete(Z),!G.has(Z))O(Z,{type:"meta",meta:iv(Z,v)});return null}},D=(Z)=>_(Z,H,{enabled:!1,relaunch:!1}),C=(Z)=>{let T=j.get(Z);if(T)T.cancelled=!0;return j.delete(Z),z.enqueue(Z,()=>D(Z))};return{capability:H,shouldCaptureDevice(Z,T){return N.get(Z)??T},setDeviceCaptureEnabled(Z,T){N.set(Z,T)},creatorVersion:Y,setFields(Z){v=Z},enableForDevice(Z){let T=j.get(Z);if(T&&!T.failed)return T.promise;let k={cancelled:!1,failed:!1,fields:[...v],promise:Promise.resolve(iv(Z,v))},g=z.enqueue(Z,async()=>{J1(Z,k);try{if(L)throw Error(L);if(G.get(Z)?.meta.attachment==="failed")await D(Z),J1(Z,k);if(await _(Z,{...H,setEnabled:({enabled:n})=>n?B(Z,k):H.setEnabled({udid:Z,enabled:!1,bundleId:null,options:{}})},{enabled:!0,relaunch:!1}),k.cancelled)await D(Z),J1(Z,k);let h=G.get(Z);if(!h)throw Error("The capture session disappeared during startup. Enable capture again.");return h.meta}catch(m){k.failed=!0;let h=G.get(Z),n=h?.meta??nK(Z,k.fields);if(n.attachment="failed",n.attachError=m instanceof Error?m.message:String(m),h)h.store.publishMeta(n);else V.set(Z,n),O(Z,{type:"meta",meta:n});throw new f4(n)}});k.promise=g,j.set(Z,k);let u=()=>{if(j.get(Z)===k)j.delete(Z)};return g.then(u,u),g},disableForDevice:C,refuseCapture(Z){L=Z},async disableAll(){let Z=new Set([...G.keys(),...V.keys(),...z.devices()]),k=(await Promise.allSettled([...Z].map(C))).flatMap((g)=>g.status==="rejected"?[g.reason]:[]);if(k.length>0)throw AggregateError(k,`Could not disable network capture on ${k.length} device(s).`)},discardArtifactsSync:K,subscribe(Z,T){let k=P.get(Z);if(!k)P.set(Z,k=new Set);return k.add(T),{meta:F(Z),unsubscribe:()=>{if(k.delete(T),k.size===0&&P.get(Z)===k)P.delete(Z)}}},metaFor(Z){return F(Z)},async refreshForDevice(Z){let T=G.get(Z);if(!T)return F(Z);if(T.meta.attachment!=="capturing"||!T.proxy)return T.meta;let k=Date.now();if(T.checking)return T.checking;if(T.checkedAt!==void 0&&k-T.checkedAt<W)return T.meta;let g=T.proxy.portFile,u=T.proxy.address;return T.checking=(async()=>{try{let m;try{m=await X(Z,g,u)}catch(h){if(!fv(h))return console.warn(`Network capture: injection probe for ${Z} failed:`,h instanceof Error?h.message:h),T.injectMisses=0,T.meta;m=!1}if(m)return T.injectMisses=0,T.meta;if(G.get(Z)!==T||T.meta.attachment!=="capturing")return T.meta;if(T.injectMisses=(T.injectMisses??0)+1,T.injectMisses<YF)return T.meta;return T.meta.attachment="failed",T.meta.attachError="This device stopped capturing. It may have restarted or shut down since capture was enabled. Enable capture again after it boots.",T.store.publishMeta(T.meta),T.meta}finally{T.checkedAt=Date.now(),T.checking=void 0}})(),T.checking},storeFor(Z){return G.get(Z)?.store??null},artifactPathsFor(Z){let T=G.get(Z)?.disk;if(!T)return null;return{networkCapturePath:T.networkCapturePath,harPath:T.harPath,entriesPath:T.entriesPath}},async flushEntriesPathFor(Z){let T=G.get(Z)?.disk;if(!T)return null;return await T.flushEntries(),T.entriesPath},async flushHarPathFor(Z){let T=G.get(Z)?.disk;if(!T)return null;return await T.flush(),T.harPath},clearForDevice(Z){let T=G.get(Z);if(!T)return!1;return T.store.clear(),!0},throughputFor(Z){let T=G.get(Z);if(!T||T.meta.attachment!=="capturing")return null;return T.store.throughput()}}}var f4,IF=1e4,YF=2,GF=60000,uK,fK=!1,P$;var cv=Q$(()=>{k0();bK();mv();Pv();L0();yU();$9();f4=class f4 extends Error{meta;constructor($){super($.attachError??"Network capture could not start");this.name="CaptureEnableError",this.meta=$}};uK=new Set;P$=v9({creatorVersion:lv()})});var mK=O6((Xf,hK)=>{var U1=1000,Q1=U1*60,X1=Q1*60,T6=X1*24,zF=T6*7,DF=T6*365.25;hK.exports=function($,v){v=v||{};var J=typeof $;if(J==="string"&&$.length>0)return jF($);else if(J==="number"&&isFinite($))return v.long?HF($):MF($);throw Error("val is not a non-empty string or a valid number. val="+JSON.stringify($))};function jF($){if($=String($),$.length>100)return;var v=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec($);if(!v)return;var J=parseFloat(v[1]),U=(v[2]||"ms").toLowerCase();switch(U){case"years":case"year":case"yrs":case"yr":case"y":return J*DF;case"weeks":case"week":case"w":return J*zF;case"days":case"day":case"d":return J*T6;case"hours":case"hour":case"hrs":case"hr":case"h":return J*X1;case"minutes":case"minute":case"mins":case"min":case"m":return J*Q1;case"seconds":case"second":case"secs":case"sec":case"s":return J*U1;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return J;default:return}}function MF($){var v=Math.abs($);if(v>=T6)return Math.round($/T6)+"d";if(v>=X1)return Math.round($/X1)+"h";if(v>=Q1)return Math.round($/Q1)+"m";if(v>=U1)return Math.round($/U1)+"s";return $+"ms"}function HF($){var v=Math.abs($);if(v>=T6)return pv($,v,T6,"day");if(v>=X1)return pv($,v,X1,"hour");if(v>=Q1)return pv($,v,Q1,"minute");if(v>=U1)return pv($,v,U1,"second");return $+" ms"}function pv($,v,J,U){var _=v>=J*1.5;return Math.round($/J)+" "+U+(_?"s":"")}});var _9=O6((Wf,lK)=>{function BF($){J.debug=J,J.default=J,J.coerce=I,J.disable=X,J.enable=_,J.enabled=W,J.humanize=mK(),J.destroy=Y,Object.keys($).forEach((G)=>{J[G]=$[G]}),J.names=[],J.skips=[],J.formatters={};function v(G){let K=0;for(let N=0;N<G.length;N++)K=(K<<5)-K+G.charCodeAt(N),K|=0;return J.colors[Math.abs(K)%J.colors.length]}J.selectColor=v;function J(G){let K,N=null,z,j;function L(...P){if(!L.enabled)return;let V=L,O=Number(new Date),F=O-(K||O);if(V.diff=F,V.prev=K,V.curr=O,K=O,P[0]=J.coerce(P[0]),typeof P[0]!=="string")P.unshift("%O");let A=0;P[0]=P[0].replace(/%([a-zA-Z%])/g,(B,M)=>{if(B==="%%")return"%";A++;let H=J.formatters[M];if(typeof H==="function"){let D=P[A];B=H.call(V,D),P.splice(A,1),A--}return B}),J.formatArgs.call(V,P),(V.log||J.log).apply(V,P)}if(L.namespace=G,L.useColors=J.useColors(),L.color=J.selectColor(G),L.extend=U,L.destroy=J.destroy,Object.defineProperty(L,"enabled",{enumerable:!0,configurable:!1,get:()=>{if(N!==null)return N;if(z!==J.namespaces)z=J.namespaces,j=J.enabled(G);return j},set:(P)=>{N=P}}),typeof J.init==="function")J.init(L);return L}function U(G,K){let N=J(this.namespace+(typeof K>"u"?":":K)+G);return N.log=this.log,N}function _(G){J.save(G),J.namespaces=G,J.names=[],J.skips=[];let K=(typeof G==="string"?G:"").trim().replace(/\s+/g,",").split(",").filter(Boolean);for(let N of K)if(N[0]==="-")J.skips.push(N.slice(1));else J.names.push(N)}function Q(G,K){let N=0,z=0,j=-1,L=0;while(N<G.length)if(z<K.length&&(K[z]===G[N]||K[z]==="*"))if(K[z]==="*")j=z,L=N,z++;else N++,z++;else if(j!==-1)z=j+1,L++,N=L;else return!1;while(z<K.length&&K[z]==="*")z++;return z===K.length}function X(){let G=[...J.names,...J.skips.map((K)=>"-"+K)].join(",");return J.enable(""),G}function W(G){for(let K of J.skips)if(Q(G,K))return!1;for(let K of J.names)if(Q(G,K))return!0;return!1}function I(G){if(G instanceof Error)return G.stack||G.message;return G}function Y(){console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.")}return J.enable(J.load()),J}lK.exports=BF});var cK=O6((iK,ov)=>{iK.formatArgs=ZF;iK.save=LF;iK.load=FF;iK.useColors=OF;iK.storage=VF();iK.destroy=(()=>{let $=!1;return()=>{if(!$)$=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.")}})();iK.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"];function OF(){if(typeof window<"u"&&window.process&&(window.process.type==="renderer"||window.process.__nwjs))return!0;if(typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))return!1;let $;return typeof document<"u"&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||typeof window<"u"&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||typeof navigator<"u"&&navigator.userAgent&&($=navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/))&&parseInt($[1],10)>=31||typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)}function ZF($){if($[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+$[0]+(this.useColors?"%c ":" ")+"+"+ov.exports.humanize(this.diff),!this.useColors)return;let v="color: "+this.color;$.splice(1,0,v,"color: inherit");let J=0,U=0;$[0].replace(/%[a-zA-Z%]/g,(_)=>{if(_==="%%")return;if(J++,_==="%c")U=J}),$.splice(U,0,v)}iK.log=console.debug||console.log||(()=>{});function LF($){try{if($)iK.storage.setItem("debug",$);else iK.storage.removeItem("debug")}catch(v){}}function FF(){let $;try{$=iK.storage.getItem("debug")||iK.storage.getItem("DEBUG")}catch(v){}if(!$&&typeof process<"u"&&"env"in process)$=process.env.DEBUG;return $}function VF(){try{return localStorage}catch($){}}ov.exports=_9()(iK);var{formatters:PF}=ov.exports;PF.j=function($){try{return JSON.stringify($)}catch(v){return"[UnexpectedJSONParseError]: "+v.message}}});var oK=O6((Yf,pK)=>{pK.exports=($,v=process.argv)=>{let J=$.startsWith("-")?"":$.length===1?"-":"--",U=v.indexOf(J+$),_=v.indexOf("--");return U!==-1&&(_===-1||U<_)}});var dK=O6((Gf,tK)=>{var CF=Y0("os"),rK=Y0("tty"),K4=oK(),{env:w$}=process,r4;if(K4("no-color")||K4("no-colors")||K4("color=false")||K4("color=never"))r4=0;else if(K4("color")||K4("colors")||K4("color=true")||K4("color=always"))r4=1;if("FORCE_COLOR"in w$)if(w$.FORCE_COLOR==="true")r4=1;else if(w$.FORCE_COLOR==="false")r4=0;else r4=w$.FORCE_COLOR.length===0?1:Math.min(parseInt(w$.FORCE_COLOR,10),3);function J9($){if($===0)return!1;return{level:$,hasBasic:!0,has256:$>=2,has16m:$>=3}}function U9($,v){if(r4===0)return 0;if(K4("color=16m")||K4("color=full")||K4("color=truecolor"))return 3;if(K4("color=256"))return 2;if($&&!v&&r4===void 0)return 0;let J=r4||0;if(w$.TERM==="dumb")return J;if(process.platform==="win32"){let U=CF.release().split(".");if(Number(U[0])>=10&&Number(U[2])>=10586)return Number(U[2])>=14931?3:2;return 1}if("CI"in w$){if(["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI","GITHUB_ACTIONS","BUILDKITE"].some((U)=>(U in w$))||w$.CI_NAME==="codeship")return 1;return J}if("TEAMCITY_VERSION"in w$)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(w$.TEAMCITY_VERSION)?1:0;if(w$.COLORTERM==="truecolor")return 3;if("TERM_PROGRAM"in w$){let U=parseInt((w$.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(w$.TERM_PROGRAM){case"iTerm.app":return U>=3?3:2;case"Apple_Terminal":return 2}}if(/-256(color)?$/i.test(w$.TERM))return 2;if(/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(w$.TERM))return 1;if("COLORTERM"in w$)return 1;return J}function gF($){let v=U9($,$&&$.isTTY);return J9(v)}tK.exports={supportsColor:gF,stdout:J9(U9(!0,rK.isatty(1))),stderr:J9(U9(!0,rK.isatty(2)))}});var $N=O6((eK,tv)=>{var xF=Y0("tty"),rv=Y0("util");eK.init=hF;eK.log=yF;eK.formatArgs=bF;eK.save=nF;eK.load=uF;eK.useColors=wF;eK.destroy=rv.deprecate(()=>{},"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");eK.colors=[6,2,3,4,5,1];try{let $=dK();if($&&($.stderr||$).level>=2)eK.colors=[20,21,26,27,32,33,38,39,40,41,42,43,44,45,56,57,62,63,68,69,74,75,76,77,78,79,80,81,92,93,98,99,112,113,128,129,134,135,148,149,160,161,162,163,164,165,166,167,168,169,170,171,172,173,178,179,184,185,196,197,198,199,200,201,202,203,204,205,206,207,208,209,214,215,220,221]}catch($){}eK.inspectOpts=Object.keys(process.env).filter(($)=>{return/^debug_/i.test($)}).reduce(($,v)=>{let J=v.substring(6).toLowerCase().replace(/_([a-z])/g,(_,Q)=>{return Q.toUpperCase()}),U=process.env[v];if(/^(yes|on|true|enabled)$/i.test(U))U=!0;else if(/^(no|off|false|disabled)$/i.test(U))U=!1;else if(U==="null")U=null;else U=Number(U);return $[J]=U,$},{});function wF(){return"colors"in eK.inspectOpts?Boolean(eK.inspectOpts.colors):xF.isatty(process.stderr.fd)}function bF($){let{namespace:v,useColors:J}=this;if(J){let U=this.color,_="\x1B[3"+(U<8?U:"8;5;"+U),Q=` ${_};1m${v} \x1B[0m`;$[0]=Q+$[0].split(`
112
112
  `).join(`
@@ -315,5 +315,5 @@ ${h}`)}})();return}if(!k){D.destroy();return}let u=k.device??T;if(AI(k.upstreamP
315
315
  \r
316
316
  `)};let B=async(H)=>{return QH(R,H)},M=yM({path:`${J}/exec-ws`,execToken:W,corsOrigins:Y,ssePrefixes:Ag(J),onUiRequest:O,serveSimBinPath:kg(),onActionResult:(H,D,C)=>Ug(H,D,C),onSseRequest(H,D){let C=new URL(H,D.url),Z=D.headers.get("origin"),T=D.headers.get("sec-fetch-site");return B(new Request(C,{headers:{accept:"text/event-stream",authorization:`Bearer ${W}`,...Z?{origin:Z}:{},...T?{"sec-fetch-site":T}:{}}}))}});return B.handleWebSocket=(H,D)=>{if(D.on("error",()=>D.close()),!j(H.headers.get("host"))||!EU(A0(H),W,{required:I}))return D.close(),!0;if(M(H,D))return!0;if(_H(H,D,{helperProxyTarget:(C)=>cI(C,U),fallbackDevice:$?.device??null,resolveSession:(C)=>N1(C,v)}))return!0;return!1},B.handleUpgrade=(H,D,C)=>{R.handleUpgrade?.(H,D,C)},B}export{Lg as startDeviceInProcess,Ag as sseStreamPaths,mi as simMiddleware,v4 as selectServeSimState,g8 as rewriteStateForRequestHost,Vg as retryPendingCaptureCleanup,l$ as readServeSimStates,oI as previewConfigForState,oH as parseGridPaging,hi as matchInstalledAppByDisplayName,hg as handleNetworkCaptureRequest,ug as handleMetricsRequest,ng as handleLogsRequest,eM as handleCrashesRequest,VI as handleCrashReportRequest,lg as handleCaptureHarRequest,ig as handleCaptureEntriesRequest,mg as handleCaptureBodyRequest,Og as gridStateToken,Zg as gridDeviceState,Fg as enableNetworkCaptureForStartedDevice,sI as disableNetworkCaptureForStoppedDevice,Gg as deviceNameFromBootedNames};
317
317
 
318
- //# debugId=4EC56EF3FDB4ED6B64756E2164756E21
318
+ //# debugId=95322A96CBFCAD2064756E2164756E21
319
319
  //# sourceMappingURL=middleware.js.map
Binary file
package/dist/serve-sim.js CHANGED
@@ -100,7 +100,7 @@ button:hover{background:#ccc}
100
100
  `);if(U=_.pop()??"",U.length>4096)U="";for(let X of _)if(X.startsWith("[servesim-capture]"))J(X.trimEnd())})}function _A($={}){let J=$.list??(()=>{try{return uP(RQ()).filter((G)=>G.startsWith(Xj)).map((G)=>b$(RQ(),G))}catch{return[]}}),U=$.psOutput??(()=>{let G=PQ("ps",["-eo","pid=,command="],{encoding:"utf8"});return G.status===0&&typeof G.stdout==="string"?G.stdout:null}),Q=$.remove??((G)=>n1(G,{recursive:!0,force:!0})),_=$.ageMs??((G)=>{try{return Date.now()-_j(G).mtimeMs}catch{return 0}}),X=U();if(X===null)return 0;let Y=0;for(let G of J()){if(X.includes(Qj(G))||_(G)<$A)continue;try{Q(G),Y++}catch{}}return Y}async function UA(){let $=bP();return new Promise((J,U)=>{$.once("error",U),$.listen(0,"127.0.0.1",()=>{let Q=$.address();if(Q==null||typeof Q==="string"){$.close(()=>U(Error("Could not reserve a local port for the capture proxy.")));return}let{port:_}=Q;$.close(()=>J(_))})})}function QA($,J,U){let Q=[];for(let _ of $.split(`
101
101
  `)){if(!_.includes(J))continue;let X=Number(_.trim().split(/\s+/)[0]);if(Number.isFinite(X)&&X!==U)Q.push(X)}return Q}function TQ(){for(let $ of qQ)try{$()}catch{}}function zj($){if(process.listenerCount($)>1)return;TQ(),process.removeListener("exit",TQ);for(let J of Gj)process.removeListener(J,zj);process.kill(process.pid,$)}function XA($){if(qQ.add($),eD)return;eD=!0,process.once("exit",TQ);for(let J of Gj)process.on(J,zj)}function YA($){qQ.delete($)}async function $j($){await new Promise((J)=>{try{$.server.close(()=>J())}catch{J()}})}async function GA($,J,U,Q,_){let X=await UA(),Y=hP(b$(RQ(),Xj)),G=b$(Y,"mitmproxy-ca-cert.pem"),z=b$(Y,"proxy-port"),W=nP(16).toString("hex"),K;try{K=await dD({store:$,token:W,fields:_,onOversizedBody:J.onOversizedControlBody})}catch(j){throw n1(Y,{recursive:!0,force:!0}),j}let N;try{oP(Y),Uj(z,String(X)),N=wP(U,["-q","--listen-host","127.0.0.1","--listen-port",String(X),"--set","anticomp=true","--set",`confdir=${Y}`,"-s",Q],{stdio:["ignore","pipe","pipe"],env:{...process.env,SERVE_SIM_CAPTURE_CONTROL_URL:`http://127.0.0.1:${K.port}`,SERVE_SIM_CAPTURE_CONTROL_TOKEN:W,SERVE_SIM_CAPTURE_FIELDS:_.join(","),[m1]:String(q2())}})}catch(j){throw await $j(K),n1(Y,{recursive:!0,force:!0}),j}let I="",D=(j)=>{I=(I+j.toString("utf8")).slice(-4000)};if(N.stdout?.on("data",D),N.stderr?.on("data",D),N.stderr)JA(N.stderr);let H=!1,V=!1,R=!1;N.once("exit",(j)=>{if(H=!0,V||!R)return;J.onUnexpectedExit?.(I.trim()||`The capture proxy stopped unexpectedly (exit ${j??"signal"}).`)});let O="";N.once("error",(j)=>{H=!0,O=j.message});let L=Qj(Y),F=(j)=>{let k=PQ("ps",["-eo","pid=,command="],{encoding:"utf8"});if(k.status!==0||typeof k.stdout!=="string")return;for(let v of QA(k.stdout,L,process.pid))try{process.kill(v,j)}catch{}},P=()=>{F("SIGKILL"),n1(Y,{recursive:!0,force:!0})};XA(P);let T=async()=>{V=!0;try{if(!H&&N.pid!=null){let j=new Promise((v)=>{let A=setTimeout(v,5000);N.once("exit",()=>{clearTimeout(A),v()})});N.kill("SIGTERM");let k=setTimeout(()=>N.kill("SIGKILL"),3000);await j,clearTimeout(k)}F("SIGTERM"),await new Promise((j)=>setTimeout(j,500)),F("SIGKILL"),await $j(K),n1(Y,{recursive:!0,force:!0,maxRetries:3,retryDelay:100})}finally{YA(P)}},Z=Date.now()+aD,B=!1;K.ready.then(()=>{B=!0});while(Date.now()<Z){if(H)throw await T(),Error(`The capture proxy exited before it started listening.
102
102
  ${O||I.trim()||"No output from mitmproxy."}`);if(U1(G)&&B){if(!rP(Y))throw await T(),new EQ("Another capture saved the shared CA first; starting again with it.");return R=!0,{address:`127.0.0.1:${X}`,portFile:z,caPem:async()=>_9(G,"utf8"),close:T}}await new Promise((j)=>setTimeout(j,iP))}let M=U1(G)?"It started but its reporting addon never loaded, so nothing would have been captured.":`Check that no other process holds 127.0.0.1:${X}.`;throw await T(),Error(`The capture proxy did not start within ${aD/1000}s. ${M}
103
- ${I.trim()}`)}function zA($){let J=$ instanceof Error?$.message:String($);return/EADDRINUSE|address already in use/i.test(J)}async function Wj($,J={}){_A();let U=tP();if(!U)throw Error(aP(process.env.SERVE_SIM_MITMDUMP));let Q=sP(),_=J.fields??_1,X;for(let Y=0;Y<cP;Y++)try{return await GA($,J,U,Q,_)}catch(G){if(X=G,!zA(G)&&!(G instanceof EQ))throw G}throw X}var OQ,aD=30000,iP=200,cP=3,Xj="serve-sim-capture-",S2,sD="mitmproxy-ca-cert.pem",pP="SERVE_SIM_CAPTURE_CA_DIR",EQ,dP,$A=60000,Gj,qQ,eD=!1;var SQ=x(()=>{a6();S8();u1();tD();OQ=n4(import.meta.url),S2=["mitmproxy-ca.pem","mitmproxy-ca-cert.pem"];EQ=class EQ extends Error{};dP=["/opt/homebrew/bin/mitmdump","/usr/local/bin/mitmdump","/Applications/mitmproxy.app/Contents/MacOS/mitmdump"];Gj=["SIGINT","SIGTERM","SIGHUP"],qQ=new Set});import{readFileSync as WA}from"node:fs";import{dirname as KA,join as NA}from"node:path";import{fileURLToPath as IA}from"node:url";function U9(){return"0.6.2-canary-20261008-c8a9613"}var kQ=()=>{};class Nj{#$=new Map;enqueue($,J){let U=this.#$.get($),Q=U?U.then(J):J(),_=Q.then(()=>{},()=>{});return this.#$.set($,_),_.then(()=>{if(this.#$.get($)===_)this.#$.delete($)}),Q}devices(){return this.#$.keys()}}function Q9($,J){return{schemaVersion:F2,udid:$,proxyAddress:null,attachment:"not-enabled",attachError:null,droppedOversizedBodies:0,fields:[...J]}}function Ij($,J){return{...Q9($,J),attachment:"failed",attachError:"Capture was turned off while it was waiting to start. Enable it again to retry."}}function l1($,J){if(J.cancelled)throw new Y6(Ij($,J.fields))}function HA($){if(Dj.add($),Kj)return;Kj=!0,process.on("exit",MA)}function MA(){for(let $ of Dj)$()}function CQ($={}){let J=$.fields??_1,U=$.startProxy??((v,A)=>Wj(v,A)),Q=$.trustCa??YD,_=$.configure??_D,X=$.dylib??GD,Y=$.isInjected??((v,A,C)=>zD(v,A,{expectedPort:Number(new URL(`http://${C}`).port)})),G=$.checkIntervalMs??DA,z=$.writeDiskArtifacts!==!1,W=$.creatorVersion??"0.0.0",K=new Map,N=()=>{for(let v of K.values())try{v.disk?.discardSync()}catch{}},I=new Map,D=new Nj,H=new Map,V=null,R=new Map,O=new Map,L=(v,A)=>{for(let C of R.get(v)??[])try{C(A)}catch{}},F=(v)=>K.get(v)?.meta??O.get(v)??Q9(v,J),P=(v,A)=>{if(!z)return{disk:null,stopDisk:null};if(!$.captureDirFor)WQ([...K.keys(),v]);let C=$.captureDirFor?{dir:$.captureDirFor(v),networkCapturePath:void 0,harPath:void 0}:p8(v),w=new J1({dir:C.dir,networkCapturePath:C.networkCapturePath,harPath:C.harPath,creatorVersion:W,flushIntervalMs:$.flushIntervalMs,harRebuildIntervalMs:BA});return HA(N),{disk:w,stopDisk:w.attach(A)}},T=async(v,A)=>{if(A.cleanup??=(async()=>{await A.proxy?.close(),A.proxy=null,A.meta.proxyAddress=null,await A.stopDisk?.(),A.stopDisk=null,A.disk=null})().catch((C)=>{throw A.cleanup=void 0,console.warn(`Network capture: cleanup for ${v} failed:`,C),C}),await A.cleanup,K.get(v)===A)K.delete(v)},Z=async(v,A)=>{if(V)throw Error(V);if(A)l1(v,A);let C=K.get(v);if(C?.proxy){if(C.meta.attachment==="failed")throw Error("The previous capture session failed. Disable capture before retrying so its launch configuration can be removed safely.");return{dylib:B(),env:{SIMNET_PROXY_PORT_FILE:C.proxy.portFile}}}let w=B(),m=[...A?.fields??J],l=new O2,n={schemaVersion:F2,udid:v,proxyAddress:null,attachment:"starting",attachError:null,droppedOversizedBodies:0,fields:m},u={store:l,meta:n,proxy:null,...P(v,l)};l.subscribe((i)=>{if(K.get(v)===u)L(v,i)}),O.delete(v),K.set(v,u),L(v,{type:"cleared"}),L(v,{type:"meta",meta:n});try{let i=await U(l,{fields:m,onUnexpectedExit:(a)=>{if(K.get(v)!==u)return;n.attachment="failed",n.attachError=`${a}
103
+ ${I.trim()}`)}function zA($){let J=$ instanceof Error?$.message:String($);return/EADDRINUSE|address already in use/i.test(J)}async function Wj($,J={}){_A();let U=tP();if(!U)throw Error(aP(process.env.SERVE_SIM_MITMDUMP));let Q=sP(),_=J.fields??_1,X;for(let Y=0;Y<cP;Y++)try{return await GA($,J,U,Q,_)}catch(G){if(X=G,!zA(G)&&!(G instanceof EQ))throw G}throw X}var OQ,aD=30000,iP=200,cP=3,Xj="serve-sim-capture-",S2,sD="mitmproxy-ca-cert.pem",pP="SERVE_SIM_CAPTURE_CA_DIR",EQ,dP,$A=60000,Gj,qQ,eD=!1;var SQ=x(()=>{a6();S8();u1();tD();OQ=n4(import.meta.url),S2=["mitmproxy-ca.pem","mitmproxy-ca-cert.pem"];EQ=class EQ extends Error{};dP=["/opt/homebrew/bin/mitmdump","/usr/local/bin/mitmdump","/Applications/mitmproxy.app/Contents/MacOS/mitmdump"];Gj=["SIGINT","SIGTERM","SIGHUP"],qQ=new Set});import{readFileSync as WA}from"node:fs";import{dirname as KA,join as NA}from"node:path";import{fileURLToPath as IA}from"node:url";function U9(){return"0.6.2"}var kQ=()=>{};class Nj{#$=new Map;enqueue($,J){let U=this.#$.get($),Q=U?U.then(J):J(),_=Q.then(()=>{},()=>{});return this.#$.set($,_),_.then(()=>{if(this.#$.get($)===_)this.#$.delete($)}),Q}devices(){return this.#$.keys()}}function Q9($,J){return{schemaVersion:F2,udid:$,proxyAddress:null,attachment:"not-enabled",attachError:null,droppedOversizedBodies:0,fields:[...J]}}function Ij($,J){return{...Q9($,J),attachment:"failed",attachError:"Capture was turned off while it was waiting to start. Enable it again to retry."}}function l1($,J){if(J.cancelled)throw new Y6(Ij($,J.fields))}function HA($){if(Dj.add($),Kj)return;Kj=!0,process.on("exit",MA)}function MA(){for(let $ of Dj)$()}function CQ($={}){let J=$.fields??_1,U=$.startProxy??((v,A)=>Wj(v,A)),Q=$.trustCa??YD,_=$.configure??_D,X=$.dylib??GD,Y=$.isInjected??((v,A,C)=>zD(v,A,{expectedPort:Number(new URL(`http://${C}`).port)})),G=$.checkIntervalMs??DA,z=$.writeDiskArtifacts!==!1,W=$.creatorVersion??"0.0.0",K=new Map,N=()=>{for(let v of K.values())try{v.disk?.discardSync()}catch{}},I=new Map,D=new Nj,H=new Map,V=null,R=new Map,O=new Map,L=(v,A)=>{for(let C of R.get(v)??[])try{C(A)}catch{}},F=(v)=>K.get(v)?.meta??O.get(v)??Q9(v,J),P=(v,A)=>{if(!z)return{disk:null,stopDisk:null};if(!$.captureDirFor)WQ([...K.keys(),v]);let C=$.captureDirFor?{dir:$.captureDirFor(v),networkCapturePath:void 0,harPath:void 0}:p8(v),w=new J1({dir:C.dir,networkCapturePath:C.networkCapturePath,harPath:C.harPath,creatorVersion:W,flushIntervalMs:$.flushIntervalMs,harRebuildIntervalMs:BA});return HA(N),{disk:w,stopDisk:w.attach(A)}},T=async(v,A)=>{if(A.cleanup??=(async()=>{await A.proxy?.close(),A.proxy=null,A.meta.proxyAddress=null,await A.stopDisk?.(),A.stopDisk=null,A.disk=null})().catch((C)=>{throw A.cleanup=void 0,console.warn(`Network capture: cleanup for ${v} failed:`,C),C}),await A.cleanup,K.get(v)===A)K.delete(v)},Z=async(v,A)=>{if(V)throw Error(V);if(A)l1(v,A);let C=K.get(v);if(C?.proxy){if(C.meta.attachment==="failed")throw Error("The previous capture session failed. Disable capture before retrying so its launch configuration can be removed safely.");return{dylib:B(),env:{SIMNET_PROXY_PORT_FILE:C.proxy.portFile}}}let w=B(),m=[...A?.fields??J],l=new O2,n={schemaVersion:F2,udid:v,proxyAddress:null,attachment:"starting",attachError:null,droppedOversizedBodies:0,fields:m},u={store:l,meta:n,proxy:null,...P(v,l)};l.subscribe((i)=>{if(K.get(v)===u)L(v,i)}),O.delete(v),K.set(v,u),L(v,{type:"cleared"}),L(v,{type:"meta",meta:n});try{let i=await U(l,{fields:m,onUnexpectedExit:(a)=>{if(K.get(v)!==u)return;n.attachment="failed",n.attachError=`${a}
104
104
 
105
105
  Relaunch apps after restarting capture; their existing sessions may still point at the stopped proxy.`,l.publishMeta(n)},onOversizedControlBody:()=>{if(K.get(v)!==u)return;n.droppedOversizedBodies+=1,l.publishMeta(n)}});if(u.proxy=i,n.proxyAddress=i.address,A)l1(v,A);if(await Q(v,await i.caPem()),A)l1(v,A);if(n.attachment==="failed")throw Error(n.attachError??"The capture proxy stopped during startup.");return{dylib:w,env:{SIMNET_PROXY_PORT_FILE:i.portFile},committed(){if(n.attachment==="failed")throw Error(n.attachError??"The capture proxy stopped during startup.");n.attachment="capturing",l.publishMeta(n)},failed(a){n.attachment="failed",n.attachError=a instanceof Error?a.message:String(a),l.publishMeta(n)},async rollback(){if(A)A.failed=!0;await T(v,u),K.set(v,u)}}}catch(i){if(A)A.failed=!0;throw n.attachment="failed",n.attachError=i instanceof Error?i.message:String(i),await T(v,u),K.set(v,u),l.publishMeta(n),i}};function B(){let v=X();if(!v)throw Error("Network capture library is missing. Rebuild serve-sim's native artifacts before enabling capture.");return v}let M={name:"networkCapture",exclusive:!0,scope:"userApps",loadPhase:"startupAndDeferred",defaultEnabled:!1,async setEnabled({udid:v,enabled:A}){if(A)return Z(v);let C=K.get(v);if(C)await T(v,C);if(O.delete(v),!K.has(v))L(v,{type:"meta",meta:Q9(v,J)});return null}},j=(v)=>_(v,M,{enabled:!1,relaunch:!1}),k=(v)=>{let A=H.get(v);if(A)A.cancelled=!0;return H.delete(v),D.enqueue(v,()=>j(v))};return{capability:M,shouldCaptureDevice(v,A){return I.get(v)??A},setDeviceCaptureEnabled(v,A){I.set(v,A)},creatorVersion:W,setFields(v){J=v},enableForDevice(v){let A=H.get(v);if(A&&!A.failed)return A.promise;let C={cancelled:!1,failed:!1,fields:[...J],promise:Promise.resolve(Q9(v,J))},w=D.enqueue(v,async()=>{l1(v,C);try{if(V)throw Error(V);if(K.get(v)?.meta.attachment==="failed")await j(v),l1(v,C);if(await _(v,{...M,setEnabled:({enabled:u})=>u?Z(v,C):M.setEnabled({udid:v,enabled:!1,bundleId:null,options:{}})},{enabled:!0,relaunch:!1}),C.cancelled)await j(v),l1(v,C);let n=K.get(v);if(!n)throw Error("The capture session disappeared during startup. Enable capture again.");return n.meta}catch(l){C.failed=!0;let n=K.get(v),u=n?.meta??Ij(v,C.fields);if(u.attachment="failed",u.attachError=l instanceof Error?l.message:String(l),n)n.store.publishMeta(u);else O.set(v,u),L(v,{type:"meta",meta:u});throw new Y6(u)}});C.promise=w,H.set(v,C);let m=()=>{if(H.get(v)===C)H.delete(v)};return w.then(m,m),w},disableForDevice:k,refuseCapture(v){V=v},async disableAll(){let v=new Set([...K.keys(),...O.keys(),...D.devices()]),C=(await Promise.allSettled([...v].map(k))).flatMap((w)=>w.status==="rejected"?[w.reason]:[]);if(C.length>0)throw AggregateError(C,`Could not disable network capture on ${C.length} device(s).`)},discardArtifactsSync:N,subscribe(v,A){let C=R.get(v);if(!C)R.set(v,C=new Set);return C.add(A),{meta:F(v),unsubscribe:()=>{if(C.delete(A),C.size===0&&R.get(v)===C)R.delete(v)}}},metaFor(v){return F(v)},async refreshForDevice(v){let A=K.get(v);if(!A)return F(v);if(A.meta.attachment!=="capturing"||!A.proxy)return A.meta;let C=Date.now();if(A.checking)return A.checking;if(A.checkedAt!==void 0&&C-A.checkedAt<G)return A.meta;let w=A.proxy.portFile,m=A.proxy.address;return A.checking=(async()=>{try{let l;try{l=await Y(v,w,m)}catch(n){if(!V8(n))return console.warn(`Network capture: injection probe for ${v} failed:`,n instanceof Error?n.message:n),A.injectMisses=0,A.meta;l=!1}if(l)return A.injectMisses=0,A.meta;if(K.get(v)!==A||A.meta.attachment!=="capturing")return A.meta;if(A.injectMisses=(A.injectMisses??0)+1,A.injectMisses<jA)return A.meta;return A.meta.attachment="failed",A.meta.attachError="This device stopped capturing. It may have restarted or shut down since capture was enabled. Enable capture again after it boots.",A.store.publishMeta(A.meta),A.meta}finally{A.checkedAt=Date.now(),A.checking=void 0}})(),A.checking},storeFor(v){return K.get(v)?.store??null},artifactPathsFor(v){let A=K.get(v)?.disk;if(!A)return null;return{networkCapturePath:A.networkCapturePath,harPath:A.harPath,entriesPath:A.entriesPath}},async flushEntriesPathFor(v){let A=K.get(v)?.disk;if(!A)return null;return await A.flushEntries(),A.entriesPath},async flushHarPathFor(v){let A=K.get(v)?.disk;if(!A)return null;return await A.flush(),A.harPath},clearForDevice(v){let A=K.get(v);if(!A)return!1;return A.store.clear(),!0},throughputFor(v){let A=K.get(v);if(!A||A.meta.attachment!=="capturing")return null;return A.store.throughput()}}}var Y6,DA=1e4,jA=2,BA=60000,Dj,Kj=!1,R$;var k2=x(()=>{o6();WD();h1();o8();u1();SQ();kQ();Y6=class Y6 extends Error{meta;constructor($){super($.attachError??"Network capture could not start");this.name="CaptureEnableError",this.meta=$}};Dj=new Set;R$=CQ({creatorVersion:U9()})});function Bj($){return typeof $==="number"&&Number.isFinite($)?$:null}function Hj($,J,U,Q){let _=Bj($);return _==null?J:Math.min(Q,Math.max(U,_))}function X9($,J,U,Q){return Math.round(Hj($,J,U,Q))}function LA($){if(!Array.isArray($)||$.length>16)return null;let J=[];for(let U of $){if(!U||typeof U!=="object")return null;let Q=U.urls;if(!Array.isArray(Q)||Q.length===0||Q.length>16||!Q.every((Y)=>typeof Y==="string"&&Y.length<=2048&&/^(stun|stuns|turn|turns):/i.test(Y)))return null;let{username:_,credential:X}=U;if(_!==void 0&&typeof _!=="string")return null;if(X!==void 0&&typeof X!=="string")return null;J.push({urls:Q,...typeof _==="string"?{username:_}:{},...typeof X==="string"?{credential:X}:{}})}return J}function Mj($,J){if(!$||typeof $!=="object"||Array.isArray($))return null;let U=$,Q=Object.keys(U),_=J==="webrtc"?vA:VA;if(Q.length===0||Q.some((X)=>!_.has(X)))return null;for(let X of["mjpegFps","mjpegQuality","maxDimension","h264Bitrate","h264Fps"])if(X in U&&Bj(U[X])==null)return null;return U}function jj($={},J=ZA){let Q=Object.prototype.hasOwnProperty.call($,"iceServers")?LA($.iceServers):J.iceServers,_=Q===null?J.iceServers:Q&&Q.length>0?Q:void 0;return{transport:$.transport==="http"||$.transport==="webrtc"?$.transport:J.transport,httpCodec:$.httpCodec==="auto"||$.httpCodec==="mjpeg"||$.httpCodec==="h264"?$.httpCodec:J.httpCodec,webRtcCodec:$.webRtcCodec==="vp8"||$.webRtcCodec==="vp9"||$.webRtcCodec==="h264"?$.webRtcCodec:J.webRtcCodec,..._?{iceServers:_}:{},...i1($,J)}}function i1($={},J=Y9){return{mjpegFps:X9($.mjpegFps,J.mjpegFps,1,120),mjpegQuality:Hj($.mjpegQuality,J.mjpegQuality,0.05,1),maxDimension:X9($.maxDimension,J.maxDimension,0,4096),h264Bitrate:X9($.h264Bitrate,J.h264Bitrate,1e5,50000000),h264Fps:X9($.h264Fps,J.h264Fps,1,140)}}function Zj($){return{mjpegFps:$.mjpegFps,mjpegQuality:$.mjpegQuality,maxDimension:$.maxDimension,h264Bitrate:$.h264Bitrate,h264Fps:$.h264Fps}}function bQ($,J){if(J==="webrtc")return{maxDimension:$.maxDimension,h264Bitrate:$.h264Bitrate,h264Fps:$.h264Fps};return{mjpegFps:$.mjpegFps,mjpegQuality:$.mjpegQuality,maxDimension:$.maxDimension,h264Bitrate:$.h264Bitrate,h264Fps:$.h264Fps}}function Lj($){let J=$?{mjpegFps:$.mjpegFps,mjpegQuality:$.mjpegQuality,maxDimension:$.maxDimension,h264Bitrate:$.h264Bitrate,h264Fps:$.h264Fps}:{};if($?.transport==="webrtc")return jj({transport:"webrtc",webRtcCodec:$.codec,iceServers:$.iceServers,...J});return jj({transport:"http",httpCodec:$?.codec??"auto",...J})}var xQ=120,wQ=140,Y9,ZA,VA,vA;var C2=x(()=>{Y9={mjpegFps:60,mjpegQuality:0.7,maxDimension:0,h264Bitrate:6000000,h264Fps:60},ZA={transport:"http",httpCodec:"auto",webRtcCodec:"h264",...Y9};VA=new Set(["mjpegFps","mjpegQuality","maxDimension","h264Bitrate","h264Fps"]),vA=new Set(["maxDimension","h264Bitrate","h264Fps"])});function L6($){return typeof $==="object"&&$!==null&&!Array.isArray($)}function G9($){return typeof $==="number"&&Number.isFinite($)?$:0}function X$($){return typeof $==="number"&&Number.isFinite($)?$:null}function Q1($){return typeof $==="string"&&$.length>0?$:null}function FA($){if(!L6($))return{};let J={};for(let[U,Q]of Object.entries($)){let _=X$(Q);if(_!==null)J[U]=_*1000}return J}function OA($,J){let U=[Q1($),Q1(J)];if(U.some((Q)=>Q===null))return"unknown";return U.includes("relay")?"relay":"direct"}function RA($){let J=G9($.framesEncoded),U=G9($.packetsSent),Q=G9($.packetsLost),_=X$($.totalEncodeTime),X=X$($.targetBitrate),Y=X$($.roundTripTime);return{sessionId:Q1($.sessionId)??"",sourceFrames:X$($.sourceFrames),sourceFps:X$($.sourceFramesPerSecond),sourceFramesDropped:X$($.sourceFramesDropped),sourceLongEdge:X$($.sourceLongEdge),levelMaxLongEdge:X$($.levelMaxLongEdge),codec:Q1($.codec),connected:$.connected===!0,qualityLimitationReason:Q1($.qualityLimitationReason),qualityLimitationMs:FA($.qualityLimitationDurations),framesEncoded:J,framesSent:G9($.framesSent),reportedFps:X$($.framesPerSecond),targetKbps:X===null?null:X/1000,totalEncodeMs:_===null?null:_*1000,encodeMsPerFrame:_===null||J<=0?null:_*1000/J,width:X$($.frameWidth),height:X$($.frameHeight),packetsSent:U,packetsLost:Q,lossRatio:U>0?Math.max(0,Q)/U:null,roundTripMs:Y===null?null:Y*1000,path:OA($.localCandidateType,$.remoteCandidateType)}}function TA($){if(!L6($))return null;let J={id:Q1($.id),hardware:typeof $.hardware==="boolean"?$.hardware:null,codec:Q1($.codec),probe:$.probe===!0};if(J.id===null&&J.hardware===null&&J.codec===null)return null;return J}function Vj($){if(!L6($)||!Array.isArray($.sessions))return{sessions:[]};return{sessions:$.sessions.filter(L6).map(RA),capture:AA($.capture),encoder:TA($.encoder),viewerResize:L6($.viewerResize)?$.viewerResize:null,sharedCanvas:PA($.sharedCanvas),sharedEncoderPeers:Array.isArray($.sharedEncoderPeers)?$.sharedEncoderPeers.filter(L6):null}}function PA($){if(!L6($))return null;let{width:J,height:U,scale:Q,step:_,steps:X}=$;if([J,U,Q,_,X].some((Y)=>typeof Y!=="number"))return null;return{width:J,height:U,scale:Q,step:_,steps:X,starvedRecoveries:X$($.starvedRecoveries),lowLatencyFallbacks:X$($.lowLatencyFallbacks)}}function AA($){if(!L6($))return null;let{screenFrames:J,idleFrames:U}=$;if(typeof J!=="number"||typeof U!=="number")return null;return{pickCount:X$($.pickCount),pickSumMs:X$($.pickSumMs),pickMaxMs:X$($.pickMaxMs),screenFrames:J,idleFrames:U,offeredFrames:X$($.offeredFrames),forwardedFrames:X$($.forwardedFrames),sharedEncodedFrames:X$($.sharedEncodedFrames),pumpRestarts:X$($.pumpRestarts),canvasMismatchDrops:X$($.canvasMismatchDrops),pumpDeferrals:X$($.pumpDeferrals),pumpRepeats:X$($.pumpRepeats),unchangedFrames:X$($.unchangedFrames),pumpTimerTicks:X$($.pumpTimerTicks),pumpTimerLateSumMs:X$($.pumpTimerLateSumMs),pumpTimerLateMaxMs:X$($.pumpTimerLateMaxMs),sourceSubmitCount:X$($.sourceSubmitCount),sourceSubmitSumMs:X$($.sourceSubmitSumMs),sourceSubmitMaxMs:X$($.sourceSubmitMaxMs),cpuFallbacks:X$($.cpuFallbacks),poolDrops:X$($.poolDrops),attempts:X$($.attempts),stalls:X$($.stalls),gapSumMs:X$($.gapSumMs),stallSumMs:X$($.stallSumMs),pollTicks:X$($.pollTicks),pollLateSumMs:X$($.pollLateSumMs),surfaceLosses:X$($.surfaceLosses),surfaceLostMs:X$($.surfaceLostMs),rewires:X$($.rewires)}}import{createRequire as EA}from"module";import{dirname as gQ,join as fQ}from"path";import{existsSync as qA}from"fs";import{fileURLToPath as vj}from"url";function bA(){let $=[fQ(gQ(process.execPath),"native","serve-sim-native.node"),fQ(gQ(vj(import.meta.url)),"native","serve-sim-native.node"),fQ(gQ(vj(import.meta.url)),"..","dist","native","serve-sim-native.node")];for(let J of $)if(qA(J))return J;throw Error(`serve-sim-native.node not found. Looked in:
106
106
  ${$.join(`
@@ -356,7 +356,7 @@ Usage:
356
356
  serve-sim permissions reset <permission|all> <bundle-id> [-d <udid|name>]
357
357
  serve-sim permissions list [bundle-id] [-d <udid|name>]
358
358
 
359
- Permissions: ${w7().join(", ")}`),process.exit(1);let _=Q.device?n$(Q.device):I4();if(!_)console.error("No booted simulator. Boot one or pass -d <udid|name>."),process.exit(1);if(Q.verb==="list"){let Y={udid:_,bundleId:Q.bundleId??null,tcc:Ik(_,Q.bundleId),location:jk(_,Q.bundleId),notifications:Zk(_,Q.bundleId)};console.log(JSON.stringify(Y,null,J?0:2)),process.exit(0)}let X=Q.bundleId;try{if(Q.permission==="all")for(let Y of w7())FH(_,"reset",Y,void 0,X);else FH(_,Q.verb,Q.permission,Q.value,X)}catch(Y){console.error(Y?.message??String(Y)),process.exit(1)}if(J)console.log(JSON.stringify({udid:_,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 ${_}`)}process.exit(0)}F9();B9();function CH($,J={}){let U=new Date($.timestamp),Q=Number.isNaN(U.getTime())?$.timestamp:U.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"}),_=J.deviceLabel??($.device?$.device.slice(0,8):null),X=$.status==="error"?" failed":"";return[Q,_,`${Lk($)}${X?` (${X.trim()})`:""}`].filter(Boolean).join(" ")}function Lk($){if($.kind==="tap"){let J=y9($.details,"current")??y9($.details,"start");return J?`Tap at ${h7(J)}`:"Tap"}if($.kind==="drag"){let J=y9($.details,"start"),U=y9($.details,"current");if(J&&U)return`Drag from ${h7(J)} to ${h7(U)}`;return"Drag"}if($.kind==="key"){let J=Vk($.details,"key")??$.action??"key",U=$.action==="down"?"down":$.action==="up"?"up":$.action;return U?`Key ${U} ${kH(J)}`:`Key ${kH(J)}`}if($.kind==="rotate"){let J=$.action?xH($.action):"";return J?`Rotate ${J}`:"Rotate"}return Fk($.msg??$.summary)}function y9($,J){let U=$?.[J];if(!U||typeof U!=="object"||Array.isArray(U))return null;let Q=U;return typeof Q.x==="number"&&typeof Q.y==="number"?{x:Q.x,y:Q.y}:null}function Vk($,J){let U=$?.[J];return typeof U==="string"&&U.length>0?U:null}function h7($){return`${SH($.x)}, ${SH($.y)}`}function SH($){if(!Number.isFinite($))return"?";return(Math.round((vk($,0,1)+Number.EPSILON)*100)/100).toFixed(2)}function vk($,J,U){return Math.min(U,Math.max(J,$))}function Fk($){return $.replace(/\b[a-z]+(?:_[a-z]+)+\b/g,xH)}function xH($){return $.replace(/[-_]+/g," ")}function kH($){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"}[$]??$}n7();C2();function l7($,J){let U=$.split(",").map((_)=>_.trim()).filter(Boolean),Q=J==="stun"?/^stuns?:/i:/^turns?:/i;if(U.length===0||U.length>16||U.some((_)=>_.length>2048||!Q.test(_)))throw Error(`Expected one or more comma-separated ${J.toUpperCase()} URLs`);return U}function i7($,J){let U=$??{transport:"http"},Q=J??{transport:"http"};if(U.transport!==Q.transport)return!1;let _=i1(U),X=i1(Q);if(_.mjpegFps!==X.mjpegFps||_.mjpegQuality!==X.mjpegQuality||_.maxDimension!==X.maxDimension||_.h264Bitrate!==X.h264Bitrate||_.h264Fps!==X.h264Fps)return!1;if(U.transport==="http"&&Q.transport==="http")return(U.codec??"auto")===(Q.codec??"auto");if(U.transport!=="webrtc"||Q.transport!=="webrtc")return!1;if(U.codec!==Q.codec)return!1;let Y=U.iceServers??[],G=Q.iceServers??[];if(Y.length!==G.length)return!1;return Y.every((z,W)=>{let K=G[W];return z.username===K.username&&z.credential===K.credential&&z.urls.length===K.urls.length&&z.urls.every((N,I)=>N===K.urls[I])})}function gH($,J){let U=[];for(let Q of $??[])for(let _ of Q.urls){let X=_.toLowerCase();if(J.some((Y)=>X.startsWith(Y)))U.push(_)}return U}function Ak($){for(let J of $??[])if(J.urls.some((U)=>/^turns?:/i.test(U)))return J;return null}function Ek($){if(!$)return[];let J=[];if(J.push("--transport",$.transport),$.transport==="http"){if($.codec)J.push("--codec",$.codec)}else{J.push("--webrtc-codec",$.codec);let U=gH($.iceServers,["stun:","stuns:"]);if(U.length)J.push("--stun-url",U.join(","));let Q=gH($.iceServers,["turn:","turns:"]);if(Q.length){J.push("--turn-url",Q.join(","));let _=Ak($.iceServers);if(_?.username)J.push("--turn-username",_.username);if(_?.credential)J.push("--turn-credential",_.credential)}}if($.mjpegFps!==void 0)J.push("--mjpeg-fps",String($.mjpegFps));if($.mjpegQuality!==void 0)J.push("--mjpeg-quality",String($.mjpegQuality));if($.maxDimension!==void 0)J.push("--max-dimension",String($.maxDimension));if($.h264Bitrate!==void 0)J.push("--video-bitrate",String($.h264Bitrate));if($.h264Fps!==void 0)J.push("--video-fps",String($.h264Fps));return J}function fH($,J,U,Q){return[$,"--port",String(J),"--host",U,...Ek(Q)]}C2();t1();t1();import qk from"ws";async function yH($,J,U={}){if(!G6(J))throw Error("Hinge angle must be between 0–180 degrees");return new Promise((Q,_)=>{let X=new qk($,{headers:U.token?{Authorization:`Bearer ${U.token}`}:void 0}),Y=!1,G=(W)=>{if(Y)return;if(Y=!0,clearTimeout(z),X.close(),W)_(W);else Q()},z=setTimeout(()=>G(Error("Timed out waiting for hinge control acknowledgement")),U.timeoutMs??5000);X.on("open",()=>{X.send(Buffer.concat([Buffer.from([15]),Buffer.from(JSON.stringify({angle:J}))]))}),X.on("message",(W)=>{let K=Buffer.from(W);if(K[0]!==143)return;let N;try{N=JSON.parse(K.subarray(1).toString())}catch{G(Error("Invalid hinge control acknowledgement"));return}if(!N||typeof N!=="object"||typeof N.ok!=="boolean"){G(Error("Invalid hinge control acknowledgement"));return}if(!N.ok)G(Error(N.error||"Hinge control is unavailable on this simulator"));else if(N.angle===J)G();else G(Error("Server acknowledged a different hinge angle"))}),X.on("error",(W)=>G(Error(`Hinge control connection failed: ${W.message}`))),X.on("close",()=>G(Error("Connection closed before hinge control acknowledgement")))})}l2();D4();import{existsSync as Sk,readFileSync as kk,unlinkSync as hH}from"node:fs";var i9=500,mH=65000;function l9($,J){return{exitCode:$?.exitCode??null,signalCode:$?.signalCode??null,forced:J}}function c9($,J){if(J)return J.exitCode!==null||J.signalCode!==null;try{return process.kill($,0),!1}catch{return!0}}async function uH($,J,U){let Q=Date.now()+U;while(Date.now()<Q){if(c9($,J))return!0;await new Promise((_)=>setTimeout(_,50))}return c9($,J)}async function c7($,J){try{let U=await fetch($,{headers:J?{Authorization:`Bearer ${J}`}:void 0,signal:AbortSignal.timeout(1000)});if(!U.ok)return i9;return(await U.json()).active===!0?mH:i9}catch{return i9}}async function nH($){let J=F8($.pid);try{hH(J)}catch{}let U=await c7($.streamUrl.replace(/\/stream\.mjpeg$/,"/recording/video"),$.token),Q=await p9($.pid,void 0,U);if(!c9($.pid))throw Error(`Previous serve-sim helper ${$.pid} is still running; cannot replace it`);let _;if(Sk(J))try{let X=JSON.parse(kk(J,"utf8"));_=Array.isArray(X.errors)?X.errors.map(String).join("; ")||"Recording finalization failed":"Recording finalization failed"}catch{_="Recording finalization failed"}if(_)try{hH(J)}catch{}return{forced:Q.forced,recordingError:_??(U===mH&&Q.forced?"Active recording was interrupted when the helper required SIGKILL":void 0)}}async function p9($,J,U=i9){if(c9($,J))return l9(J,!1);try{process.kill($,"SIGTERM")}catch{return l9(J,!1)}if(await uH($,J,U))return l9(J,!1);try{process.kill($,"SIGKILL")}catch{}return await uH($,J,1000),l9(J,!0)}b4();var Rm=20000,Tm=12000,p6=n4(import.meta.url);function rO(){return"0.6.2-canary-20261008-c8a9613"}var dO=!1;async function tO($){let J=await nH($);if(J.forced)console.error(`Previous serve-sim helper ${$.pid} required SIGKILL during stream-settings replacement.`);if(J.recordingError)dO=!0,process.exitCode=1,console.error(`Recording finalization failed while replacing helper ${$.pid}: ${J.recordingError}. Starting the replacement helper.`)}function aO(){xN(W$(),{recursive:!0})}function m$($){if($)return kN(Q2($));for(let J of g1()){let U=kN(J);if(U)return U}return null}var j8={at:0,booted:null};function Pm(){let $=Date.now();if(j8.booted&&$-j8.at<1000)return j8.booted;try{let J=M6("xcrun simctl list devices booted -j",{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3000}),U=JSON.parse(J),Q=new Set;for(let _ of Object.values(U.devices))for(let X of _)if(X.state==="Booted")Q.add(X.udid);return j8={at:$,booted:Q},Q}catch{return null}}function kN($){try{if(!k4($))return w4("state file missing %s",$),null;let J=JSON.parse(S1($,"utf-8"));try{process.kill(J.pid,0)}catch{return w4("helper pid %d dead, removing stale state %s",J.pid,$),q1($),null}let U=Pm();if(U&&!U.has(J.device)){if(J0(J.device,j8.at))return w4("keeping state for capture reboot on device %s",J.device),J;if(J.pid===process.pid){w4("dropping own stale state for non-booted device %s",J.device);try{q1($)}catch{}return null}w4("helper pid %d bound to non-booted device %s — killing stale helper",J.pid,J.device),console.error(`[serve-sim] Helper pid ${J.pid} is bound to device ${J.device} which is no longer booted — killing stale helper.`);try{process.kill(J.pid,"SIGTERM")}catch{}try{q1($)}catch{}return null}return w4("state ok pid=%d device=%s port=%d",J.pid,J.device,J.port),J}catch(J){return w4("readStateFile threw for %s: %o",$,J),null}}function B8(){let $=[];for(let J of g1()){let U=kN(J);if(U)$.push(U)}return $}function Am($){aO(),O8($),w4("wrote state pid=%d device=%s port=%d",$.pid,$.device,$.port)}function a0($){return new Om($.wsUrl,$.token?{headers:{Authorization:`Bearer ${$.token}`}}:void 0)}function s0($,J){$.on("close",(U,Q)=>{if(U===1013)J(Error(`Simulator input rejected: ${Q.toString()||"server busy"}. Try again shortly.`))})}function t0($){if($){w4("clearState device=%s",$);try{q1(Q2($))}catch{}}else{w4("clearState (all)");for(let J of g1())try{q1(J)}catch{}}}function fN(){try{let $=M6("xcrun simctl list devices -j",{encoding:"utf-8"}),J=JSON.parse($),U=Object.keys(J.devices).filter((Q)=>/SimRuntime\.iOS-/i.test(Q)).sort((Q,_)=>{let X=(Q.match(/iOS-(\d+)-(\d+)/)??[]).slice(1).map(Number),Y=(_.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 U){let X=(J.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 lO($){return sO().get($)??null}function sO(){let $=new Map;try{let J=M6("xcrun simctl list devices -j",{encoding:"utf-8"}),U=JSON.parse(J);for(let Q of Object.values(U.devices))for(let _ of Q)$.set(_.udid,_.name)}catch{}return $}function eO($){try{let J=M6("xcrun simctl list devices -j",{encoding:"utf-8"}),U=JSON.parse(J);for(let Q of Object.values(U.devices))for(let _ of Q)if(_.udid===$)return _.state==="Booted"}catch{}return!1}function CN($){try{return process.kill($,0),!0}catch{return!1}}function Em($){if(!eO($))try{M6(`xcrun simctl boot ${$}`,{encoding:"utf-8",stdio:"pipe"})}catch(J){let U=(J.stderr??J.message??"").toLowerCase();if(!U.includes("booted")&&!U.includes("current state"))throw Error(`Failed to boot device ${$}: ${J.stderr||J.message}`)}try{LH($)}catch{}}function qm(){let $=Fm();for(let J of Object.values($))for(let U of J??[])if(U.family==="IPv4"&&!U.internal)return U.address;return null}async function $R($){let J=new Set(B8().map((U)=>U.port));for(let U=$;U<$+100;U++){if(J.has(U))continue;if(await bI(U))return U}throw Error(`No available port found in range ${$}-${$+99}`)}async function JR($){Em($);try{M6(`xcrun simctl bootstatus ${$} -b`,{encoding:"utf-8",stdio:"pipe",timeout:60000})}catch(J){if(!eO($))console.error(`Device ${$} failed to reach booted state: ${J.stderr||J.message}`),process.exit(1)}await aI($)}function _R(){for(let $ of K2())try{pI($,process.pid,(J)=>{if(J.name==="camera")H8($)})}catch(J){console.error(`Could not clean up capabilities on ${$}: ${J instanceof Error?J.message:String(J)}`)}}var J6=!1,Sm;function yN(){return Sm??=(async()=>{await Y2();for(let $ of K2())try{await pU($,process.pid,(J)=>{if(J.name==="camera")H8($)})}catch(J){console.error(`Could not clean up capabilities on ${$}: ${J instanceof Error?J.message:String(J)}`)}})()}var UR="SERVE_SIM_STREAM_HELPER";function km($){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 Cm($,J=150000){let U=Date.now();while(Date.now()-U<J){let Q=m$($);if(Q)return Q;await new Promise((_)=>setTimeout(_,200))}return null}async function QR($,J,U){rQ("startHelper udid=%s port=%d detach=%s",$,J,U.detach);let Q="127.0.0.1";aO(),MH(J),t0($);let _=y4(W$(),`server-${$}.log`),X=wN(_,"w"),{command:Y,args:G}=km(fH($,J,Q,U.stream)),z=pO(Y,G,{detached:U.detach,stdio:["ignore",X,X],env:{...process.env,[UR]:"1"}});if(bN(X),U.detach)z.unref();let W=await Cm($);if(!W){if(z.pid)await p9(z.pid,z);let K="";try{K=S1(_,"utf-8").trim()}catch{}console.error(K?`Preview server failed:
359
+ Permissions: ${w7().join(", ")}`),process.exit(1);let _=Q.device?n$(Q.device):I4();if(!_)console.error("No booted simulator. Boot one or pass -d <udid|name>."),process.exit(1);if(Q.verb==="list"){let Y={udid:_,bundleId:Q.bundleId??null,tcc:Ik(_,Q.bundleId),location:jk(_,Q.bundleId),notifications:Zk(_,Q.bundleId)};console.log(JSON.stringify(Y,null,J?0:2)),process.exit(0)}let X=Q.bundleId;try{if(Q.permission==="all")for(let Y of w7())FH(_,"reset",Y,void 0,X);else FH(_,Q.verb,Q.permission,Q.value,X)}catch(Y){console.error(Y?.message??String(Y)),process.exit(1)}if(J)console.log(JSON.stringify({udid:_,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 ${_}`)}process.exit(0)}F9();B9();function CH($,J={}){let U=new Date($.timestamp),Q=Number.isNaN(U.getTime())?$.timestamp:U.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"}),_=J.deviceLabel??($.device?$.device.slice(0,8):null),X=$.status==="error"?" failed":"";return[Q,_,`${Lk($)}${X?` (${X.trim()})`:""}`].filter(Boolean).join(" ")}function Lk($){if($.kind==="tap"){let J=y9($.details,"current")??y9($.details,"start");return J?`Tap at ${h7(J)}`:"Tap"}if($.kind==="drag"){let J=y9($.details,"start"),U=y9($.details,"current");if(J&&U)return`Drag from ${h7(J)} to ${h7(U)}`;return"Drag"}if($.kind==="key"){let J=Vk($.details,"key")??$.action??"key",U=$.action==="down"?"down":$.action==="up"?"up":$.action;return U?`Key ${U} ${kH(J)}`:`Key ${kH(J)}`}if($.kind==="rotate"){let J=$.action?xH($.action):"";return J?`Rotate ${J}`:"Rotate"}return Fk($.msg??$.summary)}function y9($,J){let U=$?.[J];if(!U||typeof U!=="object"||Array.isArray(U))return null;let Q=U;return typeof Q.x==="number"&&typeof Q.y==="number"?{x:Q.x,y:Q.y}:null}function Vk($,J){let U=$?.[J];return typeof U==="string"&&U.length>0?U:null}function h7($){return`${SH($.x)}, ${SH($.y)}`}function SH($){if(!Number.isFinite($))return"?";return(Math.round((vk($,0,1)+Number.EPSILON)*100)/100).toFixed(2)}function vk($,J,U){return Math.min(U,Math.max(J,$))}function Fk($){return $.replace(/\b[a-z]+(?:_[a-z]+)+\b/g,xH)}function xH($){return $.replace(/[-_]+/g," ")}function kH($){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"}[$]??$}n7();C2();function l7($,J){let U=$.split(",").map((_)=>_.trim()).filter(Boolean),Q=J==="stun"?/^stuns?:/i:/^turns?:/i;if(U.length===0||U.length>16||U.some((_)=>_.length>2048||!Q.test(_)))throw Error(`Expected one or more comma-separated ${J.toUpperCase()} URLs`);return U}function i7($,J){let U=$??{transport:"http"},Q=J??{transport:"http"};if(U.transport!==Q.transport)return!1;let _=i1(U),X=i1(Q);if(_.mjpegFps!==X.mjpegFps||_.mjpegQuality!==X.mjpegQuality||_.maxDimension!==X.maxDimension||_.h264Bitrate!==X.h264Bitrate||_.h264Fps!==X.h264Fps)return!1;if(U.transport==="http"&&Q.transport==="http")return(U.codec??"auto")===(Q.codec??"auto");if(U.transport!=="webrtc"||Q.transport!=="webrtc")return!1;if(U.codec!==Q.codec)return!1;let Y=U.iceServers??[],G=Q.iceServers??[];if(Y.length!==G.length)return!1;return Y.every((z,W)=>{let K=G[W];return z.username===K.username&&z.credential===K.credential&&z.urls.length===K.urls.length&&z.urls.every((N,I)=>N===K.urls[I])})}function gH($,J){let U=[];for(let Q of $??[])for(let _ of Q.urls){let X=_.toLowerCase();if(J.some((Y)=>X.startsWith(Y)))U.push(_)}return U}function Ak($){for(let J of $??[])if(J.urls.some((U)=>/^turns?:/i.test(U)))return J;return null}function Ek($){if(!$)return[];let J=[];if(J.push("--transport",$.transport),$.transport==="http"){if($.codec)J.push("--codec",$.codec)}else{J.push("--webrtc-codec",$.codec);let U=gH($.iceServers,["stun:","stuns:"]);if(U.length)J.push("--stun-url",U.join(","));let Q=gH($.iceServers,["turn:","turns:"]);if(Q.length){J.push("--turn-url",Q.join(","));let _=Ak($.iceServers);if(_?.username)J.push("--turn-username",_.username);if(_?.credential)J.push("--turn-credential",_.credential)}}if($.mjpegFps!==void 0)J.push("--mjpeg-fps",String($.mjpegFps));if($.mjpegQuality!==void 0)J.push("--mjpeg-quality",String($.mjpegQuality));if($.maxDimension!==void 0)J.push("--max-dimension",String($.maxDimension));if($.h264Bitrate!==void 0)J.push("--video-bitrate",String($.h264Bitrate));if($.h264Fps!==void 0)J.push("--video-fps",String($.h264Fps));return J}function fH($,J,U,Q){return[$,"--port",String(J),"--host",U,...Ek(Q)]}C2();t1();t1();import qk from"ws";async function yH($,J,U={}){if(!G6(J))throw Error("Hinge angle must be between 0–180 degrees");return new Promise((Q,_)=>{let X=new qk($,{headers:U.token?{Authorization:`Bearer ${U.token}`}:void 0}),Y=!1,G=(W)=>{if(Y)return;if(Y=!0,clearTimeout(z),X.close(),W)_(W);else Q()},z=setTimeout(()=>G(Error("Timed out waiting for hinge control acknowledgement")),U.timeoutMs??5000);X.on("open",()=>{X.send(Buffer.concat([Buffer.from([15]),Buffer.from(JSON.stringify({angle:J}))]))}),X.on("message",(W)=>{let K=Buffer.from(W);if(K[0]!==143)return;let N;try{N=JSON.parse(K.subarray(1).toString())}catch{G(Error("Invalid hinge control acknowledgement"));return}if(!N||typeof N!=="object"||typeof N.ok!=="boolean"){G(Error("Invalid hinge control acknowledgement"));return}if(!N.ok)G(Error(N.error||"Hinge control is unavailable on this simulator"));else if(N.angle===J)G();else G(Error("Server acknowledged a different hinge angle"))}),X.on("error",(W)=>G(Error(`Hinge control connection failed: ${W.message}`))),X.on("close",()=>G(Error("Connection closed before hinge control acknowledgement")))})}l2();D4();import{existsSync as Sk,readFileSync as kk,unlinkSync as hH}from"node:fs";var i9=500,mH=65000;function l9($,J){return{exitCode:$?.exitCode??null,signalCode:$?.signalCode??null,forced:J}}function c9($,J){if(J)return J.exitCode!==null||J.signalCode!==null;try{return process.kill($,0),!1}catch{return!0}}async function uH($,J,U){let Q=Date.now()+U;while(Date.now()<Q){if(c9($,J))return!0;await new Promise((_)=>setTimeout(_,50))}return c9($,J)}async function c7($,J){try{let U=await fetch($,{headers:J?{Authorization:`Bearer ${J}`}:void 0,signal:AbortSignal.timeout(1000)});if(!U.ok)return i9;return(await U.json()).active===!0?mH:i9}catch{return i9}}async function nH($){let J=F8($.pid);try{hH(J)}catch{}let U=await c7($.streamUrl.replace(/\/stream\.mjpeg$/,"/recording/video"),$.token),Q=await p9($.pid,void 0,U);if(!c9($.pid))throw Error(`Previous serve-sim helper ${$.pid} is still running; cannot replace it`);let _;if(Sk(J))try{let X=JSON.parse(kk(J,"utf8"));_=Array.isArray(X.errors)?X.errors.map(String).join("; ")||"Recording finalization failed":"Recording finalization failed"}catch{_="Recording finalization failed"}if(_)try{hH(J)}catch{}return{forced:Q.forced,recordingError:_??(U===mH&&Q.forced?"Active recording was interrupted when the helper required SIGKILL":void 0)}}async function p9($,J,U=i9){if(c9($,J))return l9(J,!1);try{process.kill($,"SIGTERM")}catch{return l9(J,!1)}if(await uH($,J,U))return l9(J,!1);try{process.kill($,"SIGKILL")}catch{}return await uH($,J,1000),l9(J,!0)}b4();var Rm=20000,Tm=12000,p6=n4(import.meta.url);function rO(){return"0.6.2"}var dO=!1;async function tO($){let J=await nH($);if(J.forced)console.error(`Previous serve-sim helper ${$.pid} required SIGKILL during stream-settings replacement.`);if(J.recordingError)dO=!0,process.exitCode=1,console.error(`Recording finalization failed while replacing helper ${$.pid}: ${J.recordingError}. Starting the replacement helper.`)}function aO(){xN(W$(),{recursive:!0})}function m$($){if($)return kN(Q2($));for(let J of g1()){let U=kN(J);if(U)return U}return null}var j8={at:0,booted:null};function Pm(){let $=Date.now();if(j8.booted&&$-j8.at<1000)return j8.booted;try{let J=M6("xcrun simctl list devices booted -j",{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3000}),U=JSON.parse(J),Q=new Set;for(let _ of Object.values(U.devices))for(let X of _)if(X.state==="Booted")Q.add(X.udid);return j8={at:$,booted:Q},Q}catch{return null}}function kN($){try{if(!k4($))return w4("state file missing %s",$),null;let J=JSON.parse(S1($,"utf-8"));try{process.kill(J.pid,0)}catch{return w4("helper pid %d dead, removing stale state %s",J.pid,$),q1($),null}let U=Pm();if(U&&!U.has(J.device)){if(J0(J.device,j8.at))return w4("keeping state for capture reboot on device %s",J.device),J;if(J.pid===process.pid){w4("dropping own stale state for non-booted device %s",J.device);try{q1($)}catch{}return null}w4("helper pid %d bound to non-booted device %s — killing stale helper",J.pid,J.device),console.error(`[serve-sim] Helper pid ${J.pid} is bound to device ${J.device} which is no longer booted — killing stale helper.`);try{process.kill(J.pid,"SIGTERM")}catch{}try{q1($)}catch{}return null}return w4("state ok pid=%d device=%s port=%d",J.pid,J.device,J.port),J}catch(J){return w4("readStateFile threw for %s: %o",$,J),null}}function B8(){let $=[];for(let J of g1()){let U=kN(J);if(U)$.push(U)}return $}function Am($){aO(),O8($),w4("wrote state pid=%d device=%s port=%d",$.pid,$.device,$.port)}function a0($){return new Om($.wsUrl,$.token?{headers:{Authorization:`Bearer ${$.token}`}}:void 0)}function s0($,J){$.on("close",(U,Q)=>{if(U===1013)J(Error(`Simulator input rejected: ${Q.toString()||"server busy"}. Try again shortly.`))})}function t0($){if($){w4("clearState device=%s",$);try{q1(Q2($))}catch{}}else{w4("clearState (all)");for(let J of g1())try{q1(J)}catch{}}}function fN(){try{let $=M6("xcrun simctl list devices -j",{encoding:"utf-8"}),J=JSON.parse($),U=Object.keys(J.devices).filter((Q)=>/SimRuntime\.iOS-/i.test(Q)).sort((Q,_)=>{let X=(Q.match(/iOS-(\d+)-(\d+)/)??[]).slice(1).map(Number),Y=(_.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 U){let X=(J.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 lO($){return sO().get($)??null}function sO(){let $=new Map;try{let J=M6("xcrun simctl list devices -j",{encoding:"utf-8"}),U=JSON.parse(J);for(let Q of Object.values(U.devices))for(let _ of Q)$.set(_.udid,_.name)}catch{}return $}function eO($){try{let J=M6("xcrun simctl list devices -j",{encoding:"utf-8"}),U=JSON.parse(J);for(let Q of Object.values(U.devices))for(let _ of Q)if(_.udid===$)return _.state==="Booted"}catch{}return!1}function CN($){try{return process.kill($,0),!0}catch{return!1}}function Em($){if(!eO($))try{M6(`xcrun simctl boot ${$}`,{encoding:"utf-8",stdio:"pipe"})}catch(J){let U=(J.stderr??J.message??"").toLowerCase();if(!U.includes("booted")&&!U.includes("current state"))throw Error(`Failed to boot device ${$}: ${J.stderr||J.message}`)}try{LH($)}catch{}}function qm(){let $=Fm();for(let J of Object.values($))for(let U of J??[])if(U.family==="IPv4"&&!U.internal)return U.address;return null}async function $R($){let J=new Set(B8().map((U)=>U.port));for(let U=$;U<$+100;U++){if(J.has(U))continue;if(await bI(U))return U}throw Error(`No available port found in range ${$}-${$+99}`)}async function JR($){Em($);try{M6(`xcrun simctl bootstatus ${$} -b`,{encoding:"utf-8",stdio:"pipe",timeout:60000})}catch(J){if(!eO($))console.error(`Device ${$} failed to reach booted state: ${J.stderr||J.message}`),process.exit(1)}await aI($)}function _R(){for(let $ of K2())try{pI($,process.pid,(J)=>{if(J.name==="camera")H8($)})}catch(J){console.error(`Could not clean up capabilities on ${$}: ${J instanceof Error?J.message:String(J)}`)}}var J6=!1,Sm;function yN(){return Sm??=(async()=>{await Y2();for(let $ of K2())try{await pU($,process.pid,(J)=>{if(J.name==="camera")H8($)})}catch(J){console.error(`Could not clean up capabilities on ${$}: ${J instanceof Error?J.message:String(J)}`)}})()}var UR="SERVE_SIM_STREAM_HELPER";function km($){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 Cm($,J=150000){let U=Date.now();while(Date.now()-U<J){let Q=m$($);if(Q)return Q;await new Promise((_)=>setTimeout(_,200))}return null}async function QR($,J,U){rQ("startHelper udid=%s port=%d detach=%s",$,J,U.detach);let Q="127.0.0.1";aO(),MH(J),t0($);let _=y4(W$(),`server-${$}.log`),X=wN(_,"w"),{command:Y,args:G}=km(fH($,J,Q,U.stream)),z=pO(Y,G,{detached:U.detach,stdio:["ignore",X,X],env:{...process.env,[UR]:"1"}});if(bN(X),U.detach)z.unref();let W=await Cm($);if(!W){if(z.pid)await p9(z.pid,z);let K="";try{K=S1(_,"utf-8").trim()}catch{}console.error(K?`Preview server failed:
360
360
  ${K}`:"Preview server failed to start"),process.exit(1)}return U.detach?{pid:W.pid}:{pid:W.pid,child:z}}async function xm($,J,U,Q,_=!1){oQ("follow devices=%o startPort=%d",$,J);let X=$.length>0?$.map(n$):(()=>{let N=I4();if(N)return[N];let I=fN();if(!I)console.error("No device specified and no available iOS simulator found."),process.exit(1);if(!U)console.log(`No booted simulator — booting ${I.name}...`);return[I.udid]})(),Y=new Map,G=[],z=J;for(let N of X){let I=m$(N);if(I)if(_&&!i7(I.streamSettings,Q))await tO(I),t0(N);else{if(!U){let V=lO(N)??N;if(X.length>1)console.log(`
361
361
  ==> ${V} (${N}) <==`);console.log(` Already running on port ${I.port}`),console.log(` Stream: ${I.streamUrl}`),console.log(` WebSocket: ${I.wsUrl}`)}G.push(I);continue}z=await $R(z);let{child:D}=await QR(N,z,{detach:!1,stream:Q});if(D)Y.set(N,D);let H=m$(N)??r6(N,z,"/","127.0.0.1");if(G.push(H),!U){let V=lO(N)??N;if(X.length>1)console.log(`
362
362
  ==> ${V} (${N}) <==`);console.log(` Stream: ${H.streamUrl}`),console.log(` WebSocket: ${H.wsUrl}`),console.log(` Port: ${z}`)}z++}if(G.length===1){let N=G[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:G.map((N)=>({url:N.url,streamUrl:N.streamUrl,wsUrl:N.wsUrl,port:N.port,device:N.device}))}));if(Y.size===0)return;let W=!1,K=async(N)=>{if(W)return;if(W=!0,J6=!0,!U)console.log(`
@@ -414,5 +414,5 @@ Examples:
414
414
  Launch an installed app, then start the stream`).action(async($,J)=>{if(J.list!==void 0){gm(typeof J.list==="string"?J.list:void 0);return}if(J.kill!==void 0){await fm(typeof J.kill==="string"?J.kill:void 0);return}if(J.transport!=="http"&&J.transport!=="webrtc")console.error("--transport must be one of: http, webrtc."),process.exit(1);let U=(T)=>c$.getOptionValueSource(T)==="cli",Q=["webrtcCodec","stunUrl","turnUrl","turnUsername","turnCredential"].some(U);if(J.transport==="http"&&Q)console.error("WebRTC options require --transport webrtc."),process.exit(1);if(J.transport==="webrtc"&&U("codec"))console.error("--codec configures HTTP streaming; use --webrtc-codec with --transport webrtc."),process.exit(1);if(J.turnUsername===void 0!==(J.turnCredential===void 0))console.error("--turn-username and --turn-credential must be provided together."),process.exit(1);if((J.turnUsername!==void 0||J.turnCredential!==void 0)&&!J.turnUrl)console.error("--turn-username and --turn-credential require --turn-url."),process.exit(1);let _=J.stunUrl??[],X=[];if(_.length)X.push({urls:_});if(J.turnUrl)X.push({urls:J.turnUrl,username:J.turnUsername,credential:J.turnCredential});let Y=["mjpegFps","mjpegQuality","maxDimension","videoBitrate","videoFps"],G={...U("mjpegFps")?{mjpegFps:J.mjpegFps}:{},...U("mjpegQuality")?{mjpegQuality:J.mjpegQuality}:{},...U("maxDimension")?{maxDimension:J.maxDimension}:{},...U("videoBitrate")?{h264Bitrate:J.videoBitrate}:{},...U("videoFps")?{h264Fps:J.videoFps}:{}},z=J.transport==="webrtc"?{transport:"webrtc",codec:J.webrtcCodec,...X.length?{iceServers:X}:{},...G}:{transport:"http",codec:J.codec,...G},W=typeof J.launchAppIdentifier==="string"?J.launchAppIdentifier.trim():"";if(J.launchAppIdentifier!==void 0&&!W)console.error("--launch-app-identifier needs an app bundle identifier, such as host.exp.Exponent."),process.exit(1);let K=J.launchArg??[],N=J.openUrl;if(!W&&(K.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 I={enable:J.enable??[],disable:J.disable??[]};try{qU([...I.enable,...I.disable])}catch(T){console.error(T instanceof Error?T.message:T),process.exit(1)}let D=Boolean(W)||I.enable.length>0||I.disable.length>0||_I(),H=J.port,V=U("transport")||U("codec")||Q||Y.some(U),R=J.debugStream?.trim();if(J.debugStream!==void 0){let T=!R?"--debug-stream needs a file path, for example --debug-stream ./stream.ndjson":J.detach||J.preview===!1?"--debug-stream needs the preview server, so drop --detach/--no-preview.":z.transport!=="webrtc"?"--debug-stream records sender statistics, which only exist on --transport webrtc.":null;if(T!==null)console.error(T),process.exit(1)}if(J.networkCapture&&(J.detach||J.preview===!1))console.error("--network-capture needs the preview server, so drop --detach/--no-preview. The proxy and its recordings live in that process; these modes exit and would leave nothing capturing."),process.exit(1);let O=J.networkCapture?"--network-capture":I.enable.includes("networkCapture")&&!I.disable.includes("networkCapture")?"--enable networkCapture":null;if(O&&!J.requireToken&&!z1(J.host))console.error(`${O} on --host ${J.host} needs --require-token. Without it the preview page, open to anyone who can reach it, carries the session token, and that token also reads the captured traffic.`),process.exit(1);if(J.requireToken&&(J.detach||J.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(J.detach){let T=[...W?["--launch-app-identifier"]:[],...K.length>0?["--launch-arg"]:[],...N?["--open-url"]:[],...I.enable.length>0?["--enable"]:[],...I.disable.length>0?["--disable"]:[]];if(T.length>0)console.error(`${T.join(", ")} ${T.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 L=$,F=null,P=()=>{return F??=(async()=>{await(await Promise.resolve().then(() => (b4(),I6))).captureRuntime.disableAll()})(),F};if(!J.detach)try{L=WR($);{process.on("exit",()=>{_R()});for(let Z of["SIGINT","SIGTERM","SIGHUP"])process.on(Z,async()=>{J6=!0;try{await P()}catch(B){console.error(`Network capture teardown failed: ${B instanceof Error?B.message:String(B)}`)}if(await yN(),process.listenerCount(Z)>1)return;process.exit(0)})}for(let Z of L)if(await JR(Z),J6)return;let T=process.env[UR]==="1";if(!T){for(let Z of L)if(await dI(Z),J6)return}if((await Promise.resolve().then(() => (b4(),I6))).captureRuntime.refuseCapture(KR(J.host,!!J.requireToken)),await NR(J.networkCapture?L:[],J.networkCaptureField,!!J.quiet),J6)return;for(let Z of D&&!T?L:[]){if(J6)return;if(W)await HH(Z,{bundleId:W,launchArgs:K,openUrl:N,capabilities:I});else{let B=await g8(Z,null,I),M=QI(I,B);if(M.length>0)console.error(`Requested ${M.join(", ")} but ${M.length===1?"it":"they"} did not apply on ${Z}. See the message above for why.`),await P(),process.exit(1)}}}catch(T){console.error(T instanceof Error?T.message:T),await P(),process.exit(1)}if(J6)return;if(J.detach){let T=await wm(L,H??3100,z,V);bm(T)}else if(J.preview===!1)await xm(L,H??3100,!!J.quiet,z,V);else await Xn(H??3200,L,H!==void 0,J.host,{stream:z,corsOrigins:J.corsOrigin,frameAncestors:J.frameAncestor,shareUrl:J.shareUrl,allowAnyHostWhenInsecure:!!J.allowAnyHostWhenInsecure,debugStreamPath:R,requireToken:!!J.requireToken,quiet:!!J.quiet,networkCapture:!!J.networkCapture,networkCaptureFields:J.networkCaptureField})});var U6=["-d, --device <udid>","Target a specific simulator (udid or name)"];async function cO($,J){let U=Date.now()+J;while(!k4($)&&Date.now()<U)await new Promise((Q)=>setTimeout(Q,250));return k4($)}async function zn($,J){let U=Date.now()+J;while(Date.now()<U){try{process.kill($,0)}catch{return!0}await new Promise((Q)=>setTimeout(Q,250))}try{process.kill($,0)}catch{return!0}return!1}async function Wn($,J){let U=m$($);if(!U)throw Error(`No running serve-sim session found for ${$}; start serve-sim for this device and retry.`);let Q=U.streamUrl.replace(/\/stream\.mjpeg$/,"/recording/video"),_=_6(J),X=y4(_,"session.json");if(k4(X))throw Error(`Recording manifest already exists at ${X}; choose an empty output directory.`);let Y=oO(16).toString("hex"),G={"x-recording-id":Y};if(U.token)G.Authorization=`Bearer ${U.token}`;let z=()=>{},W=new Promise((T)=>{z=T}),K=!1,N=!1,I=new AbortController,D=()=>{if(K=!0,!N)I.abort();z()},H=setInterval(()=>{},60000),V,R=!1,O=()=>{},L=new Promise((T,Z)=>{O=Z});L.catch(()=>{});let F=!1,P=!1;process.on("SIGINT",D),process.on("SIGTERM",D);try{try{let B=await fetch(Q,{method:"POST",headers:{...G,"Content-Type":"application/json"},body:JSON.stringify({start:!0,output:_,recordingId:Y}),signal:AbortSignal.any([AbortSignal.timeout(30000),I.signal])});if(!B.ok)throw Error(`Recording start failed (${B.status}): ${await B.text()}`)}catch(B){if(!K)throw B;let M=await fetch(Q,{method:"DELETE",headers:G,signal:AbortSignal.timeout(120000)});if(P=!0,M.status===200){if((await M.json()).manifest===X&&await cO(X,120000)){F=!0,console.log(X);return}}throw Error(`Recording start was interrupted before a video was saved: ${String(B)}`)}N=!0,console.error("serve-sim:recording-started"),V=setInterval(()=>{if(R)return;fetch(Q,{method:"PUT",headers:G,signal:AbortSignal.timeout(1e4)}).then(async(B)=>{if(!B.ok&&!R)O(Error(`Recording lease was lost (${B.status}): ${await B.text()}`))}).catch((B)=>{if(!R)O(B instanceof Error?B:Error(String(B)))})},5000);let T,Z=!1;try{await Promise.race([W,L]),R=!0,clearInterval(V),V=void 0;let B;try{B=await fetch(Q,{method:"DELETE",headers:G,signal:AbortSignal.timeout(120000)})}catch(j){throw Z=!0,j}if(!B.ok)throw Error(`Recording stop failed (${B.status}): ${await B.text()}`);if((await B.json()).manifest!==X)throw Error("Recording stop returned an unexpected manifest path")}catch(B){T=B}if(T&&!Z)throw T;if(!await cO(X,120000))throw T??Error("Recording stopped without a session.json manifest; inspect the serve-sim session log and retry.");if(T&&!K&&!await zn(U.pid,5000))throw Error(`Recording ended before a stop was requested: ${String(T)}. A partial video is available at ${X}.`);F=!0,console.log(X)}finally{if(R=!0,V)clearInterval(V);if(!F&&!P)try{await fetch(Q,{method:"DELETE",headers:G,signal:AbortSignal.timeout(1e4)})}catch{}clearInterval(H),process.off("SIGINT",D),process.off("SIGTERM",D)}}c$.command("record-video").description("Record native-size hardware H.264 simulator video until SIGINT").requiredOption("--udid <udid>","Simulator UDID").requiredOption("--output <dir>","Output directory").action(async($)=>Wn($.udid,$.output));c$.command("gesture").description("Send a touch gesture").argument("<json>",`Gesture JSON, e.g. '{"type":"begin","x":0.5,"y":0.5}'`).option(...U6).action(($,J)=>mm($,J.device));c$.command("tap").description("Tap at normalized 0..1 coords").argument("<x>","X coord, normalized 0..1").argument("<y>","Y coord, normalized 0..1").option(...U6).action(($,J,U)=>nm($,J,U.device));c$.command("button").description("Send a hardware button press").argument("[name]","Button name","home").option(...U6).action(($,J)=>om($,J.device));c$.command("type").description("Type text (US keyboard only)").argument("[text...]","Text to type").option(...U6).option("--stdin","Read text from stdin").option("--file <path>","Read text from a file").action(($,J)=>lm($,{device:J.device,stdin:J.stdin,file:J.file}));c$.command("rotate").description("Set device orientation (portrait|portrait_upside_down|landscape_left|landscape_right)").argument("<orientation>").option(...U6).action(($,J)=>cm($,J.device));c$.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 J=ij($);if(J===void 0)throw new i4("Expected fold, half, unfold, or an angle from 0 to 180");return J}).option(...U6).action(($,J)=>im($,J.device));c$.command("ca-debug").description("Toggle a CoreAnimation debug render flag (blended|copies|misaligned|offscreen|slow-animations)").argument("<option>").argument("<state>","on|off").option(...U6).action(($,J,U)=>rm($,J,U.device));c$.command("memory-warning").description("Simulate a memory warning on the device").option(...U6).action(($)=>dm($.device));c$.command("event-log").description("Show recent simulator events").option(...U6).option("-j, --json","Print JSON").option("-n, --limit <count>","Maximum number of events").action(($)=>ym($.device,{json:$.json,limit:$.limit}));c$.command("camera").description("Inject a synthetic camera feed and launch an app (see `camera --help`)").allowUnknownOption(!0).helpOption(!1).argument("[args...]").action(($)=>Qn($));c$.command("permissions").description("Manage app permissions (see `permissions` with no args for usage)").allowUnknownOption(!0).helpOption(!1).argument("[args...]").action(($)=>qH($));c$.command("ui").description("Get or set simulator-wide UI options (see `ui --help`)").allowUnknownOption(!0).helpOption(!1).argument("[args...]").action(($)=>YB($));JI(R$.capability);c$.command("capture").description("Network capture helpers").command("har").description("Follow the capture stream; write a HAR and its event log").requiredOption("-o, --out <path>","HAR file to keep rewriting").option("--events <path>","NDJSON event log (default: <name>.network-capture.json beside the HAR)").option(...U6).option("--flush-ms <ms>","How often to rewrite the HAR, in milliseconds (250-3600000)",(J)=>d0(J,"--flush-ms",250,3600000,!0),5000).option("--force","Replace a recording that already holds requests at --out").action(async(J)=>{let U=J.device?n$(J.device):void 0,Q=m$(U);if(!Q)console.error("No serve-sim server running. Run `serve-sim --network-capture` first."),process.exit(1);if(!Q.token)console.error("This serve-sim session recorded no access token, so the capture routes cannot be reached. Restart serve-sim on localhost, or with --require-token."),process.exit(1);let _=_6(J.out),X=J.events?_6(J.events):void 0,Y=new AbortController,G=()=>Y.abort();process.on("SIGINT",G),process.on("SIGTERM",G),console.error(`Recording capture for ${Q.device} → ${_} (+ ${X??e2(_).eventsPath}) (Ctrl-C to stop)`);let z=!1;try{let W=await d9({onBegin:()=>{z=!0},onPause:(K)=>console.error(`${K}
415
415
  Still recording to ${_}; requests are appended when capture is on again (Ctrl-C to stop).`),onResume:()=>console.error("Capture is on again; recording continues."),replace:!!J.force,baseUrl:GI(Q),device:Q.device,outPath:_,eventsPath:X,flushIntervalMs:J.flushMs,signal:Y.signal,version:rO(),token:Q.token});console.error(`The capture stream closed before you stopped the recording, so later requests are not in the HAR. serve-sim stopped or the connection dropped. To keep recording, run \`serve-sim capture har\` again with a new --out path. Wrote ${W.size} entries to ${_}.`),process.exit(1)}catch(W){if(W?.name==="AbortError"){console.error(z?`Stopped. HAR at ${_}`:`Stopped before recording began; ${_} was not written.`);return}console.error(W instanceof Error?W.message:String(W)),process.exit(1)}});await c$.parseAsync(process.argv);
416
416
 
417
- //# debugId=24FD2FFC5684497D64756E2164756E21
417
+ //# debugId=FBC2E568E91567CB64756E2164756E21
418
418
  //# sourceMappingURL=serve-sim.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/serve-sim",
3
- "version": "0.6.2-canary-20261008-c8a9613",
3
+ "version": "0.6.2",
4
4
  "type": "module",
5
5
  "author": {
6
6
  "name": "Evan Bacon",