@zenovay/cli 0.1.38 → 0.1.40

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.
Files changed (98) hide show
  1. package/dist/{agency-Ba8f5PMP.js → agency-DYMQrz5e.js} +1 -1
  2. package/dist/{ai-Dz_MAHHV.js → ai-DmxR_lNU.js} +1 -1
  3. package/dist/{alerts-Cxea5iYt.js → alerts-BTG9oRsv.js} +1 -1
  4. package/dist/{analytical-screen-BGMW3z_2.js → analytical-screen-D87giHuD.js} +1 -1
  5. package/dist/analytics-CVIGm-Pz.js +1 -0
  6. package/dist/{api-keys-DyFEtD2q.js → api-keys-Blt-bNJV.js} +1 -1
  7. package/dist/{api-v2-CfYUL93L.js → api-v2-CJiN4L_x.js} +1 -1
  8. package/dist/{api-v2-UJJ6ube8.js → api-v2-DJUWqNhW.js} +1 -1
  9. package/dist/{audit-DqPlGP-B.js → audit-hYEjdAXI.js} +1 -1
  10. package/dist/{banner-gVm7GaJF.js → banner-Cr0PV2pB.js} +1 -1
  11. package/dist/{bar-BPHTpgfb.js → bar-Cjia2R58.js} +1 -1
  12. package/dist/bin.js +5 -5
  13. package/dist/{commands-BrU-VT7M.js → commands-C10MYy2m.js} +1 -1
  14. package/dist/{companies-CH3F-hmU.js → companies-B_782axY.js} +1 -1
  15. package/dist/{completions-Ba0Zr-G3.js → completions-BfHvRZZt.js} +1 -1
  16. package/dist/{data-table-BnWXIW9M.js → data-table-D-JVXhZ7.js} +1 -1
  17. package/dist/{deploys-B79-S9yT.js → deploys-F-MoAZBr.js} +1 -1
  18. package/dist/{devices-BQnWRrD3.js → devices-D3IuyL3T.js} +1 -1
  19. package/dist/{doctor-DjmsSn5Z.js → doctor-BGMQ76yQ.js} +1 -1
  20. package/dist/{domains-B4WXSAV9.js → domains-BubAWKsJ.js} +1 -1
  21. package/dist/{emit-B8RbnBJe.js → emit-NkY7PE3R.js} +1 -1
  22. package/dist/{empty-state-BkS6DKWZ.js → empty-state-BbUJUNcp.js} +1 -1
  23. package/dist/error-codes-BIVN5Cs4.js +1 -0
  24. package/dist/{error-codes-Iig3PBVk.js → error-codes-Bc_l2RPJ.js} +1 -1
  25. package/dist/{errors-CmbIkaPX.js → errors-Bwq_VCFm.js} +1 -1
  26. package/dist/{events-tail-CE5QxNmF.js → events-tail-0phSCPj0.js} +1 -1
  27. package/dist/{export-BhWUB0S0.js → export-Bg9SHfGE.js} +1 -1
  28. package/dist/{funnel-4A9Q_ZCD.js → funnel-C4kZ79_s.js} +1 -1
  29. package/dist/{geo-BAXdGLKJ.js → geo-CMznGaqu.js} +1 -1
  30. package/dist/{globe-DMOyP2MN.js → globe-BZk_6dhW.js} +1 -1
  31. package/dist/{goals-CINA9D6R.js → goals-XCpWOdgc.js} +1 -1
  32. package/dist/{health-DAyE161Z.js → health-CizdEMSG.js} +1 -1
  33. package/dist/health-_zOoA0SB.js +1 -0
  34. package/dist/{heatmaps-DkY7BW0E.js → heatmaps-cV0tljvt.js} +1 -1
  35. package/dist/{home-DL_Ty0eK.js → home-1LkDaQxp.js} +1 -1
  36. package/dist/init-CiRjjHtt.js +1 -0
  37. package/dist/{init-C13-OX68.js → init-DR0qzfwC.js} +2 -2
  38. package/dist/{insights-BDxlGN5s.js → insights-CXhjRCIv.js} +1 -1
  39. package/dist/{integrations-Eu2LbV95.js → integrations-vXJWt6_W.js} +1 -1
  40. package/dist/{journeys-CQMP6cvE.js → journeys-nd4w7bqR.js} +1 -1
  41. package/dist/{keybar-BYQ2Bam1.js → keybar-Bh-y__tC.js} +1 -1
  42. package/dist/{live-BO8Wl0Q3.js → live-DEBxTrIq.js} +1 -1
  43. package/dist/login-351KgPLk.js +1 -0
  44. package/dist/{login-D2ll-nBp.js → login-DvZAZlYo.js} +1 -1
  45. package/dist/{logout-Cp7T5T1Y.js → logout-CRFdvKCc.js} +1 -1
  46. package/dist/{metric-card-DHIjVzNg.js → metric-card-qze7DsPv.js} +1 -1
  47. package/dist/{notes-BsegG0Q-.js → notes-BAACucyo.js} +1 -1
  48. package/dist/{pages-Bi57FO27.js → pages-lLziC-AS.js} +1 -1
  49. package/dist/{plans-BXm8QsVF.js → plans-yzESSjfK.js} +1 -1
  50. package/dist/{profile-GGQyYHdV.js → profile-BRvoBbuR.js} +1 -1
  51. package/dist/{progress-row-C7gQLX4T.js → progress-row-5G_PO8xL.js} +1 -1
  52. package/dist/{projects-t5f3WFmw.js → projects-C1Z-LtgN.js} +1 -1
  53. package/dist/{prompt-Db9Y7CVt.js → prompt-BS9qJvdR.js} +1 -1
  54. package/dist/{query-BmeQkD1w.js → query-CJn5YrPb.js} +1 -1
  55. package/dist/{resolve-site-CZEwJoBj.js → resolve-site-CoOL4KPZ.js} +1 -1
  56. package/dist/{retention-6HhdWwsd.js → retention-DgmJESlQ.js} +1 -1
  57. package/dist/{revenue-CdXv5fdi.js → revenue-B8czxlib.js} +1 -1
  58. package/dist/secrets-M60NENIa.js +1 -0
  59. package/dist/self-test-gNRwOvvZ.js +16 -0
  60. package/dist/{sessions-CvSKjWsw.js → sessions-ii0FyaRs.js} +1 -1
  61. package/dist/{settings-CtEE3MFe.js → settings-B7iVOBd8.js} +1 -1
  62. package/dist/{share-5a0qKu3z.js → share-BHqYwW-L.js} +1 -1
  63. package/dist/{sources-Dtp05gd2.js → sources-DuXdHGqd.js} +1 -1
  64. package/dist/{stats-DRRgb-C3.js → stats-DvCE_0te.js} +1 -1
  65. package/dist/{team-q747Nwe6.js → team-PhCZG-T9.js} +1 -1
  66. package/dist/{teams-nDIrOaly.js → teams-C44Fpvgb.js} +1 -1
  67. package/dist/{themes-DVChFf6Y.js → themes-DXBgDytf.js} +1 -1
  68. package/dist/{tour-Dp2WmQUO.js → tour-CKGqvVm1.js} +1 -1
  69. package/dist/{update-DrsZLYAQ.js → update-BzrtEJGL.js} +1 -1
  70. package/dist/{uptime-Bmg-epd-.js → uptime-Cnsvl4uB.js} +1 -1
  71. package/dist/{usage-ZJK4hekT.js → usage-VhbOYHvU.js} +1 -1
  72. package/dist/{use-SGwWI1Rq.js → use-SKUDK4Ec.js} +1 -1
  73. package/dist/{visitors-D7FmGVz1.js → visitors-KH1Y7SJn.js} +1 -1
  74. package/dist/{vitals-CRE0nVgp.js → vitals-Bb_kw5k7.js} +1 -1
  75. package/dist/{watch-DeWYzdo4.js → watch-CvxGXxpw.js} +1 -1
  76. package/dist/{webhooks-CD7IvAxr.js → webhooks-DPs5-GwW.js} +1 -1
  77. package/dist/{webhooks-forward-X4iUnLrU.js → webhooks-forward-DBGxeHRT.js} +1 -1
  78. package/dist/wizard-bin.js +1 -1
  79. package/dist/{ws-client-Cp_nIj_N.js → ws-client-CUtNWrpp.js} +1 -1
  80. package/package.json +1 -1
  81. package/dist/analytics-5ztZSLLH.js +0 -1
  82. package/dist/health-CAnAYv9x.js +0 -1
  83. package/dist/init-C8KOSKzO.js +0 -1
  84. package/dist/login-CYaCSVUe.js +0 -1
  85. package/dist/secrets-A956dF9B.js +0 -1
  86. package/dist/self-test-Cuuondl2.js +0 -4
  87. /package/dist/{client-CN2wyAL7.js → client-Ckr8RqMm.js} +0 -0
  88. /package/dist/{confirm-Dk3CEdpn.js → confirm-DvIRDrR9.js} +0 -0
  89. /package/dist/{examples-B8b7EpXo.js → examples-BZUH8Wow.js} +0 -0
  90. /package/dist/{fmt-CdJ3NqAG.js → fmt-BQF1s-Qd.js} +0 -0
  91. /package/dist/{formatter-KOe_hjhc.js → formatter-DDG2TSOz.js} +0 -0
  92. /package/dist/{globe-WYN8kVDK.js → globe-CWe_QkQI.js} +0 -0
  93. /package/dist/{panel-jycoT562.js → panel-CYsRlDSL.js} +0 -0
  94. /package/dist/{secrets-BszMfkn1.js → secrets-DPf_7SkN.js} +0 -0
  95. /package/dist/{sparkline-BlAQSlYZ.js → sparkline-DM2BGvjD.js} +0 -0
  96. /package/dist/{tier-uaU5pkTz.js → tier-ztFrvV9H.js} +0 -0
  97. /package/dist/{ui-hZ5oXnwY.js → ui-D0SbjI89.js} +0 -0
  98. /package/dist/{wrapper-Ce_PZUZ9.js → wrapper-BcFl_bdh.js} +0 -0
@@ -1,2 +1,2 @@
1
- import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-UJJ6ube8.js";import{formatTabular as r,selectFormat as i}from"./formatter-KOe_hjhc.js";import"./panel-jycoT562.js";import"./banner-gVm7GaJF.js";import"./prompt-Db9Y7CVt.js";import"./keybar-BYQ2Bam1.js";import{resolveSiteId as a}from"./resolve-site-CZEwJoBj.js";import{DataTable as o}from"./data-table-BnWXIW9M.js";import{runAnalyticalScreen as s}from"./analytical-screen-BGMW3z_2.js";import{Box as c,Text as l}from"ink";import u from"react";function d(e){let t=Math.max(0,Math.floor((Date.now()-new Date(e).getTime())/1e3));return t<60?`${t}s`:t<3600?`${Math.floor(t/60)}m`:t<86400?`${Math.floor(t/3600)}h`:`${Math.floor(t/86400)}d`}async function f(f){if(f.connect){let t=await e(),n=t.apiBase.replace(`api.zenovay.com`,`app.zenovay.com`),r=`${n}/settings/integrations/github`;return process.stdout.write(`\n Connect GitHub to Zenovay:\n ${r}\n\n Open this URL in your browser. Zenovay re-uses the same GitHub\n OAuth app you already authorized for login (auth-zenovay), so\n no separate "Zenovay Deploys" app is needed. Pick the repos you\n want to track and deploys will appear here automatically.\n\n`),0}let p=await e(),m=await t({strict:!1}),h=new n({config:p,cliVersion:f.cliVersion,token:m}),g,_;try{({siteId:g,site:_}=await a(h,{explicit:f.siteId,headless:!!(f.json||f.csv||f.tsv||f.ndjson),cliVersion:f.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let v=i(f),y=f.limit??50,b=[{key:`pushed_at`,label:`when`,width:6,format:e=>d(String(e))},{key:`branch`,label:`branch`,width:14,format:e=>String(e??`—`).slice(0,14)},{key:`commit_sha`,label:`commit`,width:9,format:e=>String(e).slice(0,8)},{key:`commit_author`,label:`author`,width:16,format:e=>String(e??`—`).slice(0,16)},{key:`commit_message`,label:`message`,width:40,format:e=>String(e??`—`).slice(0,40)},{key:`show_on_chart`,label:`chart`,width:5,format:e=>e?`●`:`○`}];return s({cliVersion:f.cliVersion,title:`deploys · ${g}`,commandName:`deploys`,authToken:m?.accessToken??null,refreshIntervalMs:0,fetcher:e=>h.getDeploys(g,{branch:f.branch,since:f.since,limit:y},e),format:v,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){if(t===`ndjson`)for(let t of e.deploys)process.stdout.write(JSON.stringify(t)+`
1
+ import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-DJUWqNhW.js";import{formatTabular as r,selectFormat as i}from"./formatter-DDG2TSOz.js";import"./panel-CYsRlDSL.js";import"./banner-Cr0PV2pB.js";import"./prompt-BS9qJvdR.js";import"./keybar-Bh-y__tC.js";import{resolveSiteId as a}from"./resolve-site-CoOL4KPZ.js";import{DataTable as o}from"./data-table-D-JVXhZ7.js";import{runAnalyticalScreen as s}from"./analytical-screen-D87giHuD.js";import{Box as c,Text as l}from"ink";import u from"react";function d(e){let t=Math.max(0,Math.floor((Date.now()-new Date(e).getTime())/1e3));return t<60?`${t}s`:t<3600?`${Math.floor(t/60)}m`:t<86400?`${Math.floor(t/3600)}h`:`${Math.floor(t/86400)}d`}async function f(f){if(f.connect){let t=await e(),n=t.apiBase.replace(`api.zenovay.com`,`app.zenovay.com`),r=`${n}/settings/integrations/github`;return process.stdout.write(`\n Connect GitHub to Zenovay:\n ${r}\n\n Open this URL in your browser. Zenovay re-uses the same GitHub\n OAuth app you already authorized for login (auth-zenovay), so\n no separate "Zenovay Deploys" app is needed. Pick the repos you\n want to track and deploys will appear here automatically.\n\n`),0}let p=await e(),m=await t({strict:!1}),h=new n({config:p,cliVersion:f.cliVersion,token:m}),g,_;try{({siteId:g,site:_}=await a(h,{explicit:f.siteId,headless:!!(f.json||f.csv||f.tsv||f.ndjson),cliVersion:f.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let v=i(f),y=f.limit??50,b=[{key:`pushed_at`,label:`when`,width:6,format:e=>d(String(e))},{key:`branch`,label:`branch`,width:14,format:e=>String(e??`—`).slice(0,14)},{key:`commit_sha`,label:`commit`,width:9,format:e=>String(e).slice(0,8)},{key:`commit_author`,label:`author`,width:16,format:e=>String(e??`—`).slice(0,16)},{key:`commit_message`,label:`message`,width:40,format:e=>String(e??`—`).slice(0,40)},{key:`show_on_chart`,label:`chart`,width:5,format:e=>e?`●`:`○`}];return s({cliVersion:f.cliVersion,title:`deploys · ${g}`,commandName:`deploys`,authToken:m?.accessToken??null,refreshIntervalMs:0,fetcher:e=>h.getDeploys(g,{branch:f.branch,since:f.since,limit:y},e),format:v,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){if(t===`ndjson`)for(let t of e.deploys)process.stdout.write(JSON.stringify(t)+`
2
2
  `);else process.stdout.write(JSON.stringify(e,null,2));return}process.stdout.write(r(e.deploys,[`pushed_at`,`branch`,`commit_sha`,`commit_author`,`commit_message`,`repository`,`commit_url`,`show_on_chart`],t))},panels:[{id:`summary`,title:`Summary`,render:e=>{let t=e.deploys.filter(e=>e.show_on_chart).length,n=new Set(e.deploys.map(e=>e.repository).filter(e=>!!e));return u.createElement(c,{flexDirection:`column`},u.createElement(l,null,u.createElement(l,{bold:!0},e.total),u.createElement(l,{color:`gray`},` commits`,f.branch?` · branch=${f.branch}`:``)),u.createElement(l,{color:`gray`},u.createElement(l,{color:`magenta`},`● `,t,` on chart`),u.createElement(l,null,` · `),u.createElement(l,null,n.size,` `,n.size===1?`repo`:`repos`)))}},{id:`list`,title:`Recent`,render:e=>e.deploys.length===0?u.createElement(c,{flexDirection:`column`},u.createElement(l,{color:`gray`},`— no commits yet —`),u.createElement(l,{color:`gray`},"Run `zenovay deploys --connect` to wire up the GitHub integration.")):u.createElement(o,{data:e.deploys.slice(0,30),columns:b,headerStyle:`accent`})}]})}export{f as deploysCommand};
@@ -1 +1 @@
1
- import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-UJJ6ube8.js";import"./formatter-KOe_hjhc.js";import{emit as r,isHeadless as i}from"./emit-B8RbnBJe.js";import{Panel as a}from"./panel-jycoT562.js";import{Banner as o}from"./banner-gVm7GaJF.js";import"./prompt-Db9Y7CVt.js";import{Keybar as s}from"./keybar-BYQ2Bam1.js";import{resolveSiteId as c}from"./resolve-site-CZEwJoBj.js";import{DataTable as l}from"./data-table-BnWXIW9M.js";import{EmptyState as u}from"./empty-state-BkS6DKWZ.js";import{Box as d,Text as f,render as p,useApp as m,useInput as h}from"ink";import g,{useEffect as _,useState as v}from"react";import y from"ink-spinner";async function b(a){let o=await e(),s=await t({strict:!1});if(!s)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let l=new n({config:o,cliVersion:a.cliVersion,token:s}),u,d;try{({siteId:u,site:d}=await c(l,{explicit:a.siteId,headless:!!a.json,cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let f=d?.url?d.url.replace(/^https?:\/\//,``).replace(/\/$/,``):d?.name??u;if(i(a)){let e=await l.getDevices(u);return r({type:`devices.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=p(g.createElement(x,{api:l,siteId:u,siteLabel:f,cliVersion:a.cliVersion,onExit:n=>{t(),e(n)}}))})}const x=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:c}=m(),[p,b]=v(null),[x,S]=v(!0),[C,w]=v(null);if(h(e=>{e===`q`&&(c(),i(0))}),_(()=>{let n=!1;return(async()=>{try{let r=await e.getDevices(t);n||(b(r),S(!1))}catch(e){n||(w(e.message),S(!1))}})(),()=>{n=!0}},[e,t]),x)return g.createElement(d,{flexDirection:`column`},g.createElement(o,{version:r,subtitle:`devices · ${n}`}),g.createElement(a,{title:`Loading`,state:`busy`},g.createElement(d,null,g.createElement(f,{color:`magenta`},g.createElement(y,{type:`dots`})),g.createElement(f,null,` Fetching breakdown…`))));if(C)return g.createElement(d,{flexDirection:`column`},g.createElement(o,{version:r,subtitle:`devices · ${n}`}),g.createElement(u,{reason:`error`,headline:`Failed to load`,hint:C}));let T=!p||p.devices.length===0&&p.browsers.length===0&&p.os.length===0;if(T)return g.createElement(d,{flexDirection:`column`},g.createElement(o,{version:r,subtitle:`devices · ${n}`}),g.createElement(u,{reason:`no-data`,headline:`No data yet`,hint:`Visit your site to send the first event`}));let E=[{key:`name`,label:`name`,width:16},{key:`visitors`,label:`visitors`,align:`right`,width:8}];return g.createElement(d,{flexDirection:`column`},g.createElement(o,{version:r,subtitle:`devices · ${n}`}),g.createElement(d,{flexDirection:`row`},g.createElement(a,{title:`Devices`},p.devices.length===0?g.createElement(f,{color:`gray`},`— —`):g.createElement(l,{columns:E,data:p.devices,zebra:!0})),g.createElement(a,{title:`Browsers`},p.browsers.length===0?g.createElement(f,{color:`gray`},`— —`):g.createElement(l,{columns:E,data:p.browsers,zebra:!0})),g.createElement(a,{title:`OS`},p.os.length===0?g.createElement(f,{color:`gray`},`— —`):g.createElement(l,{columns:E,data:p.os,zebra:!0}))),g.createElement(s,{items:[{key:`q`,label:`quit`}]}))};export{b as devicesCommand};
1
+ import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-DJUWqNhW.js";import"./formatter-DDG2TSOz.js";import{emit as r,isHeadless as i}from"./emit-NkY7PE3R.js";import{Panel as a}from"./panel-CYsRlDSL.js";import{Banner as o}from"./banner-Cr0PV2pB.js";import"./prompt-BS9qJvdR.js";import{Keybar as s}from"./keybar-Bh-y__tC.js";import{resolveSiteId as c}from"./resolve-site-CoOL4KPZ.js";import{DataTable as l}from"./data-table-D-JVXhZ7.js";import{EmptyState as u}from"./empty-state-BbUJUNcp.js";import{Box as d,Text as f,render as p,useApp as m,useInput as h}from"ink";import g,{useEffect as _,useState as v}from"react";import y from"ink-spinner";async function b(a){let o=await e(),s=await t({strict:!1});if(!s)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let l=new n({config:o,cliVersion:a.cliVersion,token:s}),u,d;try{({siteId:u,site:d}=await c(l,{explicit:a.siteId,headless:!!a.json,cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let f=d?.url?d.url.replace(/^https?:\/\//,``).replace(/\/$/,``):d?.name??u;if(i(a)){let e=await l.getDevices(u);return r({type:`devices.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=p(g.createElement(x,{api:l,siteId:u,siteLabel:f,cliVersion:a.cliVersion,onExit:n=>{t(),e(n)}}))})}const x=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:c}=m(),[p,b]=v(null),[x,S]=v(!0),[C,w]=v(null);if(h(e=>{e===`q`&&(c(),i(0))}),_(()=>{let n=!1;return(async()=>{try{let r=await e.getDevices(t);n||(b(r),S(!1))}catch(e){n||(w(e.message),S(!1))}})(),()=>{n=!0}},[e,t]),x)return g.createElement(d,{flexDirection:`column`},g.createElement(o,{version:r,subtitle:`devices · ${n}`}),g.createElement(a,{title:`Loading`,state:`busy`},g.createElement(d,null,g.createElement(f,{color:`magenta`},g.createElement(y,{type:`dots`})),g.createElement(f,null,` Fetching breakdown…`))));if(C)return g.createElement(d,{flexDirection:`column`},g.createElement(o,{version:r,subtitle:`devices · ${n}`}),g.createElement(u,{reason:`error`,headline:`Failed to load`,hint:C}));let T=!p||p.devices.length===0&&p.browsers.length===0&&p.os.length===0;if(T)return g.createElement(d,{flexDirection:`column`},g.createElement(o,{version:r,subtitle:`devices · ${n}`}),g.createElement(u,{reason:`no-data`,headline:`No data yet`,hint:`Visit your site to send the first event`}));let E=[{key:`name`,label:`name`,width:16},{key:`visitors`,label:`visitors`,align:`right`,width:8}];return g.createElement(d,{flexDirection:`column`},g.createElement(o,{version:r,subtitle:`devices · ${n}`}),g.createElement(d,{flexDirection:`row`},g.createElement(a,{title:`Devices`},p.devices.length===0?g.createElement(f,{color:`gray`},`— —`):g.createElement(l,{columns:E,data:p.devices,zebra:!0})),g.createElement(a,{title:`Browsers`},p.browsers.length===0?g.createElement(f,{color:`gray`},`— —`):g.createElement(l,{columns:E,data:p.browsers,zebra:!0})),g.createElement(a,{title:`OS`},p.os.length===0?g.createElement(f,{color:`gray`},`— —`):g.createElement(l,{columns:E,data:p.os,zebra:!0}))),g.createElement(s,{items:[{key:`q`,label:`quit`}]}))};export{b as devicesCommand};
@@ -1,4 +1,4 @@
1
- import{readConfig as e}from"./config-CG7B8fR0.js";import"./check-D9G0N7NB.js";import{ApiClient as t}from"./api-CJnD6Auw.js";import{readToken as n}from"./token-store-C1AqhmDP.js";import{parseSseStream as r}from"./client-CN2wyAL7.js";import"./formatter-KOe_hjhc.js";import{emit as i,isHeadless as a}from"./emit-B8RbnBJe.js";import"./panel-jycoT562.js";import{runHealthChecks as o}from"./health-DAyE161Z.js";import{join as s}from"node:path";import{homedir as c,platform as l}from"node:os";import{stat as u}from"node:fs/promises";async function d(){let e=c(),t=l()===`darwin`,n=[{name:`Claude Code`,path:s(e,`.claude`)},{name:`Cursor`,path:t?s(e,`Library`,`Application Support`,`Cursor`):s(e,`.config`,`Cursor`)},{name:`Windsurf`,path:t?s(e,`Library`,`Application Support`,`Windsurf`):s(e,`.config`,`Windsurf`)},{name:`VS Code`,path:s(e,`.vscode`)}];return Promise.all(n.map(async e=>{try{return await u(e.path),{name:e.name,installed:!0,configPath:e.path}}catch{return{name:e.name,installed:!1}}}))}async function f(s){let c=await o({cliVersion:s.cliVersion,binaryPath:s.binaryPath}),l=await d();if(a(s))process.stdout.write(`${JSON.stringify({type:`doctor.agents`,agents:l})}\n`);else{process.stdout.write(`
1
+ import{readConfig as e}from"./config-CG7B8fR0.js";import"./check-D9G0N7NB.js";import{ApiClient as t}from"./api-CJnD6Auw.js";import{readToken as n}from"./token-store-C1AqhmDP.js";import{parseSseStream as r}from"./client-Ckr8RqMm.js";import"./formatter-DDG2TSOz.js";import{emit as i,isHeadless as a}from"./emit-NkY7PE3R.js";import"./panel-CYsRlDSL.js";import{runHealthChecks as o}from"./health-CizdEMSG.js";import{join as s}from"node:path";import{homedir as c,platform as l}from"node:os";import{stat as u}from"node:fs/promises";async function d(){let e=c(),t=l()===`darwin`,n=[{name:`Claude Code`,path:s(e,`.claude`)},{name:`Cursor`,path:t?s(e,`Library`,`Application Support`,`Cursor`):s(e,`.config`,`Cursor`)},{name:`Windsurf`,path:t?s(e,`Library`,`Application Support`,`Windsurf`):s(e,`.config`,`Windsurf`)},{name:`VS Code`,path:s(e,`.vscode`)}];return Promise.all(n.map(async e=>{try{return await u(e.path),{name:e.name,installed:!0,configPath:e.path}}catch{return{name:e.name,installed:!1}}}))}async function f(s){let c=await o({cliVersion:s.cliVersion,binaryPath:s.binaryPath}),l=await d();if(a(s))process.stdout.write(`${JSON.stringify({type:`doctor.agents`,agents:l})}\n`);else{process.stdout.write(`
2
2
  AI Agents:
3
3
  `);for(let e of l){let t=e.installed?`\x1B[32m✔\x1B[0m`:`\x1B[2m✗\x1B[0m`,n=e.installed&&e.configPath?` \x1b[2m${e.configPath}\x1b[0m`:``;process.stdout.write(` ${t} ${e.name}${n}\n`)}process.stdout.write(`
4
4
  `)}let u=c.filter(e=>e.status===`fail`);if(u.length===0)return a(s)||process.stdout.write(`All checks pass — no healing needed.
@@ -1,4 +1,4 @@
1
- import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{emitErrorEnvelope as n}from"./error-codes-Iig3PBVk.js";import{ApiV2Client as r}from"./api-v2-UJJ6ube8.js";import{confirmDestructive as i}from"./confirm-Dk3CEdpn.js";import"./formatter-KOe_hjhc.js";import{emitEnvelope as a,wrapItem as o,wrapList as s}from"./emit-B8RbnBJe.js";import"./panel-jycoT562.js";import"./banner-gVm7GaJF.js";import"./prompt-Db9Y7CVt.js";import{resolveSiteId as c}from"./resolve-site-CZEwJoBj.js";import{fmtNumber as l,formatTable as u,shortId as d}from"./fmt-CdJ3NqAG.js";async function f(i){let o=await e(),f=await t({strict:!1});if(!f)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let p=new r({config:o,cliVersion:i.cliVersion,token:f}),m;try{({siteId:m}=await c(p,{explicit:void 0,headless:!0,cliVersion:i.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let h;try{h=await p.getProjects(m)}catch(e){return n(e,{command:`domains list`})}let g=h.projects??[];if(i.json)return a(s(g,`domains.list`),{legacyKey:`domains`,legacyValue:g}),0;if(g.length===0)return process.stdout.write(`
1
+ import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{emitErrorEnvelope as n}from"./error-codes-Bc_l2RPJ.js";import{ApiV2Client as r}from"./api-v2-DJUWqNhW.js";import{confirmDestructive as i}from"./confirm-DvIRDrR9.js";import"./formatter-DDG2TSOz.js";import{emitEnvelope as a,wrapItem as o,wrapList as s}from"./emit-NkY7PE3R.js";import"./panel-CYsRlDSL.js";import"./banner-Cr0PV2pB.js";import"./prompt-BS9qJvdR.js";import{resolveSiteId as c}from"./resolve-site-CoOL4KPZ.js";import{fmtNumber as l,formatTable as u,shortId as d}from"./fmt-BQF1s-Qd.js";async function f(i){let o=await e(),f=await t({strict:!1});if(!f)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let p=new r({config:o,cliVersion:i.cliVersion,token:f}),m;try{({siteId:m}=await c(p,{explicit:void 0,headless:!0,cliVersion:i.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let h;try{h=await p.getProjects(m)}catch(e){return n(e,{command:`domains list`})}let g=h.projects??[];if(i.json)return a(s(g,`domains.list`),{legacyKey:`domains`,legacyValue:g}),0;if(g.length===0)return process.stdout.write(`
2
2
  No domains tracked yet — add one with \`zenovay domains add <url>\`.
3
3
 
4
4
  `),0;let _=[{key:`isCurrent`,header:``,width:1,format:e=>e?`*`:` `},{key:`name`,header:`name`,width:18,format:e=>String(e??`—`)},{key:`domain`,header:`domain`,width:28,format:e=>String(e??`—`)},{key:`tier`,header:`tier`,width:6,format:e=>String(e??`—`)},{key:`pageviews24h`,header:`24h pv`,width:8,align:`right`,format:e=>l(Number(e??0))},{key:`id`,header:`id`,width:14,format:e=>d(String(e))}];return process.stdout.write(`
@@ -1,2 +1,2 @@
1
- import{formatEvent as e,formatTabular as t}from"./formatter-KOe_hjhc.js";function n(e){return typeof e==`object`&&!!e&&Array.isArray(e._columns)&&Array.isArray(e._rows)}function r(){let e=process.argv;for(let t=0;t<e.length;t++){let n=e[t];if(n){if(n===`--json`)return`json`;if(n===`--csv`)return`csv`;if(n===`--tsv`)return`tsv`;if(n===`--ndjson`)return`ndjson`;if(n===`--format`&&t+1<e.length){let n=(e[t+1]??``).toLowerCase();if(n===`json`||n===`csv`||n===`tsv`||n===`ndjson`)return n}if(n.startsWith(`--format=`)){let e=n.slice(9).toLowerCase();if(e===`json`||e===`csv`||e===`tsv`||e===`ndjson`)return e}}}let t=(process.env.ZENOVAY_FORMAT??``).toLowerCase();return t===`json`||t===`csv`||t===`tsv`||t===`ndjson`?t:`ndjson`}function i(e={}){if(e.json||e.csv||e.tsv||e.ndjson||!process.stdout.isTTY||process.env.CI===`true`||process.env.CI===`1`||process.env.NO_COLOR!=null&&process.env.NO_COLOR!==``)return!0;let t=(process.env.ZENOVAY_FORMAT??``).toLowerCase();return t===`json`||t===`ndjson`||t===`csv`||t===`tsv`}function a(i){let a=r();if(n(i)){process.stdout.write(t(i._rows,i._columns,a));return}if(a===`ndjson`){let e={ts:new Date().toISOString(),...i};process.stdout.write(`${JSON.stringify(e)}\n`);return}process.stdout.write(e({ts:new Date().toISOString(),...i},a))}function o(){let e=process.env.ZENOVAY_CLI_VERSION??`0`,t=process.argv.slice(2).filter(e=>!e.startsWith(`-`)),n=t.join(` `)||`unknown`;return{cliVersion:e,command:n}}function s(e){let t=o(),n={cliVersion:e?.cliVersion??t.cliVersion,command:e?.command??t.command};return e?.siteId&&(n.siteId=e.siteId),e?.teamId&&(n.teamId=e.teamId),e?.cached!==void 0&&(n.cached=e.cached),n}function c(e,t,n){return{type:t,ts:new Date().toISOString(),data:e,meta:s(n)}}function l(e,t,n){return{type:t,ts:new Date().toISOString(),data:{items:e,total:e.length},meta:s(n)}}function u(e,t,n){return{type:t,ts:new Date().toISOString(),data:e,meta:s(n)}}function d(e,t){let n={...e};t?.legacyKey&&(n[t.legacyKey]=t.legacyValue,process.env.ZENOVAY_DEPRECATION_WARN===`1`&&process.stderr.write(`[deprecation] '${t.legacyKey}' top-level key is going away in 0.1.40. Read \`data.items\` instead.\n`)),process.stdout.write(JSON.stringify(n)+`
1
+ import{formatEvent as e,formatTabular as t}from"./formatter-DDG2TSOz.js";function n(e){return typeof e==`object`&&!!e&&Array.isArray(e._columns)&&Array.isArray(e._rows)}function r(){let e=process.argv;for(let t=0;t<e.length;t++){let n=e[t];if(n){if(n===`--json`)return`json`;if(n===`--csv`)return`csv`;if(n===`--tsv`)return`tsv`;if(n===`--ndjson`)return`ndjson`;if(n===`--format`&&t+1<e.length){let n=(e[t+1]??``).toLowerCase();if(n===`json`||n===`csv`||n===`tsv`||n===`ndjson`)return n}if(n.startsWith(`--format=`)){let e=n.slice(9).toLowerCase();if(e===`json`||e===`csv`||e===`tsv`||e===`ndjson`)return e}}}let t=(process.env.ZENOVAY_FORMAT??``).toLowerCase();return t===`json`||t===`csv`||t===`tsv`||t===`ndjson`?t:`ndjson`}function i(e={}){if(e.json||e.csv||e.tsv||e.ndjson||!process.stdout.isTTY||process.env.CI===`true`||process.env.CI===`1`||process.env.NO_COLOR!=null&&process.env.NO_COLOR!==``)return!0;let t=(process.env.ZENOVAY_FORMAT??``).toLowerCase();return t===`json`||t===`ndjson`||t===`csv`||t===`tsv`}function a(i){let a=r();if(n(i)){process.stdout.write(t(i._rows,i._columns,a));return}if(a===`ndjson`){let e={ts:new Date().toISOString(),...i};process.stdout.write(`${JSON.stringify(e)}\n`);return}process.stdout.write(e({ts:new Date().toISOString(),...i},a))}function o(){let e=process.env.ZENOVAY_CLI_VERSION??`0`,t=process.argv.slice(2).filter(e=>!e.startsWith(`-`)),n=t.join(` `)||`unknown`;return{cliVersion:e,command:n}}function s(e){let t=o(),n={cliVersion:e?.cliVersion??t.cliVersion,command:e?.command??t.command};return e?.siteId&&(n.siteId=e.siteId),e?.teamId&&(n.teamId=e.teamId),e?.cached!==void 0&&(n.cached=e.cached),n}function c(e,t,n){return{type:t,ts:new Date().toISOString(),data:e,meta:s(n)}}function l(e,t,n){return{type:t,ts:new Date().toISOString(),data:{items:e,total:e.length},meta:s(n)}}function u(e,t,n){return{type:t,ts:new Date().toISOString(),data:e,meta:s(n)}}function d(e,t){let n={...e};t?.legacyKey&&(n[t.legacyKey]=t.legacyValue,process.env.ZENOVAY_DEPRECATION_WARN===`1`&&process.stderr.write(`[deprecation] '${t.legacyKey}' top-level key is going away in 0.1.40. Read \`data.items\` instead.\n`)),process.stdout.write(JSON.stringify(n)+`
2
2
  `)}export{a as emit,d as emitEnvelope,i as isHeadless,u as wrapItem,l as wrapList,c as wrapSnapshot};
@@ -1 +1 @@
1
- import{useTheme as e}from"./panel-jycoT562.js";import{Box as t,Text as n}from"ink";import r from"react";const i={"no-data":`○`,"tier-gated":`◆`,error:`✗`},a=`https://app.zenovay.com/billing`;function o({headline:o,hint:s,reason:c=`no-data`,cta:l,width:u}){let{theme:d}=e(),f=i[c],p=c===`error`?d.error:c===`tier-gated`?d.accent2:d.muted,m=l??(c===`tier-gated`?`Upgrade → ${a}`:void 0);return r.createElement(t,{flexDirection:`column`,alignItems:`center`,width:u},r.createElement(n,{color:p,bold:!0},f),r.createElement(n,{color:d.typography.title.color,bold:d.typography.title.bold},o),s?r.createElement(n,{color:d.dim},s):null,m?r.createElement(n,{color:d.accent},m):null)}export{o as EmptyState};
1
+ import{useTheme as e}from"./panel-CYsRlDSL.js";import{Box as t,Text as n}from"ink";import r from"react";const i={"no-data":`○`,"tier-gated":`◆`,error:`✗`},a=`https://app.zenovay.com/billing`;function o({headline:o,hint:s,reason:c=`no-data`,cta:l,width:u}){let{theme:d}=e(),f=i[c],p=c===`error`?d.error:c===`tier-gated`?d.accent2:d.muted,m=l??(c===`tier-gated`?`Upgrade → ${a}`:void 0);return r.createElement(t,{flexDirection:`column`,alignItems:`center`,width:u},r.createElement(n,{color:p,bold:!0},f),r.createElement(n,{color:d.typography.title.color,bold:d.typography.title.bold},o),s?r.createElement(n,{color:d.dim},s):null,m?r.createElement(n,{color:d.accent},m):null)}export{o as EmptyState};
@@ -0,0 +1 @@
1
+ import"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import"./token-store-C1AqhmDP.js";import{buildErrorEnvelope as e,emitErrorEnvelope as t,isJsonOutputMode as n,normalizeError as r}from"./error-codes-Bc_l2RPJ.js";export{t as emitErrorEnvelope};
@@ -1,2 +1,2 @@
1
1
  import{ApiError as e}from"./api-CJnD6Auw.js";function t(e){let t=process.env.HOME??process.env.USERPROFILE??``;return t&&e.includes(t)?e.split(t).join(`~`):e}function n(n){if(n instanceof e){let e=n.status,r=t(n.message),i=n.body,a=typeof i==`object`&&!!i&&(i.message??i.error)||void 0,o=a?t(String(a)):r,s=new Set([`auth_required`,`auth_invalid`,`tier_insufficient`,`forbidden`,`not_found`,`validation_failed`,`rate_limited`,`idempotency_replay`,`network_error`,`server_error`,`unknown`]);if(i?.type===`error`&&typeof i.code==`string`&&s.has(i.code))return{type:`error`,code:i.code,message:o,...i.hint?{hint:t(String(i.hint))}:{}};if(e===401){let e=/no\s+token|missing\s+(token|auth)|not\s+(logged|authenticated)/i.test(r);return{type:`error`,code:e?`auth_required`:`auth_invalid`,message:o,hint:e?"Run `zenovay login` to authenticate.":"Your session expired. Run `zenovay login` to re-authenticate."}}if(e===402){let e=i?.upgradeUrl??i?.upgrade_url??`https://app.zenovay.com/billing`;return{type:`error`,code:`tier_insufficient`,message:o,hint:`Upgrade your plan: ${e}`}}if(e===403)return{type:`error`,code:`forbidden`,message:o,hint:`You do not have permission for this action.`};if(e===404)return{type:`error`,code:`not_found`,message:o};if(e===400||e===422)return{type:`error`,code:`validation_failed`,message:o,hint:`Check the command flags and arguments.`};if(e===429)return{type:`error`,code:`rate_limited`,message:o,hint:`You hit a rate limit. Wait a moment and retry.`};if(e===409){let e=/idempot/i.test(r)||/idempot/i.test(String(a??``));return e?{type:`error`,code:`idempotency_replay`,message:o,hint:`Same idempotency key was used for a different request body.`}:{type:`error`,code:`unknown`,message:o}}return e>=500&&e<600?{type:`error`,code:`server_error`,message:o,hint:`Server-side issue. Try again shortly or check status.zenovay.com.`}:{type:`error`,code:`unknown`,message:o}}let r=n,i=r?.code??r?.cause?.code;if(i===`ENOTFOUND`||i===`ECONNREFUSED`||i===`ETIMEDOUT`||i===`EAI_AGAIN`)return{type:`error`,code:`network_error`,message:t(String(r?.message??i)),hint:`Check your internet connection and try again.`};if(n instanceof Error){let e=t(n.message);return/abort/i.test(e),{type:`error`,code:`unknown`,message:e}}return{type:`error`,code:`unknown`,message:typeof n==`string`?t(n):`An unknown error occurred.`}}function r(){let e=process.env.ZENOVAY_CLI_VERSION??`0`,t=process.argv.slice(2).filter(e=>!e.startsWith(`-`)),n=t.join(` `)||`unknown`;return{cliVersion:e,command:n}}function i(e,t){let i=n(e),a=r(),o={cliVersion:t?.cliVersion??a.cliVersion,command:t?.command??a.command,...t};return{...i,ts:new Date().toISOString(),meta:o}}function a(){return!!(process.argv.includes(`--json`)||process.argv.includes(`-q`)||process.argv.includes(`--quiet`)||process.env.ZENOVAY_FORMAT===`json`||process.env.ZENOVAY_FORMAT===`ndjson`||!process.stdout.isTTY||process.env.CI===`true`||process.env.CI===`1`)}function o(e,t){let n=i(e,t);return a()?process.stderr.write(JSON.stringify(n)+`
2
- `):(process.stderr.write(`\n✗ ${n.message}\n`),n.hint&&process.stderr.write(` ${n.hint}\n`)),n.code===`validation_failed`||n.code===`auth_required`?2:1}export{o as emitErrorEnvelope,n as normalizeError};
2
+ `):(process.stderr.write(`\n✗ ${n.message}\n`),n.hint&&process.stderr.write(` ${n.hint}\n`)),n.code===`validation_failed`||n.code===`auth_required`?2:1}export{i as buildErrorEnvelope,o as emitErrorEnvelope,a as isJsonOutputMode,n as normalizeError};
@@ -1,2 +1,2 @@
1
- import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-UJJ6ube8.js";import{formatTabular as r,selectFormat as i}from"./formatter-KOe_hjhc.js";import"./panel-jycoT562.js";import"./banner-gVm7GaJF.js";import"./progress-row-C7gQLX4T.js";import"./prompt-Db9Y7CVt.js";import"./keybar-BYQ2Bam1.js";import{spark as a}from"./sparkline-BlAQSlYZ.js";import{resolveSiteId as o}from"./resolve-site-CZEwJoBj.js";import{DataTable as s}from"./data-table-BnWXIW9M.js";import"./bar-BPHTpgfb.js";import{runAnalyticalScreen as c}from"./analytical-screen-BGMW3z_2.js";import"./ui-hZ5oXnwY.js";import{Box as l,Text as u}from"ink";import d from"react";function f(e,t){return e.length<=t?e:e.slice(0,t-1)+`…`}function p(e){let t=Math.max(0,Math.floor((Date.now()-new Date(e).getTime())/1e3));return t<60?`${t}s`:t<3600?`${Math.floor(t/60)}m`:t<86400?`${Math.floor(t/3600)}h`:`${Math.floor(t/86400)}d`}async function m(m){let h=await e(),g=await t({strict:!1}),_=new n({config:h,cliVersion:m.cliVersion,token:g}),v,y;try{({siteId:v,site:y}=await o(_,{explicit:m.siteId,headless:!!(m.json||m.csv||m.tsv||m.ndjson),cliVersion:m.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let b=i(m),x=m.window??`24h`,S=m.limit??100,C=[{key:`ts`,label:`when`,width:6,format:e=>p(String(e))},{key:`class`,label:`class`,width:18,format:e=>String(e)},{key:`message`,label:`message`,width:42,format:e=>f(String(e??``),42)},{key:`page`,label:`page`,width:24,format:e=>String(e??`—`)},{key:`device`,label:`device`,width:8,format:e=>String(e??`—`)}];return c({cliVersion:m.cliVersion,title:`errors · ${v} · ${x}`,commandName:`errors`,authToken:g?.accessToken??null,refreshIntervalMs:m.watch?3e4:0,fetcher:e=>_.getErrors(v,{window:x,limit:S},e),format:b,headlessEmit:(e,t)=>{let n=m.search?e.errors.filter(e=>e.class.toLowerCase().includes(m.search.toLowerCase())||e.message.toLowerCase().includes(m.search.toLowerCase())):e.errors;if(t===`json`||t===`ndjson`){if(t===`ndjson`)for(let e of n)process.stdout.write(JSON.stringify(e)+`
1
+ import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-DJUWqNhW.js";import{formatTabular as r,selectFormat as i}from"./formatter-DDG2TSOz.js";import"./panel-CYsRlDSL.js";import"./banner-Cr0PV2pB.js";import"./progress-row-5G_PO8xL.js";import"./prompt-BS9qJvdR.js";import"./keybar-Bh-y__tC.js";import{spark as a}from"./sparkline-DM2BGvjD.js";import{resolveSiteId as o}from"./resolve-site-CoOL4KPZ.js";import{DataTable as s}from"./data-table-D-JVXhZ7.js";import"./bar-Cjia2R58.js";import{runAnalyticalScreen as c}from"./analytical-screen-D87giHuD.js";import"./ui-D0SbjI89.js";import{Box as l,Text as u}from"ink";import d from"react";function f(e,t){return e.length<=t?e:e.slice(0,t-1)+`…`}function p(e){let t=Math.max(0,Math.floor((Date.now()-new Date(e).getTime())/1e3));return t<60?`${t}s`:t<3600?`${Math.floor(t/60)}m`:t<86400?`${Math.floor(t/3600)}h`:`${Math.floor(t/86400)}d`}async function m(m){let h=await e(),g=await t({strict:!1}),_=new n({config:h,cliVersion:m.cliVersion,token:g}),v,y;try{({siteId:v,site:y}=await o(_,{explicit:m.siteId,headless:!!(m.json||m.csv||m.tsv||m.ndjson),cliVersion:m.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let b=i(m),x=m.window??`24h`,S=m.limit??100,C=[{key:`ts`,label:`when`,width:6,format:e=>p(String(e))},{key:`class`,label:`class`,width:18,format:e=>String(e)},{key:`message`,label:`message`,width:42,format:e=>f(String(e??``),42)},{key:`page`,label:`page`,width:24,format:e=>String(e??`—`)},{key:`device`,label:`device`,width:8,format:e=>String(e??`—`)}];return c({cliVersion:m.cliVersion,title:`errors · ${v} · ${x}`,commandName:`errors`,authToken:g?.accessToken??null,refreshIntervalMs:m.watch?3e4:0,fetcher:e=>_.getErrors(v,{window:x,limit:S},e),format:b,headlessEmit:(e,t)=>{let n=m.search?e.errors.filter(e=>e.class.toLowerCase().includes(m.search.toLowerCase())||e.message.toLowerCase().includes(m.search.toLowerCase())):e.errors;if(t===`json`||t===`ndjson`){if(t===`ndjson`)for(let e of n)process.stdout.write(JSON.stringify(e)+`
2
2
  `);else process.stdout.write(JSON.stringify({errors:n,total:n.length},null,2));return}process.stdout.write(r(n,[`ts`,`class`,`message`,`page`,`device`,`fingerprint`],t))},panels:[{id:`summary`,title:`Recent errors`,render:e=>{let t=m.search?e.errors.filter(e=>e.class.toLowerCase().includes(m.search.toLowerCase())||e.message.toLowerCase().includes(m.search.toLowerCase())):e.errors,n=new Map,r=Date.now(),i=60;for(let e of t){let t=new Date(e.ts).getTime(),a=Math.floor((r-t)/(60*1e3));if(a<0||a>=i)continue;let o=n.get(e.class)??Array(i).fill(0),s=i-1-a;o[s]+=1,n.set(e.class,o)}let o=[...n.entries()].sort((e,t)=>t[1].reduce((e,t)=>e+t,0)-e[1].reduce((e,t)=>e+t,0)).slice(0,6);return d.createElement(l,{flexDirection:`column`},d.createElement(u,null,d.createElement(u,{bold:!0},t.length),d.createElement(u,{color:`gray`},` errors in `,x)),o.length===0?null:d.createElement(l,{flexDirection:`column`,marginTop:1},o.map(([e,t])=>d.createElement(u,{key:e},d.createElement(u,{color:`red`},e.padEnd(20).slice(0,20)),` `,d.createElement(u,{color:`gray`},a(t,30))))))}},{id:`table`,title:`Detail`,render:e=>{let t=m.search?e.errors.filter(e=>e.class.toLowerCase().includes(m.search.toLowerCase())||e.message.toLowerCase().includes(m.search.toLowerCase())):e.errors;return t.length===0?d.createElement(u,{color:`gray`},`— no errors `,m.search?`matching "${m.search}"`:`in window`,` —`):d.createElement(s,{data:t.slice(0,30),columns:C,headerStyle:`accent`})}}]})}export{m as errorsCommand};
@@ -1,4 +1,4 @@
1
- import{readConfig as e,updateConfig as t}from"./config-CG7B8fR0.js";import{ApiClient as n}from"./api-CJnD6Auw.js";import{readToken as r}from"./token-store-C1AqhmDP.js";import{parseSseStream as i}from"./client-CN2wyAL7.js";import"./formatter-KOe_hjhc.js";import{isHeadless as a}from"./emit-B8RbnBJe.js";import{Panel as o}from"./panel-jycoT562.js";import{Banner as s}from"./banner-gVm7GaJF.js";import{TextInput as c}from"./prompt-Db9Y7CVt.js";import{Keybar as l}from"./keybar-BYQ2Bam1.js";import u from"node:path";import{promises as d}from"node:fs";import f from"node:os";import p from"node:crypto";import{Box as m,Static as h,Text as g,render as _,useApp as v,useInput as y}from"ink";import b,{useEffect as x,useRef as S,useState as C}from"react";const w=new Set([`type`,`page`,`country`,`device`,`user_id`,`sessionId`,`referrer`,`ts`,`url`,`method`,`status`]);function T(e){let t=[],n=0;for(;n<e.length;){let r=e[n];if(/\s/.test(r)){n+=1;continue}if(r===`(`){t.push({kind:`lparen`}),n+=1;continue}if(r===`)`){t.push({kind:`rparen`}),n+=1;continue}if(r===`"`||r===`'`){let i=r,a=n+1,o=``;for(;a<e.length&&e[a]!==i;)e[a]===`\\`&&a+1<e.length?(o+=e[a+1],a+=2):(o+=e[a],a+=1);if(a>=e.length)throw Error(`filter: unterminated string starting at column ${n+1}`);t.push({kind:`string`,value:o}),n=a+1;continue}if(r===`!`&&e[n+1]===`=`){t.push({kind:`op`,value:`!=`}),n+=2;continue}if(r===`!`&&e[n+1]===`~`){t.push({kind:`op`,value:`!~`}),n+=2;continue}if(r===`=`){t.push({kind:`op`,value:`=`}),n+=1;continue}if(r===`~`){t.push({kind:`op`,value:`~`}),n+=1;continue}let i=n;for(;n<e.length&&!/[\s()=!~]/.test(e[n])&&e[n]!==`"`&&e[n]!==`'`;)n+=1;let a=e.slice(i,n);if(a.length===0)throw Error(`filter: unexpected character at column ${i+1}`);let o=a.toUpperCase();o===`AND`?t.push({kind:`and`}):o===`OR`?t.push({kind:`or`}):t.push({kind:`ident`,value:a})}return t}function E(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function D(e,t,n){let r=e==null?``:String(e);switch(t){case`=`:return r===n;case`!=`:return r!==n;case`~`:{let e=new RegExp(E(n),`i`);return e.test(r)}case`!~`:{let e=new RegExp(E(n),`i`);return!e.test(r)}}}function O(e){return e.tokens[e.pos]}function k(e){let t=e.tokens[e.pos];return e.pos+=1,t}function A(e){let t=O(e);if(!t)throw Error(`filter: unexpected end of expression`);if(t.kind===`lparen`){k(e);let t=j(e),n=k(e);if(!n||n.kind!==`rparen`)throw Error(`filter: missing closing ")"`);return t}if(t.kind!==`ident`)throw Error(`filter: expected key, got ${t.kind}`);k(e);let n=t.value;if(!w.has(n))throw Error(`filter: unknown key "${n}". Allowed: ${[...w].join(`, `)}`);let r=k(e);if(!r||r.kind!==`op`)throw Error(`filter: expected operator after "${n}"`);let i=k(e);if(!i||i.kind!==`ident`&&i.kind!==`string`)throw Error(`filter: expected value after operator "${r.value}"`);let a=r.value,o=i.value;return e=>D(e[n],a,o)}function j(e){let t=A(e);for(;;){let n=O(e);if(!n)break;if(n.kind===`and`){k(e);let n=A(e),r=t;t=e=>r(e)&&n(e);continue}if(n.kind===`or`){k(e);let n=A(e),r=t;t=e=>r(e)||n(e);continue}break}return t}function M(e){if(typeof e!=`string`||e.trim().length===0)throw Error(`filter: expression is empty`);let t=T(e);if(t.length===0)throw Error(`filter: expression is empty`);let n={tokens:t,pos:0},r=j(n);if(n.pos!==t.length){let e=n.tokens[n.pos];throw Error(`filter: unexpected trailing token "${N(e)}"`)}return r}function N(e){return e.kind===`ident`||e.kind===`string`||e.kind===`op`?e.value:e.kind}const P=10*1024*1024;var F=class{currentBytes=0;initialized=!1;writeQueue=Promise.resolve();constructor(e,t=P){this.filePath=e,this.maxBytes=t}async init(){if(!this.initialized){this.initialized=!0;try{await d.mkdir(u.dirname(this.filePath),{recursive:!0,mode:448})}catch{}try{let e=await d.stat(this.filePath);this.currentBytes=e.size}catch{this.currentBytes=0}}}append(e){let t=(async()=>{await this.init();let t=e.endsWith(`
1
+ import{readConfig as e,updateConfig as t}from"./config-CG7B8fR0.js";import{ApiClient as n}from"./api-CJnD6Auw.js";import{readToken as r}from"./token-store-C1AqhmDP.js";import{parseSseStream as i}from"./client-Ckr8RqMm.js";import"./formatter-DDG2TSOz.js";import{isHeadless as a}from"./emit-NkY7PE3R.js";import{Panel as o}from"./panel-CYsRlDSL.js";import{Banner as s}from"./banner-Cr0PV2pB.js";import{TextInput as c}from"./prompt-BS9qJvdR.js";import{Keybar as l}from"./keybar-Bh-y__tC.js";import u from"node:path";import{promises as d}from"node:fs";import f from"node:os";import p from"node:crypto";import{Box as m,Static as h,Text as g,render as _,useApp as v,useInput as y}from"ink";import b,{useEffect as x,useRef as S,useState as C}from"react";const w=new Set([`type`,`page`,`country`,`device`,`user_id`,`sessionId`,`referrer`,`ts`,`url`,`method`,`status`]);function T(e){let t=[],n=0;for(;n<e.length;){let r=e[n];if(/\s/.test(r)){n+=1;continue}if(r===`(`){t.push({kind:`lparen`}),n+=1;continue}if(r===`)`){t.push({kind:`rparen`}),n+=1;continue}if(r===`"`||r===`'`){let i=r,a=n+1,o=``;for(;a<e.length&&e[a]!==i;)e[a]===`\\`&&a+1<e.length?(o+=e[a+1],a+=2):(o+=e[a],a+=1);if(a>=e.length)throw Error(`filter: unterminated string starting at column ${n+1}`);t.push({kind:`string`,value:o}),n=a+1;continue}if(r===`!`&&e[n+1]===`=`){t.push({kind:`op`,value:`!=`}),n+=2;continue}if(r===`!`&&e[n+1]===`~`){t.push({kind:`op`,value:`!~`}),n+=2;continue}if(r===`=`){t.push({kind:`op`,value:`=`}),n+=1;continue}if(r===`~`){t.push({kind:`op`,value:`~`}),n+=1;continue}let i=n;for(;n<e.length&&!/[\s()=!~]/.test(e[n])&&e[n]!==`"`&&e[n]!==`'`;)n+=1;let a=e.slice(i,n);if(a.length===0)throw Error(`filter: unexpected character at column ${i+1}`);let o=a.toUpperCase();o===`AND`?t.push({kind:`and`}):o===`OR`?t.push({kind:`or`}):t.push({kind:`ident`,value:a})}return t}function E(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function D(e,t,n){let r=e==null?``:String(e);switch(t){case`=`:return r===n;case`!=`:return r!==n;case`~`:{let e=new RegExp(E(n),`i`);return e.test(r)}case`!~`:{let e=new RegExp(E(n),`i`);return!e.test(r)}}}function O(e){return e.tokens[e.pos]}function k(e){let t=e.tokens[e.pos];return e.pos+=1,t}function A(e){let t=O(e);if(!t)throw Error(`filter: unexpected end of expression`);if(t.kind===`lparen`){k(e);let t=j(e),n=k(e);if(!n||n.kind!==`rparen`)throw Error(`filter: missing closing ")"`);return t}if(t.kind!==`ident`)throw Error(`filter: expected key, got ${t.kind}`);k(e);let n=t.value;if(!w.has(n))throw Error(`filter: unknown key "${n}". Allowed: ${[...w].join(`, `)}`);let r=k(e);if(!r||r.kind!==`op`)throw Error(`filter: expected operator after "${n}"`);let i=k(e);if(!i||i.kind!==`ident`&&i.kind!==`string`)throw Error(`filter: expected value after operator "${r.value}"`);let a=r.value,o=i.value;return e=>D(e[n],a,o)}function j(e){let t=A(e);for(;;){let n=O(e);if(!n)break;if(n.kind===`and`){k(e);let n=A(e),r=t;t=e=>r(e)&&n(e);continue}if(n.kind===`or`){k(e);let n=A(e),r=t;t=e=>r(e)||n(e);continue}break}return t}function M(e){if(typeof e!=`string`||e.trim().length===0)throw Error(`filter: expression is empty`);let t=T(e);if(t.length===0)throw Error(`filter: expression is empty`);let n={tokens:t,pos:0},r=j(n);if(n.pos!==t.length){let e=n.tokens[n.pos];throw Error(`filter: unexpected trailing token "${N(e)}"`)}return r}function N(e){return e.kind===`ident`||e.kind===`string`||e.kind===`op`?e.value:e.kind}const P=10*1024*1024;var F=class{currentBytes=0;initialized=!1;writeQueue=Promise.resolve();constructor(e,t=P){this.filePath=e,this.maxBytes=t}async init(){if(!this.initialized){this.initialized=!0;try{await d.mkdir(u.dirname(this.filePath),{recursive:!0,mode:448})}catch{}try{let e=await d.stat(this.filePath);this.currentBytes=e.size}catch{this.currentBytes=0}}}append(e){let t=(async()=>{await this.init();let t=e.endsWith(`
2
2
  `)?e:`${e}\n`,n=Buffer.byteLength(t,`utf8`);this.currentBytes+n>this.maxBytes&&await this.rotate();try{await d.appendFile(this.filePath,t,{mode:384}),this.currentBytes+=n}catch(e){process.stderr.write(`[scrollback] append failed: ${e.message}\n`)}})();return this.writeQueue=this.writeQueue.then(()=>t,()=>t),t}async rotate(){let e=e=>{if(e===0)return this.filePath;let t=u.parse(this.filePath);return u.join(t.dir,`${t.name}.${e}${t.ext}`)};try{await d.unlink(e(3))}catch{}for(let t=2;t>=0;--t)try{await d.rename(e(t),e(t+1))}catch(n){n.code!==`ENOENT`&&process.stderr.write(`[scrollback] rotate ${e(t)} failed: ${n.message}\n`)}this.currentBytes=0}async close(){await this.writeQueue}};const I=5e3,L=33,R=`─── replay end, live below ───`;async function z(i){if(i.setForwardSecret)return await t({forwardSecret:i.setForwardSecret}),process.stdout.write(`Forward secret saved.
3
3
  `),0;let o=await e(),s=await r({strict:!1});if(!s)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let c=new n({config:o,cliVersion:i.cliVersion,token:s}),l=null;if(i.filter)try{l=M(i.filter)}catch(e){return process.stderr.write(`Invalid --filter expression: ${e.message}\n`),2}if(a(i))return H(c,i,l,o.forwardSecret);let d=i.scrollbackPath??u.join(f.homedir(),`.zenovay`,`events-scrollback.log`);return new Promise(e=>{let{unmount:t}=_(b.createElement(U,{api:c,opts:i,predicate:l,forwardSecret:o.forwardSecret,scrollbackPath:d,onExit:n=>{t(),e(n)}}))})}function B(e){return{raw:JSON.stringify(e),parsed:e}}async function V(e,t,n){let r=JSON.stringify(n),i=p.createHmac(`sha256`,t).update(r).digest(`hex`);try{await fetch(e,{method:`POST`,headers:{"Content-Type":`application/json`,"X-Zenovay-Signature":`sha256=${i}`},body:r})}catch{}}async function H(e,t,n,r){let a=new AbortController;process.on(`SIGINT`,()=>a.abort());let o=()=>new Date().toISOString();try{let s=await e.openEventsStream(t.siteId,a.signal);for await(let e of i(s)){if(e.type===`error`)return process.stdout.write(`${JSON.stringify({ts:o(),type:`error`,code:e.code,message:e.message})}\n`),1;if(e.type===`done`)return 0;let i=e;if(n&&!n(i))continue;process.stdout.write(`${JSON.stringify({ts:o(),...i})}\n`),t.forwardTo&&r&&await V(t.forwardTo,r,{event:e,ts:o(),site_id:t.siteId})}return 0}catch(e){return process.stdout.write(`${JSON.stringify({ts:o(),type:`error`,code:`stream_failed`,message:e.message})}\n`),1}}const U=({api:e,opts:t,predicate:n,forwardSecret:r,scrollbackPath:a,onExit:u})=>{let{exit:f}=v(),p=S([]),_=S(null),[w,T]=C([]),[E,D]=C(null),[O,k]=C(!1),[A,j]=C(null);_.current||=new F(a),y(n=>{if(!O){if(E){D(null);return}if(n===`q`){f(),u(0);return}if(n===`f`){let e=p.current[p.current.length-1];e&&D(e);return}if(n===`w`){k(!0);return}if(n===`r`){G(e,t.siteId,p,j);return}}}),x(()=>{let e=setInterval(()=>{let e=p.current.slice(-100);T(e)},L);return()=>clearInterval(e)},[]),x(()=>{let a=new AbortController,o=!1;return(async()=>{t.replay24h&&await G(e,t.siteId,p,j);try{let s=await e.openEventsStream(t.siteId,a.signal);for await(let e of i(s)){if(o)break;if(e.type===`error`){let t={raw:`[ERR ${e.code}] ${e.message}`};W(p,t),_.current?.append(t.raw);continue}if(e.type===`done`)break;let i=e;if(n&&!n(i))continue;let a=B(e);W(p,a),_.current?.append(a.raw),t.forwardTo&&r&&V(t.forwardTo,r,{event:e,ts:new Date().toISOString(),site_id:t.siteId})}}catch(e){let t={raw:`[DISCONNECT] ${e.message}`};W(p,t)}})(),()=>{o=!0,a.abort(),_.current?.close()}},[e,t.siteId,t.replay24h,t.forwardTo,n,r]);let M=async e=>{let t=e.trim()||`events.ndjson`;try{let e=p.current.map(e=>e.raw).join(`
4
4
  `)+`
@@ -1,4 +1,4 @@
1
- import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{emitErrorEnvelope as n}from"./error-codes-Iig3PBVk.js";import{ApiV2Client as r}from"./api-v2-UJJ6ube8.js";import{requireTier as i}from"./tier-uaU5pkTz.js";import{formatTabular as a}from"./formatter-KOe_hjhc.js";import{emitEnvelope as o,wrapItem as s}from"./emit-B8RbnBJe.js";import"./panel-jycoT562.js";import"./banner-gVm7GaJF.js";import"./prompt-Db9Y7CVt.js";import{resolveSiteId as c}from"./resolve-site-CZEwJoBj.js";import{resolve as l}from"node:path";import{writeFile as u}from"node:fs/promises";function d(e,t,n){return a(e,t,n)}function f(e){let t=(e??`30d`).toLowerCase();return t===`7d`||t===`30d`||t===`90d`?t:`30d`}function p(e,t){t||process.stderr.isTTY&&process.stderr.write(`${e}\n`)}async function m(a){let d=await e(),m=await t({strict:!1}),_=new r({config:d,cliVersion:a.cliVersion,token:m});if(a.type!==`analytics`&&a.type!==`sessions`&&a.type!==`heatmaps`){let e=`Unknown export type '${a.type}'. Use one of: analytics, sessions, heatmaps.`;return a.json?n(Error(e),{command:`export`,cliVersion:a.cliVersion}):(process.stderr.write(`Error: ${e}\n`),2)}let v=a.format===`json`?`json`:`csv`,y=f(a.range),b=!!a.json;if(a.type===`sessions`||a.type===`heatmaps`)try{await i(_,`pro`)}catch(e){return a.json?n(e,{command:`export ${a.type}`,cliVersion:a.cliVersion}):(process.stderr.write(`${e.message}\n`),2)}let x;try{({siteId:x}=await c(_,{explicit:a.siteId,headless:b,cliVersion:a.cliVersion}))}catch(e){return a.json?n(e,{command:`export ${a.type}`,cliVersion:a.cliVersion}):(process.stderr.write(`${e.message}\n`),2)}try{p(`→ Fetching ${a.type} ${y}...`,b);let{rows:e,columns:t}=await h(_,a.type,x,y),n=g(e,t,v),r=a.out?l(process.cwd(),a.out):null;return r?(await u(r,n,`utf8`),a.json?(o(s({rowsWritten:e.length,file:r,format:v,range:y,type:a.type},`export.completed`,{siteId:x,command:`export ${a.type}`,cliVersion:a.cliVersion})),0):(process.stdout.write(`✓ Exported ${e.length} rows to ${r}\n`),0)):(process.stdout.write(n),n.endsWith(`
1
+ import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{emitErrorEnvelope as n}from"./error-codes-Bc_l2RPJ.js";import{ApiV2Client as r}from"./api-v2-DJUWqNhW.js";import{requireTier as i}from"./tier-ztFrvV9H.js";import{formatTabular as a}from"./formatter-DDG2TSOz.js";import{emitEnvelope as o,wrapItem as s}from"./emit-NkY7PE3R.js";import"./panel-CYsRlDSL.js";import"./banner-Cr0PV2pB.js";import"./prompt-BS9qJvdR.js";import{resolveSiteId as c}from"./resolve-site-CoOL4KPZ.js";import{resolve as l}from"node:path";import{writeFile as u}from"node:fs/promises";function d(e,t,n){return a(e,t,n)}function f(e){let t=(e??`30d`).toLowerCase();return t===`7d`||t===`30d`||t===`90d`?t:`30d`}function p(e,t){t||process.stderr.isTTY&&process.stderr.write(`${e}\n`)}async function m(a){let d=await e(),m=await t({strict:!1}),_=new r({config:d,cliVersion:a.cliVersion,token:m});if(a.type!==`analytics`&&a.type!==`sessions`&&a.type!==`heatmaps`){let e=`Unknown export type '${a.type}'. Use one of: analytics, sessions, heatmaps.`;return a.json?n(Error(e),{command:`export`,cliVersion:a.cliVersion}):(process.stderr.write(`Error: ${e}\n`),2)}let v=a.format===`json`?`json`:`csv`,y=f(a.range),b=!!a.json;if(a.type===`sessions`||a.type===`heatmaps`)try{await i(_,`pro`)}catch(e){return a.json?n(e,{command:`export ${a.type}`,cliVersion:a.cliVersion}):(process.stderr.write(`${e.message}\n`),2)}let x;try{({siteId:x}=await c(_,{explicit:a.siteId,headless:b,cliVersion:a.cliVersion}))}catch(e){return a.json?n(e,{command:`export ${a.type}`,cliVersion:a.cliVersion}):(process.stderr.write(`${e.message}\n`),2)}try{p(`→ Fetching ${a.type} ${y}...`,b);let{rows:e,columns:t}=await h(_,a.type,x,y),n=g(e,t,v),r=a.out?l(process.cwd(),a.out):null;return r?(await u(r,n,`utf8`),a.json?(o(s({rowsWritten:e.length,file:r,format:v,range:y,type:a.type},`export.completed`,{siteId:x,command:`export ${a.type}`,cliVersion:a.cliVersion})),0):(process.stdout.write(`✓ Exported ${e.length} rows to ${r}\n`),0)):(process.stdout.write(n),n.endsWith(`
2
2
  `)||process.stdout.write(`
3
3
  `),a.json&&o(s({rowsWritten:e.length,file:null,format:v,range:y,type:a.type},`export.completed`,{siteId:x,command:`export ${a.type}`,cliVersion:a.cliVersion})),0)}catch(e){return a.json?n(e,{command:`export ${a.type}`,cliVersion:a.cliVersion}):(process.stderr.write(`✗ ${e.message}\n`),1)}}async function h(e,t,n,r){if(t===`analytics`){let t=await e.getStats(n,r);if(t.daily&&t.daily.length>0){let e=t.daily.map(e=>({date:e.date,visitors:e.visitors,pageviews:e.pageviews}));return{rows:e,columns:[`date`,`visitors`,`pageviews`]}}let i=[{range:r,visitors:t.visitors,pageviews:t.pageviews,sessions:t.sessions,bounceRate:t.bounceRate,avgSessionSec:t.avgSessionSec,windowStart:t.windowStart,windowEnd:t.windowEnd}];return{rows:i,columns:[`range`,`visitors`,`pageviews`,`sessions`,`bounceRate`,`avgSessionSec`,`windowStart`,`windowEnd`]}}if(t===`sessions`){let t=await e.getSessions(n),r=t.map(e=>({id:e.id,visitor:e.visitor,durationMs:e.duration,startedAt:e.startedAt,pageCount:e.pageCount,deviceType:e.deviceType??``}));return{rows:r,columns:[`id`,`visitor`,`durationMs`,`startedAt`,`pageCount`,`deviceType`]}}let i=await e.getHeatmaps(n),a=i.map(e=>({id:e.id,url:e.url,type:e.type,captureCount:e.captureCount,createdAt:e.createdAt}));return{rows:a,columns:[`id`,`url`,`type`,`captureCount`,`createdAt`]}}function g(e,t,n){if(n===`json`){let n=e.map(e=>{let n={};for(let r of t)n[String(r)]=e[r];return n});return JSON.stringify(n,null,2)+`
4
4
  `}return d(e,t,`csv`)}export{m as exportCommand};
@@ -1,3 +1,3 @@
1
- import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-UJJ6ube8.js";import{formatTabular as r,selectFormat as i}from"./formatter-KOe_hjhc.js";import"./panel-jycoT562.js";import"./banner-gVm7GaJF.js";import"./prompt-Db9Y7CVt.js";import"./keybar-BYQ2Bam1.js";import{resolveSiteId as a}from"./resolve-site-CZEwJoBj.js";import{DataTable as o}from"./data-table-BnWXIW9M.js";import{runAnalyticalScreen as s}from"./analytical-screen-BGMW3z_2.js";import{Box as c,Text as l}from"ink";import u from"react";function d(e,t){let n=Math.round(e*t);return`█`.repeat(Math.max(0,Math.min(t,n)))+`░`.repeat(Math.max(0,t-n))}async function f(f){let m=await e(),h=await t({strict:!1}),g=new n({config:m,cliVersion:f.cliVersion,token:h}),_,v;try{({siteId:_,site:v}=await a(g,{explicit:f.siteId,headless:!!(f.json||f.csv||f.tsv||f.ndjson),cliVersion:f.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let y=i(f);if(!f.funnelId){let e=[{key:`name`,label:`name`,width:30},{key:`stepCount`,label:`steps`,width:6,align:`right`},{key:`id`,label:`id`,width:36,format:e=>String(e).slice(0,36)}];return s({cliVersion:f.cliVersion,title:`funnels · ${_}`,commandName:`funnels`,authToken:h?.accessToken??null,refreshIntervalMs:0,fetcher:e=>g.listFunnels(_,e),format:y,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){process.stdout.write(JSON.stringify(e,null,t===`json`?2:0)),t===`ndjson`&&process.stdout.write(`
1
+ import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-DJUWqNhW.js";import{formatTabular as r,selectFormat as i}from"./formatter-DDG2TSOz.js";import"./panel-CYsRlDSL.js";import"./banner-Cr0PV2pB.js";import"./prompt-BS9qJvdR.js";import"./keybar-Bh-y__tC.js";import{resolveSiteId as a}from"./resolve-site-CoOL4KPZ.js";import{DataTable as o}from"./data-table-D-JVXhZ7.js";import{runAnalyticalScreen as s}from"./analytical-screen-D87giHuD.js";import{Box as c,Text as l}from"ink";import u from"react";function d(e,t){let n=Math.round(e*t);return`█`.repeat(Math.max(0,Math.min(t,n)))+`░`.repeat(Math.max(0,t-n))}async function f(f){let m=await e(),h=await t({strict:!1}),g=new n({config:m,cliVersion:f.cliVersion,token:h}),_,v;try{({siteId:_,site:v}=await a(g,{explicit:f.siteId,headless:!!(f.json||f.csv||f.tsv||f.ndjson),cliVersion:f.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let y=i(f);if(!f.funnelId){let e=[{key:`name`,label:`name`,width:30},{key:`stepCount`,label:`steps`,width:6,align:`right`},{key:`id`,label:`id`,width:36,format:e=>String(e).slice(0,36)}];return s({cliVersion:f.cliVersion,title:`funnels · ${_}`,commandName:`funnels`,authToken:h?.accessToken??null,refreshIntervalMs:0,fetcher:e=>g.listFunnels(_,e),format:y,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){process.stdout.write(JSON.stringify(e,null,t===`json`?2:0)),t===`ndjson`&&process.stdout.write(`
2
2
  `);return}process.stdout.write(r(e.funnels,[`id`,`name`,`stepCount`],t))},panels:[{id:`funnels`,title:`Funnels`,render:t=>t.funnels.length===0?u.createElement(l,{color:`gray`},`— no funnels defined —`):u.createElement(o,{data:t.funnels,columns:e,headerStyle:`accent`})},{id:`hint`,title:`Next`,render:()=>u.createElement(l,{color:`gray`},"Run `zenovay funnel <id>` for drop-off detail.")}]})}let b=f.window??`30d`;return s({cliVersion:f.cliVersion,title:`funnel · ${f.funnelId} · ${b}`,commandName:`funnel`,authToken:h?.accessToken??null,refreshIntervalMs:0,fetcher:e=>g.getFunnel(_,f.funnelId,b,e),format:y,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){process.stdout.write(JSON.stringify(e,null,t===`json`?2:0)),t===`ndjson`&&process.stdout.write(`
3
3
  `);return}process.stdout.write(r(e.steps,[`id`,`name`,`visitors`,`conversions`],t))},panels:[{id:`overview`,title:p(`Overview`),render:e=>u.createElement(c,{flexDirection:`column`},u.createElement(l,{bold:!0},e.name),u.createElement(l,{color:`gray`},e.totalEntries.toLocaleString(),` entries · `,e.totalCompletions.toLocaleString(),` completed (`,(e.conversionRate*100).toFixed(1),`%)`))},{id:`flow`,title:`Flow`,render:e=>{let t=e.totalEntries||1;return u.createElement(c,{flexDirection:`column`},e.steps.map((n,r)=>{let i=n.visitors/t,a=e.steps[r-1],o=a?a.visitors-n.visitors:0,s=a?o/Math.max(1,a.visitors)*100:0;return u.createElement(c,{key:n.id,flexDirection:`column`},a?u.createElement(l,{color:`red`},` `,`↓ drop `,o.toLocaleString(),` (`,s.toFixed(1),`%)`):null,u.createElement(l,null,u.createElement(l,{bold:!0},`${r+1}. ${n.name}`.padEnd(22).slice(0,22)),` `,u.createElement(l,{color:`magenta`},d(i,30)),` `,u.createElement(l,null,(i*100).toFixed(1).padStart(5),`% `),u.createElement(l,{color:`gray`},n.visitors.toLocaleString())))}))}}]})}function p(e){return e}export{f as funnelCommand};
@@ -1 +1 @@
1
- import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-UJJ6ube8.js";import"./formatter-KOe_hjhc.js";import{emit as r,isHeadless as i}from"./emit-B8RbnBJe.js";import{Panel as a}from"./panel-jycoT562.js";import{Banner as o}from"./banner-gVm7GaJF.js";import"./prompt-Db9Y7CVt.js";import{Keybar as s}from"./keybar-BYQ2Bam1.js";import{resolveSiteId as c}from"./resolve-site-CZEwJoBj.js";import{DataTable as l}from"./data-table-BnWXIW9M.js";import{EmptyState as u}from"./empty-state-BkS6DKWZ.js";import{Globe as d}from"./globe-WYN8kVDK.js";import{Box as f,Text as p,render as m,useApp as h,useInput as g}from"ink";import _,{useEffect as v,useState as y}from"react";import b from"ink-spinner";async function x(a){let o=await e(),s=await t({strict:!1});if(!s)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let l=new n({config:o,cliVersion:a.cliVersion,token:s}),u,d;try{({siteId:u,site:d}=await c(l,{explicit:a.siteId,headless:!!a.json,cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let f=d?.url?d.url.replace(/^https?:\/\//,``).replace(/\/$/,``):d?.name??u;if(i(a)){let e=await l.getGeo(u);return r({type:`geo.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=m(_.createElement(S,{api:l,siteId:u,siteLabel:f,cliVersion:a.cliVersion,onExit:n=>{t(),e(n)}}))})}const S=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:c}=h(),[m,x]=y(null),[S,C]=y(!0),[w,T]=y(null);if(g(e=>{e===`q`&&(c(),i(0))}),v(()=>{let n=!1;return(async()=>{try{let r=await e.getGeo(t);n||(x(r),C(!1))}catch(e){n||(T(e.message),C(!1))}})(),()=>{n=!0}},[e,t]),S)return _.createElement(f,{flexDirection:`column`},_.createElement(o,{version:r,subtitle:`geo · ${n}`}),_.createElement(a,{title:`Loading`,state:`busy`},_.createElement(f,null,_.createElement(p,{color:`magenta`},_.createElement(b,{type:`dots`})),_.createElement(p,null,` Fetching geo…`))));if(w)return _.createElement(f,{flexDirection:`column`},_.createElement(o,{version:r,subtitle:`geo · ${n}`}),_.createElement(u,{reason:`error`,headline:`Failed to load`,hint:w}));let E=!m||m.countries.length===0&&m.cities.length===0;if(E)return _.createElement(f,{flexDirection:`column`},_.createElement(o,{version:r,subtitle:`geo · ${n}`}),_.createElement(u,{reason:`no-data`,headline:`No data yet`,hint:`Visit your site to send the first event`}));let D=[{key:`country`,label:`country`,width:18},{key:`visitors`,label:`visitors`,align:`right`,width:8}],O=[{key:`city`,label:`city`,width:20},{key:`country`,label:`country`,width:12},{key:`visitors`,label:`visitors`,align:`right`,width:8}],k=process.stdout.columns??80;return _.createElement(f,{flexDirection:`column`},_.createElement(o,{version:r,subtitle:`geo · ${n}`}),_.createElement(f,{flexDirection:`row`},_.createElement(a,{title:`Countries`},m.countries.length===0?_.createElement(p,{color:`gray`},`— —`):_.createElement(l,{columns:D,data:m.countries.slice(0,15),zebra:!0})),_.createElement(a,{title:`Globe`},_.createElement(d,{data:[],width:Math.max(36,k-60),height:12}))),_.createElement(a,{title:`Cities`},m.cities.length===0?_.createElement(p,{color:`gray`},`— —`):_.createElement(l,{columns:O,data:m.cities.slice(0,20),zebra:!0})),_.createElement(s,{items:[{key:`q`,label:`quit`}]}))};export{x as geoCommand};
1
+ import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-DJUWqNhW.js";import"./formatter-DDG2TSOz.js";import{emit as r,isHeadless as i}from"./emit-NkY7PE3R.js";import{Panel as a}from"./panel-CYsRlDSL.js";import{Banner as o}from"./banner-Cr0PV2pB.js";import"./prompt-BS9qJvdR.js";import{Keybar as s}from"./keybar-Bh-y__tC.js";import{resolveSiteId as c}from"./resolve-site-CoOL4KPZ.js";import{DataTable as l}from"./data-table-D-JVXhZ7.js";import{EmptyState as u}from"./empty-state-BbUJUNcp.js";import{Globe as d}from"./globe-CWe_QkQI.js";import{Box as f,Text as p,render as m,useApp as h,useInput as g}from"ink";import _,{useEffect as v,useState as y}from"react";import b from"ink-spinner";async function x(a){let o=await e(),s=await t({strict:!1});if(!s)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let l=new n({config:o,cliVersion:a.cliVersion,token:s}),u,d;try{({siteId:u,site:d}=await c(l,{explicit:a.siteId,headless:!!a.json,cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let f=d?.url?d.url.replace(/^https?:\/\//,``).replace(/\/$/,``):d?.name??u;if(i(a)){let e=await l.getGeo(u);return r({type:`geo.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=m(_.createElement(S,{api:l,siteId:u,siteLabel:f,cliVersion:a.cliVersion,onExit:n=>{t(),e(n)}}))})}const S=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:c}=h(),[m,x]=y(null),[S,C]=y(!0),[w,T]=y(null);if(g(e=>{e===`q`&&(c(),i(0))}),v(()=>{let n=!1;return(async()=>{try{let r=await e.getGeo(t);n||(x(r),C(!1))}catch(e){n||(T(e.message),C(!1))}})(),()=>{n=!0}},[e,t]),S)return _.createElement(f,{flexDirection:`column`},_.createElement(o,{version:r,subtitle:`geo · ${n}`}),_.createElement(a,{title:`Loading`,state:`busy`},_.createElement(f,null,_.createElement(p,{color:`magenta`},_.createElement(b,{type:`dots`})),_.createElement(p,null,` Fetching geo…`))));if(w)return _.createElement(f,{flexDirection:`column`},_.createElement(o,{version:r,subtitle:`geo · ${n}`}),_.createElement(u,{reason:`error`,headline:`Failed to load`,hint:w}));let E=!m||m.countries.length===0&&m.cities.length===0;if(E)return _.createElement(f,{flexDirection:`column`},_.createElement(o,{version:r,subtitle:`geo · ${n}`}),_.createElement(u,{reason:`no-data`,headline:`No data yet`,hint:`Visit your site to send the first event`}));let D=[{key:`country`,label:`country`,width:18},{key:`visitors`,label:`visitors`,align:`right`,width:8}],O=[{key:`city`,label:`city`,width:20},{key:`country`,label:`country`,width:12},{key:`visitors`,label:`visitors`,align:`right`,width:8}],k=process.stdout.columns??80;return _.createElement(f,{flexDirection:`column`},_.createElement(o,{version:r,subtitle:`geo · ${n}`}),_.createElement(f,{flexDirection:`row`},_.createElement(a,{title:`Countries`},m.countries.length===0?_.createElement(p,{color:`gray`},`— —`):_.createElement(l,{columns:D,data:m.countries.slice(0,15),zebra:!0})),_.createElement(a,{title:`Globe`},_.createElement(d,{data:[],width:Math.max(36,k-60),height:12}))),_.createElement(a,{title:`Cities`},m.cities.length===0?_.createElement(p,{color:`gray`},`— —`):_.createElement(l,{columns:O,data:m.cities.slice(0,20),zebra:!0})),_.createElement(s,{items:[{key:`q`,label:`quit`}]}))};export{x as geoCommand};
@@ -1,2 +1,2 @@
1
- import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-UJJ6ube8.js";import"./formatter-KOe_hjhc.js";import{emit as r,isHeadless as i}from"./emit-B8RbnBJe.js";import{Panel as a,useTheme as o}from"./panel-jycoT562.js";import{Banner as s}from"./banner-gVm7GaJF.js";import"./prompt-Db9Y7CVt.js";import{Keybar as c}from"./keybar-BYQ2Bam1.js";import{resolveSiteId as l}from"./resolve-site-CZEwJoBj.js";import{EmptyState as u}from"./empty-state-BkS6DKWZ.js";import{Bar as d}from"./bar-BPHTpgfb.js";import{Box as f,Text as p,render as m,useApp as h,useInput as g}from"ink";import _,{useEffect as v,useMemo as y,useRef as b,useState as x}from"react";import ee from"ink-spinner";import S from"open";const C={DZ:{lat:28.0339,lng:1.6596,name:`Algeria`,spread:8},EG:{lat:26.8206,lng:30.8025,name:`Egypt`,spread:6},ET:{lat:9.145,lng:40.4897,name:`Ethiopia`,spread:6},GH:{lat:7.9465,lng:-1.0232,name:`Ghana`,spread:3},KE:{lat:-.0236,lng:37.9062,name:`Kenya`,spread:4},MA:{lat:31.7917,lng:-7.0926,name:`Morocco`,spread:5},NG:{lat:9.082,lng:8.6753,name:`Nigeria`,spread:5},ZA:{lat:-30.5595,lng:22.9375,name:`South Africa`,spread:7},TZ:{lat:-6.369,lng:34.8888,name:`Tanzania`,spread:5},UG:{lat:1.3733,lng:32.2903,name:`Uganda`,spread:3},TN:{lat:33.8869,lng:9.5375,name:`Tunisia`,spread:3},SN:{lat:14.4974,lng:-14.4524,name:`Senegal`,spread:3},CI:{lat:7.54,lng:-5.5471,name:`Côte d'Ivoire`,spread:3},CM:{lat:7.3697,lng:12.3547,name:`Cameroon`,spread:4},AO:{lat:-11.2027,lng:17.8739,name:`Angola`,spread:6},MZ:{lat:-18.6657,lng:35.5296,name:`Mozambique`,spread:6},ZW:{lat:-19.0154,lng:29.1549,name:`Zimbabwe`,spread:4},ZM:{lat:-13.1339,lng:27.8493,name:`Zambia`,spread:5},RW:{lat:-1.9403,lng:29.8739,name:`Rwanda`,spread:1.5},MG:{lat:-18.7669,lng:46.8691,name:`Madagascar`,spread:5},LY:{lat:26.3351,lng:17.2283,name:`Libya`,spread:8},SD:{lat:12.8628,lng:30.2176,name:`Sudan`,spread:7},US:{lat:39.0902,lng:-98.5795,name:`United States`,spread:18},CA:{lat:56.1304,lng:-106.3468,name:`Canada`,spread:22},MX:{lat:23.6345,lng:-102.5528,name:`Mexico`,spread:9},BR:{lat:-10.235,lng:-51.9253,name:`Brazil`,spread:18},AR:{lat:-38.4161,lng:-63.6167,name:`Argentina`,spread:11},CL:{lat:-35.6751,lng:-71.543,name:`Chile`,spread:11},CO:{lat:4.5709,lng:-74.2973,name:`Colombia`,spread:6},PE:{lat:-9.19,lng:-75.0152,name:`Peru`,spread:7},VE:{lat:6.4238,lng:-66.5897,name:`Venezuela`,spread:6},EC:{lat:-1.8312,lng:-78.1834,name:`Ecuador`,spread:3},BO:{lat:-16.2902,lng:-63.5887,name:`Bolivia`,spread:6},UY:{lat:-32.5228,lng:-55.7658,name:`Uruguay`,spread:2.5},PY:{lat:-23.4425,lng:-58.4438,name:`Paraguay`,spread:4},GT:{lat:15.7835,lng:-90.2308,name:`Guatemala`,spread:2},CU:{lat:21.5218,lng:-77.7812,name:`Cuba`,spread:3},DO:{lat:18.7357,lng:-70.1627,name:`Dominican Republic`,spread:1.5},CR:{lat:9.7489,lng:-83.7534,name:`Costa Rica`,spread:1.2},PA:{lat:8.538,lng:-80.7821,name:`Panama`,spread:1.5},HN:{lat:15.2,lng:-86.2419,name:`Honduras`,spread:2},PR:{lat:18.2208,lng:-66.5901,name:`Puerto Rico`,spread:.6},JM:{lat:18.1096,lng:-77.2975,name:`Jamaica`,spread:.7},TT:{lat:10.6918,lng:-61.2225,name:`Trinidad and Tobago`,spread:.6},GB:{lat:55.3781,lng:-3.436,name:`United Kingdom`,spread:3},IE:{lat:53.4129,lng:-8.2439,name:`Ireland`,spread:2},FR:{lat:46.6034,lng:1.8883,name:`France`,spread:4},DE:{lat:51.1657,lng:10.4515,name:`Germany`,spread:3.5},IT:{lat:41.8719,lng:12.5674,name:`Italy`,spread:3.5},ES:{lat:40.4637,lng:-3.7492,name:`Spain`,spread:4},PT:{lat:39.3999,lng:-8.2245,name:`Portugal`,spread:2},NL:{lat:52.1326,lng:5.2913,name:`Netherlands`,spread:1.2},BE:{lat:50.5039,lng:4.4699,name:`Belgium`,spread:1},CH:{lat:46.8182,lng:8.2275,name:`Switzerland`,spread:1.4},AT:{lat:47.5162,lng:14.5501,name:`Austria`,spread:2},PL:{lat:51.9194,lng:19.1451,name:`Poland`,spread:3.5},CZ:{lat:49.8175,lng:15.473,name:`Czechia`,spread:1.8},SE:{lat:60.1282,lng:18.6435,name:`Sweden`,spread:5},NO:{lat:60.472,lng:8.4689,name:`Norway`,spread:5},FI:{lat:61.9241,lng:25.7482,name:`Finland`,spread:4},DK:{lat:56.2639,lng:9.5018,name:`Denmark`,spread:1.5},IS:{lat:64.9631,lng:-19.0208,name:`Iceland`,spread:3},GR:{lat:39.0742,lng:21.8243,name:`Greece`,spread:3},TR:{lat:38.9637,lng:35.2433,name:`Turkey`,spread:6},RO:{lat:45.9432,lng:24.9668,name:`Romania`,spread:3},HU:{lat:47.1625,lng:19.5033,name:`Hungary`,spread:2},UA:{lat:48.3794,lng:31.1656,name:`Ukraine`,spread:5},RU:{lat:61.524,lng:80,name:`Russia`,spread:28},BG:{lat:42.7339,lng:25.4858,name:`Bulgaria`,spread:2},HR:{lat:45.1,lng:15.2,name:`Croatia`,spread:2},RS:{lat:44.0165,lng:21.0059,name:`Serbia`,spread:2},SK:{lat:48.669,lng:19.699,name:`Slovakia`,spread:1.8},SI:{lat:46.1512,lng:14.9955,name:`Slovenia`,spread:1.2},LT:{lat:55.1694,lng:23.8813,name:`Lithuania`,spread:1.5},LV:{lat:56.8796,lng:24.6032,name:`Latvia`,spread:1.5},EE:{lat:58.5953,lng:25.0136,name:`Estonia`,spread:1.5},BY:{lat:53.7098,lng:27.9534,name:`Belarus`,spread:3},MD:{lat:47.4116,lng:28.3699,name:`Moldova`,spread:1.2},AL:{lat:41.1533,lng:20.1683,name:`Albania`,spread:1},MK:{lat:41.6086,lng:21.7453,name:`North Macedonia`,spread:1},BA:{lat:43.9159,lng:17.6791,name:`Bosnia and Herzegovina`,spread:1.2},ME:{lat:42.7087,lng:19.3744,name:`Montenegro`,spread:.8},XK:{lat:42.6026,lng:20.903,name:`Kosovo`,spread:.7},LU:{lat:49.8153,lng:6.1296,name:`Luxembourg`,spread:.4},MT:{lat:35.9375,lng:14.3754,name:`Malta`,spread:.3},CY:{lat:35.1264,lng:33.4299,name:`Cyprus`,spread:.6},CN:{lat:35.8617,lng:104.1954,name:`China`,spread:18},JP:{lat:36.2048,lng:138.2529,name:`Japan`,spread:5},KR:{lat:35.9078,lng:127.7669,name:`South Korea`,spread:2},IN:{lat:20.5937,lng:78.9629,name:`India`,spread:12},ID:{lat:-2.7893,lng:113.9213,name:`Indonesia`,spread:12},PH:{lat:12.8797,lng:121.774,name:`Philippines`,spread:5},VN:{lat:14.0583,lng:108.2772,name:`Vietnam`,spread:5},TH:{lat:15.87,lng:100.9925,name:`Thailand`,spread:4},MY:{lat:4.2105,lng:101.9758,name:`Malaysia`,spread:4},SG:{lat:1.3521,lng:103.8198,name:`Singapore`,spread:.3},PK:{lat:30.3753,lng:69.3451,name:`Pakistan`,spread:6},BD:{lat:23.685,lng:90.3563,name:`Bangladesh`,spread:3},LK:{lat:7.8731,lng:80.7718,name:`Sri Lanka`,spread:2},MM:{lat:21.9162,lng:95.956,name:`Myanmar`,spread:6},KH:{lat:12.5657,lng:104.991,name:`Cambodia`,spread:3},LA:{lat:19.8563,lng:102.4955,name:`Laos`,spread:3},NP:{lat:28.3949,lng:84.124,name:`Nepal`,spread:3},IR:{lat:32.4279,lng:53.688,name:`Iran`,spread:7},IQ:{lat:33.2232,lng:43.6793,name:`Iraq`,spread:4},IL:{lat:31.0461,lng:34.8516,name:`Israel`,spread:1},SA:{lat:23.8859,lng:45.0792,name:`Saudi Arabia`,spread:8},AE:{lat:23.4241,lng:53.8478,name:`UAE`,spread:2},QA:{lat:25.3548,lng:51.1839,name:`Qatar`,spread:.6},KW:{lat:29.3117,lng:47.4818,name:`Kuwait`,spread:.8},OM:{lat:21.4735,lng:55.9754,name:`Oman`,spread:4},JO:{lat:30.5852,lng:36.2384,name:`Jordan`,spread:2},LB:{lat:33.8547,lng:35.8623,name:`Lebanon`,spread:.7},SY:{lat:34.8021,lng:38.9968,name:`Syria`,spread:3},YE:{lat:15.5527,lng:48.5164,name:`Yemen`,spread:4},AF:{lat:33.9391,lng:67.71,name:`Afghanistan`,spread:5},KZ:{lat:48.0196,lng:66.9237,name:`Kazakhstan`,spread:13},UZ:{lat:41.3775,lng:64.5853,name:`Uzbekistan`,spread:5},TM:{lat:38.9697,lng:59.5563,name:`Turkmenistan`,spread:5},KG:{lat:41.2044,lng:74.7661,name:`Kyrgyzstan`,spread:3},TJ:{lat:38.861,lng:71.2761,name:`Tajikistan`,spread:3},AZ:{lat:40.1431,lng:47.5769,name:`Azerbaijan`,spread:2},GE:{lat:42.3154,lng:43.3569,name:`Georgia`,spread:2},AM:{lat:40.0691,lng:45.0382,name:`Armenia`,spread:1.2},HK:{lat:22.3193,lng:114.1694,name:`Hong Kong`,spread:.3},TW:{lat:23.6978,lng:120.9605,name:`Taiwan`,spread:1.5},AU:{lat:-25.2744,lng:133.7751,name:`Australia`,spread:18},NZ:{lat:-40.9006,lng:174.886,name:`New Zealand`,spread:5},PG:{lat:-6.314,lng:143.9555,name:`Papua New Guinea`,spread:5},FJ:{lat:-16.578,lng:179.4144,name:`Fiji`,spread:1}},w=Object.fromEntries(Object.entries(C).map(([e,t])=>[e,{lat:t.lat,lng:t.lng}]));function T(e){return!e||e.length!==2?null:C[e.toUpperCase()]??null}function E(e,t){let n=T(e);if(!n||t<=0)return[];let r=[],i=0;for(let t=0;t<e.length;t++)i=i*31+e.charCodeAt(t)>>>0;for(let e=0;e<t;e++){i=i+1831565813>>>0;let e=i;e=Math.imul(e^e>>>15,e|1)>>>0,e=(e^e+(Math.imul(e^e>>>7,e|61)>>>0))>>>0;let t=((e^e>>>14)>>>0)/4294967296;i=i+2246822507>>>0;let a=i;a=Math.imul(a^a>>>15,a|1)>>>0,a=(a^a+(Math.imul(a^a>>>7,a|61)>>>0))>>>0;let o=((a^a>>>14)>>>0)/4294967296,s=n.spread*Math.sqrt(t),c=o*2*Math.PI;r.push({lat:n.lat+s*Math.sin(c)*.7,lng:n.lng+s*Math.cos(c)/Math.max(.3,Math.cos(n.lat*Math.PI/180))})}return r}const D=360,O=180,k=new Uint8Array(D*O),A=new Uint8Array(D*O),j=[`__OCEAN__`];function M(e){let t=(e%360+360)%360;return Math.floor(t)}function N(e){return Math.max(0,Math.min(O-1,Math.floor(90-e)))}function P(e,t,n){let r=N(e),i=M(t);k[r*D+i]=1,A[r*D+i]=n}for(let e of Object.keys(C)){let t=C[e];j.push(e);let n=j.length-1,r=Math.max(.5,t.spread*.85),i=Math.max(.25,Math.cos(t.lat*Math.PI/180)),a=Math.max(.5,t.spread/i),o=Math.floor(t.lat-r),s=Math.ceil(t.lat+r),c=Math.floor(t.lng-a),l=Math.ceil(t.lng+a);for(let e=o;e<=s;e++)for(let i=c;i<=l;i++){let o=(e-t.lat)/r,s=(i-t.lng)/a;s*s+o*o>1||P(e,i,n)}}const F=new Uint8Array(k);for(let e=1;e<O-1;e++)for(let t=0;t<D;t++){if(k[e*D+t])continue;let n=0,r=0;for(let i=-1;i<=1;i++)for(let a=-1;a<=1;a++){if(i===0&&a===0)continue;let o=(t+a+D)%D;k[(e+i)*D+o]&&(n++,r||=A[(e+i)*D+o]??0)}n>=4&&(F[e*D+t]=1,A[e*D+t]=r)}k.set(F);const I=new Uint8Array(D*O);for(let e=0;e<O;e++)for(let t=0;t<D;t++){let n=A[e*D+t];if(!n)continue;let r=e>0?A[(e-1)*D+t]:0,i=e<O-1?A[(e+1)*D+t]:0,a=A[e*D+(t-1+D)%D],o=A[e*D+(t+1)%D];(r!==n||i!==n||a!==n||o!==n)&&(I[e*D+t]=1)}function L(e,t){if(e<-90||e>90)return 0;let n=Math.max(0,Math.min(O-1,Math.floor(90-e))),r=(t%360+360)%360,i=Math.floor(r);return k[n*D+i]===1?1:0}function R(e,t){if(e<-90||e>90)return 0;let n=Math.max(0,Math.min(O-1,Math.floor(90-e))),r=(t%360+360)%360,i=Math.floor(r);return I[n*D+i]===1?1:0}function z(e){return e*Math.PI/180}function B(e,t){let n=z(e),r=z(t);return{x:Math.cos(n)*Math.sin(r),y:Math.sin(n),z:Math.cos(n)*Math.cos(r)}}function V(e,t){let n=Math.cos(t),r=Math.sin(t);return{x:n*e.x+r*e.z,y:e.y,z:-r*e.x+n*e.z}}function H(e,t){let n=Math.cos(t),r=Math.sin(t);return{x:e.x,y:n*e.y-r*e.z,z:r*e.y+n*e.z}}function U(e,t){let n=e*2,r=t*4;return{dw:n,dh:r,bits:new Uint8Array(n*r)}}function W(e,t,n){t<0||t>=e.dw||n<0||n>=e.dh||(e.bits[n*e.dw+t]=1)}function G(e,t,n,r){let i=r*r;for(let a=-r;a<=r;a++)for(let o=-r;o<=r;o++)o*o+a*a<=i&&W(e,Math.round(t+o),Math.round(n+a))}const K=[[0,0],[0,1],[0,2],[1,0],[1,1],[1,2],[0,3],[1,3]];function q(e,t,n){let r=0;for(let i=0;i<K.length;i++){let[a,o]=K[i],s=t*2+a,c=n*4+o;e.bits[c*e.dw+s]&&(r|=1<<i)}return r===0?` `:String.fromCodePoint(10240+r)}function J(e,t,n){let r=0;for(let i=0;i<4;i++)for(let a=0;a<2;a++){let o=t*2+a,s=n*4+i;e.bits[s*e.dw+o]&&r++}return r===0?` `:r<=2?`·`:r<=5?`○`:`●`}function Y(e){if(e)return!0;let t=process.env;if(t.NO_COLOR||t.ZENOVAY_GLOBE===`ascii`)return!0;let n=(t.LANG||t.LC_ALL||t.LC_CTYPE||``).toLowerCase();return!!(n&&!n.includes(`utf`))}function X(e,t,n){if(e.z<0)return null;let r=t/2,i=n/2,a=Math.min(t,n/2)*.95;return{x:r+e.x*a,y:i-e.y*a}}function Z(e){let t=e.dw/2,n=e.dh/2,r=Math.min(e.dw,e.dh/2)*.95,i=Math.round(2*Math.PI*r);for(let a=0;a<i;a++){let o=a/i*2*Math.PI,s=Math.round(t+r*Math.cos(o)),c=Math.round(n+r*Math.sin(o));W(e,s,c)}}function te(e,t,n){for(let r of[-60,-30,0,30,60])for(let i=-180;i<=180;i+=4){let a=H(V(B(r,i),t),n),o=X(a,e.dw,e.dh);o&&W(e,Math.round(o.x),Math.round(o.y))}for(let r=-180;r<180;r+=30)for(let i=-85;i<=85;i+=4){let a=H(V(B(i,r),t),n),o=X(a,e.dw,e.dh);o&&W(e,Math.round(o.x),Math.round(o.y))}}function ne({visitors:e,highlight:t,width:n=50,height:r=25,rotationDeg:i=0,tiltDeg:a=20,gridlines:s=!0,asciiOnly:c}){let{theme:l}=o(),u=Y(c),d=U(n,r),m=U(n,r),h=U(n,r),g=U(n,r),v=U(n,r),y=z(i),b=z(-a);Z(d),s&&te(d,y,b);{let e=m.dw/2,t=m.dh/2,n=Math.min(m.dw,m.dh/2)*.95,r=Math.cos(y),i=Math.sin(y),a=Math.cos(b),o=Math.sin(b);for(let s=0;s<m.dh;s++){let c=(t-s)/n;if(!(c<-1||c>1))for(let t=0;t<m.dw;t++){let l=(t-e)/n,u=l*l+c*c;if(u>1)continue;let d=Math.sqrt(1-u),f=l,p=c,g=a*p+o*d,_=-o*p+a*d,v=r*f-i*_,y=i*f+r*_,b=Math.asin(g)*(180/Math.PI),x=Math.atan2(v,y)*(180/Math.PI);L(b,x)&&(W(m,t,s),R(b,x)&&W(h,t,s))}}}for(let t of e){let e=H(V(B(t.lat,t.lng),y),b),n=X(e,g.dw,g.dh);if(!n)continue;let r=typeof t.freshness==`number`?t.freshness:.5;G(g,n.x,n.y,r>.7?2:1)}if(t&&t.length>0)for(let e of t){let t=H(V(B(e.lat,e.lng),y),b),n=X(t,v.dw,v.dh);if(!n)continue;G(v,n.x,n.y,2)}let x=[];for(let e=0;e<r;e++){let t=[],r=null,i=(e,n)=>{r&&r.color===e?r.text+=n:(r={color:e,text:n},t.push(r))};for(let r=0;r<n;r++){let n=u?J(v,r,e):q(v,r,e);if(n!==` `){i(l.warn,n);continue}let a=u?J(g,r,e):q(g,r,e);if(a!==` `){i(l.accent,a);continue}let o=u?J(h,r,e):q(h,r,e);if(o!==` `){i(l.fg,o);continue}let s=u?J(m,r,e):q(m,r,e);if(s!==` `){i(l.success,s);continue}let c=u?J(d,r,e):q(d,r,e);if(c!==` `){i(l.muted,c);continue}let f=t.length>0?t[t.length-1]:void 0;i(f?f.color:l.muted,` `)}x.push(_.createElement(f,{key:e},_.createElement(p,null,t.map((e,t)=>_.createElement(p,{key:t,color:e.color,bold:!0},e.text)))))}return _.createElement(f,{flexDirection:`column`},x)}async function Q(e,t,n){let r=await e.getGeo(t).catch(()=>({countries:[],cities:[]})),i=(r.countries??[]).map(e=>{let t=T(e.country),r=n.get(e.country)??0;return{code:e.country,visitors:e.visitors,lat:t?.lat,lng:t?.lng,freshness:e.visitors>r?1:.4}});return{countries:i,totalVisitors:i.reduce((e,t)=>e+t.visitors,0),unknownCount:i.filter(e=>typeof e.lat!=`number`).reduce((e,t)=>e+t.visitors,0),lastFetchedAt:Date.now()}}async function re(a){let o=await e(),s=await t({strict:!1});if(!s)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let c=new n({config:o,cliVersion:a.cliVersion,token:s}),u,d;try{({siteId:u,site:d}=await l(c,{explicit:a.siteId,headless:!!a.json,cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let f=d?.url?d.url.replace(/^https?:\/\//,``).replace(/\/$/,``):d?.name??u;if(a.browser){let e=`https://app.zenovay.com/domains/${encodeURIComponent(u)}?tab=globe`;a.json?process.stdout.write(JSON.stringify({openedUrl:e})+`
1
+ import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-DJUWqNhW.js";import"./formatter-DDG2TSOz.js";import{emit as r,isHeadless as i}from"./emit-NkY7PE3R.js";import{Panel as a,useTheme as o}from"./panel-CYsRlDSL.js";import{Banner as s}from"./banner-Cr0PV2pB.js";import"./prompt-BS9qJvdR.js";import{Keybar as c}from"./keybar-Bh-y__tC.js";import{resolveSiteId as l}from"./resolve-site-CoOL4KPZ.js";import{EmptyState as u}from"./empty-state-BbUJUNcp.js";import{Bar as d}from"./bar-Cjia2R58.js";import{Box as f,Text as p,render as m,useApp as h,useInput as g}from"ink";import _,{useEffect as v,useMemo as y,useRef as b,useState as x}from"react";import ee from"ink-spinner";import S from"open";const C={DZ:{lat:28.0339,lng:1.6596,name:`Algeria`,spread:8},EG:{lat:26.8206,lng:30.8025,name:`Egypt`,spread:6},ET:{lat:9.145,lng:40.4897,name:`Ethiopia`,spread:6},GH:{lat:7.9465,lng:-1.0232,name:`Ghana`,spread:3},KE:{lat:-.0236,lng:37.9062,name:`Kenya`,spread:4},MA:{lat:31.7917,lng:-7.0926,name:`Morocco`,spread:5},NG:{lat:9.082,lng:8.6753,name:`Nigeria`,spread:5},ZA:{lat:-30.5595,lng:22.9375,name:`South Africa`,spread:7},TZ:{lat:-6.369,lng:34.8888,name:`Tanzania`,spread:5},UG:{lat:1.3733,lng:32.2903,name:`Uganda`,spread:3},TN:{lat:33.8869,lng:9.5375,name:`Tunisia`,spread:3},SN:{lat:14.4974,lng:-14.4524,name:`Senegal`,spread:3},CI:{lat:7.54,lng:-5.5471,name:`Côte d'Ivoire`,spread:3},CM:{lat:7.3697,lng:12.3547,name:`Cameroon`,spread:4},AO:{lat:-11.2027,lng:17.8739,name:`Angola`,spread:6},MZ:{lat:-18.6657,lng:35.5296,name:`Mozambique`,spread:6},ZW:{lat:-19.0154,lng:29.1549,name:`Zimbabwe`,spread:4},ZM:{lat:-13.1339,lng:27.8493,name:`Zambia`,spread:5},RW:{lat:-1.9403,lng:29.8739,name:`Rwanda`,spread:1.5},MG:{lat:-18.7669,lng:46.8691,name:`Madagascar`,spread:5},LY:{lat:26.3351,lng:17.2283,name:`Libya`,spread:8},SD:{lat:12.8628,lng:30.2176,name:`Sudan`,spread:7},US:{lat:39.0902,lng:-98.5795,name:`United States`,spread:18},CA:{lat:56.1304,lng:-106.3468,name:`Canada`,spread:22},MX:{lat:23.6345,lng:-102.5528,name:`Mexico`,spread:9},BR:{lat:-10.235,lng:-51.9253,name:`Brazil`,spread:18},AR:{lat:-38.4161,lng:-63.6167,name:`Argentina`,spread:11},CL:{lat:-35.6751,lng:-71.543,name:`Chile`,spread:11},CO:{lat:4.5709,lng:-74.2973,name:`Colombia`,spread:6},PE:{lat:-9.19,lng:-75.0152,name:`Peru`,spread:7},VE:{lat:6.4238,lng:-66.5897,name:`Venezuela`,spread:6},EC:{lat:-1.8312,lng:-78.1834,name:`Ecuador`,spread:3},BO:{lat:-16.2902,lng:-63.5887,name:`Bolivia`,spread:6},UY:{lat:-32.5228,lng:-55.7658,name:`Uruguay`,spread:2.5},PY:{lat:-23.4425,lng:-58.4438,name:`Paraguay`,spread:4},GT:{lat:15.7835,lng:-90.2308,name:`Guatemala`,spread:2},CU:{lat:21.5218,lng:-77.7812,name:`Cuba`,spread:3},DO:{lat:18.7357,lng:-70.1627,name:`Dominican Republic`,spread:1.5},CR:{lat:9.7489,lng:-83.7534,name:`Costa Rica`,spread:1.2},PA:{lat:8.538,lng:-80.7821,name:`Panama`,spread:1.5},HN:{lat:15.2,lng:-86.2419,name:`Honduras`,spread:2},PR:{lat:18.2208,lng:-66.5901,name:`Puerto Rico`,spread:.6},JM:{lat:18.1096,lng:-77.2975,name:`Jamaica`,spread:.7},TT:{lat:10.6918,lng:-61.2225,name:`Trinidad and Tobago`,spread:.6},GB:{lat:55.3781,lng:-3.436,name:`United Kingdom`,spread:3},IE:{lat:53.4129,lng:-8.2439,name:`Ireland`,spread:2},FR:{lat:46.6034,lng:1.8883,name:`France`,spread:4},DE:{lat:51.1657,lng:10.4515,name:`Germany`,spread:3.5},IT:{lat:41.8719,lng:12.5674,name:`Italy`,spread:3.5},ES:{lat:40.4637,lng:-3.7492,name:`Spain`,spread:4},PT:{lat:39.3999,lng:-8.2245,name:`Portugal`,spread:2},NL:{lat:52.1326,lng:5.2913,name:`Netherlands`,spread:1.2},BE:{lat:50.5039,lng:4.4699,name:`Belgium`,spread:1},CH:{lat:46.8182,lng:8.2275,name:`Switzerland`,spread:1.4},AT:{lat:47.5162,lng:14.5501,name:`Austria`,spread:2},PL:{lat:51.9194,lng:19.1451,name:`Poland`,spread:3.5},CZ:{lat:49.8175,lng:15.473,name:`Czechia`,spread:1.8},SE:{lat:60.1282,lng:18.6435,name:`Sweden`,spread:5},NO:{lat:60.472,lng:8.4689,name:`Norway`,spread:5},FI:{lat:61.9241,lng:25.7482,name:`Finland`,spread:4},DK:{lat:56.2639,lng:9.5018,name:`Denmark`,spread:1.5},IS:{lat:64.9631,lng:-19.0208,name:`Iceland`,spread:3},GR:{lat:39.0742,lng:21.8243,name:`Greece`,spread:3},TR:{lat:38.9637,lng:35.2433,name:`Turkey`,spread:6},RO:{lat:45.9432,lng:24.9668,name:`Romania`,spread:3},HU:{lat:47.1625,lng:19.5033,name:`Hungary`,spread:2},UA:{lat:48.3794,lng:31.1656,name:`Ukraine`,spread:5},RU:{lat:61.524,lng:80,name:`Russia`,spread:28},BG:{lat:42.7339,lng:25.4858,name:`Bulgaria`,spread:2},HR:{lat:45.1,lng:15.2,name:`Croatia`,spread:2},RS:{lat:44.0165,lng:21.0059,name:`Serbia`,spread:2},SK:{lat:48.669,lng:19.699,name:`Slovakia`,spread:1.8},SI:{lat:46.1512,lng:14.9955,name:`Slovenia`,spread:1.2},LT:{lat:55.1694,lng:23.8813,name:`Lithuania`,spread:1.5},LV:{lat:56.8796,lng:24.6032,name:`Latvia`,spread:1.5},EE:{lat:58.5953,lng:25.0136,name:`Estonia`,spread:1.5},BY:{lat:53.7098,lng:27.9534,name:`Belarus`,spread:3},MD:{lat:47.4116,lng:28.3699,name:`Moldova`,spread:1.2},AL:{lat:41.1533,lng:20.1683,name:`Albania`,spread:1},MK:{lat:41.6086,lng:21.7453,name:`North Macedonia`,spread:1},BA:{lat:43.9159,lng:17.6791,name:`Bosnia and Herzegovina`,spread:1.2},ME:{lat:42.7087,lng:19.3744,name:`Montenegro`,spread:.8},XK:{lat:42.6026,lng:20.903,name:`Kosovo`,spread:.7},LU:{lat:49.8153,lng:6.1296,name:`Luxembourg`,spread:.4},MT:{lat:35.9375,lng:14.3754,name:`Malta`,spread:.3},CY:{lat:35.1264,lng:33.4299,name:`Cyprus`,spread:.6},CN:{lat:35.8617,lng:104.1954,name:`China`,spread:18},JP:{lat:36.2048,lng:138.2529,name:`Japan`,spread:5},KR:{lat:35.9078,lng:127.7669,name:`South Korea`,spread:2},IN:{lat:20.5937,lng:78.9629,name:`India`,spread:12},ID:{lat:-2.7893,lng:113.9213,name:`Indonesia`,spread:12},PH:{lat:12.8797,lng:121.774,name:`Philippines`,spread:5},VN:{lat:14.0583,lng:108.2772,name:`Vietnam`,spread:5},TH:{lat:15.87,lng:100.9925,name:`Thailand`,spread:4},MY:{lat:4.2105,lng:101.9758,name:`Malaysia`,spread:4},SG:{lat:1.3521,lng:103.8198,name:`Singapore`,spread:.3},PK:{lat:30.3753,lng:69.3451,name:`Pakistan`,spread:6},BD:{lat:23.685,lng:90.3563,name:`Bangladesh`,spread:3},LK:{lat:7.8731,lng:80.7718,name:`Sri Lanka`,spread:2},MM:{lat:21.9162,lng:95.956,name:`Myanmar`,spread:6},KH:{lat:12.5657,lng:104.991,name:`Cambodia`,spread:3},LA:{lat:19.8563,lng:102.4955,name:`Laos`,spread:3},NP:{lat:28.3949,lng:84.124,name:`Nepal`,spread:3},IR:{lat:32.4279,lng:53.688,name:`Iran`,spread:7},IQ:{lat:33.2232,lng:43.6793,name:`Iraq`,spread:4},IL:{lat:31.0461,lng:34.8516,name:`Israel`,spread:1},SA:{lat:23.8859,lng:45.0792,name:`Saudi Arabia`,spread:8},AE:{lat:23.4241,lng:53.8478,name:`UAE`,spread:2},QA:{lat:25.3548,lng:51.1839,name:`Qatar`,spread:.6},KW:{lat:29.3117,lng:47.4818,name:`Kuwait`,spread:.8},OM:{lat:21.4735,lng:55.9754,name:`Oman`,spread:4},JO:{lat:30.5852,lng:36.2384,name:`Jordan`,spread:2},LB:{lat:33.8547,lng:35.8623,name:`Lebanon`,spread:.7},SY:{lat:34.8021,lng:38.9968,name:`Syria`,spread:3},YE:{lat:15.5527,lng:48.5164,name:`Yemen`,spread:4},AF:{lat:33.9391,lng:67.71,name:`Afghanistan`,spread:5},KZ:{lat:48.0196,lng:66.9237,name:`Kazakhstan`,spread:13},UZ:{lat:41.3775,lng:64.5853,name:`Uzbekistan`,spread:5},TM:{lat:38.9697,lng:59.5563,name:`Turkmenistan`,spread:5},KG:{lat:41.2044,lng:74.7661,name:`Kyrgyzstan`,spread:3},TJ:{lat:38.861,lng:71.2761,name:`Tajikistan`,spread:3},AZ:{lat:40.1431,lng:47.5769,name:`Azerbaijan`,spread:2},GE:{lat:42.3154,lng:43.3569,name:`Georgia`,spread:2},AM:{lat:40.0691,lng:45.0382,name:`Armenia`,spread:1.2},HK:{lat:22.3193,lng:114.1694,name:`Hong Kong`,spread:.3},TW:{lat:23.6978,lng:120.9605,name:`Taiwan`,spread:1.5},AU:{lat:-25.2744,lng:133.7751,name:`Australia`,spread:18},NZ:{lat:-40.9006,lng:174.886,name:`New Zealand`,spread:5},PG:{lat:-6.314,lng:143.9555,name:`Papua New Guinea`,spread:5},FJ:{lat:-16.578,lng:179.4144,name:`Fiji`,spread:1}},w=Object.fromEntries(Object.entries(C).map(([e,t])=>[e,{lat:t.lat,lng:t.lng}]));function T(e){return!e||e.length!==2?null:C[e.toUpperCase()]??null}function E(e,t){let n=T(e);if(!n||t<=0)return[];let r=[],i=0;for(let t=0;t<e.length;t++)i=i*31+e.charCodeAt(t)>>>0;for(let e=0;e<t;e++){i=i+1831565813>>>0;let e=i;e=Math.imul(e^e>>>15,e|1)>>>0,e=(e^e+(Math.imul(e^e>>>7,e|61)>>>0))>>>0;let t=((e^e>>>14)>>>0)/4294967296;i=i+2246822507>>>0;let a=i;a=Math.imul(a^a>>>15,a|1)>>>0,a=(a^a+(Math.imul(a^a>>>7,a|61)>>>0))>>>0;let o=((a^a>>>14)>>>0)/4294967296,s=n.spread*Math.sqrt(t),c=o*2*Math.PI;r.push({lat:n.lat+s*Math.sin(c)*.7,lng:n.lng+s*Math.cos(c)/Math.max(.3,Math.cos(n.lat*Math.PI/180))})}return r}const D=360,O=180,k=new Uint8Array(D*O),A=new Uint8Array(D*O),j=[`__OCEAN__`];function M(e){let t=(e%360+360)%360;return Math.floor(t)}function N(e){return Math.max(0,Math.min(O-1,Math.floor(90-e)))}function P(e,t,n){let r=N(e),i=M(t);k[r*D+i]=1,A[r*D+i]=n}for(let e of Object.keys(C)){let t=C[e];j.push(e);let n=j.length-1,r=Math.max(.5,t.spread*.85),i=Math.max(.25,Math.cos(t.lat*Math.PI/180)),a=Math.max(.5,t.spread/i),o=Math.floor(t.lat-r),s=Math.ceil(t.lat+r),c=Math.floor(t.lng-a),l=Math.ceil(t.lng+a);for(let e=o;e<=s;e++)for(let i=c;i<=l;i++){let o=(e-t.lat)/r,s=(i-t.lng)/a;s*s+o*o>1||P(e,i,n)}}const F=new Uint8Array(k);for(let e=1;e<O-1;e++)for(let t=0;t<D;t++){if(k[e*D+t])continue;let n=0,r=0;for(let i=-1;i<=1;i++)for(let a=-1;a<=1;a++){if(i===0&&a===0)continue;let o=(t+a+D)%D;k[(e+i)*D+o]&&(n++,r||=A[(e+i)*D+o]??0)}n>=4&&(F[e*D+t]=1,A[e*D+t]=r)}k.set(F);const I=new Uint8Array(D*O);for(let e=0;e<O;e++)for(let t=0;t<D;t++){let n=A[e*D+t];if(!n)continue;let r=e>0?A[(e-1)*D+t]:0,i=e<O-1?A[(e+1)*D+t]:0,a=A[e*D+(t-1+D)%D],o=A[e*D+(t+1)%D];(r!==n||i!==n||a!==n||o!==n)&&(I[e*D+t]=1)}function L(e,t){if(e<-90||e>90)return 0;let n=Math.max(0,Math.min(O-1,Math.floor(90-e))),r=(t%360+360)%360,i=Math.floor(r);return k[n*D+i]===1?1:0}function R(e,t){if(e<-90||e>90)return 0;let n=Math.max(0,Math.min(O-1,Math.floor(90-e))),r=(t%360+360)%360,i=Math.floor(r);return I[n*D+i]===1?1:0}function z(e){return e*Math.PI/180}function B(e,t){let n=z(e),r=z(t);return{x:Math.cos(n)*Math.sin(r),y:Math.sin(n),z:Math.cos(n)*Math.cos(r)}}function V(e,t){let n=Math.cos(t),r=Math.sin(t);return{x:n*e.x+r*e.z,y:e.y,z:-r*e.x+n*e.z}}function H(e,t){let n=Math.cos(t),r=Math.sin(t);return{x:e.x,y:n*e.y-r*e.z,z:r*e.y+n*e.z}}function U(e,t){let n=e*2,r=t*4;return{dw:n,dh:r,bits:new Uint8Array(n*r)}}function W(e,t,n){t<0||t>=e.dw||n<0||n>=e.dh||(e.bits[n*e.dw+t]=1)}function G(e,t,n,r){let i=r*r;for(let a=-r;a<=r;a++)for(let o=-r;o<=r;o++)o*o+a*a<=i&&W(e,Math.round(t+o),Math.round(n+a))}const K=[[0,0],[0,1],[0,2],[1,0],[1,1],[1,2],[0,3],[1,3]];function q(e,t,n){let r=0;for(let i=0;i<K.length;i++){let[a,o]=K[i],s=t*2+a,c=n*4+o;e.bits[c*e.dw+s]&&(r|=1<<i)}return r===0?` `:String.fromCodePoint(10240+r)}function J(e,t,n){let r=0;for(let i=0;i<4;i++)for(let a=0;a<2;a++){let o=t*2+a,s=n*4+i;e.bits[s*e.dw+o]&&r++}return r===0?` `:r<=2?`·`:r<=5?`○`:`●`}function Y(e){if(e)return!0;let t=process.env;if(t.NO_COLOR||t.ZENOVAY_GLOBE===`ascii`)return!0;let n=(t.LANG||t.LC_ALL||t.LC_CTYPE||``).toLowerCase();return!!(n&&!n.includes(`utf`))}function X(e,t,n){if(e.z<0)return null;let r=t/2,i=n/2,a=Math.min(t,n/2)*.95;return{x:r+e.x*a,y:i-e.y*a}}function Z(e){let t=e.dw/2,n=e.dh/2,r=Math.min(e.dw,e.dh/2)*.95,i=Math.round(2*Math.PI*r);for(let a=0;a<i;a++){let o=a/i*2*Math.PI,s=Math.round(t+r*Math.cos(o)),c=Math.round(n+r*Math.sin(o));W(e,s,c)}}function te(e,t,n){for(let r of[-60,-30,0,30,60])for(let i=-180;i<=180;i+=4){let a=H(V(B(r,i),t),n),o=X(a,e.dw,e.dh);o&&W(e,Math.round(o.x),Math.round(o.y))}for(let r=-180;r<180;r+=30)for(let i=-85;i<=85;i+=4){let a=H(V(B(i,r),t),n),o=X(a,e.dw,e.dh);o&&W(e,Math.round(o.x),Math.round(o.y))}}function ne({visitors:e,highlight:t,width:n=50,height:r=25,rotationDeg:i=0,tiltDeg:a=20,gridlines:s=!0,asciiOnly:c}){let{theme:l}=o(),u=Y(c),d=U(n,r),m=U(n,r),h=U(n,r),g=U(n,r),v=U(n,r),y=z(i),b=z(-a);Z(d),s&&te(d,y,b);{let e=m.dw/2,t=m.dh/2,n=Math.min(m.dw,m.dh/2)*.95,r=Math.cos(y),i=Math.sin(y),a=Math.cos(b),o=Math.sin(b);for(let s=0;s<m.dh;s++){let c=(t-s)/n;if(!(c<-1||c>1))for(let t=0;t<m.dw;t++){let l=(t-e)/n,u=l*l+c*c;if(u>1)continue;let d=Math.sqrt(1-u),f=l,p=c,g=a*p+o*d,_=-o*p+a*d,v=r*f-i*_,y=i*f+r*_,b=Math.asin(g)*(180/Math.PI),x=Math.atan2(v,y)*(180/Math.PI);L(b,x)&&(W(m,t,s),R(b,x)&&W(h,t,s))}}}for(let t of e){let e=H(V(B(t.lat,t.lng),y),b),n=X(e,g.dw,g.dh);if(!n)continue;let r=typeof t.freshness==`number`?t.freshness:.5;G(g,n.x,n.y,r>.7?2:1)}if(t&&t.length>0)for(let e of t){let t=H(V(B(e.lat,e.lng),y),b),n=X(t,v.dw,v.dh);if(!n)continue;G(v,n.x,n.y,2)}let x=[];for(let e=0;e<r;e++){let t=[],r=null,i=(e,n)=>{r&&r.color===e?r.text+=n:(r={color:e,text:n},t.push(r))};for(let r=0;r<n;r++){let n=u?J(v,r,e):q(v,r,e);if(n!==` `){i(l.warn,n);continue}let a=u?J(g,r,e):q(g,r,e);if(a!==` `){i(l.accent,a);continue}let o=u?J(h,r,e):q(h,r,e);if(o!==` `){i(l.fg,o);continue}let s=u?J(m,r,e):q(m,r,e);if(s!==` `){i(l.success,s);continue}let c=u?J(d,r,e):q(d,r,e);if(c!==` `){i(l.muted,c);continue}let f=t.length>0?t[t.length-1]:void 0;i(f?f.color:l.muted,` `)}x.push(_.createElement(f,{key:e},_.createElement(p,null,t.map((e,t)=>_.createElement(p,{key:t,color:e.color,bold:!0},e.text)))))}return _.createElement(f,{flexDirection:`column`},x)}async function Q(e,t,n){let r=await e.getGeo(t).catch(()=>({countries:[],cities:[]})),i=(r.countries??[]).map(e=>{let t=T(e.country),r=n.get(e.country)??0;return{code:e.country,visitors:e.visitors,lat:t?.lat,lng:t?.lng,freshness:e.visitors>r?1:.4}});return{countries:i,totalVisitors:i.reduce((e,t)=>e+t.visitors,0),unknownCount:i.filter(e=>typeof e.lat!=`number`).reduce((e,t)=>e+t.visitors,0),lastFetchedAt:Date.now()}}async function re(a){let o=await e(),s=await t({strict:!1});if(!s)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let c=new n({config:o,cliVersion:a.cliVersion,token:s}),u,d;try{({siteId:u,site:d}=await l(c,{explicit:a.siteId,headless:!!a.json,cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let f=d?.url?d.url.replace(/^https?:\/\//,``).replace(/\/$/,``):d?.name??u;if(a.browser){let e=`https://app.zenovay.com/domains/${encodeURIComponent(u)}?tab=globe`;a.json?process.stdout.write(JSON.stringify({openedUrl:e})+`
2
2
  `):process.stdout.write(`\n Opening Mapbox globe in your default browser:\n ${e}\n\n`);try{await S(e)}catch{}return 0}if(i(a)){let e=await Q(c,u,new Map);return r({type:`globe.snapshot`,data:{countries:e.countries,total:e.totalVisitors,unknownCount:e.unknownCount}}),0}return new Promise(e=>{let{unmount:t}=m(_.createElement($,{api:c,siteId:u,siteLabel:f,cliVersion:a.cliVersion,onExit:n=>{t(),e(n)}}))})}const ie=5e3,ae=60,oe=1,se=80,$=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:l}=h(),{theme:m}=o(),[C,w]=x(null),[D,O]=x(!0),[k,A]=x(null),[j,M]=x(0),[N,P]=x(!1),[F,I]=x(20),[L,R]=x(1),[z,B]=x(0),V=b(new Map);g(n=>{if(n===`q`){l(),i(0);return}if(n===` `){P(e=>!e);return}if(n===`+`||n===`=`){R(e=>Math.min(1.6,e+.1));return}if(n===`-`||n===`_`){R(e=>Math.max(.7,e-.1));return}if(n===`t`){I(e=>(e+15)%60);return}if(n===`j`){B(e=>e+1);return}if(n===`k`){B(e=>Math.max(0,e-1));return}if(n===`w`){let e=`https://app.zenovay.com/domains/${encodeURIComponent(t)}?tab=globe`;S(e).catch(()=>{});return}if(n===`o`&&C){let e=C.countries[z];e?.lng!==void 0&&(M(-e.lng),P(!0));return}n===`r`&&(async()=>{try{let n=await Q(e,t,V.current);V.current=new Map(n.countries.map(e=>[e.code,e.visitors])),w(n)}catch(e){A(e.message)}})()}),v(()=>{let n=!1,r=null,i=async()=>{try{let r=await Q(e,t,V.current);if(n)return;V.current=new Map(r.countries.map(e=>[e.code,e.visitors])),w(r),O(!1)}catch(e){n||(A(e.message),O(!1))}n||(r=setTimeout(i,ie))};return i(),()=>{n=!0,r&&clearTimeout(r)}},[e,t]),v(()=>{if(N)return;let e=setInterval(()=>{M(e=>(e+oe)%360)},ae);return()=>clearInterval(e)},[N]);let H=y(()=>{if(!C)return[];let e=[];for(let t of C.countries){if(typeof t.lat!=`number`||typeof t.lng!=`number`)continue;let n=Math.min(se,Math.max(3,t.visitors*5));for(let r of E(t.code,n))e.push({lat:r.lat,lng:r.lng,freshness:t.freshness})}return e},[C]),U=y(()=>{if(!C)return[];let e=C.countries[Math.min(z,C.countries.length-1)];return!e||typeof e.lat!=`number`?[]:E(e.code,Math.min(80,Math.max(8,e.visitors*4)))},[C,z]),W=`globe · ${n} · live`,G=[{key:`q`,label:`quit`},{key:`j/k`,label:`select country`},{key:`o`,label:`orbit to selected`},{key:`space`,label:N?`resume`:`pause`},{key:`t`,label:`tilt ${F}°`},{key:`+/-`,label:`zoom`},{key:`w`,label:`open Mapbox view in browser`},{key:`r`,label:`refresh`}];if(D)return _.createElement(f,{flexDirection:`column`},_.createElement(s,{version:r,subtitle:W}),_.createElement(a,{title:`Loading`,state:`busy`},_.createElement(f,null,_.createElement(p,{color:`cyan`},_.createElement(ee,{type:`dots`})),_.createElement(p,null,` Spinning up Earth…`))));if(k)return _.createElement(f,{flexDirection:`column`},_.createElement(s,{version:r,subtitle:W}),_.createElement(u,{reason:`error`,headline:`Failed to load`,hint:k}),_.createElement(c,{items:G}));if(!C||C.countries.length===0&&C.unknownCount===0)return _.createElement(f,{flexDirection:`column`},_.createElement(s,{version:r,subtitle:W}),_.createElement(u,{reason:`no-data`,headline:`No geolocated visitors yet`,hint:`Visit your site to populate the map.`}),_.createElement(c,{items:G}));let K=process.stdout.columns??100,q=36,J=Math.max(40,Math.min(90,K-q-4)),Y=Math.round(J*L),X=Math.round(Y*.5),Z=C.countries.slice(0,12),te=Math.max(1,...Z.map(e=>e.visitors)),re=Math.max(1,Math.floor((Date.now()-C.lastFetchedAt)/1e3)),$=C.countries[Math.min(z,C.countries.length-1)],ce=$?T($.code):null;return _.createElement(f,{flexDirection:`column`},_.createElement(s,{version:r,subtitle:W}),$?_.createElement(f,{flexDirection:`row`,marginBottom:1},_.createElement(f,{width:2}),_.createElement(f,{borderStyle:`round`,borderColor:m.warn,paddingX:1},_.createElement(p,{color:m.warn,bold:!0},ce?.name??$.code),_.createElement(p,{color:m.dim},` · `),_.createElement(p,{color:m.fg},$.visitors,` visitor`,$.visitors===1?``:`s`))):null,_.createElement(f,{flexDirection:`row`},_.createElement(f,{flexDirection:`column`,marginRight:2},_.createElement(ne,{visitors:H,highlight:U,width:Y,height:X,rotationDeg:j,tiltDeg:F}),_.createElement(f,{marginTop:1},_.createElement(p,{color:m.dim},C.totalVisitors,` visitors · `,C.countries.length,` countries`,C.unknownCount>0?` · ${C.unknownCount} unmapped`:``,` · `,N?`rotation paused`:`↻ ${oe}°/${ae}ms`,` · refreshed `,re,`s ago`))),_.createElement(f,{flexDirection:`column`,width:q},_.createElement(a,{title:`Live by country`},Z.map((e,t)=>{let n=t===Math.min(z,C.countries.length-1),r=e.freshness>.7,i=n?m.warn:r?m.success:m.fg;return _.createElement(f,{key:e.code,flexDirection:`row`},_.createElement(f,{width:2},_.createElement(p,{color:m.warn},n?`›`:` `)),_.createElement(f,{width:3},_.createElement(p,{color:i,bold:n},e.code)),_.createElement(d,{value:e.visitors,max:te,width:14,showPercent:!1}),_.createElement(f,{width:6},_.createElement(p,{color:m.muted},String(e.visitors).padStart(5))))})),C.countries.length>12?_.createElement(f,{marginTop:1},_.createElement(p,{color:m.muted},`+`,C.countries.length-12,` more (j/k to scroll)`)):null)),_.createElement(c,{items:G}))};export{re as globeCommand};
@@ -1,4 +1,4 @@
1
- import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{emitErrorEnvelope as n}from"./error-codes-Iig3PBVk.js";import{ApiV2Client as r}from"./api-v2-UJJ6ube8.js";import{requireTier as i}from"./tier-uaU5pkTz.js";import{confirmDestructive as a}from"./confirm-Dk3CEdpn.js";import"./formatter-KOe_hjhc.js";import{emitEnvelope as o,wrapItem as s,wrapList as c}from"./emit-B8RbnBJe.js";function l(e){return e.length>12?`${e.slice(0,8)}…${e.slice(-4)}`:e}function u(e){return e?new Date(e).toISOString().slice(0,10):`—`}async function d(d){let f=await e(),p=await t({strict:!1}),m=new r({config:f,cliVersion:d.cliVersion,token:p});try{await i(m,`pro`)}catch(e){return n(e,{command:`goals ${d.action}`})}try{switch(d.action){case`list`:{let{goals:e}=await m.listGoals();if(d.json)return o(c(e,`goals.list`),{legacyKey:`goals`,legacyValue:e}),0;if(e.length===0)return process.stdout.write("No goals yet. Create one with `zenovay goals create --name <n> --type <pageview|event> --target <url-or-event>`.\n"),0;let t=[14,24,10,30,10],n=e=>e.map((e,n)=>(e??``).padEnd(t[n])).join(` `);process.stdout.write(`
1
+ import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{emitErrorEnvelope as n}from"./error-codes-Bc_l2RPJ.js";import{ApiV2Client as r}from"./api-v2-DJUWqNhW.js";import{requireTier as i}from"./tier-ztFrvV9H.js";import{confirmDestructive as a}from"./confirm-DvIRDrR9.js";import"./formatter-DDG2TSOz.js";import{emitEnvelope as o,wrapItem as s,wrapList as c}from"./emit-NkY7PE3R.js";function l(e){return e.length>12?`${e.slice(0,8)}…${e.slice(-4)}`:e}function u(e){return e?new Date(e).toISOString().slice(0,10):`—`}async function d(d){let f=await e(),p=await t({strict:!1}),m=new r({config:f,cliVersion:d.cliVersion,token:p});try{await i(m,`pro`)}catch(e){return n(e,{command:`goals ${d.action}`})}try{switch(d.action){case`list`:{let{goals:e}=await m.listGoals();if(d.json)return o(c(e,`goals.list`),{legacyKey:`goals`,legacyValue:e}),0;if(e.length===0)return process.stdout.write("No goals yet. Create one with `zenovay goals create --name <n> --type <pageview|event> --target <url-or-event>`.\n"),0;let t=[14,24,10,30,10],n=e=>e.map((e,n)=>(e??``).padEnd(t[n])).join(` `);process.stdout.write(`
2
2
  `+n([`id`,`name`,`type`,`target`,`created`])+`
3
3
  `),process.stdout.write(n(t.map(e=>`─`.repeat(e)))+`
4
4
  `);for(let r of e)process.stdout.write(n([l(r.id),(r.name??``).slice(0,t[1]),r.type,(r.target??`—`).slice(0,t[3]),u(r.createdAt)])+`
@@ -1 +1 @@
1
- import{configPath as e,readConfig as t}from"./config-CG7B8fR0.js";import{fetchManifest as n}from"./check-D9G0N7NB.js";import{ApiClient as r}from"./api-CJnD6Auw.js";import{readToken as i}from"./token-store-C1AqhmDP.js";import{isHeadless as a}from"./emit-B8RbnBJe.js";import{Panel as o}from"./panel-jycoT562.js";import s from"node:path";import{promises as c}from"node:fs";import l from"node:os";import{Box as u,Text as d,render as f}from"ink";import p from"react";const m=6*60*60*1e3;function h(){return s.join(l.homedir(),`.zenovay`,`update.json`)}async function g(){try{let e=await c.readFile(h(),`utf8`);return JSON.parse(e)}catch{return null}}async function _(e){let t=h();await c.mkdir(s.dirname(t),{recursive:!0,mode:448}),await c.writeFile(t,JSON.stringify(e,null,2))}async function v(){let e=await t();if(e.noUpdateCheck||process.env.ZENOVAY_NO_UPDATE_CHECK===`1`||process.env.CI===`true`)return null;let r=await g();if(r&&Date.now()-r.fetchedAt<m)return r;try{let t=await n({cliBase:e.cliBase}),i={manifest:t,fetchedAt:Date.now(),lastNoticeAt:r?.lastNoticeAt};return await _(i),i}catch{return r}}async function y(){try{await v()}catch{}process.exit(0)}import.meta.url===`file://${process.argv[1]}`&&y();const b=2e3,x=5e3;async function S(e,t){let n=`${e}/mcp`,r=Date.now(),i=new AbortController,a=setTimeout(()=>i.abort(),b);try{let a=await t(n,{method:`GET`,signal:i.signal}),o=Date.now()-r;return a.ok?{name:`MCP server`,status:`pass`,detail:`${e}/mcp · ${o}ms`,latencyMs:o}:{name:`MCP server`,status:`fail`,detail:`HTTP ${a.status}`,latencyMs:o}}catch(e){return{name:`MCP server`,status:`fail`,detail:e.message}}finally{clearTimeout(a)}}async function C(){try{let t=await c.readFile(e(),`utf8`),n=JSON.parse(t),r=n.openaiApiKey;return typeof r==`string`&&r.trim().length>0?{name:`OpenAI key`,status:`pass`,detail:`configured`}:{name:`OpenAI key`,status:`warn`,detail:"not set (run `zenovay ai` to configure)"}}catch(e){return e.code===`ENOENT`?{name:`OpenAI key`,status:`warn`,detail:`no config file`}:{name:`OpenAI key`,status:`warn`,detail:`unreadable config`}}}async function w(){let e=l.homedir(),t=[s.join(e,`.zshrc`),s.join(e,`.bashrc`),s.join(e,`.config`,`fish`,`completions`,`zenovay.fish`)],n=[];for(let e of t)try{let t=await c.readFile(e,`utf8`);(/zenovay\s+(complet|--?complet)/i.test(t)||/_zenovay/.test(t)||/complete\s+-c\s+zenovay/.test(t))&&n.push(s.basename(e))}catch{}return n.length>0?{name:`Completions`,status:`pass`,detail:n.join(`, `)}:{name:`Completions`,status:`warn`,detail:"not installed (run `zenovay completions` after Wave 3)"}}async function T(e,t,n,r){if(!e||!t)return{name:`Events stream`,status:`skip`,detail:`not authenticated`};let i=new AbortController,a=setTimeout(()=>i.abort(),x),o=Date.now();try{let t=await e.openEventsStream(`probe`,i.signal),r=t.body?.getReader();if(r){let e=Promise.race([r.read().then(()=>`first`),new Promise(e=>setTimeout(()=>e(`timeout`),1500))]);await e;try{r.cancel()}catch{}}let a=Date.now()-o;return{name:`Events stream`,status:`pass`,detail:`${n}/v1/cli/events/tail · ${a}ms`,latencyMs:a}}catch(e){let t=e.message;return/40\d/.test(t)?{name:`Events stream`,status:`pass`,detail:`endpoint reachable (auth-gated)`}:{name:`Events stream`,status:`fail`,detail:t}}finally{clearTimeout(a)}}async function E(n){let a=n.fetchImpl??fetch,o=[],s=await t().catch(()=>null);o.push({name:`Binary`,status:`pass`,detail:`v${n.cliVersion} (${n.binaryPath})`}),o.push({name:`Config file`,status:s?`pass`:`warn`,detail:e()});let c=await i({strict:!1}).catch(()=>null);o.push({name:`Auth`,status:c?`pass`:`fail`,detail:c?`logged in${c.email?` as ${c.email}`:``}`:`not logged in`});let l=null;if(s)try{l=new r({config:s,cliVersion:n.cliVersion,token:c,fetchImpl:a});let e=await l.ping();o.push({name:`API connection`,status:`pass`,detail:`${s.apiBase.replace(/^https?:\/\//,``)} · ${e.latencyMs}ms`,latencyMs:e.latencyMs})}catch(e){o.push({name:`API connection`,status:`fail`,detail:`${e.message}`})}let u=await g().catch(()=>null);o.push({name:`Auto-update`,status:s?.noUpdateCheck?`warn`:`pass`,detail:s?.noUpdateCheck?`disabled`:u?`latest=${u.manifest.latest}`:`manifest not yet fetched`});let d=s?.apiBase??`https://api.zenovay.com`;return o.push(await S(d,a)),o.push(await C()),o.push(await w()),o.push(await T(l,!!c,d,a)),o}function D(e){return e.some(e=>e.status===`fail`)?1:0}async function O(e){let t=await E(e),n=D(t),r=n===0;return a({json:e.json})?(process.stdout.write(`${JSON.stringify({checks:t,passed:r})}\n`),n):new Promise(e=>{let{unmount:r}=f(p.createElement(k,{checks:t}),{exitOnCtrlC:!0});setImmediate(()=>{r(),e(n)})})}const k=({checks:e})=>p.createElement(o,{title:`Zenovay CLI health check`,state:`idle`},e.map(e=>p.createElement(u,{key:e.name},p.createElement(d,{color:j(e.status)},A(e.status)),p.createElement(d,null,` `),p.createElement(d,{bold:!0},e.name.padEnd(18)),p.createElement(d,{color:`gray`},e.detail))));function A(e){return e===`pass`?`✔`:e===`warn`?`⚠`:e===`skip`?`∼`:`✗`}function j(e){return e===`pass`?`green`:e===`warn`?`yellow`:e===`skip`?`gray`:`red`}export{k as HealthReport,D as exitCodeFor,O as healthCommand,E as runHealthChecks};
1
+ import{configPath as e,readConfig as t}from"./config-CG7B8fR0.js";import{fetchManifest as n}from"./check-D9G0N7NB.js";import{ApiClient as r}from"./api-CJnD6Auw.js";import{readToken as i}from"./token-store-C1AqhmDP.js";import{isHeadless as a}from"./emit-NkY7PE3R.js";import{Panel as o}from"./panel-CYsRlDSL.js";import s from"node:path";import{promises as c}from"node:fs";import l from"node:os";import{Box as u,Text as d,render as f}from"ink";import p from"react";const m=6*60*60*1e3;function h(){return s.join(l.homedir(),`.zenovay`,`update.json`)}async function g(){try{let e=await c.readFile(h(),`utf8`);return JSON.parse(e)}catch{return null}}async function _(e){let t=h();await c.mkdir(s.dirname(t),{recursive:!0,mode:448}),await c.writeFile(t,JSON.stringify(e,null,2))}async function v(){let e=await t();if(e.noUpdateCheck||process.env.ZENOVAY_NO_UPDATE_CHECK===`1`||process.env.CI===`true`)return null;let r=await g();if(r&&Date.now()-r.fetchedAt<m)return r;try{let t=await n({cliBase:e.cliBase}),i={manifest:t,fetchedAt:Date.now(),lastNoticeAt:r?.lastNoticeAt};return await _(i),i}catch{return r}}async function y(){try{await v()}catch{}process.exit(0)}import.meta.url===`file://${process.argv[1]}`&&y();const b=2e3,x=5e3;async function S(e,t){let n=`${e}/mcp`,r=Date.now(),i=new AbortController,a=setTimeout(()=>i.abort(),b);try{let a=await t(n,{method:`GET`,signal:i.signal}),o=Date.now()-r;return a.ok?{name:`MCP server`,status:`pass`,detail:`${e}/mcp · ${o}ms`,latencyMs:o}:{name:`MCP server`,status:`fail`,detail:`HTTP ${a.status}`,latencyMs:o}}catch(e){return{name:`MCP server`,status:`fail`,detail:e.message}}finally{clearTimeout(a)}}async function C(){try{let t=await c.readFile(e(),`utf8`),n=JSON.parse(t),r=n.openaiApiKey;return typeof r==`string`&&r.trim().length>0?{name:`OpenAI key`,status:`pass`,detail:`configured`}:{name:`OpenAI key`,status:`warn`,detail:"not set (run `zenovay ai` to configure)"}}catch(e){return e.code===`ENOENT`?{name:`OpenAI key`,status:`warn`,detail:`no config file`}:{name:`OpenAI key`,status:`warn`,detail:`unreadable config`}}}async function w(){let e=l.homedir(),t=[s.join(e,`.zshrc`),s.join(e,`.bashrc`),s.join(e,`.config`,`fish`,`completions`,`zenovay.fish`)],n=[];for(let e of t)try{let t=await c.readFile(e,`utf8`);(/zenovay\s+(complet|--?complet)/i.test(t)||/_zenovay/.test(t)||/complete\s+-c\s+zenovay/.test(t))&&n.push(s.basename(e))}catch{}return n.length>0?{name:`Completions`,status:`pass`,detail:n.join(`, `)}:{name:`Completions`,status:`warn`,detail:"not installed (run `zenovay completions` after Wave 3)"}}async function T(e,t,n,r){if(!e||!t)return{name:`Events stream`,status:`skip`,detail:`not authenticated`};let i=new AbortController,a=setTimeout(()=>i.abort(),x),o=Date.now();try{let t=await e.openEventsStream(`probe`,i.signal),r=t.body?.getReader();if(r){let e=Promise.race([r.read().then(()=>`first`),new Promise(e=>setTimeout(()=>e(`timeout`),1500))]);await e;try{r.cancel()}catch{}}let a=Date.now()-o;return{name:`Events stream`,status:`pass`,detail:`${n}/v1/cli/events/tail · ${a}ms`,latencyMs:a}}catch(e){let t=e.message;return/40\d/.test(t)?{name:`Events stream`,status:`pass`,detail:`endpoint reachable (auth-gated)`}:{name:`Events stream`,status:`fail`,detail:t}}finally{clearTimeout(a)}}async function E(n){let a=n.fetchImpl??fetch,o=[],s=await t().catch(()=>null);o.push({name:`Binary`,status:`pass`,detail:`v${n.cliVersion} (${n.binaryPath})`}),o.push({name:`Config file`,status:s?`pass`:`warn`,detail:e()});let c=await i({strict:!1}).catch(()=>null);o.push({name:`Auth`,status:c?`pass`:`fail`,detail:c?`logged in${c.email?` as ${c.email}`:``}`:`not logged in`});let l=null;if(s)try{l=new r({config:s,cliVersion:n.cliVersion,token:c,fetchImpl:a});let e=await l.ping();o.push({name:`API connection`,status:`pass`,detail:`${s.apiBase.replace(/^https?:\/\//,``)} · ${e.latencyMs}ms`,latencyMs:e.latencyMs})}catch(e){o.push({name:`API connection`,status:`fail`,detail:`${e.message}`})}let u=await g().catch(()=>null);o.push({name:`Auto-update`,status:s?.noUpdateCheck?`warn`:`pass`,detail:s?.noUpdateCheck?`disabled`:u?`latest=${u.manifest.latest}`:`manifest not yet fetched`});let d=s?.apiBase??`https://api.zenovay.com`;return o.push(await S(d,a)),o.push(await C()),o.push(await w()),o.push(await T(l,!!c,d,a)),o}function D(e){return e.some(e=>e.status===`fail`)?1:0}async function O(e){let t=await E(e),n=D(t),r=n===0;return a({json:e.json})?(process.stdout.write(`${JSON.stringify({checks:t,passed:r})}\n`),n):new Promise(e=>{let{unmount:r}=f(p.createElement(k,{checks:t}),{exitOnCtrlC:!0});setImmediate(()=>{r(),e(n)})})}const k=({checks:e})=>p.createElement(o,{title:`Zenovay CLI health check`,state:`idle`},e.map(e=>p.createElement(u,{key:e.name},p.createElement(d,{color:j(e.status)},A(e.status)),p.createElement(d,null,` `),p.createElement(d,{bold:!0},e.name.padEnd(18)),p.createElement(d,{color:`gray`},e.detail))));function A(e){return e===`pass`?`✔`:e===`warn`?`⚠`:e===`skip`?`∼`:`✗`}function j(e){return e===`pass`?`green`:e===`warn`?`yellow`:e===`skip`?`gray`:`red`}export{k as HealthReport,D as exitCodeFor,O as healthCommand,E as runHealthChecks};
@@ -0,0 +1 @@
1
+ import"./config-CG7B8fR0.js";import"./check-D9G0N7NB.js";import"./api-CJnD6Auw.js";import"./token-store-C1AqhmDP.js";import"./formatter-DDG2TSOz.js";import"./emit-NkY7PE3R.js";import"./panel-CYsRlDSL.js";import{HealthReport as e,exitCodeFor as t,healthCommand as n,runHealthChecks as r}from"./health-CizdEMSG.js";export{n as healthCommand};
@@ -1 +1 @@
1
- import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-UJJ6ube8.js";import{requireTier as r}from"./tier-uaU5pkTz.js";import"./formatter-KOe_hjhc.js";import{emit as i,isHeadless as a}from"./emit-B8RbnBJe.js";import{Panel as o}from"./panel-jycoT562.js";import{Banner as s}from"./banner-gVm7GaJF.js";import"./prompt-Db9Y7CVt.js";import{Keybar as c}from"./keybar-BYQ2Bam1.js";import{resolveSiteId as l}from"./resolve-site-CZEwJoBj.js";import{DataTable as u}from"./data-table-BnWXIW9M.js";import{EmptyState as d}from"./empty-state-BkS6DKWZ.js";import{Box as f,Text as p,render as m,useApp as h,useInput as g}from"ink";import _,{useEffect as v,useState as y}from"react";import b from"ink-spinner";async function x(o){let s=await e(),c=await t({strict:!1});if(!c)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let u=new n({config:s,cliVersion:o.cliVersion,token:c});try{await r(u,`pro`)}catch(e){return process.stderr.write(`${e.message}\n`),2}let d,f;try{({siteId:d,site:f}=await l(u,{explicit:o.siteId,headless:!!o.json,cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let p=f?.url?f.url.replace(/^https?:\/\//,``).replace(/\/$/,``):f?.name??d;if(a(o)){let e=await u.getHeatmaps(d);return i({type:`heatmaps.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=m(_.createElement(S,{api:u,siteId:d,siteLabel:p,cliVersion:o.cliVersion,onExit:n=>{t(),e(n)}}))})}const S=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:a}=h(),[l,m]=y(null),[x,S]=y(!0),[C,w]=y(null);if(g(e=>{e===`q`&&(a(),i(0))}),v(()=>{let n=!1;return(async()=>{try{let r=await e.getHeatmaps(t);n||(m(r),S(!1))}catch(e){n||(w(e.message),S(!1))}})(),()=>{n=!0}},[e,t]),x)return _.createElement(f,{flexDirection:`column`},_.createElement(s,{version:r,subtitle:`heatmaps · ${n}`}),_.createElement(o,{title:`Loading`,state:`busy`},_.createElement(f,null,_.createElement(p,{color:`magenta`},_.createElement(b,{type:`dots`})),_.createElement(p,null,` Fetching heatmaps…`))));if(C)return _.createElement(f,{flexDirection:`column`},_.createElement(s,{version:r,subtitle:`heatmaps · ${n}`}),_.createElement(d,{reason:`error`,headline:`Failed to load`,hint:C}));if(!l||l.length===0)return _.createElement(f,{flexDirection:`column`},_.createElement(s,{version:r,subtitle:`heatmaps · ${n}`}),_.createElement(d,{reason:`no-data`,headline:`No heatmaps yet`,hint:`Enable heatmaps in your site settings`}));let T=[{key:`url`,label:`page`,width:36},{key:`type`,label:`type`,width:12},{key:`captureCount`,label:`captures`,align:`right`,width:10},{key:`createdAt`,label:`first seen`,width:24}];return _.createElement(f,{flexDirection:`column`},_.createElement(s,{version:r,subtitle:`heatmaps · ${n}`}),_.createElement(o,{title:`Heatmaps (${l.length})`},_.createElement(u,{columns:T,data:l,zebra:!0})),_.createElement(f,{marginTop:1},_.createElement(p,{color:`gray`},`Open any heatmap at https://app.zenovay.com/heatmaps`)),_.createElement(c,{items:[{key:`q`,label:`quit`}]}))};export{x as heatmapsCommand};
1
+ import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-DJUWqNhW.js";import{requireTier as r}from"./tier-ztFrvV9H.js";import"./formatter-DDG2TSOz.js";import{emit as i,isHeadless as a}from"./emit-NkY7PE3R.js";import{Panel as o}from"./panel-CYsRlDSL.js";import{Banner as s}from"./banner-Cr0PV2pB.js";import"./prompt-BS9qJvdR.js";import{Keybar as c}from"./keybar-Bh-y__tC.js";import{resolveSiteId as l}from"./resolve-site-CoOL4KPZ.js";import{DataTable as u}from"./data-table-D-JVXhZ7.js";import{EmptyState as d}from"./empty-state-BbUJUNcp.js";import{Box as f,Text as p,render as m,useApp as h,useInput as g}from"ink";import _,{useEffect as v,useState as y}from"react";import b from"ink-spinner";async function x(o){let s=await e(),c=await t({strict:!1});if(!c)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let u=new n({config:s,cliVersion:o.cliVersion,token:c});try{await r(u,`pro`)}catch(e){return process.stderr.write(`${e.message}\n`),2}let d,f;try{({siteId:d,site:f}=await l(u,{explicit:o.siteId,headless:!!o.json,cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let p=f?.url?f.url.replace(/^https?:\/\//,``).replace(/\/$/,``):f?.name??d;if(a(o)){let e=await u.getHeatmaps(d);return i({type:`heatmaps.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=m(_.createElement(S,{api:u,siteId:d,siteLabel:p,cliVersion:o.cliVersion,onExit:n=>{t(),e(n)}}))})}const S=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:a}=h(),[l,m]=y(null),[x,S]=y(!0),[C,w]=y(null);if(g(e=>{e===`q`&&(a(),i(0))}),v(()=>{let n=!1;return(async()=>{try{let r=await e.getHeatmaps(t);n||(m(r),S(!1))}catch(e){n||(w(e.message),S(!1))}})(),()=>{n=!0}},[e,t]),x)return _.createElement(f,{flexDirection:`column`},_.createElement(s,{version:r,subtitle:`heatmaps · ${n}`}),_.createElement(o,{title:`Loading`,state:`busy`},_.createElement(f,null,_.createElement(p,{color:`magenta`},_.createElement(b,{type:`dots`})),_.createElement(p,null,` Fetching heatmaps…`))));if(C)return _.createElement(f,{flexDirection:`column`},_.createElement(s,{version:r,subtitle:`heatmaps · ${n}`}),_.createElement(d,{reason:`error`,headline:`Failed to load`,hint:C}));if(!l||l.length===0)return _.createElement(f,{flexDirection:`column`},_.createElement(s,{version:r,subtitle:`heatmaps · ${n}`}),_.createElement(d,{reason:`no-data`,headline:`No heatmaps yet`,hint:`Enable heatmaps in your site settings`}));let T=[{key:`url`,label:`page`,width:36},{key:`type`,label:`type`,width:12},{key:`captureCount`,label:`captures`,align:`right`,width:10},{key:`createdAt`,label:`first seen`,width:24}];return _.createElement(f,{flexDirection:`column`},_.createElement(s,{version:r,subtitle:`heatmaps · ${n}`}),_.createElement(o,{title:`Heatmaps (${l.length})`},_.createElement(u,{columns:T,data:l,zebra:!0})),_.createElement(f,{marginTop:1},_.createElement(p,{color:`gray`},`Open any heatmap at https://app.zenovay.com/heatmaps`)),_.createElement(c,{items:[{key:`q`,label:`quit`}]}))};export{x as heatmapsCommand};
@@ -1,2 +1,2 @@
1
- import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-UJJ6ube8.js";import"./formatter-KOe_hjhc.js";import{isHeadless as r}from"./emit-B8RbnBJe.js";import{Panel as i}from"./panel-jycoT562.js";import{Banner as a}from"./banner-gVm7GaJF.js";import{Keybar as o}from"./keybar-BYQ2Bam1.js";import{DataTable as s}from"./data-table-BnWXIW9M.js";import{EmptyState as c}from"./empty-state-BkS6DKWZ.js";import{Box as l,Text as u,render as d,useApp as f,useInput as p}from"ink";import m,{useEffect as h,useState as g}from"react";import _ from"ink-spinner";function v(e){if(!e)return`—`;let t=new Date(e);return Number.isNaN(t.getTime())?`—`:t.toISOString().slice(0,10)}async function y(e){let t=await e.me().catch(()=>null),n=t?.user.name?.trim()||t?.user.email||`you`,r=await e.getSites().catch(()=>[]),i=r.map(e=>({id:e.id,name:e.name,domain:e.url.replace(/^https?:\/\//,``).replace(/\/$/,``),lastActive:e.lastActiveAt??null})),a={visitors:0,pageviews:0,deltaPct:null};if(r.length>0){let t=r[0].id,[n,i]=await Promise.all([e.getStats(t,`7d`).catch(()=>null),e.getSources(t,`7d`,`prev`).catch(()=>null)]);n&&(a.visitors=n.visitors,a.pageviews=n.pageviews);let o=i?.sources?.filter(e=>typeof e.delta==`number`)??[];if(o.length>0){let e=o.reduce((e,t)=>e+(t.delta??0),0);a.deltaPct=e/o.length*100}}return{sites:i,weekly:a,userLabel:n}}async function b(i){let a=await e(),o=await t({strict:!1});if(!o)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let s=new n({config:a,cliVersion:i.cliVersion,token:o});if(r(i))try{let e=await y(s);return process.stdout.write(JSON.stringify({sites:e.sites,weekly:{visitors:e.weekly.visitors,pageviews:e.weekly.pageviews,deltaPct:e.weekly.deltaPct}},null,2)+`
1
+ import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-DJUWqNhW.js";import"./formatter-DDG2TSOz.js";import{isHeadless as r}from"./emit-NkY7PE3R.js";import{Panel as i}from"./panel-CYsRlDSL.js";import{Banner as a}from"./banner-Cr0PV2pB.js";import{Keybar as o}from"./keybar-Bh-y__tC.js";import{DataTable as s}from"./data-table-D-JVXhZ7.js";import{EmptyState as c}from"./empty-state-BbUJUNcp.js";import{Box as l,Text as u,render as d,useApp as f,useInput as p}from"ink";import m,{useEffect as h,useState as g}from"react";import _ from"ink-spinner";function v(e){if(!e)return`—`;let t=new Date(e);return Number.isNaN(t.getTime())?`—`:t.toISOString().slice(0,10)}async function y(e){let t=await e.me().catch(()=>null),n=t?.user.name?.trim()||t?.user.email||`you`,r=await e.getSites().catch(()=>[]),i=r.map(e=>({id:e.id,name:e.name,domain:e.url.replace(/^https?:\/\//,``).replace(/\/$/,``),lastActive:e.lastActiveAt??null})),a={visitors:0,pageviews:0,deltaPct:null};if(r.length>0){let t=r[0].id,[n,i]=await Promise.all([e.getStats(t,`7d`).catch(()=>null),e.getSources(t,`7d`,`prev`).catch(()=>null)]);n&&(a.visitors=n.visitors,a.pageviews=n.pageviews);let o=i?.sources?.filter(e=>typeof e.delta==`number`)??[];if(o.length>0){let e=o.reduce((e,t)=>e+(t.delta??0),0);a.deltaPct=e/o.length*100}}return{sites:i,weekly:a,userLabel:n}}async function b(i){let a=await e(),o=await t({strict:!1});if(!o)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let s=new n({config:a,cliVersion:i.cliVersion,token:o});if(r(i))try{let e=await y(s);return process.stdout.write(JSON.stringify({sites:e.sites,weekly:{visitors:e.weekly.visitors,pageviews:e.weekly.pageviews,deltaPct:e.weekly.deltaPct}},null,2)+`
2
2
  `),0}catch(e){return process.stderr.write(`✗ ${e.message}\n`),1}return new Promise(e=>{let{unmount:t}=d(m.createElement(x,{api:s,cliVersion:i.cliVersion,onExit:n=>{t(),e(n)}}))})}const x=({api:e,cliVersion:t,onExit:n})=>{let{exit:r}=f(),[d,b]=g(null),[x,S]=g(!0),[C,w]=g(null);p(e=>{e===`q`&&(r(),n(0))}),h(()=>{let t=!1;return(async()=>{try{let n=await y(e);t||(b(n),S(!1))}catch(e){t||(w(e.message),S(!1))}})(),()=>{t=!0}},[e]);let T=`home · ${d?.userLabel??`…`}`,E=[{key:`q`,label:`quit`}];if(x)return m.createElement(l,{flexDirection:`column`},m.createElement(a,{version:t,subtitle:T}),m.createElement(i,{title:`Loading`,state:`busy`},m.createElement(l,null,m.createElement(u,{color:`cyan`},m.createElement(_,{type:`dots`})),m.createElement(u,null,` Fetching your home dashboard…`))));if(C)return m.createElement(l,{flexDirection:`column`},m.createElement(a,{version:t,subtitle:T}),m.createElement(c,{reason:`error`,headline:`Failed to load`,hint:C}),m.createElement(o,{items:E}));if(!d)return m.createElement(l,{flexDirection:`column`},m.createElement(a,{version:t,subtitle:T}),m.createElement(c,{reason:`no-data`,headline:`No data`}),m.createElement(o,{items:E}));let D=[{key:`name`,label:`site`,width:24},{key:`domain`,label:`domain`,width:32},{key:`lastActive`,label:`last active`,width:12,format:e=>v(e)}],O=d.weekly.deltaPct===null?`—`:`${d.weekly.deltaPct>=0?`+`:``}${d.weekly.deltaPct.toFixed(1)}%`;return m.createElement(l,{flexDirection:`column`},m.createElement(a,{version:t,subtitle:T}),m.createElement(i,{title:`Your sites (${d.sites.length})`},d.sites.length===0?m.createElement(u,{color:`gray`},"No sites yet — run `zenovay init` to add one."):m.createElement(s,{columns:D,data:d.sites,zebra:!0})),m.createElement(i,{title:`This week`},m.createElement(u,null,m.createElement(u,{color:`cyan`},`Visitors`),` `,d.weekly.visitors.toLocaleString(),` `,m.createElement(u,{color:`cyan`},`Pageviews`),` `,d.weekly.pageviews.toLocaleString(),` `,m.createElement(u,{color:`cyan`},`Δ vs last week`),` `,O)),m.createElement(o,{items:E}))};export{b as homeCommand};
@@ -0,0 +1 @@
1
+ import"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import"./token-store-C1AqhmDP.js";import{initCommand as e}from"./init-DR0qzfwC.js";import"./client-Ckr8RqMm.js";import"./formatter-DDG2TSOz.js";import"./emit-NkY7PE3R.js";import"./secrets-DPf_7SkN.js";import"./login-DvZAZlYo.js";import"./panel-CYsRlDSL.js";import"./banner-Cr0PV2pB.js";import"./progress-row-5G_PO8xL.js";import"./prompt-BS9qJvdR.js";import"./keybar-Bh-y__tC.js";import"./sparkline-DM2BGvjD.js";export{e as initCommand};
@@ -1,4 +1,4 @@
1
- import{readConfig as e,updateConfig as t}from"./config-CG7B8fR0.js";import{ApiClient as n}from"./api-CJnD6Auw.js";import{readToken as r}from"./token-store-C1AqhmDP.js";import{parseSseStream as i}from"./client-CN2wyAL7.js";import{emit as a,isHeadless as o}from"./emit-B8RbnBJe.js";import{scrubSecrets as s}from"./secrets-BszMfkn1.js";import{loginCommand as c}from"./login-D2ll-nBp.js";import{Panel as l}from"./panel-jycoT562.js";import{Banner as u}from"./banner-gVm7GaJF.js";import{BrandGradient as d,ProgressRow as f}from"./progress-row-C7gQLX4T.js";import{Select as p}from"./prompt-Db9Y7CVt.js";import{Keybar as m}from"./keybar-BYQ2Bam1.js";import{spark as h}from"./sparkline-BlAQSlYZ.js";import g from"node:path";import{promises as _}from"node:fs";import{z as v}from"zod";import y from"node:os";import b from"node:crypto";import{Box as x,Text as S,render as C,useApp as ee,useInput as w}from"ink";import T,{useEffect as E,useRef as D,useState as O}from"react";import{globby as k}from"globby";import A from"ink-spinner";import{ulid as j}from"ulid";import{applyPatch as M}from"diff";const N=[`@zenovay/tracker`,`@zenovay/next`,`@zenovay/nuxt`,`@zenovay/svelte`,`@zenovay/astro`,`@zenovay/remix`,`@zenovay/node`],P=[`zenovay.config.ts`,`zenovay.config.js`,`zenovay.config.mjs`,`zenovay.config.json`],F=/<script[^>]*src\s*=\s*["']https:\/\/(?:api|cdn)\.zenovay\.com\/[^"']+["'][^>]*>\s*<\/script>/gi,I=/data-id\s*=\s*["'](ZV_[A-Za-z0-9]+)["']/i,L=/data-zenovay-site\s*=\s*["']([^"']+)["']/i,te=[{name:`PostHog`,patterns:[/posthog\.com\b/i,/posthog-js/,/window\.posthog/]},{name:`Plausible`,patterns:[/plausible\.io\/js/i,/window\.plausible/]},{name:`Google Analytics`,patterns:[/googletagmanager\.com\/gtag\/js/i,/www\.google-analytics\.com\/analytics\.js/i,/window\.gtag\b/]},{name:`Mixpanel`,patterns:[/cdn\.mxpnl\.com/i,/mixpanel-browser/]},{name:`Segment`,patterns:[/cdn\.segment\.com\/analytics\.js/i,/window\.analytics\b/]},{name:`Hotjar`,patterns:[/static\.hotjar\.com/i,/\(h,o,t,j,a,r\)/i]},{name:`Amplitude`,patterns:[/cdn\.amplitude\.com/i,/amplitude\.getInstance/]},{name:`Heap`,patterns:[/cdn\.heapanalytics\.com/i]},{name:`FullStory`,patterns:[/fullstory\.com\/s\/fs\.js/i,/window\.FS\.identify/]}];async function R(e,t){let n={zenovayInstalled:!1,correctTrackingCode:!1,foundTrackingCodes:[],zenovayFiles:[],competitors:[],summary:``,recommendation:`fresh-install`};try{let t=await _.readFile(g.join(e,`package.json`),`utf8`),r=JSON.parse(t),i={...r.dependencies,...r.devDependencies};for(let e of N)if(e in i){n.zenovayInstalled=!0,n.packageMarker=e;break}}catch{}for(let t of P)try{await _.access(g.join(e,t)),n.zenovayInstalled=!0,n.configFile=t;break}catch{}let r=await k([`**/*.{html,htm,tsx,jsx,vue,svelte,astro,ts,js,mjs}`,`!node_modules/**`,`!.git/**`,`!dist/**`,`!.next/**`,`!.nuxt/**`,`!build/**`,`!.output/**`],{cwd:e,gitignore:!0,deep:4,absolute:!0}).catch(()=>[]),i=new Map,a=new Set;for(let t of r.slice(0,300)){let r;try{r=await _.readFile(t,`utf8`)}catch{continue}let o=g.relative(e,t),s=r.match(F);if(s&&s.length>0){n.zenovayInstalled=!0;let e=s[0].slice(0,200),t=e.match(I)??e.match(L),r=t?.[1]??null;r&&a.add(r),n.zenovayFiles.push({file:o,currentTrackingCode:r,scriptTagCount:s.length,matchSample:e})}for(let e of te)if(e.patterns.some(e=>e.test(r))){let t=i.get(e.name)??new Set;t.add(o),i.set(e.name,t)}}if(n.foundTrackingCodes=Array.from(a),n.competitors=Array.from(i.entries()).map(([e,t])=>({name:e,files:Array.from(t).slice(0,5)})),n.zenovayInstalled)if(n.foundTrackingCodes.length>0){let e=n.foundTrackingCodes.every(e=>e===t);n.correctTrackingCode=e,n.recommendation=e?`no-op`:`update-tracking-code`}else n.correctTrackingCode=!1,n.recommendation=`no-op`;else n.competitors.length>0?n.recommendation=`fresh-install-alongside-competitor`:n.recommendation=`fresh-install`;return n.summary=ne(n,t),n}function ne(e,t){let n=[];return e.zenovayInstalled?e.foundTrackingCodes.length===0?n.push(`Zenovay package or config detected but no <script> tag found.`):e.correctTrackingCode?n.push(`Zenovay tracker present in ${e.zenovayFiles.length} file(s) with correct ID ${t}.`):n.push(`Zenovay tracker present in ${e.zenovayFiles.length} file(s), but with mismatching ID(s): ${e.foundTrackingCodes.join(`, `)} (target: ${t}).`):n.push(`No Zenovay tracker found.`),e.competitors.length>0&&n.push(`Competitor tracker(s) present (DO NOT modify): ${e.competitors.map(e=>e.name).join(`, `)}.`),n.join(` `)}async function re(e){let t=await R(e,``);return{installed:t.zenovayInstalled,reasons:t.summary?[t.summary]:[],packageMarker:t.packageMarker,configFile:t.configFile,scriptFile:t.zenovayFiles[0]?.file}}const ie=[/^package\.json$/,/^package-lock\.json$/,/^pnpm-lock\.yaml$/,/^yarn\.lock$/,/^bun\.lock$/,/^tsconfig.*\.json$/,/^(next|nuxt|vite|astro|remix|svelte|tailwind|postcss)\.config\.(ts|mts|cts|js|mjs|cjs)$/,/^app\/.*\.(tsx|ts|jsx|js|svelte|astro|vue)$/,/^pages\/.*\.(tsx|ts|jsx|js)$/,/^public\/index\.html$/,/^index\.html$/,/^src\/main\.(tsx|ts|jsx|js)$/,/^src\/App\.(tsx|ts|jsx|js|svelte|vue)$/,/^src\/routes\/\+layout\.(svelte|ts|js)$/,/^src\/routes\/root\..*$/,/^src\/layouts\/.*\.(astro|svelte|vue)$/,/^\.env\.example$/,/^README\.md$/,/^\.gitignore$/,/^nuxt\.config\.(ts|js|mjs)$/,/^plugins\/.*\.(ts|js)$/],ae=[/(^|\/)\.env($|\.(?!example$)[^/]+$)/,/(^|\/)\.git(\/|$)/,/(^|\/)node_modules\//,/(^|\/)\.ssh\//,/(^|\/)\.aws\//,/\.pem$/,/\.key$/,/(^|\/)id_rsa($|\.)/,/(^|\/)\.npmrc$/,/(^|\/)credentials(\.|$)/],z=256*1024,B=50,V=20,H=40;var U=class extends Error{constructor(e,t){super(t),this.code=e,this.name=`SandboxError`}};const W=/<script[^>]*src\s*=\s*["']https:\/\/(?:api|cdn)\.zenovay\.com\/[^"']+["'][^>]*>\s*<\/script>/i,G=[{name:`PostHog`,re:/posthog\.com\b|posthog-js|window\.posthog/i},{name:`Plausible`,re:/plausible\.io\/js|window\.plausible/i},{name:`Google Analytics`,re:/googletagmanager\.com\/gtag\/js|google-analytics\.com\/analytics\.js|window\.gtag\b/i},{name:`Mixpanel`,re:/cdn\.mxpnl\.com|mixpanel-browser/i},{name:`Segment`,re:/cdn\.segment\.com\/analytics\.js|window\.analytics\b/i},{name:`Hotjar`,re:/static\.hotjar\.com|\(h,o,t,j,a,r\)/i},{name:`Amplitude`,re:/cdn\.amplitude\.com|amplitude\.getInstance/i},{name:`Heap`,re:/cdn\.heapanalytics\.com/i},{name:`FullStory`,re:/fullstory\.com\/s\/fs\.js|window\.FS\.identify/i}];var K=class{sessionId;cwd;cwdReal;undoRoot;readCount=0;writeCount=0;roundCount=0;writtenPathsSet=new Set;constructor(e){this.sessionId=e.sessionId??j(),this.cwd=e.cwd,this.cwdReal=_.realpath(e.cwd),this.undoRoot=e.undoRoot??g.join(y.homedir(),`.zenovay`,`undo`)}incrementRound(){if(this.roundCount++,this.roundCount>H)throw new U(`round-cap`,`Tool-call recursion cap (${H}) exceeded.`)}stats(){return{sessionId:this.sessionId,reads:this.readCount,writes:this.writeCount,rounds:this.roundCount,writtenPaths:[...this.writtenPathsSet]}}async resolveForRead(e){return this.resolveSafe(e,`read`)}async resolveForWrite(e){return this.resolveSafe(e,`write`)}async resolveSafe(e,t){if(typeof e!=`string`||e.length===0)throw new U(`escape`,`Path must be a non-empty string.`);if(e.includes(`\0`))throw new U(`escape`,`Null byte in path.`);if(/^\\\\[?.]\\/.test(e)||/^\\\\[A-Za-z0-9]/.test(e))throw new U(`escape`,`Windows special path prefix: ${e}`);if(/%/.test(e))try{let t=decodeURIComponent(e);if(/%[0-9A-Fa-f]{2}/.test(t))throw new U(`escape`,`Double-encoded path: ${e}`);e=t}catch(t){throw t instanceof U?t:new U(`escape`,`Malformed percent-encoding: ${e}`)}if(e.includes(`\0`))throw new U(`escape`,`Null byte in decoded path.`);if(e.includes(`\\`))throw new U(`escape`,`Backslash in path (Windows-style separator not accepted): ${e}`);let n=await this.cwdReal,r=g.isAbsolute(e)?e:g.join(n,e),i=g.normalize(r),a=i;try{a=await _.realpath(i)}catch(e){if(e.code!==`ENOENT`)throw new U(`escape`,`realpath failed: ${e.message}`);let t=g.dirname(i);try{let e=await _.realpath(t);a=g.join(e,g.basename(i))}catch{}}if(!this.isWithin(a,n))throw new U(`escape`,`Path escapes cwd: ${e}`);let o=g.relative(n,a);for(let e of ae)if(e.test(o)){if(t===`read`&&/(^|\/)node_modules\//.test(o))continue;throw new U(`blocklisted`,`Path is on the hard blocklist: ${o}`)}if(t===`write`){let e=ie.some(e=>e.test(o));if(!e&&!/^\.env(\.local)?$/.test(o)&&!/^\.claude\//.test(o)&&!/^\.cursor\//.test(o))throw new U(`not-allowlisted`,`Write path not on allowlist: ${o}`)}return a}isWithin(e,t){let n=g.relative(t,e);return!n.startsWith(`..`)&&!g.isAbsolute(n)}async safeRead(e){if(this.readCount>=B)throw new U(`read-cap`,`Read cap (${B}) reached.`);let t=await this.resolveForRead(e),n=await _.stat(t);if(n.size>z)throw new U(`too-large`,`File exceeds ${z}B: ${e} (${n.size}B)`);let r=await _.readFile(t),i=r.subarray(0,Math.min(r.length,8192));if(i.includes(0))throw new U(`binary-rejected`,`Binary content in ${e}.`);return this.readCount++,r.toString(`utf8`)}async safeWrite(e,t){if(this.writeCount>=V)throw new U(`write-cap`,`Write cap (${V}) reached.`);if(t.length>z)throw new U(`too-large`,`Write exceeds ${z}B: ${e}`);let n=await this.resolveForWrite(e),r=await _.readFile(n,`utf8`).catch(e=>{if(e.code===`ENOENT`)return null;throw e});if(r!==null){if(W.test(r)&&!W.test(t))throw new U(`destructive-tracker-removal`,`Refusing to write ${e}: existing Zenovay tracker tag would be removed. If you want to change the data-id, use patch_file to swap the attribute value instead of overwriting the file.`);for(let{name:n,re:i}of G)if(i.test(r)&&!i.test(t))throw new U(`destructive-competitor-removal`,`Refusing to write ${e}: existing ${n} tracker would be removed. Zenovay installs alongside competitors — never replace them.`)}let i=await this.journalBackup(n);await _.mkdir(g.dirname(n),{recursive:!0}),await _.writeFile(n,t,`utf8`),this.writeCount++;let a=await this.cwdReal;return this.writtenPathsSet.add(g.relative(a,n)),{backupPath:i}}async journalBackup(e){let t=await _.readFile(e).catch(e=>{if(e.code===`ENOENT`)return null;throw e}),n=g.join(this.undoRoot,this.sessionId);await _.mkdir(n,{recursive:!0,mode:448});let r=b.createHash(`sha256`).update(e).digest(`hex`).slice(0,16),i=g.join(n,`${r}.bak`),a=g.join(n,`manifest.jsonl`);t&&await _.writeFile(i,t,{mode:384});let o=JSON.stringify({abs:e,backupPath:t?i:null,ts:Date.now()});return await _.appendFile(a,o+`
1
+ import{readConfig as e,updateConfig as t}from"./config-CG7B8fR0.js";import{ApiClient as n}from"./api-CJnD6Auw.js";import{readToken as r}from"./token-store-C1AqhmDP.js";import{parseSseStream as i}from"./client-Ckr8RqMm.js";import{emit as a,isHeadless as o}from"./emit-NkY7PE3R.js";import{scrubSecrets as s}from"./secrets-DPf_7SkN.js";import{loginCommand as c}from"./login-DvZAZlYo.js";import{Panel as l}from"./panel-CYsRlDSL.js";import{Banner as u}from"./banner-Cr0PV2pB.js";import{BrandGradient as d,ProgressRow as f}from"./progress-row-5G_PO8xL.js";import{Select as p}from"./prompt-BS9qJvdR.js";import{Keybar as m}from"./keybar-Bh-y__tC.js";import{spark as h}from"./sparkline-DM2BGvjD.js";import g from"node:path";import{promises as _}from"node:fs";import{z as v}from"zod";import y from"node:os";import b from"node:crypto";import{Box as x,Text as S,render as C,useApp as ee,useInput as w}from"ink";import T,{useEffect as E,useRef as D,useState as O}from"react";import{globby as k}from"globby";import A from"ink-spinner";import{ulid as j}from"ulid";import{applyPatch as M}from"diff";const N=[`@zenovay/tracker`,`@zenovay/next`,`@zenovay/nuxt`,`@zenovay/svelte`,`@zenovay/astro`,`@zenovay/remix`,`@zenovay/node`],P=[`zenovay.config.ts`,`zenovay.config.js`,`zenovay.config.mjs`,`zenovay.config.json`],F=/<script[^>]*src\s*=\s*["']https:\/\/(?:api|cdn)\.zenovay\.com\/[^"']+["'][^>]*>\s*<\/script>/gi,I=/data-id\s*=\s*["'](ZV_[A-Za-z0-9]+)["']/i,L=/data-zenovay-site\s*=\s*["']([^"']+)["']/i,te=[{name:`PostHog`,patterns:[/posthog\.com\b/i,/posthog-js/,/window\.posthog/]},{name:`Plausible`,patterns:[/plausible\.io\/js/i,/window\.plausible/]},{name:`Google Analytics`,patterns:[/googletagmanager\.com\/gtag\/js/i,/www\.google-analytics\.com\/analytics\.js/i,/window\.gtag\b/]},{name:`Mixpanel`,patterns:[/cdn\.mxpnl\.com/i,/mixpanel-browser/]},{name:`Segment`,patterns:[/cdn\.segment\.com\/analytics\.js/i,/window\.analytics\b/]},{name:`Hotjar`,patterns:[/static\.hotjar\.com/i,/\(h,o,t,j,a,r\)/i]},{name:`Amplitude`,patterns:[/cdn\.amplitude\.com/i,/amplitude\.getInstance/]},{name:`Heap`,patterns:[/cdn\.heapanalytics\.com/i]},{name:`FullStory`,patterns:[/fullstory\.com\/s\/fs\.js/i,/window\.FS\.identify/]}];async function R(e,t){let n={zenovayInstalled:!1,correctTrackingCode:!1,foundTrackingCodes:[],zenovayFiles:[],competitors:[],summary:``,recommendation:`fresh-install`};try{let t=await _.readFile(g.join(e,`package.json`),`utf8`),r=JSON.parse(t),i={...r.dependencies,...r.devDependencies};for(let e of N)if(e in i){n.zenovayInstalled=!0,n.packageMarker=e;break}}catch{}for(let t of P)try{await _.access(g.join(e,t)),n.zenovayInstalled=!0,n.configFile=t;break}catch{}let r=await k([`**/*.{html,htm,tsx,jsx,vue,svelte,astro,ts,js,mjs}`,`!node_modules/**`,`!.git/**`,`!dist/**`,`!.next/**`,`!.nuxt/**`,`!build/**`,`!.output/**`],{cwd:e,gitignore:!0,deep:4,absolute:!0}).catch(()=>[]),i=new Map,a=new Set;for(let t of r.slice(0,300)){let r;try{r=await _.readFile(t,`utf8`)}catch{continue}let o=g.relative(e,t),s=r.match(F);if(s&&s.length>0){n.zenovayInstalled=!0;let e=s[0].slice(0,200),t=e.match(I)??e.match(L),r=t?.[1]??null;r&&a.add(r),n.zenovayFiles.push({file:o,currentTrackingCode:r,scriptTagCount:s.length,matchSample:e})}for(let e of te)if(e.patterns.some(e=>e.test(r))){let t=i.get(e.name)??new Set;t.add(o),i.set(e.name,t)}}if(n.foundTrackingCodes=Array.from(a),n.competitors=Array.from(i.entries()).map(([e,t])=>({name:e,files:Array.from(t).slice(0,5)})),n.zenovayInstalled)if(n.foundTrackingCodes.length>0){let e=n.foundTrackingCodes.every(e=>e===t);n.correctTrackingCode=e,n.recommendation=e?`no-op`:`update-tracking-code`}else n.correctTrackingCode=!1,n.recommendation=`no-op`;else n.competitors.length>0?n.recommendation=`fresh-install-alongside-competitor`:n.recommendation=`fresh-install`;return n.summary=ne(n,t),n}function ne(e,t){let n=[];return e.zenovayInstalled?e.foundTrackingCodes.length===0?n.push(`Zenovay package or config detected but no <script> tag found.`):e.correctTrackingCode?n.push(`Zenovay tracker present in ${e.zenovayFiles.length} file(s) with correct ID ${t}.`):n.push(`Zenovay tracker present in ${e.zenovayFiles.length} file(s), but with mismatching ID(s): ${e.foundTrackingCodes.join(`, `)} (target: ${t}).`):n.push(`No Zenovay tracker found.`),e.competitors.length>0&&n.push(`Competitor tracker(s) present (DO NOT modify): ${e.competitors.map(e=>e.name).join(`, `)}.`),n.join(` `)}async function re(e){let t=await R(e,``);return{installed:t.zenovayInstalled,reasons:t.summary?[t.summary]:[],packageMarker:t.packageMarker,configFile:t.configFile,scriptFile:t.zenovayFiles[0]?.file}}const ie=[/^package\.json$/,/^package-lock\.json$/,/^pnpm-lock\.yaml$/,/^yarn\.lock$/,/^bun\.lock$/,/^tsconfig.*\.json$/,/^(next|nuxt|vite|astro|remix|svelte|tailwind|postcss)\.config\.(ts|mts|cts|js|mjs|cjs)$/,/^app\/.*\.(tsx|ts|jsx|js|svelte|astro|vue)$/,/^pages\/.*\.(tsx|ts|jsx|js)$/,/^public\/index\.html$/,/^index\.html$/,/^src\/main\.(tsx|ts|jsx|js)$/,/^src\/App\.(tsx|ts|jsx|js|svelte|vue)$/,/^src\/routes\/\+layout\.(svelte|ts|js)$/,/^src\/routes\/root\..*$/,/^src\/layouts\/.*\.(astro|svelte|vue)$/,/^\.env\.example$/,/^README\.md$/,/^\.gitignore$/,/^nuxt\.config\.(ts|js|mjs)$/,/^plugins\/.*\.(ts|js)$/],ae=[/(^|\/)\.env($|\.(?!example$)[^/]+$)/,/(^|\/)\.git(\/|$)/,/(^|\/)node_modules\//,/(^|\/)\.ssh\//,/(^|\/)\.aws\//,/\.pem$/,/\.key$/,/(^|\/)id_rsa($|\.)/,/(^|\/)\.npmrc$/,/(^|\/)credentials(\.|$)/],z=256*1024,B=50,V=20,H=40;var U=class extends Error{constructor(e,t){super(t),this.code=e,this.name=`SandboxError`}};const W=/<script[^>]*src\s*=\s*["']https:\/\/(?:api|cdn)\.zenovay\.com\/[^"']+["'][^>]*>\s*<\/script>/i,G=[{name:`PostHog`,re:/posthog\.com\b|posthog-js|window\.posthog/i},{name:`Plausible`,re:/plausible\.io\/js|window\.plausible/i},{name:`Google Analytics`,re:/googletagmanager\.com\/gtag\/js|google-analytics\.com\/analytics\.js|window\.gtag\b/i},{name:`Mixpanel`,re:/cdn\.mxpnl\.com|mixpanel-browser/i},{name:`Segment`,re:/cdn\.segment\.com\/analytics\.js|window\.analytics\b/i},{name:`Hotjar`,re:/static\.hotjar\.com|\(h,o,t,j,a,r\)/i},{name:`Amplitude`,re:/cdn\.amplitude\.com|amplitude\.getInstance/i},{name:`Heap`,re:/cdn\.heapanalytics\.com/i},{name:`FullStory`,re:/fullstory\.com\/s\/fs\.js|window\.FS\.identify/i}];var K=class{sessionId;cwd;cwdReal;undoRoot;readCount=0;writeCount=0;roundCount=0;writtenPathsSet=new Set;constructor(e){this.sessionId=e.sessionId??j(),this.cwd=e.cwd,this.cwdReal=_.realpath(e.cwd),this.undoRoot=e.undoRoot??g.join(y.homedir(),`.zenovay`,`undo`)}incrementRound(){if(this.roundCount++,this.roundCount>H)throw new U(`round-cap`,`Tool-call recursion cap (${H}) exceeded.`)}stats(){return{sessionId:this.sessionId,reads:this.readCount,writes:this.writeCount,rounds:this.roundCount,writtenPaths:[...this.writtenPathsSet]}}async resolveForRead(e){return this.resolveSafe(e,`read`)}async resolveForWrite(e){return this.resolveSafe(e,`write`)}async resolveSafe(e,t){if(typeof e!=`string`||e.length===0)throw new U(`escape`,`Path must be a non-empty string.`);if(e.includes(`\0`))throw new U(`escape`,`Null byte in path.`);if(/^\\\\[?.]\\/.test(e)||/^\\\\[A-Za-z0-9]/.test(e))throw new U(`escape`,`Windows special path prefix: ${e}`);if(/%/.test(e))try{let t=decodeURIComponent(e);if(/%[0-9A-Fa-f]{2}/.test(t))throw new U(`escape`,`Double-encoded path: ${e}`);e=t}catch(t){throw t instanceof U?t:new U(`escape`,`Malformed percent-encoding: ${e}`)}if(e.includes(`\0`))throw new U(`escape`,`Null byte in decoded path.`);if(e.includes(`\\`))throw new U(`escape`,`Backslash in path (Windows-style separator not accepted): ${e}`);let n=await this.cwdReal,r=g.isAbsolute(e)?e:g.join(n,e),i=g.normalize(r),a=i;try{a=await _.realpath(i)}catch(e){if(e.code!==`ENOENT`)throw new U(`escape`,`realpath failed: ${e.message}`);let t=g.dirname(i);try{let e=await _.realpath(t);a=g.join(e,g.basename(i))}catch{}}if(!this.isWithin(a,n))throw new U(`escape`,`Path escapes cwd: ${e}`);let o=g.relative(n,a);for(let e of ae)if(e.test(o)){if(t===`read`&&/(^|\/)node_modules\//.test(o))continue;throw new U(`blocklisted`,`Path is on the hard blocklist: ${o}`)}if(t===`write`){let e=ie.some(e=>e.test(o));if(!e&&!/^\.env(\.local)?$/.test(o)&&!/^\.claude\//.test(o)&&!/^\.cursor\//.test(o))throw new U(`not-allowlisted`,`Write path not on allowlist: ${o}`)}return a}isWithin(e,t){let n=g.relative(t,e);return!n.startsWith(`..`)&&!g.isAbsolute(n)}async safeRead(e){if(this.readCount>=B)throw new U(`read-cap`,`Read cap (${B}) reached.`);let t=await this.resolveForRead(e),n=await _.stat(t);if(n.size>z)throw new U(`too-large`,`File exceeds ${z}B: ${e} (${n.size}B)`);let r=await _.readFile(t),i=r.subarray(0,Math.min(r.length,8192));if(i.includes(0))throw new U(`binary-rejected`,`Binary content in ${e}.`);return this.readCount++,r.toString(`utf8`)}async safeWrite(e,t){if(this.writeCount>=V)throw new U(`write-cap`,`Write cap (${V}) reached.`);if(t.length>z)throw new U(`too-large`,`Write exceeds ${z}B: ${e}`);let n=await this.resolveForWrite(e),r=await _.readFile(n,`utf8`).catch(e=>{if(e.code===`ENOENT`)return null;throw e});if(r!==null){if(W.test(r)&&!W.test(t))throw new U(`destructive-tracker-removal`,`Refusing to write ${e}: existing Zenovay tracker tag would be removed. If you want to change the data-id, use patch_file to swap the attribute value instead of overwriting the file.`);for(let{name:n,re:i}of G)if(i.test(r)&&!i.test(t))throw new U(`destructive-competitor-removal`,`Refusing to write ${e}: existing ${n} tracker would be removed. Zenovay installs alongside competitors — never replace them.`)}let i=await this.journalBackup(n);await _.mkdir(g.dirname(n),{recursive:!0}),await _.writeFile(n,t,`utf8`),this.writeCount++;let a=await this.cwdReal;return this.writtenPathsSet.add(g.relative(a,n)),{backupPath:i}}async journalBackup(e){let t=await _.readFile(e).catch(e=>{if(e.code===`ENOENT`)return null;throw e}),n=g.join(this.undoRoot,this.sessionId);await _.mkdir(n,{recursive:!0,mode:448});let r=b.createHash(`sha256`).update(e).digest(`hex`).slice(0,16),i=g.join(n,`${r}.bak`),a=g.join(n,`manifest.jsonl`);t&&await _.writeFile(i,t,{mode:384});let o=JSON.stringify({abs:e,backupPath:t?i:null,ts:Date.now()});return await _.appendFile(a,o+`
2
2
  `,{mode:384}),t?i:null}static wrapForModel(e,t){let n=b.createHash(`sha256`).update(t).digest(`hex`).slice(0,16),r=t.replaceAll(`&`,`&amp;`).replaceAll(`<`,`&lt;`).replaceAll(`>`,`&gt;`);return`<FILE path="${e}" sha256="${n}">\n${r}\n</FILE>`}static scrubSecrets(e){return s(e)}};const oe=[`astro.config.ts`,`astro.config.mjs`,`astro.config.js`];async function se(e){for(let t of oe)if(await e.exists(t))return{matched:!0,confidence:.95,reason:`Detected Astro via \`${t}\`.`};let t=await e.readFile(`package.json`);if(t)try{let e=JSON.parse(t);if(e.dependencies?.astro??e.devDependencies?.astro)return{matched:!0,confidence:.8,reason:"Detected Astro via `astro` dependency."}}catch{}return{matched:!1,confidence:0,reason:"No astro.config.* or `astro` dependency found."}}function ce(e){let t=e.trackingCode??e.siteId??``,n=`<script defer data-id="${t}" data-allow-localhost="true" src="https://api.zenovay.com/z.js" is:inline></script>`;return[{targetPath:`src/layouts/Layout.astro`,anchorKind:`head-tag`,code:n,description:`Inject the Zenovay tracker inside <head> of the primary layout.`},{targetPath:`src/layouts/BaseHead.astro`,anchorKind:`head-tag`,code:n,description:"Fallback target when the project uses a dedicated `BaseHead.astro`."}]}const le={id:`astro`,displayName:`Astro`,detect:se,files:[{path:`src/layouts/Layout.astro`,kind:`mutate`,required:!1},{path:`src/layouts/BaseHead.astro`,kind:`mutate`,required:!1},{path:`.env`,kind:`create`,required:!0}],envVarName:`PUBLIC_ZENOVAY_SITE`,buildSnippets:ce},ue=[`app/layout.tsx`,`app/layout.ts`,`app/layout.jsx`,`app/layout.js`];async function de(e){for(let t of ue)if(await e.exists(t))return t;return null}async function fe(e){let t=await e.readFile(`package.json`);if(!t)return!1;try{let e=JSON.parse(t);return!!(e.dependencies?.next??e.devDependencies?.next)}catch{return!1}}async function pe(e){let t=await fe(e),n=await e.exists(`app`),r=await de(e);return t?n?r?{matched:!0,confidence:.95,reason:`Detected Next.js App Router via \`next\` dep + \`${r}\`.`}:{matched:!1,confidence:.4,reason:"Found `app/` but no root layout file (layout.tsx/ts/jsx/js)."}:{matched:!1,confidence:0,reason:"No `app/` directory found — not an App Router project."}:{matched:!1,confidence:0,reason:"package.json does not list `next` as a dependency."}}function me(e,t=`script`){let n=`app/layout.tsx`,r=e.trackingCode??e.siteId??``;return t===`npm`?ge(n,r):he(n,r)}function he(e,t){return[{targetPath:e,anchorKind:`after-imports`,code:`import Script from 'next/script';`,description:`Import next/script to inject the Zenovay tracker.`},{targetPath:e,anchorKind:`wrap-children`,code:`<Script
3
3
  defer
4
4
  data-id="${t}"
@@ -67,7 +67,7 @@ export default function App({ Component, pageProps }: AppProps) {
67
67
  `)+`
68
68
  `;if(o)await _.writeFile(i,f,`utf8`);else{let e=await _.open(i,`w`,384);try{await e.writeFile(f,`utf8`)}finally{await e.close()}}return{created:!o,existing:o,addedKeys:c,skippedKeys:l}}const Ue=`https://api.zenovay.com/mcp`,We=v.object({url:v.string().url(),headers:v.record(v.string(),v.string()).optional()}),Ge=v.object({mcpServers:v.record(v.string(),We).optional()}).passthrough();function Ke(e){return e.HOME??e.USERPROFILE??y.homedir()}function qe(e){return e.APPDATA??null}function Je(e,t){let n=Ke(t),r=qe(t),i=[];return i.push({id:`cursor`,displayName:`Cursor`,configPath:g.join(n,`.cursor`,`mcp.json`)}),e===`win32`&&r&&i.push({id:`cursor`,displayName:`Cursor (AppData)`,configPath:g.join(r,`Cursor`,`User`,`globalStorage`,`cursor.mcp`,`mcp.json`)}),e===`darwin`?i.push({id:`claude-desktop`,displayName:`Claude Desktop`,configPath:g.join(n,`Library`,`Application Support`,`Claude`,`claude_desktop_config.json`)}):e===`win32`&&r?i.push({id:`claude-desktop`,displayName:`Claude Desktop`,configPath:g.join(r,`Claude`,`claude_desktop_config.json`)}):i.push({id:`claude-desktop`,displayName:`Claude Desktop`,configPath:g.join(n,`.config`,`Claude`,`claude_desktop_config.json`)}),i.push({id:`vscode`,displayName:`VS Code`,configPath:g.join(n,`.vscode`,`mcp.json`)}),i}async function Ye(e){try{return await _.access(e),!0}catch{return!1}}async function Xe(e){try{let t=await _.readFile(e,`utf8`);if(t.trim().length===0)return{};let n=JSON.parse(t),r=Ge.safeParse(n);return r.success?r.data:n&&typeof n==`object`?n:{}}catch{return{}}}function Ze(e){return{url:Ue,headers:{Authorization:`Bearer ${e}`}}}async function Y(e){let t=e.env??process.env,n=e.platform??process.platform,r=new Set(e.skip??[]),i=[],a=[],o=[],s=new Set,c=Ze(e.accessToken);for(let e of Je(n,t)){if(r.has(e.id)){a.push(e.displayName);continue}if(s.has(e.configPath))continue;s.add(e.configPath);try{let t=await Ye(e.configPath);if(!t){a.push(e.displayName);continue}let n=await Xe(e.configPath),r=`${e.configPath}.bak`;await _.copyFile(e.configPath,r);let o={...n,mcpServers:{...n.mcpServers??{},zenovay:c}};await _.mkdir(g.dirname(e.configPath),{recursive:!0}),await _.writeFile(e.configPath,JSON.stringify(o,null,2)+`
69
69
  `,`utf8`),i.push(e.displayName)}catch(t){o.push({client:e.displayName,message:t instanceof Error?t.message:String(t)})}}return{installed:i,skipped:a,errors:o}}async function Qe(e,t,n){let r=n.timeoutMs??18e4,i=n.pollIntervalMs??2e3,a=n.now??(()=>Date.now()),o=n.sleep??(e=>new Promise(t=>setTimeout(t,e))),s=a(),c=s+r;for(n.onTick?.(0);;){let l=await n.api.getFirstEvent({siteId:e,since:t});if(l.received)return{received:!0,event:l.event};let u=a()-s;if(u>=r)return{received:!1};let d=c-a(),f=Math.min(i,Math.max(0,d));if(f<=0)return{received:!1};await o(f),n.onTick?.(a()-s)}}const $e=v.object({path:v.string().min(1)}),et=v.object({path:v.string().min(1),content:v.string(),reason:v.string().min(1)}),tt=v.object({path:v.string().min(1),patch:v.string().min(1),reason:v.string().min(1)}),nt=v.object({}),rt=v.object({question:v.string().min(1),choices:v.array(v.string()).optional()});async function it(e,t){let n=$e.safeParse(t);if(!n.success)return{ok:!1,content:null,error:`invalid_args`};try{let t=await e.safeRead(n.data.path),r=K.scrubSecrets(t);return{ok:!0,content:K.wrapForModel(n.data.path,r)}}catch(e){return{ok:!1,content:null,error:e.message}}}async function at(e,t,n){let r=et.safeParse(t);if(!r.success)return{ok:!1,content:null,error:`invalid_args`};let{path:i,content:a,reason:o}=r.data,s=``;try{s=await e.safeRead(i)}catch{s=``}let c=await n.approve({path:i,oldContent:s,newContent:a,reason:o});if(c===`n`)return{ok:!1,content:null,error:`skipped_by_user`};if(c===`e`)return{ok:!1,content:null,error:`deferred_to_user_edit`};try{let{backupPath:t}=await e.safeWrite(i,a);return{ok:!0,content:{path:i,backupPath:t}}}catch(e){return{ok:!1,content:null,error:e.message}}}async function ot(e,t,n){let r=tt.safeParse(t);if(!r.success)return{ok:!1,content:null,error:`invalid_args`};let{path:i,patch:a,reason:o}=r.data;if(/^\*\*\*\s+Begin Patch/m.test(a)||/^\*\*\*\s+Update File:/m.test(a))return{ok:!1,content:null,error:'unsupported_patch_format: This tool only accepts STANDARD unified diff with `--- a/...`, `+++ b/...`, and `@@ -N,M +N,M @@` headers. The "*** Begin Patch / *** Update File:" V4A format is NOT supported. Please call write_file with the full new file content instead.'};let s;try{s=await e.safeRead(i)}catch(e){return{ok:!1,content:null,error:e.message}}let c;try{c=M(s,a)}catch(e){return{ok:!1,content:null,error:`patch_failed: ${e.message}. Please call write_file with the full new file content instead — write_file is more reliable than patch_file for this use case.`}}return c===!1||typeof c!=`string`?{ok:!1,content:null,error:`patch_did_not_apply_cleanly. The patch context may not match the file. Please call write_file with the full new file content instead.`}:at(e,{path:i,content:c,reason:o},n)}async function st(e){try{let t=ze(e),{adapter:n,ranked:r}=await q(t);return{ok:!0,content:{matched:n!==null,adapter:n?.id,displayName:n?.displayName,ranked:r.map(e=>({id:e.adapter.id,confidence:e.result.confidence,reason:e.result.reason}))}}}catch(e){return{ok:!1,content:null,error:e.message}}}async function ct(e,t){let n=rt.safeParse(t);if(!n.success)return{ok:!1,content:null,error:`invalid_args`};try{let t=await e.ask(n.data);return{ok:!0,content:{answer:t}}}catch(e){return{ok:!1,content:null,error:e.message}}}async function lt(e){let{api:t,sandbox:n,approval:r,prompter:a,handlers:o}=e,s=[...e.initialMessages],c=``,l=0;for(;l<H;){n.incrementRound(),l++;let u=await t.openAiStream(`install`,{messages:s,cwd_fingerprint:n.sessionId,diagnosis:e.diagnosis,targetTrackingCode:e.targetTrackingCode}),d=[],f=``;for await(let e of i(u))switch(e.type){case`delta`:f+=e.content,o?.onDelta?.(e.content);break;case`tool_start`:o?.onToolStart?.({id:e.id,name:e.name});break;case`tool_call`:{let t=await ut(e.name,e.arguments,{sandbox:n,cwd:n.cwd,approval:r,prompter:a});d.push({id:e.id,name:e.name,arguments:e.arguments,result:t}),o?.onToolResult?.({id:e.id,name:e.name,result:t});break}case`usage`:o?.onUsage?.(e);break;case`error`:throw o?.onError?.(e),Error(`[${e.code}] ${e.message}`);case`done`:break}if(f&&(c+=f),d.length===0){f&&s.push({role:`assistant`,content:f});break}s.push({role:`assistant`,content:f,toolCalls:d.map(e=>({id:e.id,type:`function`,function:{name:e.name,arguments:JSON.stringify(e.arguments)}}))});for(let e of d)s.push({role:`tool`,toolCallId:e.id,toolName:e.name,content:JSON.stringify(e.result)})}return{finalText:c,rounds:l}}async function ut(e,t,n){try{switch(e){case`read_file`:return await it(n.sandbox,t);case`write_file`:return await at(n.sandbox,t,n.approval);case`patch_file`:return await ot(n.sandbox,t,n.approval);case`detect_framework`:return await st(n.cwd);case`ask_user`:return await ct(n.prompter,t);default:return{ok:!1,content:null,error:`unknown_tool:${e}`}}}catch(e){return{ok:!1,content:null,error:`tool_threw: ${e.message}`}}}const dt=e=>`<script defer\n data-id="${e}"\n data-allow-localhost="true"\n src="https://api.zenovay.com/z.js">\n</script>`;async function ft(e){let t={installed:[],skipped:[],errors:[]},n=await k([`**/*.html`,`!node_modules/**`,`!.git/**`,`!dist/**`,`!.next/**`,`!.nuxt/**`,`!build/**`,`!.output/**`],{cwd:e.cwd,gitignore:!0,absolute:!1});if(n.length===0)return t;let r=dt(e.trackingCode),i=RegExp(`data-id\\s*=\\s*["']${pt(e.trackingCode)}["']`);for(let a of n){let n=g.join(e.cwd,a),o;try{o=await _.readFile(n,`utf8`)}catch(e){t.errors.push({file:a,error:e.message});continue}if(W.test(o)&&i.test(o)){t.skipped.push({file:a,reason:`already installed with correct tracking code`});continue}let s;if(W.test(o))s=o.replace(/(<script[^>]*src\s*=\s*["']https:\/\/(?:api|cdn)\.zenovay\.com\/[^"']+["'][^>]*>)/i,t=>t.replace(/data-id\s*=\s*["']ZV_\w+["']/i,`data-id="${e.trackingCode}"`)),s===o&&(s=o.replace(/<script(\s)/i,`<script$1data-id="${e.trackingCode}"$1`));else if(e.updateOnly){t.skipped.push({file:a,reason:`updateOnly=true and no Zenovay tag present`});continue}else if(/<\/head>/i.test(o)){if(s=o.replace(/(\n[\t ]*)?<\/head>/i,(e,t)=>{let n=t??`
70
- `,i=r.replace(/\n/g,`${n}`);return`${n}${i}${n}</head>`}),s===o){t.skipped.push({file:a,reason:`</head> regex did not match unexpectedly`});continue}}else{t.skipped.push({file:a,reason:`no <head>...</head> in file (fragment or non-page)`});continue}let c=null;for(let{name:e,re:t}of G)if(t.test(o)&&!t.test(s)){c=e;break}if(c){t.errors.push({file:a,error:`would remove ${c} tracker — refusing to write`});continue}try{await _.writeFile(n,s,`utf8`),t.installed.push(a)}catch(e){t.errors.push({file:a,error:e.message})}}return t}function pt(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function mt(){let e=[12,15,18,22,28,35,41,50,58,64,72,78],t=h(e,24);return[` ↑`,` ${t}`,` └────────────────────────`,` May Jun Jul Aug Sep`]}function ht(){return[` Landing page ████████████████████ 100%`,` ↓ -28%`,` Pricing ██████████████░░░░░░ 72%`,` ↓ -50%`,` Checkout ███████░░░░░░░░░░░░░ 36%`,` ↓ -64%`,` Purchased ███░░░░░░░░░░░░░░░░░ 13%`]}function gt(){return[` ▇▇▇▇▇▇▇▇▇▎ 89 Sarah K. /pricing 🇺🇸`,` ▇▇▇▇▇▇░░░░ 61 anon /docs 🇩🇪`,` ▇▇▇░░░░░░░ 34 anon /changelog 🇯🇵`]}function _t(){return[` LCP ● 2.1s good ████████████░░░░░░`,` INP ● 89ms good ██████████████████`,` CLS ⚠ 0.14 needs ████████████░░░░░░`,` TTFB ● 380ms good ███████████████░░░`]}const X=[{title:`Welcome`,body:[`The wizard is an agent — it handles the entire`,`Zenovay setup process on your behalf.`,``,`Reading your project, deciding where the tracker`,`belongs, and writing the snippet for you.`]},{title:`Events`,body:[`Events are the foundation of Zenovay analytics.`,``,`Every pageview, click, and custom action is an`,`event. Group them into Goals to track conversions.`]},{title:`Trends`,body:[`Use trends to measure growth.`,``,`See how visitors, signups, and revenue have`,`changed over the last week, month, or quarter.`],visual:mt},{title:`Funnels`,body:[`Funnels reveal where users drop off.`,``,`Define the steps you care about — landing,`,`pricing, checkout, purchase — and Zenovay shows`,`the per-step conversion rate.`],visual:ht},{title:`Live visitors`,body:[`Watch every visitor in real time, ranked by an`,`AI score that highlights high-intent traffic.`,``,"Use `zenovay visitors --live` after install."],visual:gt},{title:`Core Web Vitals`,body:[`LCP, INP, CLS — Google's page-experience metrics,`,`collected automatically once the tracker is in.`,``,"Use `zenovay vitals` to see them per page + device."],visual:_t},{title:`MCP integration`,body:[`Your CLI session can install Zenovay's MCP server`,`into Cursor / Claude Desktop / VS Code.`,``,`Then ask your AI: "what were my top pages today?"`,`and it queries Zenovay directly.`]},{title:`AI insights`,body:[`Zenovay watches your data and surfaces anomalies`,`automatically — traffic spikes, error bursts,`,`revenue drops — without you needing to ask.`,``,"Run `zenovay ai` after install to chat with them."]},{title:`Privacy-first`,body:[`No cookies required. No third-party trackers.`,`Cookieless mode is one toggle in your dashboard.`,``,`GDPR, CCPA, and PECR-compliant out of the box.`]}],vt=8e3,yt=({width:e,height:t})=>{let[n,r]=O(0);E(()=>{let e=setInterval(()=>{r(e=>(e+1)%X.length)},vt);return()=>clearInterval(e)},[]);let i=X[n],a=i.visual?i.visual():[],o=X.map((e,t)=>t===n?`●`:`·`).join(` `);return T.createElement(x,{flexDirection:`column`,width:e,height:t,paddingX:2,paddingY:1},T.createElement(x,{marginBottom:1},T.createElement(S,{color:`magentaBright`,bold:!0},`Learn`)),T.createElement(x,{marginBottom:1},T.createElement(S,{bold:!0,color:`white`},i.title)),i.body.map((e,t)=>T.createElement(S,{key:t,color:`gray`},e||` `)),a.length>0&&T.createElement(x,{flexDirection:`column`,marginTop:1},a.map((e,t)=>T.createElement(S,{key:t,color:`cyan`},e))),T.createElement(x,{flexGrow:1}),T.createElement(x,{marginTop:1},T.createElement(S,{color:`gray`,dimColor:!0},o,` · `,n+1,` / `,X.length)))},bt={pending:`·`,active:`⠋`,done:`✓`,error:`✗`},xt={pending:`gray`,active:`magenta`,done:`green`,error:`red`},St=({tasks:e,width:t,height:n,liveLine:r})=>{let i=e.filter(e=>e.status===`done`).length;return T.createElement(x,{flexDirection:`column`,width:t,height:n,paddingX:2,paddingY:1},T.createElement(x,{marginBottom:1},T.createElement(S,{color:`magentaBright`,bold:!0},`Tasks`)),e.map(e=>T.createElement(x,{key:e.id,flexDirection:`column`},T.createElement(x,null,e.status===`active`?T.createElement(S,{color:`magenta`},T.createElement(A,{type:`dots`})):T.createElement(S,{color:xt[e.status]},bt[e.status]),T.createElement(S,null,` `),T.createElement(S,{color:e.status===`pending`?`gray`:`white`},e.label)),e.detail&&T.createElement(x,{paddingLeft:2},T.createElement(S,{color:`gray`,dimColor:!0},e.detail)))),T.createElement(x,{flexGrow:1}),r&&T.createElement(x,{marginTop:1},T.createElement(S,{color:`cyan`},`◆ `),T.createElement(S,{color:`white`},r)),T.createElement(x,{marginTop:1},T.createElement(S,{color:`gray`,dimColor:!0},i,` / `,e.length)))};async function Ct(e){if(o(e))return wt(e);let t=`quit`,n=null,r=await new Promise(r=>{let{unmount:i,waitUntilExit:a}=C(T.createElement(Tt,{opts:e,onExit:(e,a,o)=>{t=a??`quit`,n=o??null,i(),r(e)}}));a().catch(()=>r(1))});if(r!==0||t===`quit`||!n)return r;let i=n.id;if(t===`watch`){let{watchCommand:t}=await import(`./watch-DeWYzdo4.js`);return t({cliVersion:e.cliVersion,siteId:i})}if(t===`events`){let{eventsTailCommand:t}=await import(`./events-tail-CE5QxNmF.js`);return t({cliVersion:e.cliVersion,siteId:i})}return 0}async function wt(t){try{let i=await e(),o=await Be(t.cwd);if(!o)return a({type:`error`,code:`no_framework`,message:`Could not detect framework (headless mode has no picker).`}),2;a({type:`framework.detected`,framework:o.id,confidence:1});let s=await r({strict:!1});if(!s&&!process.env.ZENOVAY_API_TOKEN)return a({type:`error`,code:`not_logged_in`,message:"Run `zenovay login` first (or set ZENOVAY_API_TOKEN)."}),2;let c=new n({config:i,cliVersion:t.cliVersion,token:s}),l=await c.getSites(),u=t.siteId?l.find(e=>e.id===t.siteId):l[0];if(!u&&t.siteId)return a({type:`error`,code:`site_not_found`,message:`Site ${t.siteId} not found.`}),2;if(!u)return a({type:`error`,code:`no_site`,message:`No sites exist; create one at app.zenovay.com or re-run interactively.`}),2;a({type:`info`,message:`Using site ${u.id} (${u.name}) trackingCode=${u.trackingCode??u.id}`});let d=await J(t.cwd,{[o.envVarName]:u.trackingCode??u.id});return a({type:`info`,message:`env vars added: ${d.addedKeys.join(`,`)}`}),a({type:`done`,command:`init`,exitCode:0}),0}catch(e){return a({type:`error`,code:`init_failed`,message:e.message}),1}}const Tt=({opts:t,onExit:i})=>{let{exit:a}=ee(),[o,s]=O(`intro`),[d,f]=O(null),[p,h]=O([]),[g,_]=O(null),[v,y]=O(null),[b,C]=O(null),[w,k]=O([]),[j,M]=O(void 0),[N,P]=O(null),[F,I]=O(0),L=D(!1);return E(()=>(process.stdout.isTTY&&process.stdout.write(`\x1B[?1049h\x1B[H`),()=>{process.stdout.isTTY&&process.stdout.write(`\x1B[?1049l`)}),[]),E(()=>{L.current||(L.current=!0,(async()=>{try{s(`detecting`);let i=await Be(t.cwd);if(!i){C(`Could not detect your framework. Supported: Next.js, Nuxt, SvelteKit, Astro, Remix, plain HTML.`),s(`error`);return}f(i);let a=await r({strict:!1});!process.env.ZENOVAY_API_TOKEN&&!a&&(s(`login`),await c({cliVersion:t.cliVersion})),s(`loading-sites`);let o=await e(),l=await r({strict:!1}),u=new n({config:o,cliVersion:t.cliVersion,token:l}),d=await u.getSites(),p=await zt(t.cwd),m=Bt(d,p);if(h(d),_(p),d.length===0){s(`create-site`);return}if(t.siteId){let e=d.find(e=>e.id===t.siteId);if(!e){C(`Site ${t.siteId} not found in your account.`),s(`error`);return}y(e),Z(e,i,t,{setPhase:s,setErrorMsg:C,setTasks:k,setLiveLine:M,setSandboxStats:P});return}if(t.yes&&m){y(m),Z(m,i,t,{setPhase:s,setErrorMsg:C,setTasks:k,setLiveLine:M,setSandboxStats:P});return}s(`site-picker`)}catch(e){C(e.message),s(`error`)}})())},[]),E(()=>{o===`error`&&setTimeout(()=>{a(),i(1)},8e3)},[o]),T.createElement(x,{flexDirection:`column`},T.createElement(u,{version:t.cliVersion,subtitle:`AI install wizard`}),o===`intro`&&T.createElement(Et,null),o===`detecting`&&T.createElement(l,{title:`Scanning`,state:`busy`},T.createElement(x,null,T.createElement(S,{color:`magenta`},T.createElement(A,{type:`dots`})),T.createElement(S,null,` Detecting framework…`))),o===`login`&&T.createElement(l,{title:`Authenticating`,state:`busy`},T.createElement(S,null,`Opening browser for login… (paste ZENOVAY_API_TOKEN env var to skip)`)),o===`loading-sites`&&T.createElement(l,{title:`Loading your sites`,state:`busy`},T.createElement(x,null,T.createElement(S,{color:`magenta`},T.createElement(A,{type:`dots`})),T.createElement(S,null,` Fetching your Zenovay sites…`))),o===`site-picker`&&d&&T.createElement(Ot,{sites:p,preselectHint:g,onPick:e=>{if(e===`create-new`){s(`create-site`);return}y(e),Z(e,d,t,{setPhase:s,setErrorMsg:C,setTasks:k,setLiveLine:M,setSandboxStats:P})}}),o===`create-site`&&T.createElement(l,{title:`Create a new site`,state:`warn`},T.createElement(S,{color:`yellow`},"No site picked (or none exist yet). Visit https://app.zenovay.com/websites to create one, then re-run `zenovay init`."),T.createElement(S,{color:`gray`},`(Inline site creation from the CLI is scheduled for V1.1 — it requires a plan-limit check.)`)),o===`agent`&&d&&v&&T.createElement(Dt,{adapter:d,site:v,tasks:w,liveLine:j}),o===`install-complete`&&d&&v&&T.createElement(jt,{adapter:d,site:v,stats:N,onCommit:()=>s(`commit-prompt`),onSkipCommit:()=>s(`deploy-prompt`)}),o===`commit-prompt`&&v&&T.createElement(Mt,{cwd:t.cwd,onDone:e=>{e.committed&&M(`Pushed ${e.shortSha} to ${e.branch}`),s(`deploy-prompt`)},onError:e=>{C(e),s(`error`)}}),o===`deploy-prompt`&&v&&T.createElement(Nt,{site:v,onDeployed:()=>s(`visit-prompt`),onSkip:()=>s(`verify`)}),o===`visit-prompt`&&v&&T.createElement(Pt,{site:v,onContinue:()=>s(`verify`)}),o===`verify`&&v&&T.createElement(It,{site:v,elapsed:F,onTick:e=>I(e),onArrived:()=>s(`success`),onTimeout:()=>s(`success`)}),o===`success`&&d&&v&&T.createElement(At,{adapter:d,site:v,stats:N,onPick:e=>{a(),i(0,e,v)}}),o===`error`&&T.createElement(l,{title:`Install failed`,state:`err`},T.createElement(S,{color:`red`},b??`Unknown error`)),T.createElement(m,{items:[{key:`q`,label:`quit`},{key:`ctrl-c`,label:`abort`}]}))};async function Z(i,a,o,s){try{s.setPhase(`agent`);let c=await e(),l=await r({strict:!1}),u=new n({config:c,cliVersion:o.cliVersion,token:l}),d=new K({cwd:o.cwd}),f=i.trackingCode??i.id;await t({defaultSiteId:i.id,defaultSiteName:i.name}).catch(()=>void 0);let p=await R(o.cwd,f);if(p.recommendation===`no-op`){s.setTasks(e=>e.map(e=>e.id===`detect`||e.id===`read`||e.id===`write`?{...e,status:`done`,detail:`already installed correctly`}:e)),s.setLiveLine(p.summary),s.setSandboxStats?.({reads:0,writes:0,rounds:0}),!o.skipMcp&&l&&await Y({accessToken:l.accessToken}).catch(()=>void 0),s.setPhase(`install-complete`);return}p.competitors.length>0&&s.setLiveLine(`Detected ${p.competitors.map(e=>e.name).join(`, `)} — will install Zenovay alongside (won't touch their tags).`);let m=a.id===`plain-html`&&(p.recommendation===`fresh-install`||p.recommendation===`fresh-install-alongside-competitor`||p.recommendation===`update-tracking-code`);if(m){s.setTasks(e=>e.map(e=>e.id===`detect`?{...e,status:`done`,detail:`Plain HTML`}:e)),s.setLiveLine(`Plain HTML — using fast install path (no AI needed)…`);let e=await ft({cwd:o.cwd,trackingCode:f,updateOnly:p.recommendation===`update-tracking-code`});if(e.installed.length===0&&e.errors.length===0)throw Error(`No HTML files were modified. Either no .html files contain a <head>...</head> block, or every file already has the correct tracker.`);if(e.installed.length===0&&e.errors.length>0)throw Error(`Programmatic install failed for all ${e.errors.length} file(s). First error: ${e.errors[0].file}: ${e.errors[0].error}`);s.setTasks(t=>t.map(t=>t.id===`read`||t.id===`write`?{...t,status:`done`,detail:`${e.installed.length} file(s)`}:t)),s.setLiveLine(`Tracker added to ${e.installed.length} file(s). Skipped ${e.skipped.length}, errored ${e.errors.length}.`);let t=await J(o.cwd,{[a.envVarName]:f});if(s.setTasks(e=>e.map(e=>e.id===`env`?{...e,status:`done`,detail:`${t.addedKeys.length} key(s) added`}:e)),!o.skipMcp&&l){let e=await Y({accessToken:l.accessToken}).catch(()=>null);s.setTasks(t=>t.map(t=>t.id===`mcp`?{...t,status:`done`,detail:e&&e.installed.length>0?e.installed.join(`, `):`none detected`}:t))}else s.setTasks(e=>e.map(e=>e.id===`mcp`?{...e,status:`done`,detail:`skipped`}:e));s.setLiveLine(void 0),s.setSandboxStats?.({reads:e.installed.length,writes:e.installed.length,rounds:0}),s.setPhase(`install-complete`);return}let h=a.buildSnippets({trackingCode:f,siteId:i.id}),g=`Install Zenovay tracking into this ${a.displayName} project.\nSite: ${i.name} (trackingCode: ${f}).\n1. Call detect_framework to confirm the framework.\n2. Read the entry file(s) for this framework:\n`+a.files.map(e=>` - ${e.path}`).join(`
70
+ `,i=r.replace(/\n/g,`${n}`);return`${n}${i}${n}</head>`}),s===o){t.skipped.push({file:a,reason:`</head> regex did not match unexpectedly`});continue}}else{t.skipped.push({file:a,reason:`no <head>...</head> in file (fragment or non-page)`});continue}let c=null;for(let{name:e,re:t}of G)if(t.test(o)&&!t.test(s)){c=e;break}if(c){t.errors.push({file:a,error:`would remove ${c} tracker — refusing to write`});continue}try{await _.writeFile(n,s,`utf8`),t.installed.push(a)}catch(e){t.errors.push({file:a,error:e.message})}}return t}function pt(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function mt(){let e=[12,15,18,22,28,35,41,50,58,64,72,78],t=h(e,24);return[` ↑`,` ${t}`,` └────────────────────────`,` May Jun Jul Aug Sep`]}function ht(){return[` Landing page ████████████████████ 100%`,` ↓ -28%`,` Pricing ██████████████░░░░░░ 72%`,` ↓ -50%`,` Checkout ███████░░░░░░░░░░░░░ 36%`,` ↓ -64%`,` Purchased ███░░░░░░░░░░░░░░░░░ 13%`]}function gt(){return[` ▇▇▇▇▇▇▇▇▇▎ 89 Sarah K. /pricing 🇺🇸`,` ▇▇▇▇▇▇░░░░ 61 anon /docs 🇩🇪`,` ▇▇▇░░░░░░░ 34 anon /changelog 🇯🇵`]}function _t(){return[` LCP ● 2.1s good ████████████░░░░░░`,` INP ● 89ms good ██████████████████`,` CLS ⚠ 0.14 needs ████████████░░░░░░`,` TTFB ● 380ms good ███████████████░░░`]}const X=[{title:`Welcome`,body:[`The wizard is an agent — it handles the entire`,`Zenovay setup process on your behalf.`,``,`Reading your project, deciding where the tracker`,`belongs, and writing the snippet for you.`]},{title:`Events`,body:[`Events are the foundation of Zenovay analytics.`,``,`Every pageview, click, and custom action is an`,`event. Group them into Goals to track conversions.`]},{title:`Trends`,body:[`Use trends to measure growth.`,``,`See how visitors, signups, and revenue have`,`changed over the last week, month, or quarter.`],visual:mt},{title:`Funnels`,body:[`Funnels reveal where users drop off.`,``,`Define the steps you care about — landing,`,`pricing, checkout, purchase — and Zenovay shows`,`the per-step conversion rate.`],visual:ht},{title:`Live visitors`,body:[`Watch every visitor in real time, ranked by an`,`AI score that highlights high-intent traffic.`,``,"Use `zenovay visitors --live` after install."],visual:gt},{title:`Core Web Vitals`,body:[`LCP, INP, CLS — Google's page-experience metrics,`,`collected automatically once the tracker is in.`,``,"Use `zenovay vitals` to see them per page + device."],visual:_t},{title:`MCP integration`,body:[`Your CLI session can install Zenovay's MCP server`,`into Cursor / Claude Desktop / VS Code.`,``,`Then ask your AI: "what were my top pages today?"`,`and it queries Zenovay directly.`]},{title:`AI insights`,body:[`Zenovay watches your data and surfaces anomalies`,`automatically — traffic spikes, error bursts,`,`revenue drops — without you needing to ask.`,``,"Run `zenovay ai` after install to chat with them."]},{title:`Privacy-first`,body:[`No cookies required. No third-party trackers.`,`Cookieless mode is one toggle in your dashboard.`,``,`GDPR, CCPA, and PECR-compliant out of the box.`]}],vt=8e3,yt=({width:e,height:t})=>{let[n,r]=O(0);E(()=>{let e=setInterval(()=>{r(e=>(e+1)%X.length)},vt);return()=>clearInterval(e)},[]);let i=X[n],a=i.visual?i.visual():[],o=X.map((e,t)=>t===n?`●`:`·`).join(` `);return T.createElement(x,{flexDirection:`column`,width:e,height:t,paddingX:2,paddingY:1},T.createElement(x,{marginBottom:1},T.createElement(S,{color:`magentaBright`,bold:!0},`Learn`)),T.createElement(x,{marginBottom:1},T.createElement(S,{bold:!0,color:`white`},i.title)),i.body.map((e,t)=>T.createElement(S,{key:t,color:`gray`},e||` `)),a.length>0&&T.createElement(x,{flexDirection:`column`,marginTop:1},a.map((e,t)=>T.createElement(S,{key:t,color:`cyan`},e))),T.createElement(x,{flexGrow:1}),T.createElement(x,{marginTop:1},T.createElement(S,{color:`gray`,dimColor:!0},o,` · `,n+1,` / `,X.length)))},bt={pending:`·`,active:`⠋`,done:`✓`,error:`✗`},xt={pending:`gray`,active:`magenta`,done:`green`,error:`red`},St=({tasks:e,width:t,height:n,liveLine:r})=>{let i=e.filter(e=>e.status===`done`).length;return T.createElement(x,{flexDirection:`column`,width:t,height:n,paddingX:2,paddingY:1},T.createElement(x,{marginBottom:1},T.createElement(S,{color:`magentaBright`,bold:!0},`Tasks`)),e.map(e=>T.createElement(x,{key:e.id,flexDirection:`column`},T.createElement(x,null,e.status===`active`?T.createElement(S,{color:`magenta`},T.createElement(A,{type:`dots`})):T.createElement(S,{color:xt[e.status]},bt[e.status]),T.createElement(S,null,` `),T.createElement(S,{color:e.status===`pending`?`gray`:`white`},e.label)),e.detail&&T.createElement(x,{paddingLeft:2},T.createElement(S,{color:`gray`,dimColor:!0},e.detail)))),T.createElement(x,{flexGrow:1}),r&&T.createElement(x,{marginTop:1},T.createElement(S,{color:`cyan`},`◆ `),T.createElement(S,{color:`white`},r)),T.createElement(x,{marginTop:1},T.createElement(S,{color:`gray`,dimColor:!0},i,` / `,e.length)))};async function Ct(e){if(o(e))return wt(e);let t=`quit`,n=null,r=await new Promise(r=>{let{unmount:i,waitUntilExit:a}=C(T.createElement(Tt,{opts:e,onExit:(e,a,o)=>{t=a??`quit`,n=o??null,i(),r(e)}}));a().catch(()=>r(1))});if(r!==0||t===`quit`||!n)return r;let i=n.id;if(t===`watch`){let{watchCommand:t}=await import(`./watch-CvxGXxpw.js`);return t({cliVersion:e.cliVersion,siteId:i})}if(t===`events`){let{eventsTailCommand:t}=await import(`./events-tail-0phSCPj0.js`);return t({cliVersion:e.cliVersion,siteId:i})}return 0}async function wt(t){try{let i=await e(),o=await Be(t.cwd);if(!o)return a({type:`error`,code:`no_framework`,message:`Could not detect framework (headless mode has no picker).`}),2;a({type:`framework.detected`,framework:o.id,confidence:1});let s=await r({strict:!1});if(!s&&!process.env.ZENOVAY_API_TOKEN)return a({type:`error`,code:`not_logged_in`,message:"Run `zenovay login` first (or set ZENOVAY_API_TOKEN)."}),2;let c=new n({config:i,cliVersion:t.cliVersion,token:s}),l=await c.getSites(),u=t.siteId?l.find(e=>e.id===t.siteId):l[0];if(!u&&t.siteId)return a({type:`error`,code:`site_not_found`,message:`Site ${t.siteId} not found.`}),2;if(!u)return a({type:`error`,code:`no_site`,message:`No sites exist; create one at app.zenovay.com or re-run interactively.`}),2;a({type:`info`,message:`Using site ${u.id} (${u.name}) trackingCode=${u.trackingCode??u.id}`});let d=await J(t.cwd,{[o.envVarName]:u.trackingCode??u.id});return a({type:`info`,message:`env vars added: ${d.addedKeys.join(`,`)}`}),a({type:`done`,command:`init`,exitCode:0}),0}catch(e){return a({type:`error`,code:`init_failed`,message:e.message}),1}}const Tt=({opts:t,onExit:i})=>{let{exit:a}=ee(),[o,s]=O(`intro`),[d,f]=O(null),[p,h]=O([]),[g,_]=O(null),[v,y]=O(null),[b,C]=O(null),[w,k]=O([]),[j,M]=O(void 0),[N,P]=O(null),[F,I]=O(0),L=D(!1);return E(()=>(process.stdout.isTTY&&process.stdout.write(`\x1B[?1049h\x1B[H`),()=>{process.stdout.isTTY&&process.stdout.write(`\x1B[?1049l`)}),[]),E(()=>{L.current||(L.current=!0,(async()=>{try{s(`detecting`);let i=await Be(t.cwd);if(!i){C(`Could not detect your framework. Supported: Next.js, Nuxt, SvelteKit, Astro, Remix, plain HTML.`),s(`error`);return}f(i);let a=await r({strict:!1});!process.env.ZENOVAY_API_TOKEN&&!a&&(s(`login`),await c({cliVersion:t.cliVersion})),s(`loading-sites`);let o=await e(),l=await r({strict:!1}),u=new n({config:o,cliVersion:t.cliVersion,token:l}),d=await u.getSites(),p=await zt(t.cwd),m=Bt(d,p);if(h(d),_(p),d.length===0){s(`create-site`);return}if(t.siteId){let e=d.find(e=>e.id===t.siteId);if(!e){C(`Site ${t.siteId} not found in your account.`),s(`error`);return}y(e),Z(e,i,t,{setPhase:s,setErrorMsg:C,setTasks:k,setLiveLine:M,setSandboxStats:P});return}if(t.yes&&m){y(m),Z(m,i,t,{setPhase:s,setErrorMsg:C,setTasks:k,setLiveLine:M,setSandboxStats:P});return}s(`site-picker`)}catch(e){C(e.message),s(`error`)}})())},[]),E(()=>{o===`error`&&setTimeout(()=>{a(),i(1)},8e3)},[o]),T.createElement(x,{flexDirection:`column`},T.createElement(u,{version:t.cliVersion,subtitle:`AI install wizard`}),o===`intro`&&T.createElement(Et,null),o===`detecting`&&T.createElement(l,{title:`Scanning`,state:`busy`},T.createElement(x,null,T.createElement(S,{color:`magenta`},T.createElement(A,{type:`dots`})),T.createElement(S,null,` Detecting framework…`))),o===`login`&&T.createElement(l,{title:`Authenticating`,state:`busy`},T.createElement(S,null,`Opening browser for login… (paste ZENOVAY_API_TOKEN env var to skip)`)),o===`loading-sites`&&T.createElement(l,{title:`Loading your sites`,state:`busy`},T.createElement(x,null,T.createElement(S,{color:`magenta`},T.createElement(A,{type:`dots`})),T.createElement(S,null,` Fetching your Zenovay sites…`))),o===`site-picker`&&d&&T.createElement(Ot,{sites:p,preselectHint:g,onPick:e=>{if(e===`create-new`){s(`create-site`);return}y(e),Z(e,d,t,{setPhase:s,setErrorMsg:C,setTasks:k,setLiveLine:M,setSandboxStats:P})}}),o===`create-site`&&T.createElement(l,{title:`Create a new site`,state:`warn`},T.createElement(S,{color:`yellow`},"No site picked (or none exist yet). Visit https://app.zenovay.com/websites to create one, then re-run `zenovay init`."),T.createElement(S,{color:`gray`},`(Inline site creation from the CLI is scheduled for V1.1 — it requires a plan-limit check.)`)),o===`agent`&&d&&v&&T.createElement(Dt,{adapter:d,site:v,tasks:w,liveLine:j}),o===`install-complete`&&d&&v&&T.createElement(jt,{adapter:d,site:v,stats:N,onCommit:()=>s(`commit-prompt`),onSkipCommit:()=>s(`deploy-prompt`)}),o===`commit-prompt`&&v&&T.createElement(Mt,{cwd:t.cwd,onDone:e=>{e.committed&&M(`Pushed ${e.shortSha} to ${e.branch}`),s(`deploy-prompt`)},onError:e=>{C(e),s(`error`)}}),o===`deploy-prompt`&&v&&T.createElement(Nt,{site:v,onDeployed:()=>s(`visit-prompt`),onSkip:()=>s(`verify`)}),o===`visit-prompt`&&v&&T.createElement(Pt,{site:v,onContinue:()=>s(`verify`)}),o===`verify`&&v&&T.createElement(It,{site:v,elapsed:F,onTick:e=>I(e),onArrived:()=>s(`success`),onTimeout:()=>s(`success`)}),o===`success`&&d&&v&&T.createElement(At,{adapter:d,site:v,stats:N,onPick:e=>{a(),i(0,e,v)}}),o===`error`&&T.createElement(l,{title:`Install failed`,state:`err`},T.createElement(S,{color:`red`},b??`Unknown error`)),T.createElement(m,{items:[{key:`q`,label:`quit`},{key:`ctrl-c`,label:`abort`}]}))};async function Z(i,a,o,s){try{s.setPhase(`agent`);let c=await e(),l=await r({strict:!1}),u=new n({config:c,cliVersion:o.cliVersion,token:l}),d=new K({cwd:o.cwd}),f=i.trackingCode??i.id;await t({defaultSiteId:i.id,defaultSiteName:i.name}).catch(()=>void 0);let p=await R(o.cwd,f);if(p.recommendation===`no-op`){s.setTasks(e=>e.map(e=>e.id===`detect`||e.id===`read`||e.id===`write`?{...e,status:`done`,detail:`already installed correctly`}:e)),s.setLiveLine(p.summary),s.setSandboxStats?.({reads:0,writes:0,rounds:0}),!o.skipMcp&&l&&await Y({accessToken:l.accessToken}).catch(()=>void 0),s.setPhase(`install-complete`);return}p.competitors.length>0&&s.setLiveLine(`Detected ${p.competitors.map(e=>e.name).join(`, `)} — will install Zenovay alongside (won't touch their tags).`);let m=a.id===`plain-html`&&(p.recommendation===`fresh-install`||p.recommendation===`fresh-install-alongside-competitor`||p.recommendation===`update-tracking-code`);if(m){s.setTasks(e=>e.map(e=>e.id===`detect`?{...e,status:`done`,detail:`Plain HTML`}:e)),s.setLiveLine(`Plain HTML — using fast install path (no AI needed)…`);let e=await ft({cwd:o.cwd,trackingCode:f,updateOnly:p.recommendation===`update-tracking-code`});if(e.installed.length===0&&e.errors.length===0)throw Error(`No HTML files were modified. Either no .html files contain a <head>...</head> block, or every file already has the correct tracker.`);if(e.installed.length===0&&e.errors.length>0)throw Error(`Programmatic install failed for all ${e.errors.length} file(s). First error: ${e.errors[0].file}: ${e.errors[0].error}`);s.setTasks(t=>t.map(t=>t.id===`read`||t.id===`write`?{...t,status:`done`,detail:`${e.installed.length} file(s)`}:t)),s.setLiveLine(`Tracker added to ${e.installed.length} file(s). Skipped ${e.skipped.length}, errored ${e.errors.length}.`);let t=await J(o.cwd,{[a.envVarName]:f});if(s.setTasks(e=>e.map(e=>e.id===`env`?{...e,status:`done`,detail:`${t.addedKeys.length} key(s) added`}:e)),!o.skipMcp&&l){let e=await Y({accessToken:l.accessToken}).catch(()=>null);s.setTasks(t=>t.map(t=>t.id===`mcp`?{...t,status:`done`,detail:e&&e.installed.length>0?e.installed.join(`, `):`none detected`}:t))}else s.setTasks(e=>e.map(e=>e.id===`mcp`?{...e,status:`done`,detail:`skipped`}:e));s.setLiveLine(void 0),s.setSandboxStats?.({reads:e.installed.length,writes:e.installed.length,rounds:0}),s.setPhase(`install-complete`);return}let h=a.buildSnippets({trackingCode:f,siteId:i.id}),g=`Install Zenovay tracking into this ${a.displayName} project.\nSite: ${i.name} (trackingCode: ${f}).\n1. Call detect_framework to confirm the framework.\n2. Read the entry file(s) for this framework:\n`+a.files.map(e=>` - ${e.path}`).join(`
71
71
  `)+`
72
72
  3. Insert the tracker using the snippet below.
73
73
  4. Confirm the change with a diff before writing.
@@ -1 +1 @@
1
- import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-UJJ6ube8.js";import{requireTier as r}from"./tier-uaU5pkTz.js";import"./formatter-KOe_hjhc.js";import{emit as i,isHeadless as a}from"./emit-B8RbnBJe.js";import{Panel as o}from"./panel-jycoT562.js";import{Banner as s}from"./banner-gVm7GaJF.js";import"./prompt-Db9Y7CVt.js";import{Keybar as c}from"./keybar-BYQ2Bam1.js";import{resolveSiteId as l}from"./resolve-site-CZEwJoBj.js";import{EmptyState as u}from"./empty-state-BkS6DKWZ.js";import{Box as d,Text as f,render as p,useApp as m,useInput as h}from"ink";import g,{useEffect as _,useState as v}from"react";import y from"ink-spinner";function b(e){return e===`critical`?`err`:e===`warning`?`warn`:`ok`}function x(e){return e===`anomaly`?`⚡ anomaly`:e===`recommendation`?`✦ recommendation`:`↗ trend`}async function S(o){let s=await e(),c=await t({strict:!1});if(!c)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let u=new n({config:s,cliVersion:o.cliVersion,token:c});try{await r(u,`pro`)}catch(e){return process.stderr.write(`${e.message}\n`),2}let d,f;try{({siteId:d,site:f}=await l(u,{explicit:o.siteId,headless:!!o.json,cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let m=f?.url?f.url.replace(/^https?:\/\//,``).replace(/\/$/,``):f?.name??d;if(a(o)){let e=await u.getInsights(d);return i({type:`insights.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=p(g.createElement(C,{api:u,siteId:d,siteLabel:m,cliVersion:o.cliVersion,onExit:n=>{t(),e(n)}}))})}const C=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:a}=m(),[l,p]=v(null),[S,C]=v(!0),[w,T]=v(null);return h(e=>{e===`q`&&(a(),i(0))}),_(()=>{let n=!1;return(async()=>{try{let r=await e.getInsights(t);n||(p(r),C(!1))}catch(e){n||(T(e.message),C(!1))}})(),()=>{n=!0}},[e,t]),S?g.createElement(d,{flexDirection:`column`},g.createElement(s,{version:r,subtitle:`insights · ${n}`}),g.createElement(o,{title:`Loading`,state:`busy`},g.createElement(d,null,g.createElement(f,{color:`magenta`},g.createElement(y,{type:`dots`})),g.createElement(f,null,` Fetching insights…`)))):w?g.createElement(d,{flexDirection:`column`},g.createElement(s,{version:r,subtitle:`insights · ${n}`}),g.createElement(u,{reason:`error`,headline:`Failed to load`,hint:w})):!l||l.length===0?g.createElement(d,{flexDirection:`column`},g.createElement(s,{version:r,subtitle:`insights · ${n}`}),g.createElement(u,{reason:`no-data`,headline:`No insights yet`,hint:`Insights are generated nightly — check back tomorrow`})):g.createElement(d,{flexDirection:`column`},g.createElement(s,{version:r,subtitle:`insights · ${n}`}),l.map((e,t)=>g.createElement(o,{key:t,title:`${x(e.kind)} · ${e.severity}`,state:b(e.severity)},g.createElement(f,{bold:!0},e.title),e.body?g.createElement(f,{color:`gray`},e.body):null)),g.createElement(c,{items:[{key:`q`,label:`quit`}]}))};export{S as insightsCommand};
1
+ import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-DJUWqNhW.js";import{requireTier as r}from"./tier-ztFrvV9H.js";import"./formatter-DDG2TSOz.js";import{emit as i,isHeadless as a}from"./emit-NkY7PE3R.js";import{Panel as o}from"./panel-CYsRlDSL.js";import{Banner as s}from"./banner-Cr0PV2pB.js";import"./prompt-BS9qJvdR.js";import{Keybar as c}from"./keybar-Bh-y__tC.js";import{resolveSiteId as l}from"./resolve-site-CoOL4KPZ.js";import{EmptyState as u}from"./empty-state-BbUJUNcp.js";import{Box as d,Text as f,render as p,useApp as m,useInput as h}from"ink";import g,{useEffect as _,useState as v}from"react";import y from"ink-spinner";function b(e){return e===`critical`?`err`:e===`warning`?`warn`:`ok`}function x(e){return e===`anomaly`?`⚡ anomaly`:e===`recommendation`?`✦ recommendation`:`↗ trend`}async function S(o){let s=await e(),c=await t({strict:!1});if(!c)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let u=new n({config:s,cliVersion:o.cliVersion,token:c});try{await r(u,`pro`)}catch(e){return process.stderr.write(`${e.message}\n`),2}let d,f;try{({siteId:d,site:f}=await l(u,{explicit:o.siteId,headless:!!o.json,cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let m=f?.url?f.url.replace(/^https?:\/\//,``).replace(/\/$/,``):f?.name??d;if(a(o)){let e=await u.getInsights(d);return i({type:`insights.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=p(g.createElement(C,{api:u,siteId:d,siteLabel:m,cliVersion:o.cliVersion,onExit:n=>{t(),e(n)}}))})}const C=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:a}=m(),[l,p]=v(null),[S,C]=v(!0),[w,T]=v(null);return h(e=>{e===`q`&&(a(),i(0))}),_(()=>{let n=!1;return(async()=>{try{let r=await e.getInsights(t);n||(p(r),C(!1))}catch(e){n||(T(e.message),C(!1))}})(),()=>{n=!0}},[e,t]),S?g.createElement(d,{flexDirection:`column`},g.createElement(s,{version:r,subtitle:`insights · ${n}`}),g.createElement(o,{title:`Loading`,state:`busy`},g.createElement(d,null,g.createElement(f,{color:`magenta`},g.createElement(y,{type:`dots`})),g.createElement(f,null,` Fetching insights…`)))):w?g.createElement(d,{flexDirection:`column`},g.createElement(s,{version:r,subtitle:`insights · ${n}`}),g.createElement(u,{reason:`error`,headline:`Failed to load`,hint:w})):!l||l.length===0?g.createElement(d,{flexDirection:`column`},g.createElement(s,{version:r,subtitle:`insights · ${n}`}),g.createElement(u,{reason:`no-data`,headline:`No insights yet`,hint:`Insights are generated nightly — check back tomorrow`})):g.createElement(d,{flexDirection:`column`},g.createElement(s,{version:r,subtitle:`insights · ${n}`}),l.map((e,t)=>g.createElement(o,{key:t,title:`${x(e.kind)} · ${e.severity}`,state:b(e.severity)},g.createElement(f,{bold:!0},e.title),e.body?g.createElement(f,{color:`gray`},e.body):null)),g.createElement(c,{items:[{key:`q`,label:`quit`}]}))};export{S as insightsCommand};
@@ -1,4 +1,4 @@
1
- import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-UJJ6ube8.js";import{confirmDestructive as r}from"./confirm-Dk3CEdpn.js";import i from"open";async function a(a){let o=await e(),s=await t({strict:!1}),c=new n({config:o,cliVersion:a.cliVersion,token:s});try{switch(a.action){case`list`:{let{integrations:e}=await c.listIntegrations();if(a.json)return process.stdout.write(JSON.stringify({integrations:e},null,2)+`
1
+ import{readConfig as e}from"./config-CG7B8fR0.js";import"./api-CJnD6Auw.js";import{readToken as t}from"./token-store-C1AqhmDP.js";import{ApiV2Client as n}from"./api-v2-DJUWqNhW.js";import{confirmDestructive as r}from"./confirm-DvIRDrR9.js";import i from"open";async function a(a){let o=await e(),s=await t({strict:!1}),c=new n({config:o,cliVersion:a.cliVersion,token:s});try{switch(a.action){case`list`:{let{integrations:e}=await c.listIntegrations();if(a.json)return process.stdout.write(JSON.stringify({integrations:e},null,2)+`
2
2
  `),0;let t=[10,30,14],n=e=>e.map((e,n)=>(e??``).padEnd(t[n])).join(` `);process.stdout.write(`
3
3
  `+n([`name`,`service`,`status`])+`
4
4
  `),process.stdout.write(n(t.map(e=>`─`.repeat(e)))+`