@inkly-org/cli 0.6.0 → 0.6.1
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/README.md +4 -6
- package/dist/capture-listener.js +9 -9
- package/dist/cli.js +129 -125
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,11 +18,9 @@ Your demos are **yours, as code**, living right next to your product. Scaffold a
|
|
|
18
18
|
npm install -g @inkly-org/cli
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
npx @inkly-org/cli init my-hub
|
|
25
|
-
```
|
|
21
|
+
Use the installed `inkly` binary for all commands. Avoid running Inkly through
|
|
22
|
+
`npx`, especially capture commands, because one-off execution can resolve
|
|
23
|
+
Chrome differently and cause browser launch failures.
|
|
26
24
|
|
|
27
25
|
## Quick start
|
|
28
26
|
|
|
@@ -91,4 +89,4 @@ The CLI is one of Inkly's three authoring surfaces — alongside the visual edit
|
|
|
91
89
|
|
|
92
90
|
## License
|
|
93
91
|
|
|
94
|
-
Proprietary. © Inkly. All rights reserved.
|
|
92
|
+
Proprietary. © Inkly. All rights reserved.
|
package/dist/capture-listener.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import vt from"mri";import{spawn as Ke}from"child_process";import{createHash as
|
|
2
|
+
import vt from"mri";import{spawn as Ke,execFile as Ot}from"child_process";import{createHash as Ht,randomUUID as jt}from"crypto";import{mkdir as O,mkdtemp as Wt,open as zt,readFile as F,readdir as Vt,rm as Ze,writeFile as U}from"fs/promises";import{existsSync as de}from"fs";import{dirname as pe,isAbsolute as Zt,join as y,resolve as Je,sep as Jt}from"path";import{tmpdir as Yt,homedir as qe}from"os";import{fileURLToPath as Ye}from"url";import{unzipSync as en,zipSync as tn}from"fflate";import Xe from"ws";import sn from"sharp";import an from"subset-font";import{zipSync as At}from"fflate";import{JSDOM as dn}from"jsdom";import{randomUUID as xe}from"crypto";import{mkdir as Te,readFile as Ie,writeFile as _e}from"fs/promises";import{dirname as Ee,join as Le}from"path";import{homedir as De}from"os";import{PostHog as Ue}from"posthog-node";var ne=process.env.NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN??process.env.POSTHOG_PROJECT_TOKEN??"phc_Dmh4w8YFNosi3YHD4Sv7ShHX7ccS8kmtRcm8XSVmB5jT",Re=process.env.NEXT_PUBLIC_POSTHOG_HOST??process.env.POSTHOG_HOST??"https://us.i.posthog.com",$e="@inkly-org/cli@0.5.1",V=Le(De(),".inkly","analytics.json"),te=null,$=null,re=null;function Me(){return!!ne&&process.env.INKLY_TELEMETRY_DISABLED!=="1"}function Ne(){return Me()?(te??=new Ue(ne,{host:Re,flushAt:1,flushInterval:0}),te):null}async function Oe(){try{let e=await Ie(V,"utf8");return JSON.parse(e)}catch{return{}}}async function Fe(e){await Te(Ee(V),{recursive:!0}),await _e(V,JSON.stringify(e,null,2)+`
|
|
3
3
|
`,{encoding:"utf8",mode:384})}async function He(){return $||($=(async()=>{let e=await Oe();if(typeof e.platformUserId=="string"&&e.platformUserId&&(re=e.platformUserId),typeof e.distinctId=="string"&&e.distinctId)return e.distinctId;let r=`cli_${xe()}`;return await Fe({...e,distinctId:r}),r})(),$)}async function je(){let e=await He();return re??e}function Be(){return{surface:"cli",release:process.env.POSTHOG_RELEASE??$e,node_version:process.versions.node,platform:process.platform,arch:process.arch,ci:!!process.env.CI}}async function ie(e,r={}){let i=Ne();if(i)try{i.capture({distinctId:await je(),event:e,properties:{...Be(),...r}})}catch{}}import{mkdir as We,rename as ze,writeFile as Ve}from"fs/promises";import{dirname as Ge}from"path";async function se(e,r,i){await We(Ge(e),{recursive:!0});let t=`${e}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await Ve(t,r,i?.mode!=null?{mode:i.mode}:void 0),await ze(t,e)}var me=`Options:
|
|
4
4
|
--url <url> URL to open and arm for recording.
|
|
5
5
|
--name <name> Demo name written into the exported ZIP.
|
|
@@ -39,7 +39,7 @@ ${me}
|
|
|
39
39
|
Output:
|
|
40
40
|
Every subcommand prints JSON. This command does not accept prompts and does not plan or drive the page.
|
|
41
41
|
For self-contained HTML snapshot capture, use \`inkly capture-html\`.
|
|
42
|
-
`,
|
|
42
|
+
`,fn=`inkly capture-html - capture a self-contained HTML walkthrough for an external browser agent
|
|
43
43
|
|
|
44
44
|
Usage:
|
|
45
45
|
inkly capture-html start --url <url> --name <name>
|
|
@@ -56,7 +56,7 @@ Output:
|
|
|
56
56
|
Every subcommand prints JSON. This command does not accept prompts and does not plan or drive the page.
|
|
57
57
|
`,oe=pe(Ye(import.meta.url));var fe=1440,ge=900;var he=4e3,M=30,ae=480,et=7e3,tt=20,nt=1200,rt=1500;function T(e){return new Promise(r=>setTimeout(r,e))}function it(e,r){if(!Object.prototype.hasOwnProperty.call(e,r))return;let i=e[r];return typeof i=="string"?i:""}function st(e){return{click_tag:e?.tag??null,has_click_label:!!e?.label,has_click_selector:!!e?.selector,has_click_alpha_id:!!e?.alphaId}}async function N(e){await ie("inkly_cli_capture_step_captured",{runtime:e.session.runtime??"cli",capture_kind:e.session.cliCaptureKind??e.stepKind,step_kind:e.stepKind,action:e.action,step_count:e.session.cliScreens?.length??null,window_width:e.session.width,window_height:e.session.height,record_video:e.session.cliRecordVideo===!0,auto_apply_zoom:e.session.autoApplyZoom!==!1,...st(e.click)})}function le(e){let r=e.cliScreens??[],i=r[r.length-1]?.kind;return i==="video"||i==="html"?i:"image"}function ot(e,r,i){let t=it(e,r);if(!t)throw new Error(`missing --${r} <value>
|
|
58
58
|
|
|
59
|
-
${i}`);return t}function ce(e,r){let i=Je(e);for(;;){let t=y(i,r);if(de(t))return t;let n=pe(i);if(n===i)return null;i=n}}var I=class{constructor(r){this.nextId=1;this.pending=new Map;this.listeners=new Map;this.ws=new Xe(r,{perMessageDeflate:!1,maxPayload:512*1024*1024}),this.ready=new Promise((i,t)=>{this.ws.once("open",()=>i()),this.ws.once("error",n=>t(n))}),this.ws.on("message",i=>{let t=JSON.parse(i.toString());if(typeof t.id=="number"&&this.pending.has(t.id)){let s=this.pending.get(t.id);if(this.pending.delete(t.id),!s)return;t.error?s.reject(new Error(`${t.error.message??"CDP error"}: ${JSON.stringify(t.error.data??"")}`)):s.resolve(t.result??{});return}if(!t.method)return;let n=this.listeners.get(t.method);if(n)for(let s of n)s(t.params,t.sessionId)})}async send(r,i={},t){await this.ready;let n=this.nextId;this.nextId+=1;let s={id:n,method:r,params:i};return t&&(s.sessionId=t),new Promise((o,d)=>{this.pending.set(n,{resolve:o,reject:d}),this.ws.send(JSON.stringify(s),a=>{a&&(this.pending.delete(n),d(a))})})}on(r,i){let t=this.listeners.get(r)??new Set;return t.add(i),this.listeners.set(r,t),()=>t.delete(i)}close(){try{this.ws.close()}catch{}}};async function
|
|
59
|
+
${i}`);return t}function ce(e,r){let i=Je(e);for(;;){let t=y(i,r);if(de(t))return t;let n=pe(i);if(n===i)return null;i=n}}var I=class{constructor(r){this.nextId=1;this.pending=new Map;this.listeners=new Map;this.ws=new Xe(r,{perMessageDeflate:!1,maxPayload:512*1024*1024}),this.ready=new Promise((i,t)=>{this.ws.once("open",()=>i()),this.ws.once("error",n=>t(n))}),this.ws.on("message",i=>{let t=JSON.parse(i.toString());if(typeof t.id=="number"&&this.pending.has(t.id)){let s=this.pending.get(t.id);if(this.pending.delete(t.id),!s)return;t.error?s.reject(new Error(`${t.error.message??"CDP error"}: ${JSON.stringify(t.error.data??"")}`)):s.resolve(t.result??{});return}if(!t.method)return;let n=this.listeners.get(t.method);if(n)for(let s of n)s(t.params,t.sessionId)})}async send(r,i={},t){await this.ready;let n=this.nextId;this.nextId+=1;let s={id:n,method:r,params:i};return t&&(s.sessionId=t),new Promise((o,d)=>{this.pending.set(n,{resolve:o,reject:d}),this.ws.send(JSON.stringify(s),a=>{a&&(this.pending.delete(n),d(a))})})}on(r,i){let t=this.listeners.get(r)??new Set;return t.add(i),this.listeners.set(r,t),()=>t.delete(i)}close(){try{this.ws.close()}catch{}}};async function C(e,r,i,t=3e4){let n=await e.send("Runtime.evaluate",{expression:i,awaitPromise:!0,returnByValue:!0,timeout:t,userGesture:!0},r);if(n.exceptionDetails)throw new Error(`Runtime.evaluate failed: ${JSON.stringify(n.exceptionDetails)}`);return n.result?.value}async function H(e,r){let t=(await e.send("Target.attachToTarget",{targetId:r,flatten:!0})).sessionId;if(typeof t!="string")throw new Error("Target.attachToTarget returned no sessionId");return t}async function ue(e){return((await e.send("Target.getTargets",{filter:[{type:"page"}]})).targetInfos??[]).filter(t=>t.type==="page")}async function at(e,r){let i=await C(e,r,`JSON.stringify({
|
|
60
60
|
innerWidth: window.innerWidth,
|
|
61
61
|
innerHeight: window.innerHeight,
|
|
62
62
|
outerWidth: window.outerWidth,
|
|
@@ -245,7 +245,7 @@ function selectorFor(el) {
|
|
|
245
245
|
window.addEventListener("scroll", onMotionScroll, true);
|
|
246
246
|
window.addEventListener("wheel", onMotionScroll, true);
|
|
247
247
|
window.addEventListener("touchmove", onMotionScroll, true);
|
|
248
|
-
})();`;async function B(e,r,i=!1){i&&(await e.send("Runtime.addBinding",{name:"__inklyCliCaptureEvent"},r).catch(()=>{}),await e.send("Runtime.addBinding",{name:"__inklyCliCaptureClick"},r).catch(()=>{})),await e.send("Page.addScriptToEvaluateOnNewDocument",{source:K},r),await
|
|
248
|
+
})();`;async function B(e,r,i=!1){i&&(await e.send("Runtime.addBinding",{name:"__inklyCliCaptureEvent"},r).catch(()=>{}),await e.send("Runtime.addBinding",{name:"__inklyCliCaptureClick"},r).catch(()=>{})),await e.send("Page.addScriptToEvaluateOnNewDocument",{source:K},r),await C(e,r,K,5e3).catch(()=>{})}async function W(e,r){await C(e,r,K,5e3).catch(()=>{});let i=await C(e,r,`JSON.stringify({
|
|
249
249
|
viewport: { width: window.innerWidth, height: window.innerHeight },
|
|
250
250
|
sourceUrl: location.href,
|
|
251
251
|
title: document.title || "Captured screen",
|
|
@@ -299,7 +299,7 @@ function selectorFor(el) {
|
|
|
299
299
|
return viaNode(url, options);
|
|
300
300
|
}
|
|
301
301
|
};
|
|
302
|
-
})();`;function dt(e,r){let i,t,n;try{let s=new URL(e);i=s.hostname,t=s.pathname||"/",n=s.protocol==="https:"}catch{return""}return r.filter(s=>{let o=s.domain.replace(/^\./,""),d=i===o||i.endsWith(`.${o}`),a=t.startsWith(s.path||"/"),g=!s.secure||n;return d&&a&&g}).map(s=>`${s.name}=${s.value}`).join("; ")}async function pt(e,r,i,t){let n;try{let s=JSON.parse(i);n=s.id;let o={...s.options?.headers??{}},d=dt(s.url,t);d&&(o.cookie=d),s.options?.referrer&&(o.referer=s.options.referrer);let a=await fetch(s.url,{headers:o,redirect:"follow"}),g=Buffer.from(await a.arrayBuffer()),p={};a.headers.forEach((b,v)=>{p[v]=b});let m={status:a.status,headers:p,data:g.toString("base64")};await
|
|
302
|
+
})();`;function dt(e,r){let i,t,n;try{let s=new URL(e);i=s.hostname,t=s.pathname||"/",n=s.protocol==="https:"}catch{return""}return r.filter(s=>{let o=s.domain.replace(/^\./,""),d=i===o||i.endsWith(`.${o}`),a=t.startsWith(s.path||"/"),g=!s.secure||n;return d&&a&&g}).map(s=>`${s.name}=${s.value}`).join("; ")}async function pt(e,r,i,t){let n;try{let s=JSON.parse(i);n=s.id;let o={...s.options?.headers??{}},d=dt(s.url,t);d&&(o.cookie=d),s.options?.referrer&&(o.referer=s.options.referrer);let a=await fetch(s.url,{headers:o,redirect:"follow"}),g=Buffer.from(await a.arrayBuffer()),p={};a.headers.forEach((b,v)=>{p[v]=b});let m={status:a.status,headers:p,data:g.toString("base64")};await C(e,r,`globalThis.__inklyResolveFetch(${n}, ${JSON.stringify(m)})`,2e4)}catch(s){if(n===void 0)return;await C(e,r,`globalThis.__inklyRejectFetch(${n}, ${JSON.stringify({error:String(s)})})`,2e4).catch(()=>{})}}var G=Math.max(6e4,Number(process.env.INKLY_CAPTURE_TIMEOUT_MS)||24e4);async function mt(e,r,i=!1){let t=await F(lt(),"utf8");await e.send("Network.enable",{},r).catch(()=>{}),await e.send("Runtime.addBinding",{name:Z},r).catch(()=>{});let n=[];try{n=(await e.send("Network.getAllCookies",{},r)).cookies??[]}catch{}let s=e.on("Runtime.bindingCalled",(o,d)=>{if(d!==r)return;let a=o;a.name!==Z||typeof a.payload!="string"||pt(e,r,a.payload,n)});try{await C(e,r,t,3e4),await C(e,r,ut,1e4);let o=await C(e,r,`(async () => {
|
|
303
303
|
const sf = globalThis.__inklySingleFile;
|
|
304
304
|
if (!sf || typeof sf.getPageData !== "function") throw new Error("SingleFile not loaded");
|
|
305
305
|
// initOptions (2nd arg) is forwarded to single-file-core/core/util.js
|
|
@@ -315,10 +315,10 @@ function selectorFor(el) {
|
|
|
315
315
|
]);
|
|
316
316
|
if (typeof data.content === "string") return data.content;
|
|
317
317
|
return new TextDecoder().decode(new Uint8Array(data.content));
|
|
318
|
-
})()`,G+15e3);return String(o)}finally{s()}}async function ft(e,r){if(e.runtime!=="cli")throw new Error("HTML capture is only available for --runtime cli sessions");if(!e.captureDir)throw new Error("CLI capture session has no captureDir");let i=new I(e.browserWsUrl);try{let t=await H(i,e.targetId);await i.send("Page.enable",{},t).catch(()=>{}),await i.send("Runtime.enable",{},t).catch(()=>{}),await B(i,t),await j(i,t,e.targetId,e.width,e.height);let n=await W(i,t),s=await mt(i,t,e.cliBlockVideos===!0),o=(e.cliScreens?.length??0)+1,d=y(e.captureDir,`html-${String(o).padStart(3,"0")}`),a=y(d,"index.html");await O(d,{recursive:!0}),await U(a,s,"utf8");let g={...e,cliScreens:[...e.cliScreens??[],{kind:"html",pngPath:null,htmlPath:a,viewport:n.viewport,naturalSize:n.viewport,sourceUrl:n.sourceUrl,title:n.title,click:r??n.click,scroll:n.scroll,capturedAt:new Date().toISOString()}],tabUrl:n.sourceUrl};return await i.send("Target.detachFromTarget",{sessionId:t}).catch(()=>{}),await
|
|
318
|
+
})()`,G+15e3);return String(o)}finally{s()}}async function ft(e,r){if(e.runtime!=="cli")throw new Error("HTML capture is only available for --runtime cli sessions");if(!e.captureDir)throw new Error("CLI capture session has no captureDir");let i=new I(e.browserWsUrl);try{let t=await H(i,e.targetId);await i.send("Page.enable",{},t).catch(()=>{}),await i.send("Runtime.enable",{},t).catch(()=>{}),await B(i,t),await j(i,t,e.targetId,e.width,e.height);let n=await W(i,t),s=await mt(i,t,e.cliBlockVideos===!0),o=(e.cliScreens?.length??0)+1,d=y(e.captureDir,`html-${String(o).padStart(3,"0")}`),a=y(d,"index.html");await O(d,{recursive:!0}),await U(a,s,"utf8");let g={...e,cliScreens:[...e.cliScreens??[],{kind:"html",pngPath:null,htmlPath:a,viewport:n.viewport,naturalSize:n.viewport,sourceUrl:n.sourceUrl,title:n.title,click:r??n.click,scroll:n.scroll,capturedAt:new Date().toISOString()}],tabUrl:n.sourceUrl};return await i.send("Target.detachFromTarget",{sessionId:t}).catch(()=>{}),await _(g),g}finally{i.close()}}async function gt(e){await new Promise((r,i)=>{let t=Ke("ffmpeg",e,{stdio:["ignore","ignore","pipe"]}),n=[];t.stderr.on("data",s=>n.push(s)),t.on("error",i),t.on("close",s=>{if(s===0){r();return}i(new Error(`ffmpeg exited ${s}: ${Buffer.concat(n).toString("utf8").slice(-2e3)}`))})})}async function ht(e){let r=[...e.frames].sort((h,k)=>h.receivedAt-k.receivedAt),i=[],t=r[0]?.receivedAt;if(t!==void 0){let h=1e3/M,k=t;for(let A of r)A.receivedAt<k&&A!==r[r.length-1]||(i.push(A),k=A.receivedAt+h)}let n=i.slice(-Math.ceil(he/1e3*M)-2),s=n[0]?.receivedAt,o=n[n.length-1]?.receivedAt,d=s!==void 0&&o!==void 0?o-s:0;if(n.length<tt||d<nt||new Set(n.map(h=>h.data)).size<=1)return null;let a=Math.ceil(rt/1e3*M),g=n.length>=a?n:n.concat(Array.from({length:a-n.length},()=>n[n.length-1])),p=y(e.captureDir,`video-${String(e.index).padStart(3,"0")}`);await Ze(p,{recursive:!0,force:!0}).catch(()=>{}),await O(p,{recursive:!0});for(let[h,k]of g.entries())await U(y(p,`frame-${String(h+1).padStart(5,"0")}.png`),Buffer.from(k.data,"base64"));let m=y(p,"poster.png");await U(m,Buffer.from(n[0].data,"base64"));let b=y(e.captureDir,`video-${String(e.index).padStart(3,"0")}.webm`);await gt(["-y","-framerate",String(M),"-i",y(p,"frame-%05d.png"),"-c:v","libvpx-vp9","-pix_fmt","yuv420p","-deadline","realtime","-cpu-used","6",b]);let v=new Uint8Array(await F(m));return{videoPath:b,posterPngPath:m,naturalSize:J(v)??{width:fe,height:ge}}}async function we(e,r,i,t){if(!e.captureDir)throw new Error("CLI capture session has no captureDir");let n=Buffer.from(r,"base64"),s=(e.cliScreens?.length??0)+1,o=y(e.captureDir,`screen-${String(s).padStart(3,"0")}.png`);await O(e.captureDir,{recursive:!0}),await U(o,n);let d=J(n)??i.viewport,a={...e,cliScreens:[...e.cliScreens??[],{kind:"image",pngPath:o,viewport:i.viewport,naturalSize:d,sourceUrl:i.sourceUrl,title:i.title,click:t,scroll:i.scroll,capturedAt:new Date().toISOString()}],tabUrl:i.sourceUrl};return await _(a),a}async function wt(e,r,i,t,n){if(e.runtime!=="cli")throw new Error("video capture is only available for --runtime cli sessions");if(!e.captureDir)throw new Error("CLI capture session has no captureDir");let s=t??null,o=null;try{if(!s){o=new I(e.browserWsUrl);let p=await H(o,e.targetId);await o.send("Page.enable",{},p).catch(()=>{}),await o.send("Runtime.enable",{},p).catch(()=>{}),await B(o,p),await j(o,p,e.targetId,e.width,e.height),s=await W(o,p),await o.send("Target.detachFromTarget",{sessionId:p}).catch(()=>{})}let d=(e.cliScreens?.length??0)+1,a=await ht({frames:r,captureDir:e.captureDir,index:d});if(!a)return n&&t?we(e,n,t,i??null):ye(e,void 0,i,"click");let g={...e,cliScreens:[...e.cliScreens??[],{kind:"video",pngPath:a.posterPngPath,videoPath:a.videoPath,posterPngPath:a.posterPngPath,viewport:s.viewport,naturalSize:a.naturalSize,sourceUrl:s.sourceUrl,title:s.title,click:i??s.click,scroll:s.scroll,capturedAt:new Date().toISOString()}],tabUrl:s.sourceUrl};return await _(g),g}finally{o?.close()}}async function ye(e,r,i,t="click"){if(e.runtime!=="cli")throw new Error("capture is only available for --runtime cli sessions");if(!e.captureDir)throw new Error("CLI capture session has no captureDir");let n=new I(e.browserWsUrl);try{let s=await H(n,e.targetId);await n.send("Page.enable",{},s).catch(()=>{}),await n.send("Runtime.enable",{},s).catch(()=>{}),await B(n,s),await j(n,s,e.targetId,e.width,e.height);let o=await W(n,s),a=(await n.send("Page.captureScreenshot",{format:"png",fromSurface:!0,captureBeyondViewport:!1},s)).data;if(typeof a!="string")throw new Error("Page.captureScreenshot returned no data");let g=Buffer.from(a,"base64"),p=(e.cliScreens?.length??0)+1,m=y(e.captureDir,`screen-${String(p).padStart(3,"0")}.png`);await O(e.captureDir,{recursive:!0}),await U(m,g);let b=J(g)??o.viewport,v=t==="click"?i??o.click:null,h=r&&t==="click"?{...v??{x:.5,y:.5},label:r}:v,k={...e,cliScreens:[...e.cliScreens??[],{kind:"image",pngPath:m,viewport:o.viewport,naturalSize:b,sourceUrl:o.sourceUrl,title:o.title,click:h,scroll:o.scroll,capturedAt:new Date().toISOString()}],tabUrl:o.sourceUrl};return await n.send("Target.detachFromTarget",{sessionId:s}).catch(()=>{}),await _(k),k}finally{n.close()}}function be(){return y(process.env.INKLY_CAPTURE_AGENT_HOME||y(qe(),".inkly"),"capture-agent","sessions")}function ve(e){if(!/^[a-zA-Z0-9._:-]+$/.test(e))throw new Error(`invalid session id: ${e}`);return y(be(),`${e}.json`)}function yt(e){return y(be(),`${e}.listener.json`)}async function bt(e){try{let r=await F(yt(e),"utf8");return JSON.parse(r)}catch{return null}}async function _(e){await se(ve(e.id),`${JSON.stringify(e,null,2)}
|
|
319
319
|
`)}async function x(e){let r=await F(ve(e),"utf8");return JSON.parse(r)}async function ke(e){let r=ot(e,"session",Qe),i=await x(r);if(i.runtime!=="cli")throw new Error("listen subcommand is only available for cli runtime sessions");let t=await bt(r),n=new I(i.browserWsUrl),s=null,o=i.targetId,d=Promise.resolve(),a=Promise.resolve(),g=0,p=new Set,m=[],b=!1,v=null,h=null,k=!1;async function A(u){s&&(await n.send("Page.stopScreencast",{},s).catch(()=>{}),await n.send("Target.detachFromTarget",{sessionId:s}).catch(()=>{})),m=[],b=!1,v=null,h=null,o=u,s=await H(n,u),await n.send("Page.enable",{},s).catch(()=>{}),await n.send("Runtime.enable",{},s).catch(()=>{});let w=await x(r).catch(()=>i);await j(n,s,u,w.width,w.height),await B(n,s,!0),m=[],b=!1,v=null,h=null;let c=await x(r).catch(()=>w);c.cliRecordVideo&&c.cliCaptureKind!=="html"&&await n.send("Page.startScreencast",{format:"png",quality:90,maxWidth:c.width,maxHeight:c.height,everyNthFrame:1},s).catch(f=>{process.stderr.write(`capture video start failed: ${f.message}
|
|
320
|
-
`)});let l=await x(r).catch(()=>i);await
|
|
320
|
+
`)});let l=await x(r).catch(()=>i);await _({...l,targetId:u,cliListenerPid:l.cliListenerPid??t?.cliListenerPid??null,cliListenerLogPath:l.cliListenerLogPath??t?.cliListenerLogPath??null,cliListenerReadyAt:l.cliListenerReadyAt??new Date().toISOString()})}async function R(u){k||(k=!0,s&&(await n.send("Page.stopScreencast",{},s).catch(()=>{}),await n.send("Target.detachFromTarget",{sessionId:s}).catch(()=>{})),n.close(),process.exit(u))}process.once("SIGTERM",()=>{R(0)}),process.once("SIGINT",()=>{R(0)}),await n.send("Target.setDiscoverTargets",{discover:!0}).catch(()=>{});for(let u of await ue(n).catch(()=>[]))p.add(u.targetId);await A(i.targetId);{let u=await x(r).catch(()=>i);await _({...u,targetId:o,cliListenerPid:u.cliListenerPid??t?.cliListenerPid??null,cliListenerLogPath:u.cliListenerLogPath??t?.cliListenerLogPath??null,cliListenerReadyAt:u.cliListenerReadyAt??new Date().toISOString()})}n.on("Target.targetCreated",u=>{let c=u.targetInfo;!c||c.type!=="page"||!(c.openerId===o||Date.now()<g)||(a=a.then(async()=>{await T(250),await A(c.targetId),p.add(c.targetId)}).catch(f=>{process.stderr.write(`capture target follow failed: ${f.message}
|
|
321
321
|
`)}))}),n.on("Page.screencastFrame",(u,w)=>{if(w!==s)return;let c=u;typeof c.sessionId=="number"&&n.send("Page.screencastFrameAck",{sessionId:c.sessionId},w).catch(()=>{}),typeof c.data=="string"&&(m.push({data:c.data,receivedAt:Date.now()}),m.length>ae&&(m=m.slice(-ae)))});async function q(){let u=await ue(n).catch(()=>[]),w=u.find(c=>c.openerId===o)??u.find(c=>c.targetId!==o&&!p.has(c.targetId));for(let c of u)p.add(c.targetId);!w||w.targetId===o||await A(w.targetId)}async function Y(u){!u||!s||await n.send("Page.navigate",{url:u},s).catch(w=>{process.stderr.write(`capture post-click navigation failed: ${w.message}
|
|
322
|
-
`)})}n.on("Runtime.bindingCalled",(u,w)=>{if(w!==s)return;let c=u;if(c.name!=="__inklyCliCaptureEvent"&&c.name!=="__inklyCliCaptureClick"||typeof c.payload!="string")return;let l=null;try{let f=JSON.parse(c.payload);c.name==="__inklyCliCaptureClick"?l={type:"click",click:f,page:null}:l={type:f.type==="input"||f.type==="scroll"?f.type:"click",click:typeof f.click=="object"&&f.click?f.click:null,page:typeof f.page=="object"&&f.page?f.page:null}}catch{l=null}if(l){if(l.type==="click")g=Date.now()+3e3;else{let f=Date.now();v=v??f,h=f,b=!0}d=d.then(async()=>{if(l.type!=="click")return;let f=Date.now(),
|
|
323
|
-
`)})}});let
|
|
322
|
+
`)})}n.on("Runtime.bindingCalled",(u,w)=>{if(w!==s)return;let c=u;if(c.name!=="__inklyCliCaptureEvent"&&c.name!=="__inklyCliCaptureClick"||typeof c.payload!="string")return;let l=null;try{let f=JSON.parse(c.payload);c.name==="__inklyCliCaptureClick"?l={type:"click",click:f,page:null}:l={type:f.type==="input"||f.type==="scroll"?f.type:"click",click:typeof f.click=="object"&&f.click?f.click:null,page:typeof f.page=="object"&&f.page?f.page:null}}catch{l=null}if(l){if(l.type==="click")g=Date.now()+3e3;else{let f=Date.now();v=v??f,h=f,b=!0}d=d.then(async()=>{if(l.type!=="click")return;let f=Date.now(),E=v,X=h,Ce=b&&E!==null&&X!==null&&f-X<=et;b=!1,v=null,h=null;let Ae=Math.max(E?E-250:0,f-he),Pe=E?m.filter(S=>S.receivedAt>=Ae):[...m],z=l.page?.navigationUrl??null,L=m.length?m[m.length-1].data:null,D=l.page?{viewport:l.page.viewport,sourceUrl:l.page.url,title:l.page.title,click:l.click,scroll:l.page.scroll}:null;if(s&&(D||(D=await W(n,s).catch(()=>null)),!L)){let S=await n.send("Page.captureScreenshot",{format:"png",fromSurface:!0,captureBeyondViewport:!1},s).catch(()=>null),ee=S&&S.data;L=typeof ee=="string"?ee:null}m=[];let P=await x(r).catch(()=>null);if(!P||P.runtime!=="cli"){await R(0);return}if(P.cliCaptureKind==="html"){await T(z?500:2e3);let S=await ft(P,l.click);await N({session:S,stepKind:"html",action:l.type,click:l.click}),await Y(z),await T(2e3),await a,await q();return}if(await Y(z),await T(2e3),await a,await q(),P.cliRecordVideo&&Ce){let S=await wt(P,Pe,l.click,D??void 0,L);await N({session:S,stepKind:le(S),action:l.type,click:l.click});return}if(L&&D){let S=await we(P,L,D,l.click??null);await N({session:S,stepKind:"image",action:l.type,click:l.click});return}let Q=await ye(P,void 0,l.click,"click");await N({session:Q,stepKind:le(Q),action:l.type,click:l.click})}).catch(f=>{process.stderr.write(`capture listener failed: ${f.message}
|
|
323
|
+
`)})}});let Se=setInterval(()=>{x(r).catch(()=>{clearInterval(Se),R(0)})},1e3);return await new Promise(()=>{}),0}async function kt(){let e=vt(process.argv.slice(2));process.exit(await ke(e))}kt().catch(e=>{process.stderr.write(`capture listener failed: ${e.message}
|
|
324
324
|
`),process.exit(1)});
|