@appetize/cli 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/cli.js +10 -19
- package/config-D0ukqfLN.js +3 -0
- package/daemon.js +2 -2
- package/package.json +6 -4
- package/skills/appetize/SKILL.md +37 -31
- package/skills/appetize/references/commands.md +38 -20
- package/viewer.html +1 -1
- package/signals-C8NaADLb.js +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @appetize/cli
|
|
2
2
|
|
|
3
|
+
## 0.19.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- feat(keychain): add the keychain clear command
|
|
8
|
+
- feat!: CLI output improvements
|
|
9
|
+
|
|
10
|
+
## 0.18.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- feat: add a global `--json` flag
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- fix: Ctrl-C cancels build, device and skill commands with an error
|
|
19
|
+
|
|
3
20
|
## 0.17.0
|
|
4
21
|
|
|
5
22
|
### Minor Changes
|
package/cli.js
CHANGED
|
@@ -1,20 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
`
|
|
4
|
-
`)}
|
|
5
|
-
`)}
|
|
6
|
-
`)
|
|
7
|
-
`}
|
|
8
|
-
`)
|
|
9
|
-
`)};function
|
|
10
|
-
`)
|
|
11
|
-
`)
|
|
12
|
-
`)};function Nt(e){return typeof e=="string"&&Object.hasOwn(ae,e)}const At=async({device:e,positionals:[t]})=>{const o=await e.screenshot(),n=Lt(o.mimeType,t);await K(n,o.data),process.stdout.write(`${JSON.stringify({bytes:o.data.byteLength,mimeType:o.mimeType,output:n},null,2)}
|
|
13
|
-
`)};function Tt(e){const t=e.split("/").at(1);return`.${t==="jpeg"?"jpg":t??"png"}`}function Lt(e,t="screenshot"){return N(t,{extension:Tt(e)})}function kt(e){const t=q(new URL("./daemon.js",import.meta.url)),o=ze(Oe(e.sessionId),"a"),n=Ke(process.execPath,[t],{detached:!0,env:{...process.env,[$e]:Ie(e),DEBUG:Dt(process.env.DEBUG)},stdio:["ignore",o,o]});if(Fe(o),n.unref(),n.pid===void 0)throw new Error("Failed to spawn the session daemon");return n.pid}function Dt(e){return e?`${e},appetize:daemon`:"appetize:daemon"}const _t=/^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/i;function Rt(){return qe({capitalize:!1,separator:"-"})}function Ut(e){if(!_t.test(e))throw new Error('--session-id must use letters, digits, ".", "-" or "_"');return e}const zt=["device-os-version","open","proxy"],Ft=150;async function jt(e,{onPhase:t,signal:o}){let n;for(;;){const i=C(e),r=i?.state?.phase;if(r&&r!==n&&(n=r,t?.(r)),i&&r==="ready"&&i.controlSocket!==void 0)return{...i,controlSocket:i.controlSocket};if(r==="error")throw new Error(i?.endedReason??"The session failed to start");if(r==="ended")throw new Error(i?.endedReason??"The session ended");await Bt(Ft,o)}}function Ct(e){const t=m(e,"--open");if(t!==void 0){try{new URL(t)}catch{throw new Error("--open expects a URL, e.g., myapp://orders/42")}return t}}function Jt(e){if(!(e===void 0||e===!1)){if(e===""||e==="intercept")return"intercept";if(typeof e!="string"||!Gt(e))throw new Error("--proxy expects 'intercept' or an http:// url, e.g., http://proxy:8080");return e}}async function Mt(e,t,o){const n=m(o["device-os-version"],"--device-os-version"),i=m(o["session-id"],"--session-id"),r=i===void 0?Rt():Ut(i);if(C(r)!==void 0)throw new Error(`Session ${r} already exists`);const a={device:n===void 0?{id:e}:{id:e,osVersion:n},endpoint:Ne(o),featureFlags:Pe(),open:Ct(o.open),proxy:Jt(o.proxy),sessionId:r,target:t};kt(a),console.error(`session started with id: ${r}`);const c=Ae(r,a.proxy);if(o.wait===!1){process.stdout.write(`${JSON.stringify({logs:c,sessionId:r},null,2)}
|
|
14
|
-
`);return}const v=await jt(r,{onPhase:ye=>{console.error(ye)},signal:J()}),ge={adbSerial:v.adbSerial,baseUrl:v.baseUrl,controlSocket:v.controlSocket,logs:c,sessionId:r,viewerUrl:v.viewerUrl};process.stdout.write(`${JSON.stringify(ge,null,2)}
|
|
15
|
-
`)}function Bt(e,t){return new Promise((o,n)=>{if(t.aborted){n(ce(t.reason));return}const i=()=>{clearTimeout(r),n(ce(t.reason))},r=setTimeout(()=>{t.removeEventListener("abort",i),o()},e);t.addEventListener("abort",i,{once:!0})})}function Gt(e){return e.startsWith("http://")}function ce(e){return e instanceof Error?e:new Error(String(e))}const Kt=async({record:{pid:e,sessionId:t}})=>{Te(e)&&process.kill(e,"SIGTERM"),process.stdout.write(`${JSON.stringify({ended:!0,sessionId:t},null,2)}
|
|
16
|
-
`)},pe="appetize",qt=q(new URL(`./skills/${pe}/`,import.meta.url)),R=["agents","claude","codex","copilot","cursor"],de=["project","user"],Xt={agents:".agents",claude:".claude",codex:".codex",copilot:".copilot",cursor:".cursor"},Zt=w(".agents","skills"),Vt=["claude","agents"];function Wt(e){return R.some(t=>t===e)}function Ht(e){return de.some(t=>t===e)}async function Yt(e){const t=e.agents??await Qt(e),o=await Promise.all(t.map(n=>le(n,e)));return[...new Set(o.flat())]}async function le(e,t){const o=ue(e,t);if(e==="claude")return[w(o,"skills")];const n=w(t.root,Zt);return t.scope==="project"?[n]:await fe(o)?[n,w(o,"skills")]:[n]}function ue(e,t){if(e==="claude"&&t.scope==="user"){const o=process.env.CLAUDE_CONFIG_DIR?.trim();if(o)return G(o)}return w(t.root,Xt[e])}async function Qt(e){const o=(await Promise.all(R.map(async n=>await eo(n,e)?n:void 0))).filter(n=>n!==void 0);return o.length>0?o:Vt}async function eo(e,t){const o=[ue(e,t),...await le(e,t)];return(await Promise.all(o.map(i=>fe(i)))).includes(!0)}async function fe(e){try{return(await Me(e)).isDirectory()}catch{return!1}}const to=["agent","scope"];async function oo(e){const t=ro(e.scope),o=io(e.agent),n=t==="user"?Xe():process.cwd(),i=await Yt({agents:o,root:n,scope:t}),r=[];for(const a of i){const c=w(a,pe);await Be(c,{force:!0,recursive:!0}),await Ge(qt,c,{recursive:!0}),r.push(t==="user"?c:Je(n,c))}process.stdout.write(`${JSON.stringify({installed:r},null,2)}
|
|
17
|
-
`)}function no(e){const t=x(e,"--agent");if(!Wt(t))throw new Error(`--agent expects one of ${R.join(", ")}`);return t}function io(e){return e===void 0?void 0:(Array.isArray(e)?e:[e]).map(o=>no(o))}function ro(e){if(e===void 0)return"project";const t=x(e,"--scope");if(!Ht(t))throw new Error(`--scope expects one of ${de.join(", ")}`);return t}const l="from",u="to",so=[...D({prefix:l}),...D({prefix:u})],ao=async({device:e,options:t})=>{await e.swipe(uo(t),mo(t)),process.stdout.write(`${JSON.stringify({swiped:!0},null,2)}
|
|
18
|
-
`)};function co(e){return I.some(t=>t===e)}function po(e){if(e===void 0)return;const t=x(e,"--direction");if(!co(t))throw new Error(`--direction expects one of ${I.join(", ")}`);return t}function lo(e,t){const o=Le(e.distance,"--distance");if(b(e,{prefix:u})!==void 0)throw new Error(`--direction may not be combined with --${u}-*`);return{direction:t,distance:o,from:b(e,{prefix:l})}}function uo(e){const t=po(e.direction);return t===void 0?fo(e):lo(e,t)}function fo(e){if(e.distance!==void 0)throw new Error("--distance is only valid with --direction");return{from:me(b(e,{prefix:l}),l),to:me(b(e,{prefix:u}),u)}}function mo(e){const t=p(e.duration,"--duration"),o=p(e.timeout,"--timeout");return t===void 0&&o===void 0?void 0:{duration:t,timeout:o}}function me(e,t){if(e===void 0)throw new Error(`A swipe needs --direction, or both endpoints: pass one of ${S({prefix:t})}`);return e}const wo=D(),ho=async({device:e,options:t})=>{const o=te(t);await e.tap(o,ee(t)),process.stdout.write(`${JSON.stringify({tapped:!0},null,2)}
|
|
19
|
-
`)},go=async({device:e,options:t,positionals:[o]})=>{await e.type(o,yo(t)),process.stdout.write(`${JSON.stringify({typed:!0},null,2)}
|
|
20
|
-
`)};function yo(e){const t=p(e.delay,"--delay");return t===void 0?void 0:{delay:t}}const U=Ze("appetize:cli");function So(e,t){if(e.controlSocket===void 0)throw new Error("Session is not ready");return Ve(e.controlSocket,{baseUrl:e.baseUrl,signal:t})}async function vo(e,t){if(e.controlSocket===void 0)throw new Error("Session is not ready");const o=await F(e.controlSocket,{signal:t}),{client:n}=ke(o,{});return{close:()=>{o.close()},recordStart:async i=>await n.request("appetizeio.cli.record.start",i),recordStop:async()=>await n.request("appetizeio.cli.record.stop")}}function xo(e){return async(...t)=>{const{options:o,positionals:n}=$o(t),i=o["session-id"],r=De(typeof i=="string"?i:void 0),a=AbortSignal.any([J(),_e(r.pid)]);await e({options:o,positionals:n,record:r,signal:a})}}function Eo(e){return async({options:t,positionals:o,record:n,signal:i})=>{const r=await So(n,i);try{await e({device:r,options:t,positionals:o,signal:i})}finally{r.close()}}}function bo(e){return async({options:t,positionals:o,record:n,signal:i})=>{const r=await vo(n,i);try{await e({control:r,options:t,positionals:o,signal:i})}finally{r.close()}}}function Oo(e){return typeof e=="object"&&e!==null}function $o(e){const t=e.at(-1);return{options:Oo(t)?t:{},positionals:e.slice(0,-1).filter(o=>typeof o=="string")}}const Io=["session-id",...We,...Qe,...ct,...wt,...to,...zt,...so,...wo];function Po(e){const t=Se("appetize").version(e);return g(t.command("session start <device-id> <target>").describe(["Start a device session and wait until it is ready","","Environment variables:","APPETIZE_API_TOKEN: Authorizes private APIs and session targets","APPETIZE_ENDPOINT: Appetize URL used when --endpoint is omitted"]).option("--device-os-version","Device OS version (e.g., 17 for iOS, 14 for Android)").option("--endpoint","Appetize URL (e.g., https://appetize.io); overrides APPETIZE_ENDPOINT").option("--no-wait","Return without waiting for the device session to be ready").option("--open","URL opened once the session is ready").option("--proxy","Route traffic through a proxy: 'intercept' to capture it, or an http url").option("--session-id","Session id; defaults to a generated 3-word id").example("session start iphone15pro app_a1b2c3").example("session start pixel7 app_a1b2c3 --device-os-version 14").example("session start iphone15pro app_a1b2c3 --open myapp://orders/42"),Mt),z(t.command("session stop").describe("Stop a running device session"),Kt),g(t.command("build list").describe(["List uploaded builds, printing session start targets","","Environment variables:","APPETIZE_API_TOKEN: Authorizes the listing request","APPETIZE_ENDPOINT: Appetize URL used when --endpoint is omitted"]).option("--app","App id to filter by (bundle or package id)").option("--endpoint","Appetize URL (e.g., https://appetize.io); overrides APPETIZE_ENDPOINT").option("--limit","Builds per page (default 10, max 200)").option("--page","Page of results to fetch (default 1)").example("build list").example("build list --app com.example.app").example("build list --app com.example.app --page 2"),Ye),g(t.command("build upload <file>").describe([`Upload a build (${P.join(", ")}) as a session start target`,"","Environment variables:","APPETIZE_API_TOKEN: Authorizes the upload","APPETIZE_ENDPOINT: Appetize URL used when --endpoint is omitted"]).option("--endpoint","Appetize URL (e.g., https://appetize.io); overrides APPETIZE_ENDPOINT").option("--note","Note to store with the build").option("--tags","Comma separated tags to store with the build").option("--timeout",`Milliseconds to wait with --wait (default ${String(H)})`).option("--wait","Wait for the app id and version metadata to resolve").example("build upload ./app.apk").example("build upload ./app.zip").example("build upload ./app.apk --wait").example('build upload ./app.apk --tags beta,latest --note "PR 42"'),ot),g(t.command("device list").describe(["List device models and their supported OS versions","","Environment variables:","APPETIZE_ENDPOINT: Appetize URL used when --endpoint is omitted"]).option("--endpoint","Appetize URL (e.g., https://appetize.io); overrides APPETIZE_ENDPOINT").option("--platform","Platform to filter by: ios or android").example("device list").example("device list --platform ios"),pt),f(t.command("press <button>").describe(`Press a device button: ${Z.join(", ")}; Android only: ${X.join(", ")}`).example("press home").example("press volumeUp"),Et),f(t.command("rotate <orientation>").describe("Rotate the device to an orientation: portrait, landscapeLeft, landscapeRight or upsideDown").example("rotate portrait").example("rotate landscapeLeft"),Pt),f(t.command("open <url>").describe("Open a URL or deep link on the device").example("open myapp://orders/42").example("open https://example.com"),St),f(t.command("screenshot [output]").describe("Take a screenshot of the current device screen").example("screenshot").example("screenshot home-screen").example("screenshot ./shots/checkout.png"),At),f(k(t.command("tap").describe(["Tap an element matched by a selector, or a screen position","",`Pick one of: ${S()}`])).option("--timeout","Milliseconds to wait for the element").example("tap --select-text 'Log in'").example("tap --select-test-id save").example("tap --select-text '/^Item \\d+/i' --select-index 2").example("tap --select-position 0.5,0.75").example("tap --select-test-id slider --select-x 0.9").example("tap --select-test-id dialog --select-x=-0.1").example("tap --select-test-id row --select-y=1.2"),ho),f(k(k(t.command("swipe").describe(["Swipe in a direction, or along a path between two points","",`Pick a --direction with an optional --${l} starting point,`,`or both a --${l}-* and a --${u}-* point to form a path`,"",`Pick one per point: ${S({prefix:l})}`,` ${S({prefix:u})}`]).option("--direction",`Direction to travel: ${I.join(", ")}`).option("--distance","Travel as a fraction of the screen (0-1)"),{prefix:l}),{prefix:u}).option("--duration","Milliseconds the gesture travels for").option("--timeout",`Milliseconds to wait for any --${l}/--${u} elements`).example("swipe --direction up").example("swipe --direction up --distance 0.25").example("swipe --direction left --from-test-id card --from-index 1").example("swipe --from-position 0.5,0.75 --to-position 0.5,0.3").example("swipe --from-text 'Drag me' --from-y 0.9 --to-test-id drop-zone"),ao),f(Y(t.command("inspect [output]").describe("Capture the view hierarchy of the screen, or of an element matched by a selector")).option("--timeout","Milliseconds to wait for the element").option("--pretty","Pretty-print the JSON",!1).example("inspect").example("inspect --select-text 'Log in'").example("inspect hierarchy.json --pretty"),ht),f(t.command("type <text>").describe(`Type text; {...} presses a named key: ${Re.join(", ")}`).option("--delay","Milliseconds to wait between steps").example("type 'hello{Enter}'").example("type '{Backspace>16/}'").example("type 'user@example.com{Tab}hunter2{Enter}' --delay 50"),go),we(t.command("recording start <output>").describe("Start recording the device video to an mp4 file").option("--force","Overwrite the file if it already exists",!1).example("recording start login-flow").example("recording start ./captures/checkout.mp4").example("recording start login-flow --force"),Ot),we(t.command("recording stop").describe("Stop recording the device video and close the file").example("recording stop"),$t),g(t.command("skill install").describe("Install the Appetize agent skill for coding agents").option("--agent","Agent to install for, repeatable; defaults to the agents detected").option("--scope","Install for the project (default) or the user").example("skill install").example("skill install --scope user").example("skill install --agent claude --agent cursor"),oo),t}function g(e,t){return e.action(Ao(t))}function z(e,t){return g(e.option("--session-id","Target session id; defaults to the sole active session"),xo(t))}function f(e,t){return z(e,Eo(t))}function we(e,t){return z(e,bo(t))}function he(e){return`${String(Date.now()-e)}ms`}async function No(e,...t){const o=Date.now();U(`invoked: ${process.argv.slice(2).join(" ")}`);try{await e(...t),U(`ok in ${he(o)}`)}catch(n){const i=n instanceof Error?n.message:String(n);console.error(i),U(`failed after ${he(o)}:`,n),process.exitCode=1}}function Ao(e){return(...t)=>{No(e,...t)}}Po("0.17.0").parse(process.argv,{string:Io});
|
|
2
|
+
import Ue from"sade";import{d as X,D as je,p as v,a as m,f as L,U as c,b as V,c as ze,i as Fe,e as Ce,r as H,g as k,h as Me,j as Be,s as qe,k as J,l as Ge,m as Ke,n as Ze,S as Y,o as Q,q as We,t as Xe,u as ee,v as Ve,w as He,x as Je,y as Ye,z as Qe,A as et}from"./config-D0ukqfLN.js";import{existsSync as te,openAsBlob as tt,openSync as nt,closeSync as ot}from"node:fs";import{basename as D,extname as it,resolve as ne,dirname as rt,join as S,relative as st}from"node:path";import{writeFile as oe,stat as at,rm as ct,cp as pt}from"node:fs/promises";import{spawn as dt}from"node:child_process";import{fileURLToPath as ie}from"node:url";import{humanId as lt}from"human-id";import{homedir as ut}from"node:os";import ft from"debug";import mt from"yocto-spinner";import ht from"cli-table3";import"stream";import"module";import"node:net";import"json-rpc-2.0";const re=["back","menu","unlock","volumeDown","volumeUp"],se=["home","lock"],ae=[...se,...re],N=["down","left","right","up"];async function wt(e,t={}){const n=await X(e,{signal:t.signal});return new je(n,{...t,onClose:()=>{n.close(),t.onClose?.()}})}const ce=[{header:"Target",key:"id"},{header:"App",key:"appId"},{header:"Platform",key:"platform"},{header:"Version",key:"versionName"},{header:"Build",key:"buildNumber"},{header:"Uploaded",key:"created"}];function _({appId:e,buildNumber:t,created:n,id:o,platform:i,versionName:r}){return{appId:e,buildNumber:t,created:n,id:o,platform:i,versionName:r}}const gt=["app"],yt=10,vt=[{fields:ce,key:"builds"},{header:"Total",key:"total"},{header:"Next page",key:"nextPage"}];async function St({options:e,signal:t}){const n=v(e.app,"--app"),o=m(e.limit,"--limit")??yt,i=m(e.page,"--page"),r={limit:String(o)};n!==void 0&&(r.appId=n),i!==void 0&&(r.page=String(i));const s=await L("/api/v2/builds",{commandOptions:e,query:r,signal:t});return{builds:s.builds.map(_),nextPage:s.nextPage,total:s.total}}const bt=["note","tags"],pe=12e4,xt=2e3,R=[".apk",".apks",".zip",".tar.gz",".tgz"],Et={".apk":"android",".apks":"android",".tar.gz":"ios",".tgz":"ios",".zip":"ios"},Ot=ce;async function kt({options:e,positionals:[t],progress:n,signal:o}){const i=$t(t),r=D(t);n.status(`Uploading ${r}`);const s=await At(t,i,e,o);if(e.wait!==!0)return n.status(`Uploaded ${r}`),_(s);n.step(`Uploaded ${r}`),n.status("Waiting for build metadata");const a=await Pt(s.id,e,o);return n.status(`Processed ${r}`),_(a)}async function Pt(e,t,n){const o=m(t.timeout,"--timeout")??pe,i=Date.now()+o;for(;;){const r=await L(`/api/v2/builds/${e}`,{commandOptions:t,signal:n});if(r.appId!==void 0)return r;if(Date.now()>=i)throw new Error(`Build ${e} is still being processed after ${String(o)}ms; find it with 'appetize build list'`);await V(xt,n)}}async function It(e){if(!te(e))throw new Error(`No build file at ${e}`);return await tt(e)}function $t(e){const t=e.toLowerCase(),n=R.find(o=>t.endsWith(o));if(n===void 0)throw new c(`Cannot tell the platform of ${D(e)}; upload a ${R.join(", ")} file`);return Et[n]}async function At(e,t,n,o){const i=new FormData;i.set("platform",t);const r=v(n.note,"--note");r!==void 0&&i.set("note",r);const s=v(n.tags,"--tags");return s!==void 0&&i.set("tags",s),i.set("file",await It(e),D(e)),await L("/api/v2/builds",{body:i,commandOptions:n,method:"POST",signal:o})}const Tt=["platform"],Lt=[{fields:[{header:"ID",key:"id"},{header:"Name",key:"name"},{header:"Platform",key:"platform"},{header:"OS versions",key:"osVersions"}],key:"devices"}];async function Dt({options:e,signal:t}){const n=Nt(e.platform);return{devices:(await ze(e,t)).filter(i=>n===void 0||i.platform===n).map(_t)}}function Nt(e){const t=v(e,"--platform");if(t!==void 0){if(!Fe(t))throw new c(`--platform expects one of: ${Ce.join(", ")}`);return t}}function _t({id:e,name:t,osVersions:n,platform:o}){return{id:e,name:t,osVersions:n,platform:o}}const Rt="APPETIZE_OUTPUT";function Ut(e,t,n){return{format:jt(e,t),progress:zt(e,n)}}function U(e,{extension:t,strict:n=!1}){const o=it(e);if(o==="")return`${e}${t}`;if(n&&o!==t)throw new c(`The output must be a path ending in ${t}`);return e}function jt(e,t){if(e.json===!0)return"json";if(e.json===!1)return"text";const n=process.env[Rt]?.trim();return n==="json"||n==="text"?n:t.isTTY===!0?"text":"json"}function zt(e,t){return e.quiet===!0?"silent":t.isTTY===!0&&process.env.TERM!=="dumb"&&!("CI"in process.env)?"interactive":"silent"}const b=["text","testId"],h="select",E={testId:{help:"Test id to match by exact string",suffix:"test-id"},text:{help:'Text to match by exact string or regex (e.g., "Sign in" or "/sign in/i")',suffix:"text"}},j="index",P="position",z="x",F="y";function de(e,{prefix:t=h}={}){return b.reduce((n,o)=>{const{help:i,suffix:r}=E[o];return n.option(`--${p(t,r)}`,i)},e).option(`--${p(t,j)}`,"Which match when multiple (0-based)")}function C(e,t={}){const{prefix:n=h}=t;return de(e,t).option(`--${p(n,P)}`,"Screen position to use as x,y (0-1), e.g., 0.5,0.75").option(`--${p(n,z)}`,"Horizontal position within the element (0-1, outside allowed)").option(`--${p(n,F)}`,"Vertical position within the element (0-1, outside allowed)")}function le(e,{prefix:t=h}={}){const n=B(e,t);if(n.length===0)throw new c(`A selector is required: pass one of ${$(b,t)}`);if(n.length>1)throw new c(`Only one selector may be given, got ${$(n,t)}`);const[o]=n,i=ge(e,p(t,E[o].suffix)),r=m(e[p(t,j)],`--${p(t,j)}`);switch(o){case"testId":return{by:"testId",index:r,testId:i};case"text":return{by:"text",index:r,text:Mt(i)}}}function ue(e){const t=m(e.timeout,"--timeout");return t===void 0?void 0:{timeout:t}}function Ft(e,{prefix:t=h}={}){return he(e,t)?le(e,{prefix:t}):void 0}function I(e,{prefix:t=h}={}){return he(e,t)?fe(e,{prefix:t}):void 0}function fe(e,{prefix:t=h}={}){const n=p(t,P),o=e[n],i=we(e,p(t,z)),r=we(e,p(t,F));if(o===void 0){if(B(e,t).length===0)throw new c(`A selector is required: pass one of ${O({prefix:t})}`);return{...le(e,{prefix:t}),x:i,y:r}}if(B(e,t).length>0)throw new c(`--${n} may not be combined with ${$(b,t)}`);if(i!==void 0||r!==void 0)throw new c(`--${n} may not be combined with --${p(t,z)} or --${p(t,F)}`);return Ct(ge(e,n),n)}function O(e={}){const{prefix:t=h}=e;return`${$(b,t)}, --${p(t,P)}`}function M(e={}){const{prefix:t=h}=e;return[...me(e),p(t,P)]}function me({prefix:e=h}={}){return b.map(t=>p(e,E[t].suffix))}function B(e,t){return b.filter(n=>e[p(t,E[n].suffix)]!==void 0)}function p(...e){return e.filter(Boolean).join("-")}function $(e,t){return e.map(n=>`--${p(t,E[n].suffix)}`).join(", ")}function he(e,t){return Object.entries(e).some(([n,o])=>o!==void 0&&n.startsWith(`${t}-`))}function we(e,t){return m(e[t],`--${t}`)}function Ct(e,t){const n=e.split(",");if(n.length!==2)throw new c(`--${t} expects x,y (0-1), e.g., 0.5,0.75`);const[o,i]=n.map(r=>Number(r.trim()));return{by:"position",x:H(o,`--${t}`),y:H(i,`--${t}`)}}function Mt(e){const t=/^\/(.*)\/([a-z]*)$/s.exec(e);return t?new RegExp(t[1],t[2]):e}function ge(e,t){return k(e[t],`--${t}`)}const Bt=me(),qt=async({device:e,options:t,positionals:[n]})=>{const o=Gt(n),i=Ft(t),r=await e.inspect(i,ue(t)),s=Kt(r,t.pretty===!0);return await oe(o,s),{bytes:Buffer.byteLength(s),nodes:ye(r.root),output:o}};function ye(e){return e.children.reduce((t,n)=>t+ye(n),1)}function Gt(e="inspect"){return U(e,{extension:".json"})}function Kt(e,t){return`${JSON.stringify(e,null,t?2:void 0)}
|
|
3
|
+
`}const Zt=async({device:e})=>{await e.clearKeychain()},Wt=async({device:e,positionals:[t]})=>{await e.open(Xt(t))};function Xt(e){if(typeof e=="string")try{return new URL(e),e}catch{throw new c("<url> expects a URL, e.g., myapp://orders/42")}throw new c("<url> expects a URL, e.g., myapp://orders/42")}const Vt=new Set(ae),Ht=async({device:e,positionals:[t]})=>{if(!Jt(t))throw new c(`Button must be one of: ${ae.join(", ")}`);await e.press(t)};function Jt(e){return typeof e=="string"&&Vt.has(e)}const Yt=async({control:e,options:t,positionals:[n]})=>{const{path:o}=await e.recordStart({force:t.force===!0,path:en(n)});return{path:o}},Qt=async({control:e})=>{const{path:t}=await e.recordStop();return{path:t}};function en(e){const t=ne(U(e,{extension:".mp4",strict:!0})),n=rt(t);if(!te(n))throw new c(`No such directory: ${n}`);return t}const ve={landscapeLeft:!0,landscapeRight:!0,portrait:!0,upsideDown:!0},tn=async({device:e,positionals:[t]})=>{if(!nn(t))throw new c(`Orientation must be one of: ${Object.keys(ve).join(", ")}`);await e.rotate(t)};function nn(e){return typeof e=="string"&&Object.hasOwn(ve,e)}const on=async({device:e,positionals:[t]})=>{const n=await e.screenshot(),o=sn(n.mimeType,t);return await oe(o,n.data),{bytes:n.data.byteLength,output:o}};function rn(e){const t=e.split("/").at(1);return`.${t==="jpeg"?"jpg":t??"png"}`}function sn(e,t="screenshot"){return U(t,{extension:rn(e)})}function an(e){const t=ie(new URL("./daemon.js",import.meta.url)),n=nt(Me(e.sessionId),"a"),o=dt(process.execPath,[t],{detached:!0,env:{...process.env,[Be]:qe(e),DEBUG:cn(process.env.DEBUG)},stdio:["ignore",n,n]});if(ot(n),o.unref(),o.pid===void 0)throw new Error("Failed to spawn the session daemon");return o.pid}function cn(e){return e?`${e},appetize:daemon`:"appetize:daemon"}const pn=/^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/i;function dn(){return lt({capitalize:!1,separator:"-"})}function ln(e){if(!pn.test(e))throw new c('--session-id must use letters, digits, ".", "-" or "_"');return e}const un=["device-os-version","open","proxy"],fn=150,mn={downloadingApp:"Downloading the app",installingApp:"Installing the app",launchingApp:"Launching the app",queued:"Queued",ready:"Device ready",requesting:"Requesting a device",starting:"Starting the device"},hn=[{header:"Session ID",key:"sessionId"},{header:"Web view",key:"viewerUrl"},{format:e=>`adb connect ${e}`,header:"adb",key:"adbSerial"},{header:"Host",key:"baseUrl"},{fields:[{header:"Device",key:"device"},{header:"Daemon",key:"daemon"},{header:"Network",key:"network"}],header:"Logs",key:"logs"},{hidden:!0,key:"controlSocket"}];async function wn(e,{onPhase:t,signal:n}){let o;for(;;){const i=J(e),r=i?.state?.phase;if(r&&r!==o&&(o=r,t?.(r)),i&&r==="ready"&&i.controlSocket!==void 0)return{...i,controlSocket:i.controlSocket};if(r==="error")throw new Error(i?.endedReason??"The session failed to start");if(r==="ended")throw new Error(i?.endedReason??"The session ended");await V(fn,n)}}function gn(e){const t=v(e,"--open");if(t!==void 0){try{new URL(t)}catch{throw new c("--open expects a URL, e.g., myapp://orders/42")}return t}}function yn(e){if(!(e===void 0||e===!1)){if(e===""||e==="intercept")return"intercept";if(typeof e!="string"||!Sn(e))throw new c("--proxy expects 'intercept' or an http:// url, e.g., http://proxy:8080");return e}}async function vn({options:e,positionals:[t,n],progress:o,signal:i}){const r=v(e["device-os-version"],"--device-os-version"),s=v(e["session-id"],"--session-id"),a=s===void 0?dn():ln(s);if(J(a)!==void 0)throw new Error(`Session ${a} already exists`);const d={device:r===void 0?{id:t}:{id:t,osVersion:r},endpoint:Ke(e),featureFlags:Ge(),open:gn(e.open),proxy:yn(e.proxy),sessionId:a,target:n};an(d),o.step(`Session ${a}`);const l=Ze(a,d.proxy);if(e.wait===!1)return{logs:l,sessionId:a};const u=await wn(a,{onPhase:f=>{bn(f)&&o.status(mn[f]??"Starting the session")},signal:i}).catch(f=>{throw Y.wrap(f,Q(a))});return{adbSerial:u.adbSerial,baseUrl:u.baseUrl,controlSocket:u.controlSocket,logs:l,sessionId:a,viewerUrl:u.viewerUrl}}function Sn(e){return e.startsWith("http://")}function bn(e){return e!=="ended"&&e!=="error"}const xn=async({record:{pid:e,sessionId:t}})=>(We(e)&&process.kill(e,"SIGTERM"),{sessionId:t}),Se="appetize",En=ie(new URL(`./skills/${Se}/`,import.meta.url)),q=["agents","claude","codex","copilot","cursor"],be=["project","user"],On={agents:".agents",claude:".claude",codex:".codex",copilot:".copilot",cursor:".cursor"},kn=S(".agents","skills"),Pn=["claude","agents"];function In(e){return q.some(t=>t===e)}function $n(e){return be.some(t=>t===e)}async function An(e){const t=e.agents??await Tn(e),n=await Promise.all(t.map(o=>xe(o,e)));return[...new Set(n.flat())]}async function xe(e,t){const n=Ee(e,t);if(e==="claude")return[S(n,"skills")];const o=S(t.root,kn);return t.scope==="project"?[o]:await Oe(n)?[o,S(n,"skills")]:[o]}function Ee(e,t){if(e==="claude"&&t.scope==="user"){const n=process.env.CLAUDE_CONFIG_DIR?.trim();if(n)return ne(n)}return S(t.root,On[e])}async function Tn(e){const n=(await Promise.all(q.map(async o=>await Ln(o,e)?o:void 0))).filter(o=>o!==void 0);return n.length>0?n:Pn}async function Ln(e,t){const n=[Ee(e,t),...await xe(e,t)];return(await Promise.all(n.map(i=>Oe(i)))).includes(!0)}async function Oe(e){try{return(await at(e)).isDirectory()}catch{return!1}}const Dn=["agent","scope"];async function Nn({options:e,signal:t}){const n=Un(e.scope),o=Rn(e.agent),i=n==="user"?ut():process.cwd(),r=await An({agents:o,root:i,scope:n}),s=[];for(const a of r){t.throwIfAborted();const d=S(a,Se);await ct(d,{force:!0,recursive:!0}),await pt(En,d,{recursive:!0}),s.push(n==="user"?d:st(i,d))}return{installed:s}}function _n(e){const t=k(e,"--agent");if(!In(t))throw new c(`--agent expects one of ${q.join(", ")}`);return t}function Rn(e){return e===void 0?void 0:(Array.isArray(e)?e:[e]).map(n=>_n(n))}function Un(e){if(e===void 0)return"project";const t=k(e,"--scope");if(!$n(t))throw new c(`--scope expects one of ${be.join(", ")}`);return t}const w="from",g="to",jn=[...M({prefix:w}),...M({prefix:g})],zn=async({device:e,options:t})=>{await e.swipe(Bn(t),Gn(t))};function Fn(e){return N.some(t=>t===e)}function Cn(e){if(e===void 0)return;const t=k(e,"--direction");if(!Fn(t))throw new c(`--direction expects one of ${N.join(", ")}`);return t}function Mn(e,t){const n=Xe(e.distance,"--distance");if(I(e,{prefix:g})!==void 0)throw new c(`--direction may not be combined with --${g}-*`);return{direction:t,distance:n,from:I(e,{prefix:w})}}function Bn(e){const t=Cn(e.direction);return t===void 0?qn(e):Mn(e,t)}function qn(e){if(e.distance!==void 0)throw new c("--distance is only valid with --direction");return{from:ke(I(e,{prefix:w}),w),to:ke(I(e,{prefix:g}),g)}}function Gn(e){const t=m(e.duration,"--duration"),n=m(e.timeout,"--timeout");return t===void 0&&n===void 0?void 0:{duration:t,timeout:n}}function ke(e,t){if(e===void 0)throw new c(`A swipe needs --direction, or both endpoints: pass one of ${O({prefix:t})}`);return e}const Kn=M(),Zn=async({device:e,options:t})=>{const n=fe(t);await e.tap(n,ue(t))},Wn=async({device:e,options:t,positionals:[n]})=>{await e.type(n,Xn(t))};function Xn(e){const t=m(e.delay,"--delay");return t===void 0?void 0:{delay:t}}const G=ft("appetize:cli"),Vn={fail:()=>{},status:()=>{},step:()=>{},succeed:()=>{}};function Hn(e,t,n){return e==="interactive"?Jn(t,n):Vn}function Jn(e,t){const n=mt({handleSignals:!1,stream:e});let o=0;const i=()=>{n.stop()};t.addEventListener("abort",i,{once:!0});const r=()=>(process.off("exit",i),n.isSpinning);return{fail:()=>{r()&&n.stop()},status:s=>{if(!t.aborted){if(n.isSpinning){n.text=s;return}o=Date.now(),process.once("exit",i),n.start(s)}},step:s=>{e.write(`\u25B8 ${s}
|
|
4
|
+
`)},succeed:()=>{if(!r())return;const s=Math.round((Date.now()-o)/1e3);n.success(`${n.text} (${String(s)}s)`)}}}const Yn=new Set(["adb","api","apk","id","os","url"]),Qn={bottom:"","bottom-left":"","bottom-mid":"","bottom-right":"",left:"","left-mid":"",mid:"","mid-mid":"",middle:" ",right:"","right-mid":"",top:"","top-left":"","top-mid":"","top-right":""},Pe=2,eo=10;function to(e){return e.split(/(?=[A-Z])/).map((t,n)=>{const o=t.toLowerCase();return Yn.has(o)?o.toUpperCase():n===0?o.charAt(0).toUpperCase()+o.slice(1):o}).join(" ")}function no(e,t,n){return Z(e)?De(e,t,n):A(e,{fields:t,key:""},n)}function oo(e,t){const n=[];for(let o=0;o<e.length;o+=t)n.push(e.slice(o,o+t));return n.length===0?[e]:n}function Ie(e){return new ht({chars:Qn,head:e,style:{border:[],head:[],"padding-left":0,"padding-right":Pe}})}function $e(e,t){return e.find(n=>n.key===t)}function Ae(e,t){return t?.header??to(e)}function K(e){return e!=null}function Z(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Te(e){return["boolean","number","string"].includes(typeof e)}function Le(e,t){const n=new Set(t),o=e.map(r=>r.key).filter(r=>n.has(r)),i=new Set(e.filter(r=>r.hidden).map(r=>r.key));return[...new Set([...o,...t])].filter(r=>!i.has(r))}function De(e,t,n){const o=new Map(Object.entries(e)),i=Le(t,[...o.keys()]).filter(u=>K(o.get(u))),r=i.map(u=>$e(t,u)),s=i.map((u,f)=>Ae(u,r[f])),a=Math.max(0,...s.map(u=>u.length))+Pe,d=n===void 0?void 0:n-a-1,l=Ie();return l.push(...i.map((u,f)=>[s[f],A(o.get(u),r[f],d)])),Ne(l.toString())}function io(e,t){const n=e.map(s=>new Map(Object.entries(s))),o=Le(t,n.flatMap(s=>[...s.keys()])),i=o.map(s=>$e(t,s)),r=Ie(o.map((s,a)=>Ae(s,i[a])));for(const s of n)r.push(o.map((a,d)=>{const l=s.get(a);return K(l)?A(l,i[d]):""}));return Ne(r.toString())}function A(e,t,n){if(t?.format)return T(t.format(e),n);if(Te(e))return T(ee(e),n);if(Array.isArray(e)){const o=e.filter(K);return o.every(Te)?T(ee(o),n):o.every(Z)?io(o,t?.fields??[]):o.map(i=>A(i,t,n)).join(`
|
|
5
|
+
`)}return Z(e)?De(e,t?.fields??[],n):T(String(e),n)}function Ne(e){return e.split(`
|
|
6
|
+
`).map(t=>t.trimEnd()).join(`
|
|
7
|
+
`)}function T(e,t){return t===void 0||t<eo?e:e.split(`
|
|
8
|
+
`).flatMap(n=>ro(n,t)).join(`
|
|
9
|
+
`)}function ro(e,t){const n=[];let o="";for(const i of e.split(" ").flatMap(r=>oo(r,t)))o===""?o=i:o.length+1+i.length<=t?o=`${o} ${i}`:(n.push(o),o=i);return n.push(o),n}function so(e,t){if(e.controlSocket===void 0)throw new Error("Session is not ready");return wt(e.controlSocket,{baseUrl:e.baseUrl,signal:t})}async function ao(e,t){if(e.controlSocket===void 0)throw new Error("Session is not ready");const n=await X(e.controlSocket,{signal:t}),{client:o}=Ve(n,{});return{close:()=>{n.close()},recordStart:async i=>await o.request("appetizeio.cli.record.start",i),recordStop:async()=>await o.request("appetizeio.cli.record.stop")}}function co(e){return async({options:t,positionals:n,progress:o,signal:i})=>{const r=t["session-id"],s=He(typeof r=="string"?r:void 0);try{return await e({options:t,positionals:n,progress:o,record:s,signal:AbortSignal.any([i,Je(s.pid)])})}catch(a){throw Y.wrap(a,Q(s.sessionId))}}}function po(e){return async({options:t,positionals:n,progress:o,record:i,signal:r})=>{const s=await so(i,r);try{return await e({device:s,options:t,positionals:n,progress:o,signal:r})}finally{s.close()}}}function lo(e){return async({options:t,positionals:n,progress:o,record:i,signal:r})=>{const s=await ao(i,r);try{return await e({control:s,options:t,positionals:n,progress:o,signal:r})}finally{s.close()}}}const uo=["session-id",...gt,...bt,...Tt,...Bt,...Dn,...un,...jn,...Kn],fo=["json","quiet"];function mo(e){const t=Ue("appetize").version(e).option("--json","Print the result as JSON").option("--quiet","Hide progress");return x(t,"session start <device-id> <target>",n=>n.describe(["Start a device session and wait until it is ready","","Environment variables:","APPETIZE_API_TOKEN: Authorizes private APIs and session targets","APPETIZE_ENDPOINT: Appetize URL used when --endpoint is omitted"]).option("--device-os-version","Device OS version (e.g., 17 for iOS, 14 for Android)").option("--endpoint","Appetize URL (e.g., https://appetize.io); overrides APPETIZE_ENDPOINT").option("--no-wait","Return without waiting for the device session to be ready").option("--open","URL opened once the session is ready").option("--proxy","Route traffic through a proxy: 'intercept' to capture it, or an http url").option("--session-id","Session id; defaults to a generated 3-word id").example("session start iphone15pro app_a1b2c3").example("session start pixel7 app_a1b2c3 --device-os-version 14").example("session start iphone15pro app_a1b2c3 --open myapp://orders/42"),vn,{fields:hn}),W(t,"session stop",n=>n.describe("Stop a running device session"),xn),x(t,"build list",n=>n.describe(["List uploaded builds, printing session start targets","","Environment variables:","APPETIZE_API_TOKEN: Authorizes the listing request","APPETIZE_ENDPOINT: Appetize URL used when --endpoint is omitted"]).option("--app","App id to filter by (bundle or package id)").option("--endpoint","Appetize URL (e.g., https://appetize.io); overrides APPETIZE_ENDPOINT").option("--limit","Builds per page (default 10, max 200)").option("--page","Page of results to fetch (default 1)").example("build list").example("build list --app com.example.app").example("build list --app com.example.app --page 2"),St,{fields:vt}),x(t,"build upload <file>",n=>n.describe([`Upload a build (${R.join(", ")}) as a session start target`,"","Environment variables:","APPETIZE_API_TOKEN: Authorizes the upload","APPETIZE_ENDPOINT: Appetize URL used when --endpoint is omitted"]).option("--endpoint","Appetize URL (e.g., https://appetize.io); overrides APPETIZE_ENDPOINT").option("--note","Note to store with the build").option("--tags","Comma separated tags to store with the build").option("--timeout",`Milliseconds to wait with --wait (default ${String(pe)})`).option("--wait","Wait for the app id and version metadata to resolve").example("build upload ./app.apk").example("build upload ./app.zip").example("build upload ./app.apk --wait").example('build upload ./app.apk --tags beta,latest --note "PR 42"'),kt,{fields:Ot}),x(t,"device list",n=>n.describe(["List device models and their supported OS versions","","Environment variables:","APPETIZE_ENDPOINT: Appetize URL used when --endpoint is omitted"]).option("--endpoint","Appetize URL (e.g., https://appetize.io); overrides APPETIZE_ENDPOINT").option("--platform","Platform to filter by: ios or android").example("device list").example("device list --platform ios"),Dt,{fields:Lt}),y(t,"press <button>",n=>n.describe(`Press a device button: ${se.join(", ")}; Android only: ${re.join(", ")}`).example("press home").example("press volumeUp"),Ht),y(t,"rotate <orientation>",n=>n.describe("Rotate the device to an orientation: portrait, landscapeLeft, landscapeRight or upsideDown").example("rotate portrait").example("rotate landscapeLeft"),tn),y(t,"open <url>",n=>n.describe("Open a URL or deep link on the device").example("open myapp://orders/42").example("open https://example.com"),Wt),y(t,"keychain clear",n=>n.describe("Clear the entire device keychain (iOS only)").example("keychain clear"),Zt),y(t,"screenshot [output]",n=>n.describe("Take a screenshot of the current device screen").example("screenshot").example("screenshot home-screen").example("screenshot ./shots/checkout.png"),on),y(t,"tap",n=>C(n.describe(["Tap an element matched by a selector, or a screen position","",`Pick one of: ${O()}`])).option("--timeout","Milliseconds to wait for the element").example("tap --select-text 'Log in'").example("tap --select-test-id save").example("tap --select-text '/^Item \\d+/i' --select-index 2").example("tap --select-position 0.5,0.75").example("tap --select-test-id slider --select-x 0.9").example("tap --select-test-id dialog --select-x=-0.1").example("tap --select-test-id row --select-y=1.2"),Zn),y(t,"swipe",n=>C(C(n.describe(["Swipe in a direction, or along a path between two points","",`Pick a --direction with an optional --${w} starting point,`,`or both a --${w}-* and a --${g}-* point to form a path`,"",`Pick one per point: ${O({prefix:w})}`,` ${O({prefix:g})}`]).option("--direction",`Direction to travel: ${N.join(", ")}`).option("--distance","Travel as a fraction of the screen (0-1)"),{prefix:w}),{prefix:g}).option("--duration","Milliseconds the gesture travels for").option("--timeout",`Milliseconds to wait for any --${w}/--${g} elements`).example("swipe --direction up").example("swipe --direction up --distance 0.25").example("swipe --direction left --from-test-id card --from-index 1").example("swipe --from-position 0.5,0.75 --to-position 0.5,0.3").example("swipe --from-text 'Drag me' --from-y 0.9 --to-test-id drop-zone"),zn),y(t,"inspect [output]",n=>de(n.describe("Capture the view hierarchy of the screen, or of an element matched by a selector")).option("--timeout","Milliseconds to wait for the element").option("--pretty","Pretty-print the JSON",!1).example("inspect").example("inspect --select-text 'Log in'").example("inspect hierarchy.json --pretty"),qt),y(t,"type <text>",n=>n.describe(`Type text; {...} presses a named key: ${et.join(", ")}`).option("--delay","Milliseconds to wait between steps").example("type 'hello{Enter}'").example("type '{Backspace>16/}'").example("type 'user@example.com{Tab}hunter2{Enter}' --delay 50"),Wn),_e(t,"recording start <output>",n=>n.describe("Start recording the device video to an mp4 file").option("--force","Overwrite the file if it already exists",!1).example("recording start login-flow").example("recording start ./captures/checkout.mp4").example("recording start login-flow --force"),Yt),_e(t,"recording stop",n=>n.describe("Stop recording the device video and close the file").example("recording stop"),Qt),x(t,"skill install",n=>n.describe("Install the Appetize agent skill for coding agents").option("--agent","Agent to install for, repeatable; defaults to the agents detected").option("--scope","Install for the project (default) or the user").example("skill install").example("skill install --scope user").example("skill install --agent claude --agent cursor"),Nn),t}function x(e,t,n,o,{fields:i}={}){const r=t.split(" ").filter(s=>!/^[<[]/.test(s)).join(" ");return n(e.command(t)).action(go({action:o,fields:i,name:r}))}function W(e,t,n,o){return x(e,t,i=>n(i).option("--session-id","Target session id; defaults to the sole active session"),co(o))}function y(e,t,n,o){return W(e,t,n,po(o))}function _e(e,t,n,o){return W(e,t,n,lo(o))}function Re(e){return`${String(Date.now()-e)}ms`}function ho(e,t,n){if(e==="json")return JSON.stringify(t===void 0?{}:t,null,2);const o=t===void 0?"":no(t,n,process.stdout.columns);return o===""?void 0:o}async function wo({action:e,fields:t=[],name:n},o){const i=Date.now();G(`invoked: ${process.argv.slice(2).join(" ")}`);const r=Ye(o),{format:s,progress:a}=Ut(r.options,process.stdout,process.stderr),d=Hn(a,process.stderr,r.signal);try{const l=ho(s,await e({...r,progress:d}),t);d.succeed(),l!==void 0&&process.stdout.write(`${l}
|
|
10
|
+
`),G(`ok in ${Re(i)}`)}catch(l){d.fail(),process.stderr.write(`${Qe(s,l,{command:n})}
|
|
11
|
+
`),G(`failed after ${Re(i)}:`,l),process.exitCode=1}}function go(e){return(...t)=>{wo(e,t)}}mo("0.19.0").parse(process.argv,{boolean:fo,string:uo});
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{Transform as ar}from"stream";import{createRequire as lr}from"module";import{connect as cr}from"node:net";import Fe from"debug";import{JSONRPCServerAndClient as fr,JSONRPCServer as ur,JSONRPCClient as dr,JSONRPC as hr}from"json-rpc-2.0";import{homedir as bt}from"node:os";import{sep as pr,join as te}from"node:path";import{writeFileSync as yr,renameSync as wr,mkdirSync as gt,readFileSync as mr,readdirSync as br}from"node:fs";let ze;try{ze=new TextDecoder}catch{}let p,V,c=0;const je=[],gr=105,Er=57342,Sr=57343,Et=57337,St=6,fe={};let me=11281e4,Y=1681e4,re=je,be=0,k={},_,ge,Ee=0,se=0,N,q,D=[],Ve=[],K,j,Se,vt={useRecords:!1,mapsAsObjects:!0},ve=!1,At=2;try{new Function("")}catch{At=1/0}class pe{constructor(e){if(e&&((e.keyMap||e._keyMap)&&!e.useRecords&&(e.useRecords=!1,e.mapsAsObjects=!0),e.useRecords===!1&&e.mapsAsObjects===void 0&&(e.mapsAsObjects=!0),e.getStructures&&(e.getShared=e.getStructures),e.getShared&&!e.structures&&((e.structures=[]).uninitialized=!0),e.keyMap)){this.mapKey=new Map;for(let[r,s]of Object.entries(e.keyMap))this.mapKey.set(s,r)}Object.assign(this,e)}decodeKey(e){return this.keyMap&&this.mapKey.get(e)||e}encodeKey(e){return this.keyMap&&this.keyMap.hasOwnProperty(e)?this.keyMap[e]:e}encodeKeys(e){if(!this._keyMap)return e;let r=new Map;for(let[s,n]of Object.entries(e))r.set(this._keyMap.hasOwnProperty(s)?this._keyMap[s]:s,n);return r}decodeKeys(e){if(!this._keyMap||e.constructor.name!="Map")return e;if(!this._mapKey){this._mapKey=new Map;for(let[s,n]of Object.entries(this._keyMap))this._mapKey.set(n,s)}let r={};return e.forEach((s,n)=>r[J(this._mapKey.has(n)?this._mapKey.get(n):n)]=s),r}mapDecode(e,r){let s=this.decode(e);return this._keyMap&&s.constructor.name==="Array"?s.map(n=>this.decodeKeys(n)):s}decode(e,r){if(p)return Tt(()=>(Je(),this?this.decode(e,r):pe.prototype.decode.call(vt,e,r)));V=r>-1?r:e.length,c=0,be=0,se=0,ge=null,re=je,N=null,p=e;try{j=e.dataView||(e.dataView=new DataView(e.buffer,e.byteOffset,e.byteLength))}catch(s){throw p=null,e instanceof Uint8Array?s:new Error("Source must be a Uint8Array or Buffer but was a "+(e&&typeof e=="object"?e.constructor.name:typeof e))}if(this instanceof pe){if(k=this,K=this.sharedValues&&(this.pack?new Array(this.maxPrivatePackedValues||16).concat(this.sharedValues):this.sharedValues),this.structures)return _=this.structures,Ie();(!_||_.length>0)&&(_=[])}else k=vt,(!_||_.length>0)&&(_=[]),K=null;return Ie()}decodeMultiple(e,r){let s,n=0;try{let o=e.length;ve=!0;let f=this?this.decode(e,o):Ge.decode(e,o);if(r){if(r(f)===!1)return;for(;c<o;)if(n=c,r(Ie())===!1)return}else{for(s=[f];c<o;)n=c,s.push(Ie());return s}}catch(o){throw o.lastPosition=n,o.values=s,o}finally{ve=!1,Je()}}}function Ie(){try{let t=I();if(N){if(c>=N.postBundlePosition){let e=new Error("Unexpected bundle position");throw e.incomplete=!0,e}c=N.postBundlePosition,N=null}if(c==V)_=null,p=null,q&&(q=null);else if(c>V){let e=new Error("Unexpected end of CBOR data");throw e.incomplete=!0,e}else if(!ve)throw new Error("Data read, but end of buffer not reached");return t}catch(t){throw Je(),(t instanceof RangeError||t.message.startsWith("Unexpected end of buffer"))&&(t.incomplete=!0),t}}function ne(){let t=new Error("Unexpected end of CBOR data");return t.incomplete=!0,t}function I(){if(!(c<V))throw ne();let t=p[c++],e=t>>5;if(t=t&31,t>23)switch(t){case 24:if(c>=V)throw ne();t=p[c++];break;case 25:if(e==7)return kr();t=j.getUint16(c),c+=2;break;case 26:if(e==7){let r=j.getFloat32(c);if(k.useFloat32>2){let s=We[(p[c]&127)<<1|p[c+1]>>7];return c+=4,(s*r+(r>0?.5:-.5)>>0)/s}return c+=4,r}if(t=j.getUint32(c),c+=4,e===1)return-1-t;break;case 27:if(e==7){let r=j.getFloat64(c);return c+=8,r}if(e>1){if(j.getUint32(c)>0)throw new Error("JavaScript does not support arrays, maps, or strings with length over 4294967295");t=j.getUint32(c+4)}else k.int64AsNumber?(t=j.getUint32(c)*4294967296,t+=j.getUint32(c+4)):t=j.getBigUint64(c);c+=8;break;case 31:switch(e){case 2:case 3:throw new Error("Indefinite length not supported for byte or text strings");case 4:let r=[],s,n=0;for(;(s=I())!=fe;){if(n>=me)throw new Error(`Array length exceeds ${me}`);r[n++]=s}return e==4?r:e==3?r.join(""):Buffer.concat(r);case 5:let o;if(k.mapsAsObjects){let f={},m=0;if(k.keyMap)for(;(o=I())!=fe;){if(m++>=Y)throw new Error(`Property count exceeds ${Y}`);f[J(k.decodeKey(o))]=I()}else for(;(o=I())!=fe;){if(m++>=Y)throw new Error(`Property count exceeds ${Y}`);f[J(o)]=I()}return f}else{Se&&(k.mapsAsObjects=!0,Se=!1);let f=new Map;if(k.keyMap){let m=0;for(;(o=I())!=fe;){if(m++>=Y)throw new Error(`Map size exceeds ${Y}`);f.set(k.decodeKey(o),I())}}else{let m=0;for(;(o=I())!=fe;){if(m++>=Y)throw new Error(`Map size exceeds ${Y}`);f.set(o,I())}}return f}case 7:return fe;default:throw new Error("Invalid major type for indefinite length "+e)}default:throw new Error("Unknown token "+t)}switch(e){case 0:return t;case 1:return~t;case 2:return Or(t);case 3:if(se>=c)return ge.slice(c-Ee,(c+=t)-Ee);if(se==0&&V<140&&t<32){let n=t<16?It(t):Ar(t);if(n!=null)return n}return kt(t);case 4:if(t>=me)throw new Error(`Array length exceeds ${me}`);if(t>V-c)throw ne();let r=new Array(t);for(let n=0;n<t;n++)r[n]=I();return r;case 5:if(t>=Y)throw new Error(`Map size exceeds ${me}`);if(t>(V-c)/2)throw ne();if(k.mapsAsObjects){let n={};if(k.keyMap)for(let o=0;o<t;o++)n[J(k.decodeKey(I()))]=I();else for(let o=0;o<t;o++)n[J(I())]=I();return n}else{Se&&(k.mapsAsObjects=!0,Se=!1);let n=new Map;if(k.keyMap)for(let o=0;o<t;o++)n.set(k.decodeKey(I()),I());else for(let o=0;o<t;o++)n.set(I(),I());return n}case 6:if(t>=Et){let n=_[t&8191];if(n)return n.read||(n.read=Ke(n)),n.read();if(t<65536){if(t==Sr){let o=de(),f=I(),m=I();$e(f,m);let y={};if(k.keyMap)for(let v=2;v<o;v++){let g=k.decodeKey(m[v-2]);y[J(g)]=I()}else for(let v=2;v<o;v++){let g=m[v-2];y[J(g)]=I()}return y}else if(t==Er){let o=de(),f=I();for(let m=2;m<o;m++)$e(f++,I());return I()}else if(t==Et)return Cr();if(k.getShared&&(qe(),n=_[t&8191],n))return n.read||(n.read=Ke(n)),n.read()}}let s=D[t];if(s)return s.handlesRead?s(I):s(I());{let n=I();for(let o=0;o<Ve.length;o++){let f=Ve[o](t,n);if(f!==void 0)return f}return new ie(n,t)}case 7:switch(t){case 20:return!1;case 21:return!0;case 22:return null;case 23:return;default:let n=(K||oe())[t];if(n!==void 0)return n;throw new Error("Unknown token "+t)}default:throw isNaN(t)?ne():new Error("Unknown CBOR token "+t)}}const Ot=/^[a-zA-Z_$][a-zA-Z\d_$]*$/;function Ke(t){if(!t)throw new Error("Structure is required in record definition");function e(){let r=p[c++];if(r=r&31,r>23)switch(r){case 24:r=p[c++];break;case 25:r=j.getUint16(c),c+=2;break;case 26:r=j.getUint32(c),c+=4;break;default:throw new Error("Expected array header, but got "+p[c-1])}let s=this.compiledReader;for(;s;){if(s.propertyCount===r)return s(I);s=s.next}if(this.slowReads++>=At){let o=this.length==r?this:this.slice(0,r);return s=k.keyMap?new Function("r","return {"+o.map(f=>k.decodeKey(f)).map(f=>Ot.test(f)?J(f)+":r()":"["+JSON.stringify(f)+"]:r()").join(",")+"}"):new Function("r","return {"+o.map(f=>Ot.test(f)?J(f)+":r()":"["+JSON.stringify(f)+"]:r()").join(",")+"}"),this.compiledReader&&(s.next=this.compiledReader),s.propertyCount=r,this.compiledReader=s,s(I)}let n={};if(k.keyMap)for(let o=0;o<r;o++)n[J(k.decodeKey(this[o]))]=I();else for(let o=0;o<r;o++)n[J(this[o])]=I();return n}return t.slowReads=0,e}function J(t){if(typeof t=="string")return t==="__proto__"?"__proto_":t;if(typeof t=="number"||typeof t=="boolean"||typeof t=="bigint")return t.toString();if(t==null)return t+"";throw new Error("Invalid property name type "+typeof t)}let kt=xe;function vr(t){kt=e();function e(r){return function(n){let o=re[be++];if(o==null){if(N)return xe(n);let m=t(c,V,n,p);if(typeof m=="string")o=m,re=je;else if(re=m,be=1,se=1,o=re[0],o===void 0)throw new Error("Unexpected end of buffer")}let f=o.length;return f<=n?(c+=n,o):(ge=o,Ee=c,se=c+f,c+=n,o.slice(0,n))}}}function xe(t){let e;if(t<16&&(e=It(t)))return e;if(t>64&&ze)return ze.decode(p.subarray(c,c+=t));const r=c+t,s=[];for(e="";c<r;){const n=p[c++];if((n&128)===0)s.push(n);else if((n&224)===192)if(n<194||c>=r||(p[c]&192)!==128)s.push(65533);else{const o=p[c++]&63;s.push((n&31)<<6|o)}else if((n&240)===224){const o=c<r?p[c]:0;if(c>=r||(o&192)!==128||n===224&&o<160||n===237&&o>=160)s.push(65533);else if(c++,c>=r||(p[c]&192)!==128)s.push(65533);else{const f=p[c++]&63;s.push((n&31)<<12|(o&63)<<6|f)}}else if((n&248)===240){const o=c<r?p[c]:0;if(n>244||c>=r||(o&192)!==128||n===240&&o<144||n===244&&o>=144)s.push(65533);else if(c++,c>=r||(p[c]&192)!==128)s.push(65533);else{const f=p[c++]&63;if(c>=r||(p[c]&192)!==128)s.push(65533);else{const m=p[c++]&63;let y=(n&7)<<18|(o&63)<<12|f<<6|m;y-=65536,s.push(y>>>10&1023|55296),s.push(56320|y&1023)}}}else s.push(65533);s.length>=4096&&(e+=F.apply(String,s),s.length=0)}return s.length>0&&(e+=F.apply(String,s)),e}let F=String.fromCharCode;function Ar(t){let e=c,r=new Array(t);for(let s=0;s<t;s++){const n=p[c++];if((n&128)>0){c=e;return}r[s]=n}return F.apply(String,r)}function It(t){if(t<4)if(t<2){if(t===0)return"";{let e=p[c++];if((e&128)>1){c-=1;return}return F(e)}}else{let e=p[c++],r=p[c++];if((e&128)>0||(r&128)>0){c-=2;return}if(t<3)return F(e,r);let s=p[c++];if((s&128)>0){c-=3;return}return F(e,r,s)}else{let e=p[c++],r=p[c++],s=p[c++],n=p[c++];if((e&128)>0||(r&128)>0||(s&128)>0||(n&128)>0){c-=4;return}if(t<6){if(t===4)return F(e,r,s,n);{let o=p[c++];if((o&128)>0){c-=5;return}return F(e,r,s,n,o)}}else if(t<8){let o=p[c++],f=p[c++];if((o&128)>0||(f&128)>0){c-=6;return}if(t<7)return F(e,r,s,n,o,f);let m=p[c++];if((m&128)>0){c-=7;return}return F(e,r,s,n,o,f,m)}else{let o=p[c++],f=p[c++],m=p[c++],y=p[c++];if((o&128)>0||(f&128)>0||(m&128)>0||(y&128)>0){c-=8;return}if(t<10){if(t===8)return F(e,r,s,n,o,f,m,y);{let v=p[c++];if((v&128)>0){c-=9;return}return F(e,r,s,n,o,f,m,y,v)}}else if(t<12){let v=p[c++],g=p[c++];if((v&128)>0||(g&128)>0){c-=10;return}if(t<11)return F(e,r,s,n,o,f,m,y,v,g);let M=p[c++];if((M&128)>0){c-=11;return}return F(e,r,s,n,o,f,m,y,v,g,M)}else{let v=p[c++],g=p[c++],M=p[c++],R=p[c++];if((v&128)>0||(g&128)>0||(M&128)>0||(R&128)>0){c-=12;return}if(t<14){if(t===12)return F(e,r,s,n,o,f,m,y,v,g,M,R);{let L=p[c++];if((L&128)>0){c-=13;return}return F(e,r,s,n,o,f,m,y,v,g,M,R,L)}}else{let L=p[c++],U=p[c++];if((L&128)>0||(U&128)>0){c-=14;return}if(t<15)return F(e,r,s,n,o,f,m,y,v,g,M,R,L,U);let P=p[c++];if((P&128)>0){c-=15;return}return F(e,r,s,n,o,f,m,y,v,g,M,R,L,U,P)}}}}}function Or(t){return k.copyBuffers?Uint8Array.prototype.slice.call(p,c,c+=t):p.subarray(c,c+=t)}let xt=new Float32Array(1),Me=new Uint8Array(xt.buffer,0,4);function kr(){let t=p[c++],e=p[c++],r=(t&127)>>2;if(r===31)return e||t&3?NaN:t&128?-1/0:1/0;if(r===0){let s=((t&3)<<8|e)/16777216;return t&128?-s:s}return Me[3]=t&128|(r>>1)+56,Me[2]=(t&7)<<5|e>>3,Me[1]=e<<5,Me[0]=0,xt[0]}new Array(4096);class ie{constructor(e,r){this.value=e,this.tag=r}}D[0]=t=>new Date(t),D[1]=t=>new Date(Math.round(t*1e3)),D[2]=t=>{let e=BigInt(0);for(let r=0,s=t.byteLength;r<s;r++)e=BigInt(t[r])+(e<<BigInt(8));return e},D[3]=t=>BigInt(-1)-D[2](t),D[4]=t=>+(t[1]+"e"+t[0]),D[5]=t=>t[1]*Math.exp(t[0]*Math.log(2));const $e=(t,e)=>{t=t-57344;let r=_[t];r&&r.isShared&&((_.restoreStructures||(_.restoreStructures=[]))[t]=r),_[t]=e,e.read=Ke(e)};D[gr]=t=>{let e=t.length,r=t[1];$e(t[0],r);let s={};for(let n=2;n<e;n++){let o=r[n-2];s[J(o)]=t[n]}return s},D[14]=t=>N?N[0].slice(N.position0,N.position0+=t):new ie(t,14),D[15]=t=>N?N[1].slice(N.position1,N.position1+=t):new ie(t,15);let Ir={Error,RegExp};D[27]=t=>(Ir[t[0]]||Error)(t[1],t[2]);const Mt=t=>{if(p[c++]!=132){let r=new Error("Packed values structure must be followed by a 4 element array");throw p.length<c&&(r.incomplete=!0),r}let e=t();if(!e||!e.length){let r=new Error("Packed values structure must be followed by a 4 element array");throw r.incomplete=!0,r}return K=K?e.concat(K.slice(e.length)):e,K.prefixes=t(),K.suffixes=t(),t()};Mt.handlesRead=!0,D[51]=Mt,D[St]=t=>{if(!K)if(k.getShared)qe();else return new ie(t,St);if(typeof t=="number")return K[16+(t>=0?2*t:-2*t-1)];let e=new Error("No support for non-integer packed references yet");throw t===void 0&&(e.incomplete=!0),e},D[28]=t=>{q||(q=new Map,q.id=0);let e=q.id++,r=c,s=p[c],n;s>>5==4?n=[]:n={};let o={target:n};q.set(e,o);let f=t();return o.used?(Object.getPrototypeOf(n)!==Object.getPrototypeOf(f)&&(c=r,n=f,q.set(e,{target:n}),f=t()),Object.assign(n,f)):(o.target=f,f)},D[28].handlesRead=!0,D[29]=t=>{let e=q.get(t);return e.used=!0,e.target},D[258]=t=>new Set(t),(D[259]=t=>(k.mapsAsObjects&&(k.mapsAsObjects=!1,Se=!0),t())).handlesRead=!0;function ue(t,e){return typeof t=="string"?t+e:t instanceof Array?t.concat(e):Object.assign({},t,e)}function oe(){if(!K)if(k.getShared)qe();else throw new Error("No packed values available");return K}const xr=1399353956;Ve.push((t,e)=>{if(t>=225&&t<=255)return ue(oe().prefixes[t-224],e);if(t>=28704&&t<=32767)return ue(oe().prefixes[t-28672],e);if(t>=1879052288&&t<=2147483647)return ue(oe().prefixes[t-1879048192],e);if(t>=216&&t<=223)return ue(e,oe().suffixes[t-216]);if(t>=27647&&t<=28671)return ue(e,oe().suffixes[t-27639]);if(t>=1811940352&&t<=1879048191)return ue(e,oe().suffixes[t-1811939328]);if(t==xr)return{packedValues:K,structures:_.slice(0),version:e};if(t==55799)return e});const Mr=new Uint8Array(new Uint16Array([1]).buffer)[0]==1,Rt=[Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array,typeof BigUint64Array>"u"?{name:"BigUint64Array"}:BigUint64Array,Int8Array,Int16Array,Int32Array,typeof BigInt64Array>"u"?{name:"BigInt64Array"}:BigInt64Array,Float32Array,Float64Array],Rr=[64,68,69,70,71,72,77,78,79,85,86];for(let t=0;t<Rt.length;t++)Tr(Rt[t],Rr[t]);function Tr(t,e){let r="get"+t.name.slice(0,-5),s;typeof t=="function"?s=t.BYTES_PER_ELEMENT:t=null;for(let n=0;n<2;n++){if(!n&&s==1)continue;let o=s==2?1:s==4?2:s==8?3:0;D[n?e:e-4]=s==1||n==Mr?f=>{if(!t)throw new Error("Could not find typed array for code "+e);return!k.copyBuffers&&(s===1||s===2&&!(f.byteOffset&1)||s===4&&!(f.byteOffset&3)||s===8&&!(f.byteOffset&7))?new t(f.buffer,f.byteOffset,f.byteLength>>o):new t(Uint8Array.prototype.slice.call(f,0).buffer)}:f=>{if(!t)throw new Error("Could not find typed array for code "+e);let m=new DataView(f.buffer,f.byteOffset,f.byteLength),y=f.length>>o,v=new t(y),g=m[r];for(let M=0;M<y;M++)v[M]=g.call(m,M<<o,n);return v}}}function Cr(){let t=de(),e=c+I();for(let s=2;s<t;s++){let n=de();c+=n}let r=c;return c=e,N=[xe(de()),xe(de())],N.position0=0,N.position1=0,N.postBundlePosition=c,c=r,I()}function de(){if(!(c<V))throw ne();let t=p[c++]&31;if(t>23)switch(t){case 24:if(c>=V)throw ne();t=p[c++];break;case 25:t=j.getUint16(c),c+=2;break;case 26:t=j.getUint32(c),c+=4;break}return t}function qe(){if(k.getShared){let t=Tt(()=>(p=null,k.getShared()))||{},e=t.structures||[];k.sharedVersion=t.version,K=k.sharedValues=t.packedValues,_===!0?k.structures=_=e:_.splice.apply(_,[0,e.length].concat(e))}}function Tt(t){let e=V,r=c,s=be,n=Ee,o=se,f=ge,m=re,y=q,v=N,g=new Uint8Array(p.slice(0,V)),M=_,R=k,L=ve,U=t();return V=e,c=r,be=s,Ee=n,se=o,ge=f,re=m,q=y,N=v,p=g,ve=L,_=M,k=R,j=new DataView(p.buffer,p.byteOffset,p.byteLength),U}function Je(){p=null,q=null,_=null}const We=new Array(147);for(let t=0;t<256;t++)We[t]=+("1e"+Math.floor(45.15-t*.30103));let Ge=new pe({useRecords:!1});const Pr=Ge.decode;Ge.decodeMultiple;let Re;try{Re=new TextEncoder}catch{}let He,Ct;const Te=typeof globalThis=="object"&&globalThis.Buffer,Ae=typeof Te<"u",Ze=Ae?Te.allocUnsafeSlow:Uint8Array,Pt=Ae?Te:Uint8Array,Ut=256,Lt=Ae?4294967296:2144337920;let Ye,l,C,i=0,Q,B=null;const Ur=61440,Lr=/[\u0080-\uFFFF]/,$=Symbol("record-id");class _t extends pe{constructor(e){super(e),this.offset=0;let r,s,n,o,f;e=e||{};let m=Pt.prototype.utf8Write?function(a,w){return l.utf8Write(a,w,l.byteLength-w)}:Re&&Re.encodeInto?function(a,w){return Re.encodeInto(a,l.subarray(w)).written}:!1,y=this,v=e.structures||e.saveStructures,g=e.maxSharedStructures;if(g==null&&(g=v?128:0),g>8190)throw new Error("Maximum maxSharedStructure is 8190");let M=e.sequential;M&&(g=0),this.structures||(this.structures=[]),this.saveStructures&&(this.saveShared=this.saveStructures);let R,L,U=e.sharedValues,P;if(U){P=Object.create(null);for(let a=0,w=U.length;a<w;a++)P[U[a]]=a}let W=[],ye=0,G=0;this.mapEncode=function(a,w){return this._keyMap&&!this._mapped&&a.constructor.name==="Array"&&(a=a.map(d=>this.encodeKeys(d))),this.encode(a,w)},this.encode=function(a,w){if(l||(l=new Ze(8192),C=new DataView(l.buffer,0,8192),i=0),Q=l.length-10,Q-i<2048?(l=new Ze(l.length),C=new DataView(l.buffer,0,l.length),Q=l.length-10,i=0):w===Ft&&(i=i+7&2147483640),r=i,y.useSelfDescribedHeader&&(C.setUint32(i,3654940416),i+=3),f=y.structuredClone?new Map:null,y.bundleStrings&&typeof a!="string"?(B=[],B.size=1/0):B=null,s=y.structures,s){if(s.uninitialized){let h=y.getShared()||{};y.structures=s=h.structures||[],y.sharedVersion=h.version;let u=y.sharedValues=h.packedValues;if(u){P={};for(let b=0,E=u.length;b<E;b++)P[u[b]]=b}}let d=s.length;if(d>g&&!M&&(d=g),!s.transitions){s.transitions=Object.create(null);for(let h=0;h<d;h++){let u=s[h];if(!u)continue;let b,E=s.transitions;for(let S=0,A=u.length;S<A;S++){E[$]===void 0&&(E[$]=h);let x=u[S];b=E[x],b||(b=E[x]=Object.create(null)),E=b}E[$]=h|1048576}}M||(s.nextId=d)}if(n&&(n=!1),o=s||[],L=P,e.pack){let d=new Map;if(d.values=[],d.encoder=y,d.maxValues=e.maxPrivatePackedValues||(P?16:1/0),d.objectMap=P||!1,d.samplingPackedValues=R,Ce(a,d),d.values.length>0){l[i++]=216,l[i++]=51,H(4);let h=d.values;O(h),H(0),H(0),L=Object.create(P||null);for(let u=0,b=h.length;u<b;u++)L[h[u]]=u}}Ye=w&tt;try{if(Ye)return;if(O(a),B&&Bt(r,O),y.offset=i,f&&f.idsToInsert){i+=f.idsToInsert.length*2,i>Q&&le(i),y.offset=i;let d=Dr(l.subarray(r,i),f.idsToInsert);return f=null,d}return w&Ft?(l.start=r,l.end=i,l):l.subarray(r,i)}finally{if(s){if(G<10&&G++,s.length>g&&(s.length=g),ye>1e4)s.transitions=null,G=0,ye=0,W.length>0&&(W=[]);else if(W.length>0&&!M){for(let d=0,h=W.length;d<h;d++)W[d][$]=void 0;W=[]}}if(n&&y.saveShared){y.structures.length>g&&(y.structures=y.structures.slice(0,g));let d=l.subarray(r,i);return y.updateSharedData()===!1?y.encode(a):d}w&Fr&&(i=r)}},this.findCommonStringsToPack=()=>(R=new Map,P||(P=Object.create(null)),a=>{let w=a&&a.threshold||4,d=this.pack?a.maxPrivatePackedValues||16:0;U||(U=this.sharedValues=[]);for(let[h,u]of R)u.count>w&&(P[h]=d++,U.push(h),n=!0);for(;this.saveShared&&this.updateSharedData()===!1;);R=null});const O=a=>{i>Q&&(l=le(i));var w=typeof a,d;if(w==="string"){if(L){let E=L[a];if(E>=0){E<16?l[i++]=E+224:(l[i++]=198,E&1?O(15-E>>1):O(E-16>>1));return}else if(R&&!e.pack){let S=R.get(a);S?S.count++:R.set(a,{count:1})}}let h=a.length;if(B&&h>=4&&h<1024){if((B.size+=h)>Ur){let S,A=(B[0]?B[0].length*3+B[1].length:0)+10;i+A>Q&&(l=le(i+A)),l[i++]=217,l[i++]=223,l[i++]=249,l[i++]=B.position?132:130,l[i++]=26,S=i-r,i+=4,B.position&&Bt(r,O),B=["",""],B.size=0,B.position=S}let E=Lr.test(a);B[E?0:1]+=a,l[i++]=E?206:207,O(h);return}let u;h<32?u=1:h<256?u=2:h<65536?u=3:u=5;let b=h*3;if(i+b>Q&&(l=le(i+b)),h<64||!m){let E,S,A,x=i+u;for(E=0;E<h;E++)S=a.charCodeAt(E),S<128?l[x++]=S:S<2048?(l[x++]=S>>6|192,l[x++]=S&63|128):(S&64512)===55296&&((A=a.charCodeAt(E+1))&64512)===56320?(S=65536+((S&1023)<<10)+(A&1023),E++,l[x++]=S>>18|240,l[x++]=S>>12&63|128,l[x++]=S>>6&63|128,l[x++]=S&63|128):(l[x++]=S>>12|224,l[x++]=S>>6&63|128,l[x++]=S&63|128);d=x-i-u}else d=m(a,i+u,b);d<24?l[i++]=96|d:d<256?(u<2&&l.copyWithin(i+2,i+1,i+1+d),l[i++]=120,l[i++]=d):d<65536?(u<3&&l.copyWithin(i+3,i+2,i+2+d),l[i++]=121,l[i++]=d>>8,l[i++]=d&255):(u<5&&l.copyWithin(i+5,i+3,i+3+d),l[i++]=122,C.setUint32(i,d),i+=4),i+=d}else if(w==="number")if(!this.alwaysUseFloat&&a>>>0===a)a<24?l[i++]=a:a<256?(l[i++]=24,l[i++]=a):a<65536?(l[i++]=25,l[i++]=a>>8,l[i++]=a&255):(l[i++]=26,C.setUint32(i,a),i+=4);else if(!this.alwaysUseFloat&&a>>0===a)a>=-24?l[i++]=31-a:a>=-256?(l[i++]=56,l[i++]=~a):a>=-65536?(l[i++]=57,C.setUint16(i,~a),i+=2):(l[i++]=58,C.setUint32(i,~a),i+=4);else if(!this.alwaysUseFloat&&a<0&&a>=-4294967296&&Math.floor(a)===a)l[i++]=58,C.setUint32(i,-1-a),i+=4;else{let h;if((h=this.useFloat32)>0&&a<4294967296&&a>=-2147483648){l[i++]=250,C.setFloat32(i,a);let u;if(h<4||(u=a*We[(l[i]&127)<<1|l[i+1]>>7])>>0===u){i+=4;return}else i--}l[i++]=251,C.setFloat64(i,a),i+=8}else if(w==="object")if(!a)l[i++]=246;else{if(f){let u=f.get(a);if(u){if(l[i++]=216,l[i++]=29,l[i++]=25,!u.references){let b=f.idsToInsert||(f.idsToInsert=[]);u.references=[],b.push(u)}u.references.push(i-r),i+=2;return}else f.set(a,{offset:i-r})}let h=a.constructor;if(h===Object)this.skipFunction===!0&&(a=Object.fromEntries([...Object.keys(a).filter(u=>typeof a[u]!="function").map(u=>[u,a[u]])])),z(a);else if(h===Array){d=a.length,d<24?l[i++]=128|d:H(d);for(let u=0;u<d;u++)O(a[u])}else if(h===Map)if((this.mapsAsObjects?this.useTag259ForMaps!==!1:this.useTag259ForMaps)&&(l[i++]=217,l[i++]=1,l[i++]=3),d=a.size,d<24?l[i++]=160|d:d<256?(l[i++]=184,l[i++]=d):d<65536?(l[i++]=185,l[i++]=d>>8,l[i++]=d&255):(l[i++]=186,C.setUint32(i,d),i+=4),y.keyMap)for(let[u,b]of a)O(y.encodeKey(u)),O(b);else for(let[u,b]of a)O(u),O(b);else{for(let u=0,b=He.length;u<b;u++){let E=Ct[u];if(a instanceof E){let S=He[u],A=S.tag;A==null&&(A=S.getTag&&S.getTag.call(this,a)),A<24?l[i++]=192|A:A<256?(l[i++]=216,l[i++]=A):A<65536?(l[i++]=217,l[i++]=A>>8,l[i++]=A&255):A>-1&&(l[i++]=218,C.setUint32(i,A),i+=4),S.encode.call(this,a,O,le);return}}if(a[Symbol.iterator]){if(Ye){let u=new Error("Iterable should be serialized as iterator");throw u.iteratorNotHandled=!0,u}l[i++]=159;for(let u of a)O(u);l[i++]=255;return}if(a[Symbol.asyncIterator]||Xe(a)){let u=new Error("Iterable/blob should be serialized as iterator");throw u.iteratorNotHandled=!0,u}if(this.useToJSON&&a.toJSON){const u=a.toJSON();if(u!==a)return O(u)}z(a)}}else if(w==="boolean")l[i++]=a?245:244;else if(w==="bigint"){if(a<BigInt(1)<<BigInt(64)&&a>=0)l[i++]=27,C.setBigUint64(i,a);else if(a>-(BigInt(1)<<BigInt(64))&&a<0)l[i++]=59,C.setBigUint64(i,-a-BigInt(1));else if(this.largeBigIntToFloat)l[i++]=251,C.setFloat64(i,Number(a));else{a>=BigInt(0)?l[i++]=194:(l[i++]=195,a=BigInt(-1)-a);let h=[];for(;a;)h.push(Number(a&BigInt(255))),a>>=BigInt(8);Qe(new Uint8Array(h.reverse()),le);return}i+=8}else if(w==="undefined")l[i++]=247;else throw new Error("Unknown type: "+w)},z=this.useRecords===!1?this.variableMapSize?a=>{let w=Object.keys(a),d=Object.values(a),h=w.length;if(h<24?l[i++]=160|h:h<256?(l[i++]=184,l[i++]=h):h<65536?(l[i++]=185,l[i++]=h>>8,l[i++]=h&255):(l[i++]=186,C.setUint32(i,h),i+=4),y.keyMap)for(let u=0;u<h;u++)O(y.encodeKey(w[u])),O(d[u]);else for(let u=0;u<h;u++)O(w[u]),O(d[u])}:a=>{l[i++]=185;let w=i-r;i+=2;let d=0;if(y.keyMap)for(let h in a)(typeof a.hasOwnProperty!="function"||a.hasOwnProperty(h))&&(O(y.encodeKey(h)),O(a[h]),d++);else for(let h in a)(typeof a.hasOwnProperty!="function"||a.hasOwnProperty(h))&&(O(h),O(a[h]),d++);l[w+++r]=d>>8,l[w+r]=d&255}:(a,w)=>{let d,h=o.transitions||(o.transitions=Object.create(null)),u=0,b=0,E,S;if(this.keyMap){S=Object.keys(a).map(x=>this.encodeKey(x)),b=S.length;for(let x=0;x<b;x++){let mt=S[x];d=h[mt],d||(d=h[mt]=Object.create(null),u++),h=d}}else for(let x in a)(typeof a.hasOwnProperty!="function"||a.hasOwnProperty(x))&&(d=h[x],d||(h[$]&1048576&&(E=h[$]&65535),d=h[x]=Object.create(null),u++),h=d,b++);let A=h[$];if(A!==void 0)A&=65535,l[i++]=217,l[i++]=A>>8|224,l[i++]=A&255;else if(S||(S=h.__keys__||(h.__keys__=Object.keys(a))),E===void 0?(A=o.nextId++,A||(A=0,o.nextId=1),A>=Ut&&(o.nextId=(A=g)+1)):A=E,o[A]=S,A<g){l[i++]=217,l[i++]=A>>8|224,l[i++]=A&255,h=o.transitions;for(let x=0;x<b;x++)(h[$]===void 0||h[$]&1048576)&&(h[$]=A),h=h[S[x]];h[$]=A|1048576,n=!0}else{if(h[$]=A,C.setUint32(i,3655335680),i+=3,u&&(ye+=G*u),W.length>=Ut-g&&(W.shift()[$]=void 0),W.push(h),H(b+2),O(57344+A),O(S),w)return;for(let x in a)(typeof a.hasOwnProperty!="function"||a.hasOwnProperty(x))&&O(a[x]);return}if(b<24?l[i++]=128|b:H(b),!w)for(let x in a)(typeof a.hasOwnProperty!="function"||a.hasOwnProperty(x))&&O(a[x])},le=a=>{let w;if(a>16777216){if(a-r>Lt)throw new Error("Encoded buffer would be larger than maximum buffer size");w=Math.min(Lt,Math.round(Math.max((a-r)*(a>67108864?1.25:2),4194304)/4096)*4096)}else w=(Math.max(a-r<<2,l.length-1)>>12)+1<<12;let d=new Ze(w);return C=new DataView(d.buffer,0,w),l.copy?l.copy(d,0,r,a):d.set(l.slice(r,a)),i-=r,r=0,Q=d.length-10,l=d};let ee=100,pt=1e3;this.encodeAsIterable=function(a,w){return yt(a,w,ce)},this.encodeAsAsyncIterable=function(a,w){return yt(a,w,wt)};function*ce(a,w,d){let h=a.constructor;if(h===Object){let u=y.useRecords!==!1;u?z(a,!0):Nt(Object.keys(a).length,160);for(let b in a){let E=a[b];u||O(b),E&&typeof E=="object"?w[b]?yield*ce(E,w[b]):yield*Be(E,w,b):O(E)}}else if(h===Array){let u=a.length;H(u);for(let b=0;b<u;b++){let E=a[b];E&&(typeof E=="object"||i-r>ee)?w.element?yield*ce(E,w.element):yield*Be(E,w,"element"):O(E)}}else if(a[Symbol.iterator]&&!a.buffer){l[i++]=159;for(let u of a)u&&(typeof u=="object"||i-r>ee)?w.element?yield*ce(u,w.element):yield*Be(u,w,"element"):O(u);l[i++]=255}else Xe(a)?(Nt(a.size,64),yield l.subarray(r,i),yield a,we()):a[Symbol.asyncIterator]?(l[i++]=159,yield l.subarray(r,i),yield a,we(),l[i++]=255):O(a);d&&i>r?yield l.subarray(r,i):i-r>ee&&(yield l.subarray(r,i),we())}function*Be(a,w,d){let h=i-r;try{O(a),i-r>ee&&(yield l.subarray(r,i),we())}catch(u){if(u.iteratorNotHandled)w[d]={},i=r+h,yield*ce.call(this,a,w[d]);else throw u}}function we(){ee=pt,y.encode(null,tt)}function yt(a,w,d){return w&&w.chunkThreshold?ee=pt=w.chunkThreshold:ee=100,a&&typeof a=="object"?(y.encode(null,tt),d(a,y.iterateProperties||(y.iterateProperties={}),!0)):[y.encode(a)]}async function*wt(a,w){for(let d of ce(a,w,!0)){let h=d.constructor;if(h===Pt||h===Uint8Array)yield d;else if(Xe(d)){let u=d.stream().getReader(),b;for(;!(b=await u.read()).done;)yield b.value}else if(d[Symbol.asyncIterator])for await(let u of d)we(),u?yield*wt(u,w.async||(w.async={})):yield y.encode(u);else yield d}}}useBuffer(e){l=e,C=new DataView(l.buffer,l.byteOffset,l.byteLength),i=0}clearSharedData(){this.structures&&(this.structures=[]),this.sharedValues&&(this.sharedValues=void 0)}updateSharedData(){let e=this.sharedVersion||0;this.sharedVersion=e+1;let r=this.structures.slice(0),s=new Dt(r,this.sharedValues,this.sharedVersion),n=this.saveShared(s,o=>(o&&o.version||0)==e);return n===!1?(s=this.getShared()||{},this.structures=s.structures||[],this.sharedValues=s.packedValues,this.sharedVersion=s.version,this.structures.nextId=this.structures.length):r.forEach((o,f)=>this.structures[f]=o),n}}function Nt(t,e){t<24?l[i++]=e|t:t<256?(l[i++]=e|24,l[i++]=t):t<65536?(l[i++]=e|25,l[i++]=t>>8,l[i++]=t&255):(l[i++]=e|26,C.setUint32(i,t),i+=4)}class Dt{constructor(e,r,s){this.structures=e,this.packedValues=r,this.version=s}}function H(t){t<24?l[i++]=128|t:t<256?(l[i++]=152,l[i++]=t):t<65536?(l[i++]=153,l[i++]=t>>8,l[i++]=t&255):(l[i++]=154,C.setUint32(i,t),i+=4)}const _r=typeof Blob>"u"?function(){}:Blob;function Xe(t){if(t instanceof _r)return!0;let e=t[Symbol.toStringTag];return e==="Blob"||e==="File"}function Ce(t,e){switch(typeof t){case"string":if(t.length>3){if(e.objectMap[t]>-1||e.values.length>=e.maxValues)return;let s=e.get(t);if(s)++s.count==2&&e.values.push(t);else if(e.set(t,{count:1}),e.samplingPackedValues){let n=e.samplingPackedValues.get(t);n?n.count++:e.samplingPackedValues.set(t,{count:1})}}break;case"object":if(t)if(t instanceof Array)for(let s=0,n=t.length;s<n;s++)Ce(t[s],e);else{let s=!e.encoder.useRecords;for(var r in t)t.hasOwnProperty(r)&&(s&&Ce(r,e),Ce(t[r],e))}break;case"function":console.log(t)}}const Nr=new Uint8Array(new Uint16Array([1]).buffer)[0]==1;Ct=[Date,Set,Error,RegExp,ie,ArrayBuffer,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array,typeof BigUint64Array>"u"?function(){}:BigUint64Array,Int8Array,Int16Array,Int32Array,typeof BigInt64Array>"u"?function(){}:BigInt64Array,Float32Array,Float64Array,Dt],He=[{tag:1,encode(t,e){let r=t.getTime()/1e3;(this.useTimestamp32||t.getMilliseconds()===0)&&r>=0&&r<4294967296?(l[i++]=26,C.setUint32(i,r),i+=4):(l[i++]=251,C.setFloat64(i,r),i+=8)}},{tag:258,encode(t,e){let r=Array.from(t);e(r)}},{tag:27,encode(t,e){e([t.name,t.message])}},{tag:27,encode(t,e){e(["RegExp",t.source,t.flags])}},{getTag(t){return t.tag},encode(t,e){e(t.value)}},{encode(t,e,r){Qe(t,r)}},{getTag(t){if(t.constructor===Uint8Array&&(this.tagUint8Array||Ae&&this.tagUint8Array!==!1))return 64},encode(t,e,r){Qe(t,r)}},Z(68,1),Z(69,2),Z(70,4),Z(71,8),Z(72,1),Z(77,2),Z(78,4),Z(79,8),Z(85,4),Z(86,8),{encode(t,e){let r=t.packedValues||[],s=t.structures||[];if(r.values.length>0){l[i++]=216,l[i++]=51,H(4);let n=r.values;e(n),H(0),H(0),packedObjectMap=Object.create(sharedPackedObjectMap||null);for(let o=0,f=n.length;o<f;o++)packedObjectMap[n[o]]=o}if(s){C.setUint32(i,3655335424),i+=3;let n=s.slice(0);n.unshift(57344),n.push(new ie(t.version,1399353956)),e(n)}else e(new ie(t.version,1399353956))}}];function Z(t,e){return!Nr&&e>1&&(t-=4),{tag:t,encode:function(s,n){let o=s.byteLength,f=s.byteOffset||0,m=s.buffer||s;n(Ae?Te.from(m,f,o):new Uint8Array(m,f,o))}}}function Qe(t,e){let r=t.byteLength;r<24?l[i++]=64+r:r<256?(l[i++]=88,l[i++]=r):r<65536?(l[i++]=89,l[i++]=r>>8,l[i++]=r&255):(l[i++]=90,C.setUint32(i,r),i+=4),i+r>=l.length&&e(i+r),l.set(t.buffer?t:new Uint8Array(t),i),i+=r}function Dr(t,e){let r,s=e.length*2,n=t.length-s;e.sort((o,f)=>o.offset>f.offset?1:-1);for(let o=0;o<e.length;o++){let f=e[o];f.id=o;for(let m of f.references)t[m++]=o>>8,t[m]=o&255}for(;r=e.pop();){let o=r.offset;t.copyWithin(o+s,o,n),s-=2;let f=o+s;t[f++]=216,t[f++]=28,n=o}return t}function Bt(t,e){C.setUint32(B.position+t,i-B.position-t+1);let r=B;B=null,e(r[0]),e(r[1])}let et=new _t({useRecords:!1});const Br=et.encode;et.encodeAsIterable,et.encodeAsAsyncIterable;const Ft=512,Fr=1024,tt=2048;class zr extends ar{constructor(e){e||(e={}),e.objectMode=!0,super(e),e.structures=[],this.decoder=e.decoder||new pe(e)}_transform(e,r,s){this.incompleteBuffer&&(e=Buffer.concat([this.incompleteBuffer,e]),this.incompleteBuffer=null);let n;try{n=this.decoder.decodeMultiple(e)}catch(o){if(o.incomplete)this.incompleteBuffer=e.slice(o.lastPosition),n=o.values;else return s(o)}finally{for(let o of n||[])o===null&&(o=this.getNullValue()),this.push(o)}s()}getNullValue(){return Symbol.for(null)}}const jr=process.env.CBOR_NATIVE_ACCELERATION_DISABLED!==void 0&&process.env.CBOR_NATIVE_ACCELERATION_DISABLED.toLowerCase()==="true";if(!jr){let t;try{typeof require=="function"?t=require("cbor-extract"):t=lr(import.meta.url)("cbor-extract"),t&&vr(t.extractStrings)}catch{}}class Vr extends Event{code;reason;wasClean;constructor(e,r={}){super(e,r),this.code=r.code??0,this.reason=r.reason??"",this.wasClean=r.wasClean??!1}}function Kr(t,e){const r="CloseEvent"in globalThis?globalThis.CloseEvent:Vr;return new r(t,e)}class $r{#e=new EventTarget;addEventListener(e,r,s){return this.#e.addEventListener(e,r,s),()=>{this.#e.removeEventListener(e,r,s)}}removeEventListener(e,r,s){this.#e.removeEventListener(e,r,s)}dispatchEvent(e){return this.#e.dispatchEvent(e)}}const T=Symbol.for("@appetizeio/rpc:rpcMethods");class qr extends $r{send;constructor(e){super(),this.send=e}dispatchClose(e){return this.dispatchEvent(Kr("close",e))}dispatchMessage(e){return this.dispatchEvent(new CustomEvent("message",{detail:e}))}}function rt(t){return!!t&&typeof t=="object"&&"jsonrpc"in t}function Jr(){let t,e;return{promise:new Promise((s,n)=>{e=s,t=n}),reject:t,resolve:e}}class Oe{closed=!1;[T];#e;constructor(e,{signal:r}={}){this[T]=new qr(e),this.#e=r,this.#e?.addEventListener("abort",this.#r)}close(e={}){this.closed||(this.closed=!0,this.handleClose(e))}handleClose(e){this.#e?.removeEventListener("abort",this.#r),this[T].dispatchClose(e)}#r=()=>{this.close({code:1e3,reason:String(this.#e?.reason)})}}const zt={useRecords:!1},Wr=new _t(zt);class jt extends Oe{#e=[];#r;constructor(e,{signal:r}={}){super(async f=>{this.#r.write(Wr.encode(f))},{signal:r}),this.#r=e;const s=new zr(zt);s.on("data",f=>{rt(f)&&this[T].dispatchMessage(f)}),s.on("error",()=>{this.close()});const n=f=>{s.write(f)},o=()=>{this.close()};e.on("data",n),e.once("close",o),e.once("error",o),this.#e.push(()=>{e.off("data",n),e.off("close",o),e.off("error",o),s.destroy()})}handleClose(e){for(const r of this.#e.splice(0))r();super.handleClose(e)}}function Gr(t,e){const{promise:r,reject:s,resolve:n}=Jr(),o=cr(t),f=e?.signal,m=()=>{o.off("connect",g),o.off("error",M),f?.removeEventListener("abort",v)},y=R=>{m(),o.destroy(),s(R)},v=()=>{y(new Error("The connection was aborted"))},g=()=>{m();const R=new jt(o,e);R[T].addEventListener("close",()=>{o.destroy()},{once:!0}),n(R)},M=R=>{y(R)};return f?.aborted?(y(new Error("The connection was aborted")),r):(o.once("connect",g),o.once("error",M),f?.addEventListener("abort",v,{once:!0}),r)}const Vt=Fe("appetize.io:error:rpc");function st(t,e){const r=new fr(new ur({errorListener:Vt}),Hr(t),{errorListener:Vt}),s=t[T].addEventListener("message",({detail:o})=>{r.receiveAndSend(o)}),n=t[T].addEventListener("close",()=>{s(),r.rejectAllPendingRequests("Transport closed")},{once:!0});for(const o in e){const f=e[o];f&&r.addMethod(o,f.bind(e))}return{rpc:r,unsub:()=>{s(),n()}}}function Kt(t,e){const{rpc:r,unsub:s}=st(t,e);return{client:r.client,unsub:s}}function Pe(t,e){const r=t[T].addEventListener("message",({detail:n})=>{if("method"in n)try{e({method:n.method,param:n.params})}catch{}}),s=t[T].addEventListener("close",r,{once:!0});return()=>{r(),s()}}function Hr(t){return new dr(t[T].send.bind(t[T]),()=>Math.floor(Math.random()*Number.MAX_SAFE_INTEGER)+1)}function nt(t,e,{leftEffects:r=()=>({}),notifiesLeft:s,notifiesRight:n,rightEffects:o=()=>({})}={}){const f=st(t,{}),m=st(e,{}),y=[()=>{f.unsub(),m.unsub()}],v=()=>{for(const U of y)try{U()}catch{}},g=m.rpc.client,M=f.rpc.client;y.push(t[T].addEventListener("close",()=>{v()},{once:!0}),e[T].addEventListener("close",()=>{v()},{once:!0}));const R=r(g,M);for(const U in R){const P=R[U];P&&f.rpc.addMethod(U,P)}const L=o(M,g);for(const U in L){const P=L[U];P&&m.rpc.addMethod(U,P)}return $t(f.rpc,m.rpc,{notifies:s}),$t(m.rpc,f.rpc,{notifies:n}),v}function $t(t,e,{notifies:r}={}){t.applyServerMiddleware(async(s,n)=>{const o=r?.();if(o){const{id:m,...y}=n;o[T].send(y)}if(t.hasMethod(n.method))return await s(n);if(!n.id)return e.notify(n.method,n.params),null;const f=await e.request(n.method,n.params);return{id:n.id,jsonrpc:hr,result:f}})}function X(t,...e){t.notify(e[0],e[1],e[2])}const Zr=(...t)=>Kt(...t),it=["ArrowDown","ArrowLeft","ArrowRight","ArrowUp","Backspace","Enter","Tab"];function ot(){const t=new Oe(async r=>{e[T].dispatchMessage(r)}),e=new Oe(async r=>{t[T].dispatchMessage(r)});return t[T].addEventListener("close",()=>{e.close()},{once:!0}),e[T].addEventListener("close",()=>{t.close()},{once:!0}),[t,e]}function qt(t,e){const r=[],s=()=>{for(const n of r)n()};r.push(t[T].addEventListener("message",n=>e[T].send(n.detail))),r.push(t[T].addEventListener("close",s,{once:!0})),r.push(e[T].addEventListener("message",n=>t[T].send(n.detail))),r.push(e[T].addEventListener("close",s,{once:!0}))}const ae=Fe("appetize.io:trace:transport:iframe");class Jt extends Oe{onmessage;#e;#r;constructor(e,{origin:r="*",signal:s}={}){super(async n=>{e.postMessage(n,this.#e)},{signal:s}),this.#r=e,this.#e=r,window.addEventListener("message",this.#t)}postMessage(e,r,s){ae("postMessage(legacy)",{message:e,targetOrigin:r,transfer:s}),this.#r.postMessage(e,r??this.#e,s)}handleClose(e){ae("close()"),window.removeEventListener("message",this.#t),super.handleClose(e)}#t=async e=>{if(ae("handleMessage()",e),e.source!==this.#r||(ae("handleMessage() -> source ok"),this.#e!=="*"&&e.origin!==this.#e))return;ae("handleMessage() -> origin ok");const r=e.data;if(!rt(r)){ae("handleMessage() -> legacy"),this.onmessage?.(e);return}ae("handleMessage() -> jsonrpc"),this[T].dispatchMessage(r)}}function Ue(){let t,e;return{promise:new Promise((s,n)=>{e=s,t=n}),reject:t,resolve:e}}const Yr=2*1024*1024,Wt=Fe("appetize:client:acked-writable-stream");class Xr{unacked=0;#e;#r;#t;#s;#n=[];#i;constructor(e){this.#t=e,this.#i=e.window??Yr}abort(e){this.#a(e),this.#t.onAbort?.(e)}async close(){await this.#l(()=>this.unacked===0),this.#t.onClose?.()}fail(e){this.#a(e)&&this.#t.onError?.(e)}start(e){this.#e=e}write(e){const r=e.byteLength;return this.unacked+=r,this.#t.send(e).then(()=>{this.unacked-=r,this.#s&&(this.#s.acked+=r),this.#o()},s=>{this.fail(s)}),this.unacked>=this.#i&&!this.#s&&(this.#s={acked:0,at:performance.now()},Wt("window full: %d bytes unacked, writes stalled",this.unacked)),this.#l(()=>this.unacked<this.#i)}#o(){if(this.#s&&this.unacked<=this.#i/2){const e=performance.now()-this.#s.at;Wt("pressure relieved after %dms: %d bytes acked, %s MB/s",Math.round(e),this.#s.acked,(this.#s.acked/Math.max(e,1)/1e3).toFixed(2)),this.#s=void 0}this.#n=this.#n.filter(e=>e.until()?(e.resolve(void 0),!1):!0)}#a(e){if(this.#r)return!1;this.#r={reason:e},this.#e.error(e);const r=this.#n;this.#n=[];for(const s of r)s.reject(e);return!0}#l(e){if(e())return Promise.resolve();const r={...Ue(),until:e};return this.#n.push(r),r.promise}}class Qr extends WritableStream{get unacked(){return this.#e.unacked}#e;constructor(e){const r=new Xr(e);super({abort:s=>{r.abort(s)},close:()=>r.close(),start:s=>{r.start(s)},write:s=>r.write(s)}),this.#e=r}fail(e){this.#e.fail(e)}}const es=1024*1024;class ts{#e;#r=!1;#t;#s;constructor(e){this.#t=e}cancel(e){this.#n(),this.#t?.(e)}close(){this.#n()&&this.#e.close()}error(e){this.#n()&&this.#e.error(e)}pull(){const e=this.#s;this.#s=void 0,e?.resolve(void 0)}async push(e){if(this.#r)return;this.#s??=Ue();const{promise:r}=this.#s;this.#e.enqueue(e),await r}start(e){this.#e=e}#n(){return this.#r?!1:(this.#r=!0,this.pull(),!0)}}class rs extends ReadableStream{#e;constructor({highWaterMark:e=es,onCancel:r}={}){const s=new ts(r);super({cancel:n=>{s.cancel(n)},pull:()=>{s.pull()},start:n=>{s.start(n)}},new ByteLengthQueuingStrategy({highWaterMark:e})),this.#e=s}close(){this.#e.close()}error(e){this.#e.error(e)}push(e){return this.#e.push(e)}}class ss{closed;readable;writable;#e=[];#r;#t;#s;#n;#i;#o="starting";constructor(e,{onClose:r,receiveBuffer:s,sendWindow:n,signal:o}){if(this.#i=e,this.#r=Ue(),this.closed=this.#r.promise,this.closed.catch(ns),this.#s=new rs({highWaterMark:s,onCancel:()=>{this.#a(void 0)}}),this.readable=this.#s,this.#n=new Qr({onAbort:()=>{this.#a(void 0)},onClose:()=>{this.#a(void 0)},onError:f=>{this.#a(f)},send:f=>e.request("appetizeio.device.server.debug.adbTunnel.data",{data:f}),window:n}),this.writable=this.#n,o){const f=()=>{this.#a(o.reason)};o.addEventListener("abort",f,{once:!0}),this.#e.push(()=>{o.removeEventListener("abort",f)})}this.#e.push(()=>{r(this)})}close=()=>{this.#a(void 0)};detach(){this.#a(void 0,{notifyServer:!1})}async handleData(e){this.#o==="open"&&await this.#s.push(e)}handleStopped({error:e}){this.#o==="open"&&this.#a(e?new Error(e):void 0)}async start(){try{await this.#i.request("appetizeio.device.server.debug.adbTunnel.start",void 0)}catch(e){throw this.#a(e),e}if(this.#o==="closed")throw this.#t?this.#t:new Error("The adb tunnel closed before it started");this.#o="open"}async[Symbol.asyncDispose](){this.close();try{await this.closed}catch{}}#a(e,{notifyServer:r=!0}={}){if(this.#o!=="closed"){this.#o="closed",this.#t=e,r&&X(this.#i,"appetizeio.device.server.debug.adbTunnel.stop",void 0),e?(this.#s.error(e),this.#n.fail(e)):(this.#s.close(),this.#n.fail(new Error("The adb tunnel has stopped")));for(const s of this.#e)s();e?this.#r.reject(e):this.#r.resolve(void 0)}}}function ns(){}class is{readable;ready;#e=[];#r=!1;#t;#s;#n;constructor({label:e,onClose:r,signal:s}){this.#s=e,this.ready=new Promise((o,f)=>{this.#n={reject:f,resolve:o}});let n;if(this.readable=new ReadableStream({cancel:()=>{this.#o()},start:o=>{n=o}}),!n)throw new Error("ReadableStream controller was not initialized");if(this.#t=n,s){const o=()=>{this.fail(s.reason)};s.addEventListener("abort",o,{once:!0}),this.#e.push(()=>{s.removeEventListener("abort",o)})}this.#e.push(()=>{r(this)})}close=()=>{this.#i()};fail(e){this.#i(e)}handleItem(e){this.#t.enqueue(e)}markReady(){if(!this.#n)return;const{resolve:e}=this.#n;this.#n=void 0,e(this)}async*[Symbol.asyncIterator](){const e=this.readable.getReader();try{for(let r=await e.read();!r.done;r=await e.read())yield r.value}finally{await e.cancel()}}#i(e){this.#r||(this.#t.close(),this.#o(e))}#o(e){this.#r=!0;for(const r of this.#e)r();this.#n?.reject(e??new Error(`${this.#s} closed before it started`)),this.#n=void 0}}class os{get subscribers(){return this.#t}#e;#r;#t=new Set;constructor(e){this.#e=e}close(){this.#r=void 0;for(const e of[...this.#t])e.close();this.#t.clear()}add(e){this.#t.add(e)}ensureStarted(){return this.#r||(this.#r=(async()=>{try{return await this.#e.start()}catch(e){throw this.#r=void 0,e}})()),this.#r}release(e){this.#t.delete(e),!(this.#t.size>0||!this.#r)&&(this.#r=void 0,this.#e.stop())}}class Gt extends os{#e;constructor(e){super({start:e.start,stop:e.stop}),this.#e=e.label}async createStream({signal:e}={}){e?.throwIfAborted();const r=new is({label:this.#e,onClose:s=>{this.release(s)},signal:e});this.add(r);try{await this.ensureStarted(),r.markReady()}catch(s){r.fail(s)}return await r.ready}handleNotification(e){for(const r of this.subscribers)r.handleItem(e)}}class as{#e;#r;#t;#s;constructor(e){this.#s=e,this.#r=new Gt({label:"Log stream",start:()=>e.request("appetizeio.device.server.debug.log.start"),stop:()=>{X(e,"appetizeio.device.server.debug.log.stop",void 0)}}),this.#t=new Gt({label:"Proxy intercept stream",start:()=>e.request("appetizeio.device.server.debug.proxyIntercept.start"),stop:()=>{X(e,"appetizeio.device.server.debug.proxyIntercept.stop",void 0)}})}close(){this.#e?.detach(),this.#r.close(),this.#t.close()}async createAdbTunnel({signal:e}={}){e?.throwIfAborted(),this.#e?.close();const r=new ss(this.#s,{onClose:()=>{this.#e=void 0},signal:e});return this.#e=r,await r.start(),r}async createLogStream(e){return await this.#r.createStream(e)}async createProxyInterceptStream(e){return await this.#t.createStream(e)}async handleAdbTunnelData({data:e}){await this.#e?.handleData(e)}handleAdbTunnelStopped(e){this.#e?.handleStopped(e)}handleLogEntry(e){this.#r.handleNotification(e)}handleProxyInterceptEvent(e){this.#t.handleNotification(e)}}function at(t){return{...ls(t),index:t.index,within:t.within?at(t.within):void 0}}function ls(t){switch(t.by){case"testId":return{by:"testId",testId:t.testId};case"text":return{by:"text",text:cs(t.text)}}}function cs(t){return typeof t=="string"?{kind:"exact",value:t}:{flags:t.flags,kind:"regex",source:t.source}}function fs(t){return{press:e=>{X(t,"appetizeio.device.server.keyboard.press",{key:e})}}}function us({onRequest:t,parent:e,proxyInlet:r,signal:s}){const n=new Jt(e,{signal:s}),o=[()=>{n.close()}];return qt(n,r),t&&o.push(Pe(n,f=>{t(f,{source:"parent"})})),{cleanup:()=>{for(const f of o)f()},notifies:()=>e===globalThis.window?void 0:n}}const ds="@appetizeio/rpc:playwrightAdapter",Le=Symbol.for(ds);function hs(t){window[Le]&&console.warn("playwright exposed more than once, overwriting previous adapter");const e={send(r){t[T].send(r)},subscribe(r){return t[T].addEventListener("message",s=>{r(s.detail)})}};return window[Le]=e,()=>{window[Le]===e&&delete window[Le]}}function ps({onRequest:t,proxyInlet:e}){const[r,s]=ot(),o=[hs(s),()=>{r.close()}];return qt(r,e),t&&o.push(Pe(r,f=>{t(f,{source:"parent"})})),{cleanup:()=>{for(const f of o)f()},notifies:()=>r}}function _e(t){return t.by==="position"?{by:"position",x:t.x,y:t.y}:{...at(t),x:t.x,y:t.y}}function ys(t){return"to"in t?{from:_e(t.from),kind:"path",to:_e(t.to)}:{direction:t.direction,distance:t.distance,from:t.from?_e(t.from):void 0,kind:"direction"}}function ws(t){return{down:(e,r)=>{X(t,"appetizeio.device.server.touch.down",{x:e,y:r})},move:(e,r)=>{X(t,"appetizeio.device.server.touch.move",{x:e,y:r})},up:(e,r)=>{X(t,"appetizeio.device.server.touch.up",{x:e,y:r})}}}const ms=new Set(it),bs=/^(?<key>[A-Za-z]+)>(?<repeat>\d+)\/$/u,gs=/(\{\{|\{[^{}]*\})/u;function Es(t){const e=[];let r="";function s(){r.length>0&&(e.push({kind:"text",text:r}),r="")}for(const[n,o]of t.split(gs).entries())if(n%2===0){if(o.includes("{"))throw new Error(`Unclosed "{" in ${JSON.stringify(t)}`);r+=o}else o==="{{"?r+="{":(s(),e.push(vs(o.slice(1,-1))));return s(),e}function Ss(t,e){if(!ms.has(t))throw e.endsWith(">")?new Error(`Holding a key is not supported: {${e}}`):e.startsWith("/")?new Error(`Releasing a key is not supported: {${e}}`):new Error(`{${e}} does not name a supported key. Supported: ${it.join(", ")}. Type characters as text, and escape a literal "{" as "{{".`)}function vs(t){const e=bs.exec(t)?.groups,r=e?.key??t;if(Ss(r,t),!e)return{key:r,kind:"press"};const s=Number(e.repeat);if(s<1)throw new Error(`Repeat for {${t}} must be at least 1`);return{key:r,kind:"press",repeat:s}}const As=Symbol("@appetizeio/client:v1Compat");function Ht(t){return t?.[As]}class Os{readable;ready;get dimensions(){return this.#s}#e=[];#r=!1;#t;#s;#n;#i;constructor({onClose:e,requestKeyFrame:r,signal:s}){this.#n=r,this.ready=new Promise((o,f)=>{this.#i={reject:f,resolve:o}});let n;if(this.readable=new ReadableStream({cancel:()=>{this.#a()},start:o=>{n=o}}),!n)throw new Error("ReadableStream controller was not initialized");if(this.#t=n,s){const o=()=>{this.fail(s.reason)};s.addEventListener("abort",o,{once:!0}),this.#e.push(()=>{s.removeEventListener("abort",o)})}this.#e.push(()=>{e(this)})}close=()=>{this.#o()};fail(e){this.#o(e)}handleChunk(e){if(this.#i){if(e.type!=="key")return;const{resolve:r}=this.#i;this.#i=void 0,this.#s={height:e.height,width:e.width},r(this)}else e.type==="key"&&(this.#s={height:e.height,width:e.width});this.#t.enqueue(e)}requestKeyFrame=()=>{this.#r||this.#n()};async*[Symbol.asyncIterator](){const e=this.readable.getReader();try{for(let r=await e.read();!r.done;r=await e.read())yield r.value}finally{await e.cancel()}}#o(e){this.#r||(this.#t.close(),this.#a(e))}#a(e){this.#r=!0;for(const r of this.#e)r();this.#i?.reject(e??new Error("Video stream closed before the first key chunk")),this.#i=void 0}}class ks{#e=!1;#r;#t;#s=new Set;constructor(e){this.#r=e}close(){this.#t=void 0;for(const e of[...this.#s])e.close()}async createStream({signal:e}={}){e?.throwIfAborted();const r=new Os({onClose:s=>{this.#i(s)},requestKeyFrame:()=>{this.#o()},signal:e});this.#s.add(r);try{await this.#n()}catch(s){r.fail(s)}return await r.ready}handleChunk(e){e.type==="key"&&(this.#e=!1);for(const r of this.#s)r.handleChunk(e)}#n(){return this.#t?(this.#o(),this.#t):(this.#e=!0,this.#t=(async()=>{try{await this.#r.request("appetizeio.device.server.video.start")}catch(e){throw this.#t=void 0,e}})(),this.#t)}#i(e){this.#s.delete(e),!(this.#s.size>0||!this.#t)&&(this.#t=void 0,X(this.#r,"appetizeio.device.server.video.stop",void 0))}#o(){this.#e||(this.#e=!0,X(this.#r,"appetizeio.device.server.video.requestKeyFrame",void 0))}}class Is{debug;keyboard;touch;video;#e;#r=[];#t;constructor(e,r={}){const s=Ht(r)??{},{baseUrl:n,onClose:o,signal:f}=r;this.#e=n?xs(n):void 0;const{onRequest:m,parent:y,proxyRequest:v}=s,g=Ms(m);f?.addEventListener("abort",this.close);const[M,R]=ot(),[L,U]=ot();this.#r.push(()=>{M.close(),R.close(),L.close(),U.close()}),this.#r.push(nt(U,e,{leftEffects:v}));const P=y==="playwright"?ps({onRequest:g,proxyInlet:L}):y?us({onRequest:g,parent:y,proxyInlet:L,signal:f}):void 0;P&&this.#r.push(P.cleanup),this.#r.push(nt(R,L,{notifiesLeft:P?.notifies}));const{client:W,unsub:ye}=Zr(M,{"appetizeio.device.client.debug.adbTunnel.data":z=>G.handleAdbTunnelData(z),"appetizeio.device.client.debug.adbTunnel.stopped":async z=>{G.handleAdbTunnelStopped(z)},"appetizeio.device.client.debug.log.entry":async z=>{G.handleLogEntry(z)},"appetizeio.device.client.debug.proxyIntercept.event":async z=>{G.handleProxyInterceptEvent(z)},"appetizeio.device.client.video.chunk":async z=>{O.handleChunk(z)}});this.#t=W,this.#r.push(ye);const G=new as(this.#t);this.#r.push(()=>{G.close()});const O=new ks(this.#t);this.#r.push(()=>{O.close()}),this.debug=G,this.keyboard=fs(this.#t),this.touch=ws(this.#t),this.video=O,g&&(this.#r.push(Pe(R,z=>{g(z,{source:"self"})})),e instanceof Jt&&this.#r.push(Pe(e,z=>{g(z,{source:"iframe"})}))),this.#r.push(()=>o?.())}async clearKeychain(){await this.#t.request("appetizeio.device.server.clearKeychain")}close=()=>{for(const e of this.#r)try{e()}catch(r){console.error("Device cleanup error:",r)}};async inspect(e,r){return await this.#t.request("appetizeio.device.server.inspect",{options:r,selector:e?at(e):void 0})}async open(e){new URL(e),await this.#t.request("appetizeio.device.server.open",{url:e})}async press(e){await this.#t.request("appetizeio.device.server.press",{action:e})}async rotate(e){return await this.#t.request("appetizeio.device.server.rotate",{orientation:e})}async screenshot(){const e=await this.#t.request("appetizeio.device.server.screenshot"),r=this.#e?new URL(e.url,this.#e).href:e.url,s=await fetch(r);if(!s.ok)throw new Error(`Screenshot download failed: ${String(s.status)} ${s.statusText}`);const n=s.headers.get("content-type")??"application/octet-stream";return{data:new Uint8Array(await s.arrayBuffer()),mimeType:n}}async swipe(e,r){await this.#t.request("appetizeio.device.server.swipe",{gesture:ys(e),options:r})}async tap(e,r){await this.#t.request("appetizeio.device.server.tap",{options:r,selector:_e(e)})}async type(e,r){await this.#t.request("appetizeio.device.server.type",{options:r,steps:Es(e)})}}function xs(t){const e=new URL(t);return e.protocol==="ws:"?e.protocol="http:":e.protocol==="wss:"&&(e.protocol="https:"),e.href}const Ms=t=>{if(t)return(e,r)=>{e.method.startsWith("appetizeio.device.server.")&&t(e,r)}},Rs={dateStyle:"medium",timeStyle:"short"},Ts=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:\d{2})$/;function lt(t){return Array.isArray(t)?t.map(lt).join(", "):typeof t=="boolean"?t?"yes":"no":typeof t=="number"?t.toLocaleString():Cs(t)}function Cs(t){if(Ts.test(t)){const r=new Date(t);if(!Number.isNaN(r.getTime()))return r.toLocaleString(void 0,Rs)}const e=bt();return t===e?"~":t.startsWith(`${e}${pr}`)?`~${t.slice(e.length)}`:t}class Ne extends Error{details;constructor(e,r={},s){super(e,s===void 0?void 0:{cause:s}),this.name="CommandError",this.details=r}hints(e){return[]}}class De extends Ne{sessionDir;constructor(e,r,s={},n){super(e,Object.assign({sessionDir:r},s),n),this.name="SessionError",this.sessionDir=r}static wrap(e,r){if(e instanceof De||e instanceof he)return e;const s=e instanceof Error?e.message:String(e),n=e instanceof Ne?e.details:{};return new De(s,r,n,e)}hints(){return[`Check the session logs for details: ${lt(this.sessionDir)}`]}}class he extends Ne{constructor(e){super(e),this.name="UsageError"}hints({command:e}){return[`Run 'appetize ${e} --help' for usage`]}}function Ps(t,e,r){const s=e instanceof Error?e.message:String(e);return e instanceof Ne?t==="json"?JSON.stringify({error:{message:s,...e.details}},null,2):[`\u2716 ${s}`,...e.hints(r).map(n=>` ${n}`)].join(`
|
|
2
|
+
`):t==="json"?JSON.stringify({error:{message:s}},null,2):`\u2716 ${s}`}function ct(t){try{return process.kill(t,0),!0}catch{return!1}}const Us=["SIGINT","SIGTERM"],Ls=150;function _s(t){const e=new AbortController,r=setInterval(()=>{ct(t)||(clearInterval(r),e.abort(new Error("The device session exited")))},Ls);return r.unref(),e.signal}function Zt(){const t=new AbortController;for(const e of Us)process.once(e,()=>{t.abort(new Error(`Received ${e}`))});return t.signal}function Ns(t,e){return new Promise((r,s)=>{if(e.aborted){s(Yt(e.reason));return}const n=()=>{clearTimeout(o),s(Yt(e.reason))},o=setTimeout(()=>{e.removeEventListener("abort",n),r()},t);e.addEventListener("abort",n,{once:!0})})}function Yt(t){return t instanceof Error?t:new Error(String(t))}function Ds(t){const e=t.at(-1);return{options:zs(e)?e:{},positionals:t.slice(0,-1).filter(r=>typeof r=="string"),signal:Zt()}}function Bs(t,e){const r=Xt(t,e);return r===void 0?void 0:Qt(r,e)}function Xt(t,e){if(t===void 0)return;const r=typeof t=="boolean"?Number.NaN:Number(t);if(!Number.isFinite(r))throw new he(`${e} expects a number, e.g., ${e}=-0.1`);return r}function ft(t,e){if(t!==void 0){if(typeof t!="string"||t==="")throw new he(`${e} needs a value`);return t}}function Qt(t,e){if(!(t>=0&&t<=1))throw new he(`${e} expects a number between 0 and 1`);return t}function Fs(t,e){const r=ft(t,e);if(r===void 0)throw new he(`${e} needs a value`);return r}function zs(t){return typeof t=="object"&&t!==null}const js="APPETIZEIO_FEATURE_FLAGS";function Vs(){const t={};for(const e of(process.env[js]??"").split(",")){const r=e.trim();r!==""&&(t[r]=!0)}return t}function Ks(){const t=process.env.APPETIZE_API_TOKEN;if(!t)throw new Error("APPETIZE_API_TOKEN must be set");return t}function er(t){return ft(t.endpoint,"--endpoint")??$s()}function $s(){const t=process.env.APPETIZE_ENDPOINT?.trim();return t===""?void 0:t}const qs="https://appetize.io";async function tr(t,{authorize:e=!0,commandOptions:r={},query:s={},...n}={}){const o=new URL(t,er(r)??qs);for(const[y,v]of Object.entries(s))o.searchParams.set(y,v);const f=new Headers(n.headers);e&&f.set("x-api-key",Ks());const m=await fetch(o,{...n,headers:f});if(!m.ok)throw new Error(`The webserver rejected the request (${String(m.status)})`);return await m.json()}const rr=["android","ios"];function sr(t={},e){return tr("/api/v2/service/devices",{authorize:!1,commandOptions:t,signal:e})}function Js(t){return rr.includes(t)}async function Ws(t,e={}){return(await sr(e)).find(s=>s.id===t)?.platform}function Gs(t){let e={...t,updatedAt:new Date().toISOString()};return{path:dt(e.sessionId),save:r=>(e={...e,...r,updatedAt:new Date().toISOString()},rn(e),e)}}function Hs(){const t=ir();return gt(t,{recursive:!0}),br(t).map(e=>ut(e)).filter(e=>e!==void 0)}function Zs(t){if(t!==void 0){const r=ut(t);if(!r)throw new Error(`No session found for id ${t}`);return r}const e=Hs().filter(tn);if(e.length===0)throw new Error("No active sessions");if(e.length>1)throw new Error("Multiple active sessions; specify --session-id");return e[0]}function ut(t){try{return JSON.parse(mr(dt(t),"utf8"))}catch{return}}function Ys(t){return te(ke(t),"control.sock")}function nr(t){return te(ke(t),"daemon.log")}function Xs(t){return te(ke(t),"device.log.jsonl")}function Qs(t,e){return{daemon:nr(t),device:Xs(t),...e==="intercept"?{network:en(t)}:void 0}}function en(t){return te(ke(t),"network.jsonl")}function ke(t){const e=or(t);return gt(e,{recursive:!0}),e}function dt(t){return te(ke(t),"state.json")}function ir(){return process.env.APPETIZE_CLI_HOME??te(bt(),".appetize","cli","sessions")}function or(t){return te(ir(),t)}function tn(t){const e=t.state?.phase;return e==="ended"||e==="error"?!1:ct(t.pid)}function rn(t){const e=dt(t.sessionId),r=`${e}.tmp`;yr(r,`${JSON.stringify(t,null,2)}
|
|
3
|
+
`),wr(r,e)}const ht="APPETIZE_DAEMON_CONFIG";function sn(){const t=process.env[ht];if(!t)throw new Error(`${ht} is not set`);return JSON.parse(t)}function nn(t){return JSON.stringify(t)}export{it as A,Br as B,T as C,Is as D,Pr as E,rt as F,Ht as G,Ue as H,sn as I,Gs as J,Ws as K,jt as L,nt as M,Ys as N,Zt as O,De as S,Oe as T,he as U,Xt as a,Ns as b,sr as c,Gr as d,rr as e,tr as f,Fs as g,nr as h,Js as i,ht as j,ut as k,Vs as l,er as m,Qs as n,or as o,ft as p,ct as q,Qt as r,nn as s,Bs as t,lt as u,Kt as v,Zs as w,_s as x,Ds as y,Ps as z};
|
package/daemon.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{T as M,x as L,y as O,z as b,A as z,D as _,B as F,C as V,E as N,m as j,F as H,G as Q,S as G,H as k,I as J,n as K}from"./signals-C8NaADLb.js";import S from"debug";import{createServer as A}from"node:net";import{pipeline as $}from"node:stream";import{rm as B}from"node:fs/promises";import{readFileSync as Z,createWriteStream as X,existsSync as Y,rmSync as ee}from"node:fs";import{createServer as te}from"node:http";import{WebSocketServer as ne}from"ws";import{pipeline as re}from"node:stream/promises";import{EncodedVideoPacketSource as oe,Output as se,FilePathTarget as ie,Mp4OutputFormat as ae,EncodedPacket as ce}from"mediabunny";import"stream";import"module";import"json-rpc-2.0";import"node:os";import"node:path";const de=S("appetize.io:transport:ws-ping"),ue=3e4;function le(e){let t=!0;const n=()=>{t=!0};e.on("pong",n);const r=setInterval(()=>{if(!t){clearInterval(r),de("liveness ping went unanswered, terminating"),e.terminate();return}e.readyState===e.OPEN&&(t=!1,e.ping())},ue);return{destroy(){clearInterval(r),e.off("pong",n)},pong:n}}const v=S("appetize.io:trace:transport:websocket");class E extends M{constructor(t,{signal:n}={}){super(async o=>{this.#e.send(L(o))},{signal:n}),this.wsOrUrl=t,typeof t=="string"?(this.#e=new WebSocket(t),this.#e.binaryType="arraybuffer"):this.#e=t;const r=this.#e;if(r instanceof WebSocket?(r.addEventListener("open",this.#s),r.addEventListener("message",this.#o),r.addEventListener("error",this.#r),r.addEventListener("close",this.#n),this.#t.push(()=>{r.removeEventListener("open",this.#s),r.removeEventListener("message",this.#o),r.removeEventListener("error",this.#r),r.removeEventListener("close",this.#n)})):(r.addEventListener("open",this.#s),r.addEventListener("message",this.#o),r.addEventListener("error",this.#r),r.addEventListener("close",this.#n),this.#t.push(()=>{r.removeEventListener("open",this.#s),r.removeEventListener("message",this.#o),r.removeEventListener("error",this.#r),r.removeEventListener("close",this.#n)})),this.send=r.send.bind(r),"ping"in r){const{destroy:o,pong:s}=le(r);this.#c=s,this.#t.push(o)}}wsOrUrl;onclose;onerror;onmessage;onopen;send;get bufferedAmount(){return this.#e.bufferedAmount}get readyState(){return this.#e.readyState}#t=[];#i=!1;#a=!1;#c;#e;close({destroyWs:t=!1,...n}={}){this.closed||(this.#i=t,super.close(n))}handleClose(t){v("close()");for(const n of this.#t.splice(0))n();if((typeof this.wsOrUrl=="string"||this.#i)&&(this.#e.close(t.code,t.reason),"terminate"in this.#e)){const n=this.#e;setTimeout(()=>{n.terminate()},100)}this.#d(),super.handleClose(t)}#d(t){this.#a||(this.#a=!0,this.onclose?.(t))}#n=t=>{v("handleWebSocketClose()",t);try{this.#d(t)}finally{this.close()}};#r=t=>{v("handleWebSocketError()",t),this.onerror?.(t)};#o=async t=>{v("handleWebSocketMessage()",t),this.#c?.();const n=this.#u(t);if(!n){v("handleWebSocketMessage() -> legacy"),this.onmessage?.(t);return}v("handleWebSocketMessage() -> jsonrpc",n),this[O].dispatchMessage(n)};#s=t=>{v("handleWebSocketOpen()",t),this.onopen?.(t)};#u(t){try{const n=b(new Uint8Array(t.data));return z(n)?n:null}catch{return null}}}function y(e){return typeof e=="object"&&e!==null}function R(e){try{const t=b(new Uint8Array(e.data));if(y(t)&&typeof t.name=="string")return{name:t.name,payload:"payload"in t?t.payload:void 0}}catch{}}async function fe(e,t={}){const n=t.baseUrl??(typeof e=="string"?new URL(e).origin:void 0),r=typeof e=="string"?new E(e,{signal:t.signal}):e,o=new _(r,{...t,baseUrl:n});return typeof e=="string"&&await pe(r,o,t),o}function pe(e,t,n){const r=F(n)?.onLegacyMessage;return new Promise((o,s)=>{e.onopen=()=>{o()},e.onclose=()=>{t.close(),n.signal?.aborted?s(n.signal.reason):s(new Error("The websocket was closed before the device connection was established"))},e.onerror=s,e.onmessage=i=>{const c=R(i);c&&r?.(c)}})}async function he(e,{device:t,onStateChange:n,signal:r}){r?.throwIfAborted(),n?.({device:t,phase:"starting"}),await new Promise((o,s)=>{const i=()=>{c(),s(r?.reason)},c=()=>{e.onmessage=void 0,e.onclose=void 0,r?.removeEventListener("abort",i)};e.onmessage=a=>{const d=we(R(a),t);d&&(n?.(d),d.phase==="ready"&&(c(),o()))},e.onclose=()=>{c(),s(new Error("The device closed before it was ready"))},r?.addEventListener("abort",i,{once:!0})})}function we(e,t){if(!e)return;if(e.name==="ready")return{device:t,phase:"ready"};if(e.name!=="launchStatus")return;switch(y(e.payload)&&typeof e.payload.status=="string"?e.payload.status:void 0){case"downloadingApp":return{device:t,phase:"downloadingApp"};case"installingApp":return{device:t,phase:"installingApp"};case"launchingApp":return{device:t,phase:"launchingApp"};default:return}}function ve(){return typeof process>"u"?void 0:process}function ge(e){return{deviceType:e.id,osVersion:e.osVersion}}function ye(e){return e==="intercept"?"interceptOnDemand":e}class g extends Error{code;constructor(t,n){super(n),this.name="SessionRequestError",this.code=t}}function me(e,{onClose:t,onEvent:n,signal:r}={}){return new Promise((o,s)=>{const i=new WebSocket(e);i.binaryType="arraybuffer",i.onopen=()=>{P(i,{capabilities:{},t:"handshake"})},i.onmessage=c=>{be(i,c,{onEvent:n,onHandshake:a=>{o({close:()=>{i.close()},id:a})}})},i.onclose=()=>{s(new g("disconnected",`The connection to ${e} closed`)),t?.()},r?.addEventListener("abort",()=>{s(r.reason),i.close()},{once:!0})})}function be(e,t,n){const r=b(new Uint8Array(t.data));y(r)&&(r.t==="handshake"&&typeof r.id=="string"?n.onHandshake(r.id):r.name==="ping"?P(e,{name:"pong"}):typeof r.name=="string"&&n.onEvent?.(r.name,r.payload))}function P(e,t){e.send(L(t))}async function Se(e,t,{apiToken:n,onQueue:r,signal:o}={}){const s=V();ke(s.reject,o);const i=await me(Ae(e),{onClose:()=>{s.reject(Ee())},onEvent:(c,a)=>{Te(c,a,s,r)},signal:o});return Le(e,{apiToken:n,data:t,socketid:i.id},o).catch(s.reject),await s.promise.finally(()=>{i.close()})}function Ee(){return new g("disconnected","The webserver connection closed before a session was granted")}function C(e,t){return y(e)?e[t]:void 0}function Te(e,t,n,r){if(e==="queue"||e==="concurrentQueue"){const o=e==="queue"?Re(t):Pe(t);o&&r?.(o)}else e==="newSession"?$e(n,t):e==="userError"&&n.reject(new g("denied",Ce(t)))}function I(e,t){const n=C(e,t);return typeof n=="number"?n:void 0}function m(e,t){const n=C(e,t);return typeof n=="string"?n:void 0}async function Le(e,t,n){const r=await fetch(new URL("/api/session/request",e),{body:JSON.stringify(t),headers:{"content-type":"application/json"},method:"POST",signal:n});if(!r.ok)throw new g("denied",`The webserver rejected the session request (${String(r.status)})`)}function ke(e,t){t?.addEventListener("abort",()=>{e(t.reason)},{once:!0})}function Ae(e){const t=new URL("/client",e);return t.protocol=t.protocol==="http:"?"ws:":"wss:",t.href}function $e(e,t){const n=m(t,"path"),r=m(t,"sessionToken");n!==void 0&&r!==void 0?e.resolve({path:n,sessionToken:r}):e.reject(new g("denied","The granted session is missing its address"))}function Re(e){const t=I(e,"position");return t===void 0?void 0:{position:t,reason:"capacity"}}function Pe(e){const t=I(e,"position");if(t!==void 0)return{limit:m(e,"name")??"Queue",position:t,reason:"concurrency"}}function Ce(e){return m(e,"message")??"The session request was denied"}async function Ie({apiToken:e=Ue(),codec:t="h264",device:n,endpoint:r="https://appetize.io",onStateChange:o,open:s,proxy:i,signal:c,target:a}){if(c?.throwIfAborted(),!a)throw new TypeError("target is required");if(!n.id)throw new TypeError("device.id is required");o?.({phase:"requesting"});const d=await Se(r,{codec:t,launchUrl:s,noVideo:!0,proxy:ye(i),publicKey:a,...ge(n)},{apiToken:e,onQueue:p=>{o?.({phase:"queued",queue:p})},signal:c});return{baseUrl:new URL(d.path).origin,url:We(d)}}function Ue(){return ve()?.env.APPETIZE_API_TOKEN}function We(e){const t=new URL("/client",e.path);return t.protocol=t.protocol==="http:"?"ws:":"wss:",t.searchParams.set("sessionToken",e.sessionToken),t.href}const xe=S("appetize:daemon");function f(e){xe(e)}function De(e,{message:t="The operation timed out"}={}){const n=new AbortController,r=setTimeout(()=>{n.abort(new Error(t))},e),o=()=>{clearTimeout(r)};return{cancel:o,signal:n.signal,[Symbol.dispose]:o}}var qe=(e,t)=>(t=Symbol[e])?t:Symbol.for("Symbol."+e),U=e=>{throw TypeError(e)},Me=(e,t,n)=>{if(t!=null){typeof t!="object"&&typeof t!="function"&&U("Object expected");var r,o;r===void 0&&(r=t[qe("dispose")]),typeof r!="function"&&U("Object not disposable"),o&&(r=function(){try{o.call(this)}catch(s){return Promise.reject(s)}}),e.push([n,r,t])}return t},Oe=(e,t,n)=>{var r=typeof SuppressedError=="function"?SuppressedError:function(i,c,a,d){return d=Error(a),d.name="SuppressedError",d.error=i,d.suppressed=c,d},o=i=>t=n?new r(i,t,"An error was suppressed during disposal"):(n=!0,i),s=i=>{for(;i=e.pop();)try{var c=i[1]&&i[1].call(i[2]);if(i[0])return Promise.resolve(c).then(s,a=>(o(a),s()))}catch(a){o(a)}if(n)throw t};return s()};const ze=1e4;async function _e(e,t,{onClose:n,signal:r}={}){var o=[];try{const c=Me(o,De(ze,{message:"Timed out waiting for session request state"})),a=AbortSignal.any([r,c.signal].filter(w=>!!w)),d=w=>{t.save({state:w}),f(w.phase),w.phase!=="requesting"&&c.cancel()},{baseUrl:p,url:u}=await Ie({device:e.device,endpoint:e.endpoint,onStateChange:d,open:e.open,proxy:e.proxy,signal:a,target:e.target});t.save({baseUrl:p});const l=new E(u,{signal:a});return await he(l,{device:e.device,onStateChange:d,signal:a}),l.onclose=()=>{n?.("The device connection closed")},{device:await fe(l,{baseUrl:p,signal:a}),transport:l}}catch(c){var s=c,i=!0}finally{Oe(o,s,i)}}function Fe(){const e=N(),t=j(e.sessionId,e.proxy),n=H({device:e.device,endpoint:e.endpoint,open:e.open,pid:process.pid,proxy:e.proxy,sessionId:e.sessionId,startedAt:new Date().toISOString(),target:e.target});return n.save({logs:t}),{config:e,logs:t,store:n}}async function Ve(e,{host:t="127.0.0.1",onError:n,port:r=0,signal:o}={}){o?.throwIfAborted();let s;const i=()=>{const u=s;s=void 0,u&&(u.tunnel?.close(),u.socket.destroy())},c=async u=>{const{socket:l}=u;try{const h=await e.debug.createAdbTunnel();if(l.destroyed){h.close();return}u.tunnel=h,h.closed.catch(w=>{n?.(w)}),Ne(l,h)}catch(h){l.destroyed||n?.(h),l.destroy()}},a=A(u=>{i();const l={socket:u};s=l,u.once("close",()=>{s===l&&(s=void 0)}),c(l)}),d=()=>{o?.removeEventListener("abort",d),i(),a.close()};o?.addEventListener("abort",d,{once:!0});const p=await je(a,t,r);return{close:d,url:new URL(`adb://${p.address}:${String(p.port)}`)}}function Ne(e,t){$(t.readable,e,W),$(e,async n=>{const r=t.writable.getWriter();try{for await(const o of n)await r.write(o);await r.close()}catch(o){throw await r.abort(o),o}},W)}function W(){}function je(e,t,n){return new Promise((r,o)=>{e.once("error",o),e.listen({host:t,port:n},()=>{e.off("error",o);const s=e.address();if(s===null||typeof s=="string"){o(new Error("The listener has no tcp address"));return}r(s)})})}async function He(e,t,n,{signal:r}={}){try{if(!await Qe(t))return;const o=await Ve(e,{onError:s=>{f(`adb endpoint error: ${x(s)}`)},signal:r});n.save({adbSerial:o.url.host}),f(`adb endpoint listening at ${o.url.host}`)}catch(o){f(`adb endpoint unavailable: ${x(o)}`)}}async function Qe(e){return await Q(e.device.id,{endpoint:e.endpoint})==="android"}function x(e){return e instanceof Error?e.message:String(e)}async function Ge(e,t,{methods:n={},signal:r}={}){await B(t,{force:!0});const o=new Set,s=A(i=>{f("control client connected"),o.add(i),i.once("close",()=>{o.delete(i)});const c=new G(i,{signal:r});k(c,e,{leftEffects:()=>n})});r?.addEventListener("abort",()=>{for(const i of o)i.destroy()},{once:!0}),await new Promise((i,c)=>{s.once("error",c),s.listen({path:t,signal:r},()=>{s.off("error",c),i()})})}async function Je(e,t,n,{recorder:r,signal:o}){const s=J(n);return await Ge(e,s,{methods:{"appetizeio.cli.record.start":async i=>await r.start(i),"appetizeio.cli.record.stop":async()=>await r.stop()},signal:o}),t.save({controlSocket:s}),s}const D="127.0.0.1";async function Ke(e,t,n={}){try{const r=await Be(e,n);return t.save({viewerUrl:r.url.href}),f(`web endpoint listening at ${r.url.href}`),r}catch(r){f(`web endpoint unavailable: ${tt(r)}`);return}}async function Be(e,{port:t=0,signal:n,viewerHtml:r=Z(new URL("./viewer.html",import.meta.url),"utf8")}){n?.throwIfAborted();const o=te((u,l)=>{Xe(u,l,r)}),s=new Set,i=new ne({noServer:!0,perMessageDeflate:!1});let c;i.on("connection",u=>{if(s.size>0){u.close(1013,"Viewer already connected");return}s.add(u);const l=new E(u);k(l,e),u.once("close",()=>{s.delete(u)})}),o.on("upgrade",(u,l,h)=>{Ye(i,u,l,h)});const a=()=>(c??=new Promise((u,l)=>{n?.removeEventListener("abort",d);for(const h of s)Ze(h);i.close(),o.close(h=>{h?l(h):u()})}),c),d=()=>{a()};await et(o,t),n?.addEventListener("abort",d,{once:!0});const p=o.address();if(!p||typeof p=="string")throw await a(),new Error("Web address unavailable");return{close:a,url:new URL(`http://${D}:${String(p.port)}/`)}}function Ze(e){e.close(1001)}function Xe(e,t,n){if(e.method==="GET"&&e.url==="/"){t.writeHead(200,{"Cache-Control":"no-store","Content-Type":"text/html; charset=utf-8"}),t.end(n);return}t.writeHead(404).end()}function Ye(e,t,n,r){if(t.url!=="/ws"){n.destroy();return}e.handleUpgrade(t,n,r,o=>{e.emit("connection",o,t)})}function et(e,t){return new Promise((n,r)=>{const o=s=>{r(s)};e.once("error",o),e.listen(t,D,()=>{e.removeListener("error",o),n()})})}function tt(e){return e instanceof Error?e.message:String(e)}function nt(e){const t=new AbortController,n=rt(e,t),r=K();return r.addEventListener("abort",()=>{const{reason:o}=r;n(o instanceof Error?o.message:String(o))},{once:!0}),{shutdown:n,signal:t.signal}}function rt(e,t){let n=!1;return r=>{n||(n=!0,e.save({endedAt:new Date().toISOString(),endedReason:r,state:{phase:"ended"}}),f(r),t.abort())}}async function q(e,t,{label:n,signal:r}){try{const o=await e();await re(o.readable.pipeThrough(ot()),X(t,{flags:"a"}))}catch(o){if(r?.aborted)return;const s=o instanceof Error?o.message:String(o);f(`${n} ended with an error: ${s}`)}}function ot(){return new TransformStream({transform:(e,t)=>{t.enqueue(`${JSON.stringify(e)}
|
|
2
|
-
`)}})}async function st(e,t,{signal:n}={}){await
|
|
1
|
+
import{T as M,B as L,C as O,E as b,F as _,D as z,G as F,H as V,I as N,n as j,J as H,K as J,L as Q,M as k,N as G,O as K}from"./config-D0ukqfLN.js";import S from"debug";import{createServer as A}from"node:net";import{pipeline as $}from"node:stream";import{rm as B}from"node:fs/promises";import{readFileSync as Z,createWriteStream as X,existsSync as Y,rmSync as ee}from"node:fs";import{createServer as te}from"node:http";import{WebSocketServer as ne}from"ws";import{pipeline as re}from"node:stream/promises";import{EncodedVideoPacketSource as oe,Output as se,FilePathTarget as ie,Mp4OutputFormat as ae,EncodedPacket as ce}from"mediabunny";import"stream";import"module";import"json-rpc-2.0";import"node:os";import"node:path";const de=S("appetize.io:transport:ws-ping"),ue=3e4;function le(e){let t=!0;const n=()=>{t=!0};e.on("pong",n);const r=setInterval(()=>{if(!t){clearInterval(r),de("liveness ping went unanswered, terminating"),e.terminate();return}e.readyState===e.OPEN&&(t=!1,e.ping())},ue);return{destroy(){clearInterval(r),e.off("pong",n)},pong:n}}const v=S("appetize.io:trace:transport:websocket");class E extends M{constructor(t,{signal:n}={}){super(async o=>{this.#e.send(L(o))},{signal:n}),this.wsOrUrl=t,typeof t=="string"?(this.#e=new WebSocket(t),this.#e.binaryType="arraybuffer"):this.#e=t;const r=this.#e;if(r instanceof WebSocket?(r.addEventListener("open",this.#s),r.addEventListener("message",this.#o),r.addEventListener("error",this.#r),r.addEventListener("close",this.#n),this.#t.push(()=>{r.removeEventListener("open",this.#s),r.removeEventListener("message",this.#o),r.removeEventListener("error",this.#r),r.removeEventListener("close",this.#n)})):(r.addEventListener("open",this.#s),r.addEventListener("message",this.#o),r.addEventListener("error",this.#r),r.addEventListener("close",this.#n),this.#t.push(()=>{r.removeEventListener("open",this.#s),r.removeEventListener("message",this.#o),r.removeEventListener("error",this.#r),r.removeEventListener("close",this.#n)})),this.send=r.send.bind(r),"ping"in r){const{destroy:o,pong:s}=le(r);this.#c=s,this.#t.push(o)}}wsOrUrl;onclose;onerror;onmessage;onopen;send;get bufferedAmount(){return this.#e.bufferedAmount}get readyState(){return this.#e.readyState}#t=[];#i=!1;#a=!1;#c;#e;close({destroyWs:t=!1,...n}={}){this.closed||(this.#i=t,super.close(n))}handleClose(t){v("close()");for(const n of this.#t.splice(0))n();if((typeof this.wsOrUrl=="string"||this.#i)&&(this.#e.close(t.code,t.reason),"terminate"in this.#e)){const n=this.#e;setTimeout(()=>{n.terminate()},100)}this.#d(),super.handleClose(t)}#d(t){this.#a||(this.#a=!0,this.onclose?.(t))}#n=t=>{v("handleWebSocketClose()",t);try{this.#d(t)}finally{this.close()}};#r=t=>{v("handleWebSocketError()",t),this.onerror?.(t)};#o=async t=>{v("handleWebSocketMessage()",t),this.#c?.();const n=this.#u(t);if(!n){v("handleWebSocketMessage() -> legacy"),this.onmessage?.(t);return}v("handleWebSocketMessage() -> jsonrpc",n),this[O].dispatchMessage(n)};#s=t=>{v("handleWebSocketOpen()",t),this.onopen?.(t)};#u(t){try{const n=b(new Uint8Array(t.data));return _(n)?n:null}catch{return null}}}function y(e){return typeof e=="object"&&e!==null}function R(e){try{const t=b(new Uint8Array(e.data));if(y(t)&&typeof t.name=="string")return{name:t.name,payload:"payload"in t?t.payload:void 0}}catch{}}async function fe(e,t={}){const n=t.baseUrl??(typeof e=="string"?new URL(e).origin:void 0),r=typeof e=="string"?new E(e,{signal:t.signal}):e,o=new z(r,{...t,baseUrl:n});return typeof e=="string"&&await pe(r,o,t),o}function pe(e,t,n){const r=F(n)?.onLegacyMessage;return new Promise((o,s)=>{e.onopen=()=>{o()},e.onclose=()=>{t.close(),n.signal?.aborted?s(n.signal.reason):s(new Error("The websocket was closed before the device connection was established"))},e.onerror=s,e.onmessage=i=>{const c=R(i);c&&r?.(c)}})}async function he(e,{device:t,onStateChange:n,signal:r}){r?.throwIfAborted(),n?.({device:t,phase:"starting"}),await new Promise((o,s)=>{const i=()=>{c(),s(r?.reason)},c=()=>{e.onmessage=void 0,e.onclose=void 0,r?.removeEventListener("abort",i)};e.onmessage=a=>{const d=we(R(a),t);d&&(n?.(d),d.phase==="ready"&&(c(),o()))},e.onclose=()=>{c(),s(new Error("The device closed before it was ready"))},r?.addEventListener("abort",i,{once:!0})})}function we(e,t){if(!e)return;if(e.name==="ready")return{device:t,phase:"ready"};if(e.name!=="launchStatus")return;switch(y(e.payload)&&typeof e.payload.status=="string"?e.payload.status:void 0){case"downloadingApp":return{device:t,phase:"downloadingApp"};case"installingApp":return{device:t,phase:"installingApp"};case"launchingApp":return{device:t,phase:"launchingApp"};default:return}}function ve(){return typeof process>"u"?void 0:process}function ge(e){return{deviceType:e.id,osVersion:e.osVersion}}function ye(e){return e==="intercept"?"interceptOnDemand":e}class g extends Error{code;constructor(t,n){super(n),this.name="SessionRequestError",this.code=t}}function me(e,{onClose:t,onEvent:n,signal:r}={}){return new Promise((o,s)=>{const i=new WebSocket(e);i.binaryType="arraybuffer",i.onopen=()=>{P(i,{capabilities:{},t:"handshake"})},i.onmessage=c=>{be(i,c,{onEvent:n,onHandshake:a=>{o({close:()=>{i.close()},id:a})}})},i.onclose=()=>{s(new g("disconnected",`The connection to ${e} closed`)),t?.()},r?.addEventListener("abort",()=>{s(r.reason),i.close()},{once:!0})})}function be(e,t,n){const r=b(new Uint8Array(t.data));y(r)&&(r.t==="handshake"&&typeof r.id=="string"?n.onHandshake(r.id):r.name==="ping"?P(e,{name:"pong"}):typeof r.name=="string"&&n.onEvent?.(r.name,r.payload))}function P(e,t){e.send(L(t))}async function Se(e,t,{apiToken:n,onQueue:r,signal:o}={}){const s=V();ke(s.reject,o);const i=await me(Ae(e),{onClose:()=>{s.reject(Ee())},onEvent:(c,a)=>{Te(c,a,s,r)},signal:o});return Le(e,{apiToken:n,data:t,socketid:i.id},o).catch(s.reject),await s.promise.finally(()=>{i.close()})}function Ee(){return new g("disconnected","The webserver connection closed before a session was granted")}function C(e,t){return y(e)?e[t]:void 0}function Te(e,t,n,r){if(e==="queue"||e==="concurrentQueue"){const o=e==="queue"?Re(t):Pe(t);o&&r?.(o)}else e==="newSession"?$e(n,t):e==="userError"&&n.reject(new g("denied",Ce(t)))}function I(e,t){const n=C(e,t);return typeof n=="number"?n:void 0}function m(e,t){const n=C(e,t);return typeof n=="string"?n:void 0}async function Le(e,t,n){const r=await fetch(new URL("/api/session/request",e),{body:JSON.stringify(t),headers:{"content-type":"application/json"},method:"POST",signal:n});if(!r.ok)throw new g("denied",`The webserver rejected the session request (${String(r.status)})`)}function ke(e,t){t?.addEventListener("abort",()=>{e(t.reason)},{once:!0})}function Ae(e){const t=new URL("/client",e);return t.protocol=t.protocol==="http:"?"ws:":"wss:",t.href}function $e(e,t){const n=m(t,"path"),r=m(t,"sessionToken");n!==void 0&&r!==void 0?e.resolve({path:n,sessionToken:r}):e.reject(new g("denied","The granted session is missing its address"))}function Re(e){const t=I(e,"position");return t===void 0?void 0:{position:t,reason:"capacity"}}function Pe(e){const t=I(e,"position");if(t!==void 0)return{limit:m(e,"name")??"Queue",position:t,reason:"concurrency"}}function Ce(e){return m(e,"message")??"The session request was denied"}async function Ie({apiToken:e=Ue(),codec:t="h264",device:n,endpoint:r="https://appetize.io",onStateChange:o,open:s,proxy:i,signal:c,target:a}){if(c?.throwIfAborted(),!a)throw new TypeError("target is required");if(!n.id)throw new TypeError("device.id is required");o?.({phase:"requesting"});const d=await Se(r,{codec:t,launchUrl:s,noVideo:!0,proxy:ye(i),publicKey:a,...ge(n)},{apiToken:e,onQueue:p=>{o?.({phase:"queued",queue:p})},signal:c});return{baseUrl:new URL(d.path).origin,url:We(d)}}function Ue(){return ve()?.env.APPETIZE_API_TOKEN}function We(e){const t=new URL("/client",e.path);return t.protocol=t.protocol==="http:"?"ws:":"wss:",t.searchParams.set("sessionToken",e.sessionToken),t.href}const De=S("appetize:daemon");function f(e){De(e)}function qe(e,{message:t="The operation timed out"}={}){const n=new AbortController,r=setTimeout(()=>{n.abort(new Error(t))},e),o=()=>{clearTimeout(r)};return{cancel:o,signal:n.signal,[Symbol.dispose]:o}}var xe=(e,t)=>(t=Symbol[e])?t:Symbol.for("Symbol."+e),U=e=>{throw TypeError(e)},Me=(e,t,n)=>{if(t!=null){typeof t!="object"&&typeof t!="function"&&U("Object expected");var r,o;r===void 0&&(r=t[xe("dispose")]),typeof r!="function"&&U("Object not disposable"),o&&(r=function(){try{o.call(this)}catch(s){return Promise.reject(s)}}),e.push([n,r,t])}return t},Oe=(e,t,n)=>{var r=typeof SuppressedError=="function"?SuppressedError:function(i,c,a,d){return d=Error(a),d.name="SuppressedError",d.error=i,d.suppressed=c,d},o=i=>t=n?new r(i,t,"An error was suppressed during disposal"):(n=!0,i),s=i=>{for(;i=e.pop();)try{var c=i[1]&&i[1].call(i[2]);if(i[0])return Promise.resolve(c).then(s,a=>(o(a),s()))}catch(a){o(a)}if(n)throw t};return s()};const _e=1e4;async function ze(e,t,{onClose:n,signal:r}={}){var o=[];try{const c=Me(o,qe(_e,{message:"Timed out waiting for session request state"})),a=AbortSignal.any([r,c.signal].filter(w=>!!w)),d=w=>{t.save({state:w}),f(w.phase),w.phase!=="requesting"&&c.cancel()},{baseUrl:p,url:u}=await Ie({device:e.device,endpoint:e.endpoint,onStateChange:d,open:e.open,proxy:e.proxy,signal:a,target:e.target});t.save({baseUrl:p});const l=new E(u,{signal:a});return await he(l,{device:e.device,onStateChange:d,signal:a}),l.onclose=()=>{n?.("The device connection closed")},{device:await fe(l,{baseUrl:p,signal:a}),transport:l}}catch(c){var s=c,i=!0}finally{Oe(o,s,i)}}function Fe(){const e=N(),t=j(e.sessionId,e.proxy),n=H({device:e.device,endpoint:e.endpoint,open:e.open,pid:process.pid,proxy:e.proxy,sessionId:e.sessionId,startedAt:new Date().toISOString(),target:e.target});return n.save({logs:t}),{config:e,logs:t,store:n}}async function Ve(e,{host:t="127.0.0.1",onError:n,port:r=0,signal:o}={}){o?.throwIfAborted();let s;const i=()=>{const u=s;s=void 0,u&&(u.tunnel?.close(),u.socket.destroy())},c=async u=>{const{socket:l}=u;try{const h=await e.debug.createAdbTunnel();if(l.destroyed){h.close();return}u.tunnel=h,h.closed.catch(w=>{n?.(w)}),Ne(l,h)}catch(h){l.destroyed||n?.(h),l.destroy()}},a=A(u=>{i();const l={socket:u};s=l,u.once("close",()=>{s===l&&(s=void 0)}),c(l)}),d=()=>{o?.removeEventListener("abort",d),i(),a.close()};o?.addEventListener("abort",d,{once:!0});const p=await je(a,t,r);return{close:d,url:new URL(`adb://${p.address}:${String(p.port)}`)}}function Ne(e,t){$(t.readable,e,W),$(e,async n=>{const r=t.writable.getWriter();try{for await(const o of n)await r.write(o);await r.close()}catch(o){throw await r.abort(o),o}},W)}function W(){}function je(e,t,n){return new Promise((r,o)=>{e.once("error",o),e.listen({host:t,port:n},()=>{e.off("error",o);const s=e.address();if(s===null||typeof s=="string"){o(new Error("The listener has no tcp address"));return}r(s)})})}async function He(e,t,n,{signal:r}={}){try{if(!await Je(t))return;const o=await Ve(e,{onError:s=>{f(`adb endpoint error: ${D(s)}`)},signal:r});n.save({adbSerial:o.url.host}),f(`adb endpoint listening at ${o.url.host}`)}catch(o){f(`adb endpoint unavailable: ${D(o)}`)}}async function Je(e){return await J(e.device.id,{endpoint:e.endpoint})==="android"}function D(e){return e instanceof Error?e.message:String(e)}async function Qe(e,t,{methods:n={},signal:r}={}){await B(t,{force:!0});const o=new Set,s=A(i=>{f("control client connected"),o.add(i),i.once("close",()=>{o.delete(i)});const c=new Q(i,{signal:r});k(c,e,{leftEffects:()=>n})});r?.addEventListener("abort",()=>{for(const i of o)i.destroy()},{once:!0}),await new Promise((i,c)=>{s.once("error",c),s.listen({path:t,signal:r},()=>{s.off("error",c),i()})})}async function Ge(e,t,n,{recorder:r,signal:o}){const s=G(n);return await Qe(e,s,{methods:{"appetizeio.cli.record.start":async i=>await r.start(i),"appetizeio.cli.record.stop":async()=>await r.stop()},signal:o}),t.save({controlSocket:s}),s}const q="127.0.0.1";async function Ke(e,t,n={}){try{const r=await Be(e,n);return t.save({viewerUrl:r.url.href}),f(`web endpoint listening at ${r.url.href}`),r}catch(r){f(`web endpoint unavailable: ${tt(r)}`);return}}async function Be(e,{port:t=0,signal:n,viewerHtml:r=Z(new URL("./viewer.html",import.meta.url),"utf8")}){n?.throwIfAborted();const o=te((u,l)=>{Xe(u,l,r)}),s=new Set,i=new ne({noServer:!0,perMessageDeflate:!1});let c;i.on("connection",u=>{if(s.size>0){u.close(1013,"Viewer already connected");return}s.add(u);const l=new E(u);k(l,e),u.once("close",()=>{s.delete(u)})}),o.on("upgrade",(u,l,h)=>{Ye(i,u,l,h)});const a=()=>(c??=new Promise((u,l)=>{n?.removeEventListener("abort",d);for(const h of s)Ze(h);i.close(),o.close(h=>{h?l(h):u()})}),c),d=()=>{a()};await et(o,t),n?.addEventListener("abort",d,{once:!0});const p=o.address();if(!p||typeof p=="string")throw await a(),new Error("Web address unavailable");return{close:a,url:new URL(`http://${q}:${String(p.port)}/`)}}function Ze(e){e.close(1001)}function Xe(e,t,n){if(e.method==="GET"&&e.url==="/"){t.writeHead(200,{"Cache-Control":"no-store","Content-Type":"text/html; charset=utf-8"}),t.end(n);return}t.writeHead(404).end()}function Ye(e,t,n,r){if(t.url!=="/ws"){n.destroy();return}e.handleUpgrade(t,n,r,o=>{e.emit("connection",o,t)})}function et(e,t){return new Promise((n,r)=>{const o=s=>{r(s)};e.once("error",o),e.listen(t,q,()=>{e.removeListener("error",o),n()})})}function tt(e){return e instanceof Error?e.message:String(e)}function nt(e){const t=new AbortController,n=rt(e,t),r=K();return r.addEventListener("abort",()=>{const{reason:o}=r;n(o instanceof Error?o.message:String(o))},{once:!0}),{shutdown:n,signal:t.signal}}function rt(e,t){let n=!1;return r=>{n||(n=!0,e.save({endedAt:new Date().toISOString(),endedReason:r,state:{phase:"ended"}}),f(r),t.abort())}}async function x(e,t,{label:n,signal:r}){try{const o=await e();await re(o.readable.pipeThrough(ot()),X(t,{flags:"a"}))}catch(o){if(r?.aborted)return;const s=o instanceof Error?o.message:String(o);f(`${n} ended with an error: ${s}`)}}function ot(){return new TransformStream({transform:(e,t)=>{t.enqueue(`${JSON.stringify(e)}
|
|
2
|
+
`)}})}async function st(e,t,{signal:n}={}){await x(async()=>await e.debug.createLogStream({signal:n}),t,{label:"log capture",signal:n})}async function it(e,t,{signal:n}={}){await x(async()=>await e.debug.createProxyInterceptStream({signal:n}),t,{label:"network capture",signal:n})}const T=30;async function at(e,t){await e.pipeTo(dt(t))}function ct(e){return{decoderConfig:{codec:"avc1.640028",codedHeight:e.height,codedWidth:e.width}}}function dt(e){let t;const n=async()=>{await t?.output.finalize()};return new WritableStream({abort:n,close:n,write:async r=>{r.data.byteLength!==0&&(t??=await ut(ft(r),e),lt(t,r),await pt(t,r))}})}async function ut(e,t){const n=new oe("avc"),r=new se({format:new ae({fastStart:"fragmented"}),target:new ie(t,{chunked:!1})});return r.addVideoTrack(n,{frameRate:T}),await r.start(),{frame:0,output:r,seen:{height:e.height,width:e.width},size:{height:e.height,width:e.width},source:n}}function lt(e,t){if(t.type!=="key")return;const{seen:n,size:r}=e;t.width===n.width&&t.height===n.height||(e.seen={height:t.height,width:t.width},f(`video resized to ${String(t.width)}x${String(t.height)}; keeping ${String(r.width)}x${String(r.height)}`))}function ft(e){if(e.type!=="key")throw new Error("Video stream started without a key chunk");return e}async function pt(e,t){const n=new ce(t.data,t.type,e.frame/T,1/T);e.frame+=1,await e.source.add(n,ct(e.size))}function ht(e,t,{signal:n}={}){let r,o;const s=async(a,{force:d=!1}={})=>{if(Y(a)){if(!d)throw new Error(`A recording already exists at ${a}; pass --force to overwrite`);ee(a)}const p=await e.video.createStream({signal:n});return r={done:wt(p,a),path:a,stream:p},t.save({video:{path:a,recording:!0}}),f(`recording video to ${a}`),{path:a}},i=async a=>{a.stream.close();try{await a.done,t.save({video:{path:a.path,recording:!1}})}finally{r=void 0,o=void 0}},c=async()=>{if(!r)return;const{path:a}=r;await i(r),f(`closed the video recording: ${a}`)};return n?.addEventListener("abort",()=>{c()},{once:!0}),{start:async({force:a=!1,path:d})=>{const p=r?.path??o;if(p!==void 0)throw new Error(`Already recording to ${p}`);o=d;try{return await s(d,{force:a})}finally{o=void 0}},stop:async()=>{if(!r)throw new Error("No video recording in progress");const{path:a}=r;return await i(r),{path:a}}}}async function wt(e,t){try{await at(e.readable,t)}catch(n){f(`video capture ended with an error: ${String(n)}`)}}async function vt(){const{config:e,logs:t,store:n}=Fe();f(`recording to ${n.path}`);const{shutdown:r,signal:o}=nt(n);try{const{device:s,transport:i}=await ze(e,n,{onClose:r,signal:o}),c=ht(s,n,{signal:o});await He(s,e,n,{signal:o}),await Ke(i,n,{signal:o});const a=await Ge(i,n,e.sessionId,{recorder:c,signal:o});f(`control socket listening at ${a}`),st(s,t.device,{signal:o}),f(`recording device logs to ${t.device}`),t.network&&(it(s,t.network,{signal:o}),f(`recording network events to ${t.network}`))}catch(s){if(o.aborted)return;const i=s instanceof Error?s.message:String(s);n.save({endedAt:new Date().toISOString(),endedReason:i,state:{message:i,phase:"error"}}),f(`error: ${i}`),process.exitCode=1}}vt();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appetize/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "Run, inspect and control iOS and Android apps on Appetize cloud devices",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"homepage": "https://appetize.io",
|
|
@@ -28,11 +28,13 @@
|
|
|
28
28
|
"appetize": "cli.js"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
+
"cli-table3": "^0.6.5",
|
|
31
32
|
"debug": "^4.4.3",
|
|
32
33
|
"human-id": "^4.2.1",
|
|
33
|
-
"json-rpc-2.0": "^1.8.
|
|
34
|
-
"mediabunny": "^1.
|
|
34
|
+
"json-rpc-2.0": "^1.8.1",
|
|
35
|
+
"mediabunny": "^1.58.1",
|
|
35
36
|
"sade": "^1.8.1",
|
|
36
|
-
"ws": "^8.21.3"
|
|
37
|
+
"ws": "^8.21.3",
|
|
38
|
+
"yocto-spinner": "^1.2.2"
|
|
37
39
|
}
|
|
38
40
|
}
|