@zenovay/cli 0.1.64 → 0.1.65

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 (140) hide show
  1. package/dist/ai-eSlGP6ay.js +1 -0
  2. package/dist/alerts-CcKnqwmm.js +3 -0
  3. package/dist/analytical-screen-BrOFDrQ_.js +2 -0
  4. package/dist/analytics-B8yy7gjr.js +2 -0
  5. package/dist/{annotation-BuwTxCIH.js → annotation-BiviGSmz.js} +1 -1
  6. package/dist/{api-keys-CHRLCfrl.js → api-keys-DQob1q69.js} +1 -1
  7. package/dist/{apply-B19bFTz0.js → apply-oUMOH7u2.js} +1 -1
  8. package/dist/{audit-Demn5lBp.js → audit-B4a5u54T.js} +2 -3
  9. package/dist/banner-MAYlzjcP.js +1 -0
  10. package/dist/{bar-DWT-1xOE.js → bar-DG-MqgGx.js} +1 -1
  11. package/dist/bin.js +6 -5
  12. package/dist/chat-panel-dXLm3hUn.js +7 -0
  13. package/dist/{commands-BX5I2UyT.js → commands-B-NMyq2s.js} +1 -1
  14. package/dist/companies-CpDnB5NR.js +2 -0
  15. package/dist/csv-emit-DYTuKBke.js +1 -0
  16. package/dist/csv-emit-XJfJC5e2.js +1 -0
  17. package/dist/{data-table-BpbyyNSA.js → data-table-BvnWCG-w.js} +1 -1
  18. package/dist/deploys-CI88FRFO.js +2 -0
  19. package/dist/devices-DNkzamfH.js +2 -0
  20. package/dist/{doctor-C1O4DlbQ.js → doctor-DJbNKwdF.js} +5 -5
  21. package/dist/{domains-BCDiOFYb.js → domains-BoRRxWzR.js} +1 -1
  22. package/dist/{emit-DBYk96TD.js → emit-D4YlMlzk.js} +1 -1
  23. package/dist/{empty-state-CJxa1jUN.js → empty-state-DdLBcz4h.js} +1 -1
  24. package/dist/errors-BtGhPNBy.js +2 -0
  25. package/dist/events-tail-ig5nAsbQ.js +5 -0
  26. package/dist/export-CTI3xHqF.js +4 -0
  27. package/dist/funnel-DkcJHeX6.js +3 -0
  28. package/dist/geo-UBu3aUHh.js +2 -0
  29. package/dist/{globe-C_m7zGZM.js → globe-GU2r8P23.js} +2 -2
  30. package/dist/{goals-OQ1s7Vhq.js → goals-CcA4qOM5.js} +1 -1
  31. package/dist/health-C-efHHs0.js +1 -0
  32. package/dist/health-am28BgPf.js +2 -0
  33. package/dist/heatmaps-C6ynBgMW.js +1 -0
  34. package/dist/home-B0miYclo.js +2 -0
  35. package/dist/init-CqcqX8o5.js +79 -0
  36. package/dist/init-awEnG3zC.js +1 -0
  37. package/dist/insights-C8PBisLR.js +1 -0
  38. package/dist/{integrations-S-9EITZH.js → integrations-CS16nG51.js} +3 -3
  39. package/dist/journeys-DaqlziL4.js +1 -0
  40. package/dist/{keybar-DsYTkKZX.js → keybar-BcHUm3hI.js} +1 -1
  41. package/dist/keybar-deep-link-Dagnpllp.js +1 -0
  42. package/dist/live-cIPlpoWN.js +1 -0
  43. package/dist/login-CiJG9-gq.js +1 -0
  44. package/dist/login-RVU9FkAl.js +2 -0
  45. package/dist/{logout-eXZJMigi.js → logout-BSSOsDr7.js} +1 -1
  46. package/dist/{metric-card-COEIZmbN.js → metric-card-CaFIymSQ.js} +1 -1
  47. package/dist/open-url-dPoDcwsm.js +1 -0
  48. package/dist/pages-3tis8juF.js +2 -0
  49. package/dist/panel-DB1HLxAw.js +1 -0
  50. package/dist/{plans-CNWFx-qt.js → plans-DCon6c8N.js} +5 -5
  51. package/dist/progress-row-BS7fwhn_.js +3 -0
  52. package/dist/projects-B7xPHSK2.js +2 -0
  53. package/dist/{prompt-D-Uzz_GF.js → prompt-D7Ek9MYk.js} +1 -1
  54. package/dist/query-CC7wPhmz.js +8 -0
  55. package/dist/resolve-site-DYBsBK4c.js +2 -0
  56. package/dist/retention-DeG_P1-s.js +1 -0
  57. package/dist/revenue-Dobs3EQH.js +2 -0
  58. package/dist/secrets-BBaEWu03.js +1 -0
  59. package/dist/self-test-DKOYwgHD.js +16 -0
  60. package/dist/sessions-DM4XGC2N.js +1 -0
  61. package/dist/{share-BG5ipcQi.js → share-6Dt695rC.js} +1 -1
  62. package/dist/sources-BofnMkYR.js +2 -0
  63. package/dist/stats-DkrgaDDP.js +2 -0
  64. package/dist/{status-agent-Dej6dGvX.js → status-agent-CQ955HRn.js} +1 -1
  65. package/dist/{team-B1qfFxKA.js → team-N-Ycc7Mh.js} +1 -1
  66. package/dist/theme-Brz9wK0w.js +1 -0
  67. package/dist/themes-lGJ4GHVu.js +4 -0
  68. package/dist/{tour-Bwbv_E4Q.js → tour-BA4g04Qt.js} +1 -1
  69. package/dist/ui-DXrdVAc-.js +1 -0
  70. package/dist/{update-BDMLrzzb.js → update-CYLXsiSE.js} +1 -1
  71. package/dist/uptime-I3klxuzW.js +1 -0
  72. package/dist/{usage-kXVWbunU.js → usage-DIzd9nzk.js} +1 -1
  73. package/dist/{use-B8cSIrZL.js → use-DlyoJe6I.js} +1 -1
  74. package/dist/visitors-BFBitwBV.js +2 -0
  75. package/dist/vitals-Bq1y2LBt.js +2 -0
  76. package/dist/watch-BYIKjsGC.js +1 -0
  77. package/dist/{webhooks-BhZkT0SX.js → webhooks-DKBhl3fL.js} +1 -1
  78. package/dist/webhooks-forward-Cfzd9veV.js +3 -0
  79. package/dist/wizard-bin.js +1 -1
  80. package/package.json +3 -2
  81. package/dist/ai-CPogCNEQ.js +0 -7
  82. package/dist/alerts-DWVCFKlS.js +0 -3
  83. package/dist/analytical-screen-BasvNR-9.js +0 -1
  84. package/dist/analytics-C7mAE3gV.js +0 -2
  85. package/dist/banner-3iSWTDFy.js +0 -1
  86. package/dist/chat-panel-CqJaCIg3.js +0 -7
  87. package/dist/companies-DEdYd-bV.js +0 -2
  88. package/dist/csv-emit-BuRZNWYM.js +0 -1
  89. package/dist/csv-emit-Dn3c0RCG.js +0 -1
  90. package/dist/deploys-DTIU1Kqt.js +0 -2
  91. package/dist/devices-DK_o0JcI.js +0 -2
  92. package/dist/errors-Dig3nVCV.js +0 -2
  93. package/dist/events-tail-u_lwZas2.js +0 -5
  94. package/dist/export-DkAIRS9F.js +0 -4
  95. package/dist/funnel-Brtq8avo.js +0 -3
  96. package/dist/geo-c9hA42_9.js +0 -2
  97. package/dist/health-B5DBRP3C.js +0 -1
  98. package/dist/health-BttlLZWZ.js +0 -2
  99. package/dist/heatmaps-BPxqgMmV.js +0 -1
  100. package/dist/home-DGrXLbbO.js +0 -2
  101. package/dist/init-BIJkCrgc.js +0 -79
  102. package/dist/init-BhfcLbDE.js +0 -1
  103. package/dist/insights-CrUKfMD5.js +0 -1
  104. package/dist/journeys-BbySeXM2.js +0 -1
  105. package/dist/keybar-deep-link-DC31T3CP.js +0 -1
  106. package/dist/live-dcM0RwGp.js +0 -1
  107. package/dist/login-DgU__egg.js +0 -1
  108. package/dist/login-yhuXiFqh.js +0 -2
  109. package/dist/pages-Bk5gbJ2v.js +0 -1
  110. package/dist/panel-B_yDcIcn.js +0 -1
  111. package/dist/progress-row-BpAXjJPL.js +0 -3
  112. package/dist/projects-BOU9sd2x.js +0 -2
  113. package/dist/query-CFNNsz6m.js +0 -8
  114. package/dist/resolve-site-mj0esTrm.js +0 -2
  115. package/dist/retention-CYDhYbyf.js +0 -1
  116. package/dist/revenue-D8uN4mjW.js +0 -2
  117. package/dist/secrets-c-NB_plk.js +0 -1
  118. package/dist/self-test-Cc5PWB08.js +0 -16
  119. package/dist/sessions-DqTjJFcP.js +0 -1
  120. package/dist/sources-D0FxjzeB.js +0 -2
  121. package/dist/stats-DmkvUylD.js +0 -2
  122. package/dist/themes-Dqt--qhd.js +0 -4
  123. package/dist/ui-Cey-h6wI.js +0 -1
  124. package/dist/uptime-CNGVODGc.js +0 -1
  125. package/dist/visitors-D7Q6chjq.js +0 -2
  126. package/dist/vitals-DmMAuIdP.js +0 -2
  127. package/dist/watch-D5WeMSz2.js +0 -1
  128. package/dist/webhooks-forward-D9PZDQ77.js +0 -3
  129. /package/dist/{client-DTXWADkX.js → client-I4GTcUcm.js} +0 -0
  130. /package/dist/{completions-CaYLmArp.js → completions-Cy6kF9kp.js} +0 -0
  131. /package/dist/{examples-BtWVpY-G.js → examples-C0LrZPUl.js} +0 -0
  132. /package/dist/{fmt-gMsty5jy.js → fmt-iR2sYwsO.js} +0 -0
  133. /package/dist/{formatter-DutfcQAc.js → formatter-C4YSOKuq.js} +0 -0
  134. /package/dist/{notes-DUqpXghJ.js → notes-ZXJfqA4H.js} +0 -0
  135. /package/dist/{profile-CZm-_uy-.js → profile-CY1_dG5d.js} +0 -0
  136. /package/dist/{secrets-ApB7yh2A.js → secrets-DzueUVGL.js} +0 -0
  137. /package/dist/{settings-CTbX2BXa.js → settings-C_st_Aqq.js} +0 -0
  138. /package/dist/{sparkline-BZ0eMB-w.js → sparkline-8ucKVUV7.js} +0 -0
  139. /package/dist/{teams-BzLZoKsj.js → teams-BmzDAiAn.js} +0 -0
  140. /package/dist/{telemetry--Yk0J5zc.js → telemetry-Ckn12kyP.js} +0 -0
@@ -0,0 +1 @@
1
+ import"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import"./token-store-BQuGH0z2.js";import"./formatter-C4YSOKuq.js";import"./emit-D4YlMlzk.js";import"./open-url-dPoDcwsm.js";import{loginCommand as e}from"./login-RVU9FkAl.js";export{e as loginCommand};
@@ -0,0 +1,2 @@
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import{ApiClient as t,pollDeviceToken as n,startDeviceAuthorization as r}from"./api-FCanTxsb.js";import{writeToken as i}from"./token-store-BQuGH0z2.js";import{emit$1 as a,isHeadless as o}from"./emit-D4YlMlzk.js";import{openInBrowser as s}from"./open-url-dPoDcwsm.js";import c from"node:path";import{promises as l}from"node:fs";import u from"node:os";async function d(c){let l=await e(),u=o({json:c.json}),d=await r({apiBase:l.apiBase}),f=d.verification_uri_complete??d.verification_uri;u?a({type:`info`,message:`Open ${f} and enter code ${d.user_code}`}):c.onCode?c.onCode({userCode:d.user_code,verificationUri:d.verification_uri,verificationUriComplete:d.verification_uri_complete}):process.stdout.write(`\n Open this URL to authorize the CLI:\n ${f}\n Or enter code: ${d.user_code}\n\n`);let p=c.openBrowser??!u;if(p)try{await s(f)}catch{}let m=await n({apiBase:l.apiBase,deviceCode:d.device_code,interval:d.interval,expiresIn:d.expires_in});await i(m);let h=new t({config:l,cliVersion:c.cliVersion,token:m}),_=await h.me().catch(()=>null);if(_){let e={...m,userId:_.user.id,teamId:_.team?.id,email:_.user.email};await i(e)}return u?a({type:`done`,command:`login`,exitCode:0}):await g().catch(()=>void 0),{email:_?.user.email}}function f(){let e=process.env.SHELL??``,t=u.homedir();if(e.endsWith(`/zsh`)||e.endsWith(`zsh`))return{shell:`zsh`,rcPath:c.join(t,`.zshrc`)};if(e.endsWith(`/bash`)||e.endsWith(`bash`)){let e=process.platform===`darwin`?c.join(t,`.bash_profile`):c.join(t,`.bashrc`);return{shell:`bash`,rcPath:e}}return e.endsWith(`/fish`)||e.endsWith(`fish`)?{shell:`fish`,rcPath:c.join(t,`.config`,`fish`,`config.fish`)}:null}const p=/zenovay\s+completions/;async function m(e,t){try{let n=await l.readFile(e,`utf8`);return t.test(n)}catch{return!1}}function h(e){return process.stdin.isTTY?new Promise(t=>{process.stdout.write(e),process.stdin.setEncoding(`utf8`);let n=e=>{process.stdin.removeListener(`data`,n);try{process.stdin.pause()}catch{}let r=e.trim().toLowerCase();return t(r===``||r===`y`||r===`yes`)};process.stdin.resume(),process.stdin.on(`data`,n)}):Promise.resolve(!1)}async function g(){let e=f();if(!e||await m(e.rcPath,p))return;let t=await h(`Install shell completions for ${e.shell}? [Y/n] `);if(!t){process.stdout.write(`Skipped. You can install later with: zenovay completions ${e.shell} >> ${e.rcPath}\n`);return}let n=e.shell===`fish`?`zenovay completions fish | source
2
+ `:`eval "$(zenovay completions ${e.shell})"\n`;try{await l.mkdir(c.dirname(e.rcPath),{recursive:!0}),await l.appendFile(e.rcPath,`\n# Added by zenovay login\n${n}`,`utf8`),process.stdout.write(`✓ Completions installed. Restart your shell or source ${e.rcPath}.\n`)}catch(t){process.stdout.write(`Could not write ${e.rcPath} (${t.message}). Run manually: zenovay completions ${e.shell} >> ${e.rcPath}\n`)}}export{d as loginCommand};
@@ -1,2 +1,2 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import{ApiClient as t}from"./api-FCanTxsb.js";import{clearToken as n,readToken as r}from"./token-store-BQuGH0z2.js";import"./formatter-DutfcQAc.js";import{emit$1 as i,isHeadless as a}from"./emit-DBYk96TD.js";async function o(o){let s=await e(),c=await r({strict:!1}).catch(()=>null);if(c)try{let e=new t({config:s,cliVersion:o.cliVersion,token:c});await e.revokeCurrentToken()}catch{}await n(),a({json:o.json})?i({type:`done`,command:`logout`,exitCode:0}):process.stdout.write(`Logged out.
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import{ApiClient as t}from"./api-FCanTxsb.js";import{clearToken as n,readToken as r}from"./token-store-BQuGH0z2.js";import"./formatter-C4YSOKuq.js";import{emit$1 as i,isHeadless as a}from"./emit-D4YlMlzk.js";async function o(o){let s=await e(),c=await r({strict:!1}).catch(()=>null);if(c)try{let e=new t({config:s,cliVersion:o.cliVersion,token:c});await e.revokeCurrentToken()}catch{}await n(),a({json:o.json})?i({type:`done`,command:`logout`,exitCode:0}):process.stdout.write(`Logged out.
2
2
  `)}export{o as logoutCommand};
@@ -1 +1 @@
1
- import{useTheme as e}from"./panel-B_yDcIcn.js";import{spark as t}from"./sparkline-BZ0eMB-w.js";import{Box as n,Text as r}from"ink";import i from"react";function a(e,t){if(typeof e==`string`)return e;switch(t){case`percent`:{let t=Math.abs(e)<=1?e*100:e;return`${t.toFixed(1)}%`}case`duration`:{if(e<60)return`${Math.round(e)}s`;let t=Math.floor(e/60),n=Math.round(e%60);return`${t}m ${n.toString().padStart(2,`0`)}s`}case`currency`:{let t=e/100;return`$${t.toLocaleString(void 0,{minimumFractionDigits:0,maximumFractionDigits:2})}`}case`number`:default:return e.toLocaleString()}}const o=[`• `,`•• `,`•••`,` ••`,` •`,` `];function s(){let[e,t]=i.useState(0);return i.useEffect(()=>{let e=setInterval(()=>{t(e=>(e+1)%o.length)},180);return()=>clearInterval(e)},[]),e}function c({title:c,value:l,series:u,delta:d,format:f=`number`,loading:p=!1,emptyHint:m,width:h}){let{theme:g}=e(),_=s(),v=i.createElement(r,{color:g.typography.label.color,dimColor:g.typography.label.dim},c.toUpperCase()),y=({children:e})=>i.createElement(n,{flexDirection:`column`,width:h,marginRight:2,minHeight:3},e);if(p)return i.createElement(y,null,v,i.createElement(r,{color:g.accent},o[_]));let b=typeof l==`number`?l:Number(l),x=(l===``||l===`—`||typeof l==`number`&&!Number.isFinite(b))&&(!u||u.length===0);if(x)return i.createElement(y,null,v,i.createElement(r,{color:g.dim},m??`no data yet`));let S=a(l,f),C=typeof h==`number`?Math.max(8,h-4):16,w=u&&u.length>0?t(u,C):``,T=null;if(typeof d==`number`&&Number.isFinite(d)){let e=Math.abs(d*100);T=e<.5?i.createElement(r,{color:g.dim},` `,`→ `,e.toFixed(1),`%`):d>0?i.createElement(r,{color:g.success},` `,`↑ `,e.toFixed(1),`%`):i.createElement(r,{color:g.error},` `,`↓ `,e.toFixed(1),`%`)}return i.createElement(y,null,v,i.createElement(r,{color:g.typography.headline.color,bold:g.typography.headline.bold},S),w?i.createElement(n,{flexDirection:`row`},i.createElement(r,{color:g.accent},w),T):T?i.createElement(n,{flexDirection:`row`},T):i.createElement(n,{height:1}))}export{c as MetricCard};
1
+ import{useTheme as e}from"./panel-DB1HLxAw.js";import{spark as t}from"./sparkline-8ucKVUV7.js";import{Box as n,Text as r}from"ink";import i from"react";function a(e,t){if(typeof e==`string`)return e;switch(t){case`percent`:{let t=Math.abs(e)<=1?e*100:e;return`${t.toFixed(1)}%`}case`duration`:{if(e<60)return`${Math.round(e)}s`;let t=Math.floor(e/60),n=Math.round(e%60);return`${t}m ${n.toString().padStart(2,`0`)}s`}case`currency`:{let t=e/100;return`$${t.toLocaleString(void 0,{minimumFractionDigits:0,maximumFractionDigits:2})}`}case`number`:default:return e.toLocaleString()}}const o=[`• `,`•• `,`•••`,` ••`,` •`,` `];function s(){let[e,t]=i.useState(0);return i.useEffect(()=>{let e=setInterval(()=>{t(e=>(e+1)%o.length)},180);return()=>clearInterval(e)},[]),e}function c({title:c,value:l,series:u,delta:d,format:f=`number`,loading:p=!1,emptyHint:m,width:h}){let{theme:g}=e(),_=s(),v=i.createElement(r,{color:g.typography.label.color,dimColor:g.typography.label.dim},c.toUpperCase()),y=({children:e})=>i.createElement(n,{flexDirection:`column`,width:h,marginRight:2,minHeight:3},e);if(p)return i.createElement(y,null,v,i.createElement(r,{color:g.accent},o[_]));let b=typeof l==`number`?l:Number(l),x=(l===``||l===`—`||typeof l==`number`&&!Number.isFinite(b))&&(!u||u.length===0);if(x)return i.createElement(y,null,v,i.createElement(r,{color:g.dim},m??`no data yet`));let S=a(l,f),C=typeof h==`number`?Math.max(8,h-4):16,w=u&&u.length>0?t(u,C):``,T=null;if(typeof d==`number`&&Number.isFinite(d)){let e=Math.abs(d*100);T=e<.5?i.createElement(r,{color:g.dim},` `,`→ `,e.toFixed(1),`%`):d>0?i.createElement(r,{color:g.success},` `,`↑ `,e.toFixed(1),`%`):i.createElement(r,{color:g.error},` `,`↓ `,e.toFixed(1),`%`)}return i.createElement(y,null,v,i.createElement(r,{color:g.typography.headline.color,bold:g.typography.headline.bold},S),w?i.createElement(n,{flexDirection:`row`},i.createElement(r,{color:g.accent},w),T):T?i.createElement(n,{flexDirection:`row`},T):i.createElement(n,{height:1}))}export{c as MetricCard};
@@ -0,0 +1 @@
1
+ import e from"open";const t=new Set([`zenovay.com`,`app.zenovay.com`,`auth.zenovay.com`]);function n(e){let n;try{n=new URL(e)}catch{throw Error(`Refusing to open malformed URL: ${e}`)}if(n.protocol!==`https:`)throw Error(`Refusing to open non-https URL (${n.protocol})`);let r=n.hostname.toLowerCase(),i=t.has(r)||r===`zenovay.com`||r.endsWith(`.zenovay.com`);if(!i)throw Error(`Refusing to open non-Zenovay host: ${r}`);return n.toString()}async function r(t){let r;try{r=n(t)}catch(e){process.stderr.write(`\n ${e.message}\n Open it manually: ${t}\n`);return}await e(r)}export{r as openInBrowser};
@@ -0,0 +1,2 @@
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import"./formatter-C4YSOKuq.js";import{emit$1 as r,isHeadless as i}from"./emit-D4YlMlzk.js";import{openInBrowser as a}from"./open-url-dPoDcwsm.js";import"./theme-Brz9wK0w.js";import{Panel as o,useTheme as s}from"./panel-DB1HLxAw.js";import{Banner as c}from"./banner-MAYlzjcP.js";import"./prompt-D7Ek9MYk.js";import{Keybar as l}from"./keybar-BcHUm3hI.js";import{resolveSiteId as u}from"./resolve-site-DYBsBK4c.js";import{DataTable as d}from"./data-table-BvnWCG-w.js";import{EmptyState as f}from"./empty-state-DdLBcz4h.js";import{deepLinkFor as p}from"./keybar-deep-link-Dagnpllp.js";import{Box as m,Text as h,render as g,useApp as _,useInput as v}from"ink";import y,{useEffect as b,useState as x}from"react";import S from"ink-spinner";async function C(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}),l,d;try{({siteId:l,site:d}=await u(c,{explicit:a.siteId,headless:!!(a.json||a.csv||a.tsv||a.ndjson),cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let f=d?.url?d.url.replace(/^https?:\/\//,``).replace(/\/$/,``):d?.name??l;if(i(a)){let e=await c.getPages(l);if(a.csv||a.tsv){let{writeCsv:t}=await import(`./csv-emit-XJfJC5e2.js`);return t(e,[`path`,`views`,`uniqueVisitors`,`avgTime`,`bounceRate`],a.tsv?`tsv`:`csv`)}if(a.ndjson){for(let t of e)process.stdout.write(JSON.stringify(t)+`
2
+ `);return 0}return r({type:`pages.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=g(y.createElement(w,{api:c,siteId:l,siteLabel:f,cliVersion:a.cliVersion,onExit:n=>{t(),e(n)}}))})}const w=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:u}=_(),{theme:g}=s(),[C,w]=x(null),[T,E]=x(!0),[D,O]=x(null);if(v(e=>{if(e===`o`||e===`O`){a(p(`pages`,{siteId:t}));return}e===`q`&&(u(),i(0))}),b(()=>{let n=!1;return(async()=>{try{let r=await e.getPages(t);n||(w(r),E(!1))}catch(e){n||(O(e.message),E(!1))}})(),()=>{n=!0}},[e,t]),T)return y.createElement(m,{flexDirection:`column`},y.createElement(c,{version:r,subtitle:`pages · ${n}`}),y.createElement(o,{title:`Loading`,state:`busy`},y.createElement(m,null,y.createElement(h,{color:g.accent},y.createElement(S,{type:`dots`})),y.createElement(h,null,` Fetching pages…`))));if(D)return y.createElement(m,{flexDirection:`column`},y.createElement(c,{version:r,subtitle:`pages · ${n}`}),y.createElement(f,{reason:`error`,headline:`Failed to load`,hint:D}));if(!C||C.length===0)return y.createElement(m,{flexDirection:`column`},y.createElement(c,{version:r,subtitle:`pages · ${n}`}),y.createElement(f,{reason:`no-data`,headline:`No pages yet`,hint:`Visit your site to send the first event`}));let k=[{key:`path`,label:`path`,width:36},{key:`views`,label:`views`,align:`right`,width:8},{key:`uniqueVisitors`,label:`unique`,align:`right`,width:8},{key:`avgTime`,label:`avg time`,align:`right`,width:9,format:e=>typeof e==`number`?`${Math.round(e/1e3)}s`:`—`},{key:`bounceRate`,label:`bounce`,align:`right`,width:7,format:e=>typeof e==`number`?`${(e*100).toFixed(0)}%`:`—`}];return y.createElement(m,{flexDirection:`column`},y.createElement(c,{version:r,subtitle:`pages · ${n}`}),y.createElement(o,{title:`Top pages (${C.length})`},y.createElement(d,{columns:k,data:C,zebra:!0})),y.createElement(l,{items:[{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}]}))};export{C as pagesCommand};
@@ -0,0 +1 @@
1
+ import{mocha as e}from"./theme-Brz9wK0w.js";import{Box as t,Text as n}from"ink";import r,{createContext as i,useContext as a,useEffect as o,useState as s}from"react";const c=i({theme:e});function l(){return a(c)}function u(e,t,n){if(n)return e.accent;switch(t){case`busy`:return e.accent;case`ok`:return e.success;case`warn`:return e.warn;case`err`:return e.error;case`idle`:default:return e.border}}function d(){let e=process.stdout.columns;return typeof e==`number`&&e>0?e:80}function f({title:e,state:i=`idle`,pillColor:a,width:o,focused:s=!1,density:c=`comfortable`,children:f}){let{theme:p}=l(),m=u(p,i,s),h=o??d(),g=a??m,_=c===`compact`?``:` `,v=`╭─ `,y=` ─╮`,b=e??``,x=e?b.length:0,S=2,C=e?v.length+x+y.length+S<=h:!0,w=e?v.length+x+y.length:4,T=Math.max(S,h-w),E=e&&C?r.createElement(t,{flexDirection:`row`},r.createElement(n,{color:m},v),r.createElement(n,{color:g,bold:!0},b),r.createElement(n,{color:m},y,`─`.repeat(T))):e?r.createElement(t,{flexDirection:`column`},r.createElement(t,{flexDirection:`row`},r.createElement(n,{color:m},`╭`,`─`.repeat(Math.max(2,h-2)),`╮`)),r.createElement(t,{flexDirection:`row`},r.createElement(n,{color:m},`│ `),r.createElement(t,{flexGrow:1},r.createElement(n,{color:g,bold:!0},b)),r.createElement(n,{color:m},` │`))):r.createElement(t,{flexDirection:`row`},r.createElement(n,{color:m},`╭`,`─`.repeat(Math.max(2,h-2)),`╮`)),D=r.createElement(t,{flexDirection:`row`},r.createElement(n,{color:m},`╰`,`─`.repeat(Math.max(2,h-2)),`╯`));return r.createElement(t,{flexDirection:`column`},E,r.createElement(t,{flexDirection:`row`},r.createElement(n,{color:m},`│`,_),r.createElement(t,{flexDirection:`column`,flexGrow:1},f),r.createElement(n,{color:m},_,`│`)),D)}export{f as Panel,l as useTheme};
@@ -1,8 +1,8 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import{ApiError as t}from"./api-FCanTxsb.js";import{readToken as n}from"./token-store-BQuGH0z2.js";import{ApiV2Client as r}from"./api-v2-CI5hxW-O.js";import{fmtCurrency as i,formatTable as a}from"./fmt-gMsty5jy.js";import o from"open";async function s(s){let c=await e(),l=await n({strict:!1}),u=new r({config:c,cliVersion:s.cliVersion,token:l});try{switch(s.action){case`info`:{let e=await u.getPlanInfo();if(s.json)return process.stdout.write(JSON.stringify(e,null,2)+`
2
- `),0;let t=[{key:`plan`,value:e.plan},{key:`status`,value:`${e.status}${e.cancelAtPeriodEnd?` (cancels at period end)`:``}`},{key:`current period`,value:`${e.currentPeriodStart??`—`} → ${e.currentPeriodEnd??`—`}`},{key:`websites in use`,value:String(e.usage.websites)}];e.nextInvoice&&t.push({key:`next invoice`,value:`${i(e.nextInvoice.amountDue,e.nextInvoice.currency)} on ${e.nextInvoice.periodEnd??`—`}`});let n=[{key:`key`,header:`field`,width:18},{key:`value`,header:`value`,width:48}];return process.stdout.write(`
3
- `),process.stdout.write(a({rows:t,cols:n})),process.stdout.write(`
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import{ApiError as t}from"./api-FCanTxsb.js";import{readToken as n}from"./token-store-BQuGH0z2.js";import{ApiV2Client as r}from"./api-v2-CI5hxW-O.js";import{openInBrowser as i}from"./open-url-dPoDcwsm.js";import{fmtCurrency as a,formatTable as o}from"./fmt-iR2sYwsO.js";async function s(s){let c=await e(),l=await n({strict:!1}),u=new r({config:c,cliVersion:s.cliVersion,token:l});try{switch(s.action){case`info`:{let e=await u.getPlanInfo();if(s.json)return process.stdout.write(JSON.stringify(e,null,2)+`
2
+ `),0;let t=[{key:`plan`,value:e.plan},{key:`status`,value:`${e.status}${e.cancelAtPeriodEnd?` (cancels at period end)`:``}`},{key:`current period`,value:`${e.currentPeriodStart??`—`} → ${e.currentPeriodEnd??`—`}`},{key:`websites in use`,value:String(e.usage.websites)}];e.nextInvoice&&t.push({key:`next invoice`,value:`${a(e.nextInvoice.amountDue,e.nextInvoice.currency)} on ${e.nextInvoice.periodEnd??`—`}`});let n=[{key:`key`,header:`field`,width:18},{key:`value`,header:`value`,width:48}];return process.stdout.write(`
3
+ `),process.stdout.write(o({rows:t,cols:n})),process.stdout.write(`
4
4
  `),0}case`upgrade`:if(!s.targetPlan)return process.stderr.write("Error: pass <plan> (pro | scale | enterprise) — e.g. `zenovay plans upgrade pro`.\n"),2;try{let e=await u.upgradePlan(s.targetPlan);return s.json?(process.stdout.write(JSON.stringify(e,null,2)+`
5
5
  `),0):(process.stdout.write(`✔ Upgraded to ${e.plan} (subscription ${e.subscriptionId}, status ${e.status}).\n`),0)}catch(e){if(e instanceof t&&e.status===409){let t=e.body??{},n=t.checkoutUrl??`https://app.zenovay.com/plans?upgrade=${s.targetPlan}`;if(s.json)return process.stdout.write(JSON.stringify({requiresCheckout:!0,checkoutUrl:n},null,2)+`
6
- `),0;process.stdout.write(`Opening browser to complete checkout:\n ${n}\n`);try{await o(n)}catch{}return 0}throw e}case`cancel`:{if(!s.yes)return process.stderr.write("Error: `plans cancel` requires --yes to confirm. Your subscription will continue until the end of the current period.\n"),2;let e=await u.cancelPlan();return s.json?(process.stdout.write(JSON.stringify(e,null,2)+`
6
+ `),0;process.stdout.write(`Opening browser to complete checkout:\n ${n}\n`);try{await i(n)}catch{}return 0}throw e}case`cancel`:{if(!s.yes)return process.stderr.write("Error: `plans cancel` requires --yes to confirm. Your subscription will continue until the end of the current period.\n"),2;let e=await u.cancelPlan();return s.json?(process.stdout.write(JSON.stringify(e,null,2)+`
7
7
  `),0):(process.stdout.write(`✔ Subscription scheduled to cancel on ${e.effectiveAt}.\n`),0)}case`payment`:{if(s.paymentAction!==`update`)return process.stderr.write("Error: only `plans payment update` is supported.\n"),2;let e=`https://app.zenovay.com/billing/portal`;if(s.json)return process.stdout.write(JSON.stringify({portalUrl:e},null,2)+`
8
- `),0;process.stdout.write(`Opening Stripe Customer Portal:\n ${e}\n`);try{await o(e)}catch{}return 0}}}catch(e){return process.stderr.write(`✗ ${e.message}\n`),1}}export{s as plansCommand};
8
+ `),0;process.stdout.write(`Opening Stripe Customer Portal:\n ${e}\n`);try{await i(e)}catch{}return 0}}}catch(e){return process.stderr.write(`✗ ${e.message}\n`),1}}export{s as plansCommand};
@@ -0,0 +1,3 @@
1
+ import{useTheme as e}from"./panel-DB1HLxAw.js";import{Box as t,Text as n,useInput as r}from"ink";import i,{useMemo as a,useState as o}from"react";import{diffLines as s}from"diff";function c(e){return e.endsWith(`
2
+ `)?e.slice(0,-1):e}function l(e,t,n){let r=s(e,t),i=0,a=0,o=[];for(let e of r){let t=c(e.value),n=t.length===0?[``]:t.split(`
3
+ `);e.added?(i+=n.length,o.push({kind:`add`,lines:n})):e.removed?(a+=n.length,o.push({kind:`remove`,lines:n})):o.push({kind:`context`,lines:n})}let l=[];for(let e=0;e<o.length;e+=1){let t=o[e];if(!t)continue;if(t.kind!==`context`){for(let e of t.lines)l.push({kind:t.kind,text:e});continue}let r=e>0&&o[e-1]&&o[e-1].kind!==`context`,i=e+1<o.length&&o[e+1]&&o[e+1].kind!==`context`,a=t.lines;if(!r&&!i){let e=a.slice(0,n);for(let t of e)l.push({kind:`context`,text:t});continue}if(r&&i){if(a.length<=n*2)for(let e of a)l.push({kind:`context`,text:e});else{for(let e of a.slice(0,n))l.push({kind:`context`,text:e});l.push({kind:`context`,text:`…`});for(let e of a.slice(-n))l.push({kind:`context`,text:e})}continue}if(r){for(let e of a.slice(0,n))l.push({kind:`context`,text:e});continue}for(let e of a.slice(-n))l.push({kind:`context`,text:e})}return{lines:l,added:i,removed:a}}const u=30;function d({oldContent:s,newContent:c,filePath:d,contextLines:f=3,onApprove:p}){let{theme:m}=e(),{lines:h,added:g,removed:_}=a(()=>l(s,c,f),[s,c,f]),[v,y]=o(0),b=Math.max(0,h.length-u);r((e,t)=>{if(e===`y`||e===`Y`){p(`y`);return}if(e===`n`||e===`N`||e===`s`||e===`S`){p(`n`);return}if(e===`a`||e===`A`){p(`a`);return}if(e===`e`||e===`E`){p(`e`);return}if(t.downArrow||e===`j`){y(e=>Math.min(b,e+1));return}(t.upArrow||e===`k`)&&y(e=>Math.max(0,e-1))});let x=h.slice(v,v+u),S=h.length>u,C=`┌ ${d} ───── +${g} -${_} ┐`;return i.createElement(t,{flexDirection:`column`},i.createElement(n,{color:m.border},C),x.map((e,t)=>e.kind===`add`?i.createElement(n,{key:t,color:m.success},`+ `,e.text):e.kind===`remove`?i.createElement(n,{key:t,color:m.error},`- `,e.text):i.createElement(n,{key:t,color:m.dim},` `,e.text)),S?i.createElement(n,{color:m.dim},`… `,v+u,`/`,h.length,` lines (`,b-v,` more)`):null,i.createElement(t,{marginTop:1},i.createElement(n,{color:m.dim},i.createElement(n,{color:m.accent},`[y]`),` apply`,` `,i.createElement(n,{color:m.accent},`[s]`),` skip`,` `,i.createElement(n,{color:m.accent},`[e]`),` edit`,` `,i.createElement(n,{color:m.accent},`[a]`),` apply all`,` `,i.createElement(n,{color:m.muted},`jk/↑↓ scroll`))))}const f=({done:r,total:a,label:o})=>{let{theme:s}=e(),c=a>0&&r>=a,l=c?s.success:s.accent,u=c?`Done`:o??``;return i.createElement(t,{flexDirection:`row`},i.createElement(n,{color:l},`[`,r,`/`,a,`]`),u?i.createElement(n,{color:s.fg},` `,u):null)};export{d as DiffView,f as ProgressRow};
@@ -0,0 +1,2 @@
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import"./error-codes-C5caZH9p.js";import"./telemetry-DRh10SvO.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{formatTabular as r,selectFormat as i}from"./formatter-C4YSOKuq.js";import"./client-I4GTcUcm.js";import"./theme-Brz9wK0w.js";import{useTheme as a}from"./panel-DB1HLxAw.js";import"./banner-MAYlzjcP.js";import"./prompt-D7Ek9MYk.js";import"./keybar-BcHUm3hI.js";import"./chat-panel-dXLm3hUn.js";import{resolveSiteId as o}from"./resolve-site-DYBsBK4c.js";import{DataTable as s}from"./data-table-BvnWCG-w.js";import{runAnalyticalScreen as c}from"./analytical-screen-BrOFDrQ_.js";import{Text as l}from"ink";import u from"react";const d=()=>{let{theme:e}=a();return u.createElement(l,{color:e.muted},`— no projects yet —`)};function f(){let e=process.stdout.columns??80,t=Math.max(40,e-4-18),n=1,r=t-n,i=Math.max(8,Math.floor(r*.3)),a=Math.max(8,Math.floor(r*.32)),o=Math.max(4,Math.floor(r*.1)),s=Math.max(6,Math.floor(r*.12)),c=Math.max(4,r-i-a-o-s);return{current:n,name:i,domain:a,tier:o,pageviews24h:s,id:c}}async function p(a){let l=await e(),p=await t({strict:!1}),m=new n({config:l,cliVersion:a.cliVersion,token:p}),h,g;try{({siteId:h,site:g}=await o(m,{explicit:a.siteId,headless:!!(a.json||a.csv||a.tsv||a.ndjson),cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let _=i(a),v=f(),y=[{key:`isCurrent`,label:``,width:v.current,format:e=>e?`*`:` `},{key:`name`,label:`project`,width:v.name},{key:`domain`,label:`domain`,width:v.domain,format:e=>String(e??`—`)},{key:`tier`,label:`tier`,width:v.tier},{key:`pageviews24h`,label:`24h pv`,width:v.pageviews24h,align:`right`},{key:`id`,label:`id`,width:v.id}];return c({cliVersion:a.cliVersion,title:`projects · ${p?.teamId??`—`}`,commandName:`projects`,authToken:p?.accessToken??null,refreshIntervalMs:0,fetcher:e=>m.getProjects(h,e),format:_,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){if(t===`ndjson`)for(let t of e.projects)process.stdout.write(JSON.stringify(t)+`
2
+ `);else process.stdout.write(JSON.stringify(e,null,2));return}process.stdout.write(r(e.projects,[`id`,`name`,`domain`,`tier`,`pageviews24h`,`isCurrent`],t))},keybindings:{s:{label:`switch project (logout + login)`,handler:()=>{process.stderr.write("To switch project: run `zenovay logout` then `zenovay login`.\n")}}},panels:[{id:`projects`,title:`Projects`,render:e=>e.projects.length===0?u.createElement(d,null):u.createElement(s,{data:e.projects,columns:y,headerStyle:`accent`})}]})}export{p as projectsCommand};
@@ -1 +1 @@
1
- import{useTheme as e}from"./panel-B_yDcIcn.js";import{Box as t,Text as n,useInput as r}from"ink";import i,{useCallback as a,useState as o}from"react";import s from"ink-select-input";import c from"ink-text-input";function l({hints:t}){let{theme:r}=e();return i.createElement(n,{color:r.dim},t)}function u({items:r,onSelect:c}){let{theme:u}=e(),[d,f]=o(r[0]),[p,m]=o(null),h=a(e=>{m({label:e.label}),setTimeout(()=>c(e.value),200)},[c]),g=a(e=>{f(e)},[]);return p?i.createElement(n,{color:u.success},`✓ `,p.label):i.createElement(t,{flexDirection:`column`},i.createElement(s,{items:r.map((e,t)=>({key:`${t}`,label:e.label,value:e.value})),onSelect:e=>{let t=r.find(t=>t.value===e.value);t&&h(t)},onHighlight:e=>{let t=r.find(t=>t.value===e.value);t&&g(t)}}),d?.description?i.createElement(t,{marginTop:1},i.createElement(n,{color:u.muted},d.description)):null,i.createElement(t,{marginTop:1},i.createElement(l,{hints:`[↑↓/jk nav] [enter select]`})))}function d({question:r,onSubmit:a,placeholder:s,mask:u}){let{theme:d}=e(),[f,p]=o(``);return i.createElement(t,{flexDirection:`column`},i.createElement(t,null,i.createElement(n,{color:d.fg},r,` `),i.createElement(c,{value:f,onChange:p,onSubmit:e=>a(e),placeholder:s,mask:u?`•`:void 0})),i.createElement(l,{hints:`[enter submit]`}))}export{u as Select,d as TextInput};
1
+ import{useTheme as e}from"./panel-DB1HLxAw.js";import{Box as t,Text as n,useInput as r}from"ink";import i,{useCallback as a,useState as o}from"react";import s from"ink-select-input";import c from"ink-text-input";function l({hints:t}){let{theme:r}=e();return i.createElement(n,{color:r.dim},t)}function u({items:r,onSelect:c}){let{theme:u}=e(),[d,f]=o(r[0]),[p,m]=o(null),h=a(e=>{m({label:e.label}),setTimeout(()=>c(e.value),200)},[c]),g=a(e=>{f(e)},[]);return p?i.createElement(n,{color:u.success},`✓ `,p.label):i.createElement(t,{flexDirection:`column`},i.createElement(s,{items:r.map((e,t)=>({key:`${t}`,label:e.label,value:e.value})),onSelect:e=>{let t=r.find(t=>t.value===e.value);t&&h(t)},onHighlight:e=>{let t=r.find(t=>t.value===e.value);t&&g(t)}}),d?.description?i.createElement(t,{marginTop:1},i.createElement(n,{color:u.muted},d.description)):null,i.createElement(t,{marginTop:1},i.createElement(l,{hints:`[↑↓/jk nav] [enter select]`})))}function d({question:r,onSubmit:a,placeholder:s,mask:u}){let{theme:d}=e(),[f,p]=o(``);return i.createElement(t,{flexDirection:`column`},i.createElement(t,null,i.createElement(n,{color:d.fg},r,` `),i.createElement(c,{value:f,onChange:p,onSubmit:e=>a(e),placeholder:s,mask:u?`•`:void 0})),i.createElement(l,{hints:`[enter submit]`}))}export{u as Select,d as TextInput};
@@ -0,0 +1,8 @@
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{requireTier as r}from"./tier-BneaO4vD.js";import{formatTabular as i,selectFormat as a}from"./formatter-C4YSOKuq.js";import"./theme-Brz9wK0w.js";import{Panel as o,useTheme as s}from"./panel-DB1HLxAw.js";import{Banner as c}from"./banner-MAYlzjcP.js";import"./progress-row-BS7fwhn_.js";import"./prompt-D7Ek9MYk.js";import"./keybar-BcHUm3hI.js";import"./sparkline-8ucKVUV7.js";import{resolveSiteId as l}from"./resolve-site-DYBsBK4c.js";import{DataTable as u}from"./data-table-BvnWCG-w.js";import"./bar-DG-MqgGx.js";import"./ui-DXrdVAc-.js";import{Box as d,Text as f,useApp as p,useInput as m}from"ink";import h,{useMemo as g,useState as _}from"react";import v from"ink-text-input";function y({api:e,siteId:t,maxRows:n}){let{theme:r}=s(),{exit:i}=p(),[a,l]=_(``),[y,b]=_(null),[x,S]=_(null),[C,w]=_(!1),[T,E]=_([]);m((e,t)=>{t.escape&&i()});let D=async r=>{if(r.trim()){if(r.trim()===`\\q`||r.trim()===`exit`||r.trim()===`quit`){i();return}E(e=>[...e,r]),w(!0),S(null);try{let i=await e.runSqlQuery(t,r,{maxRows:n});b(i)}catch(e){S(e.message),b(null)}finally{w(!1),l(``)}}},O=g(()=>y?y.columns.map(e=>({key:e,label:e,width:18,format:e=>e==null?`∅`:String(e).slice(0,18)})):[],[y]);return h.createElement(d,{flexDirection:`column`},h.createElement(c,{version:`query`}),h.createElement(o,{title:`History`,state:`idle`},T.length===0?h.createElement(f,{color:r.muted},`— no queries yet — Esc or \\q to exit —`):T.slice(-5).map((e,t)=>h.createElement(f,{key:t,color:r.muted},`> ${e.slice(0,80)}${e.length>80?`…`:``}`))),h.createElement(d,null,h.createElement(f,{color:r.accent},`sql`,`>`,` `),h.createElement(v,{value:a,onChange:l,onSubmit:D})),C?h.createElement(f,{color:r.dim},`running…`):null,x?h.createElement(o,{title:`Error`,state:`err`},h.createElement(f,{color:r.error},x)):null,y?h.createElement(o,{title:`${y.row_count} rows · ${y.duration_ms}ms${y.truncated?` · truncated`:``}`,state:`ok`},y.row_count===0?h.createElement(f,{color:r.muted},`— empty —`):h.createElement(u,{data:y.rows.slice(0,50),columns:O,headerStyle:`accent`})):null)}async function b(o){let s=await e(),c=await t({strict:!1}),u=new n({config:s,cliVersion:o.cliVersion,token:c});try{await r(u,`scale`)}catch(e){return process.stderr.write(`${e.message}\n`),2}let d;try{({siteId:d}=await l(u,{explicit:o.siteId,headless:!!(o.json||o.csv||o.tsv||o.ndjson),cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let f=o.maxRows??1e3,p=a(o);if(o.sql)try{let e=await u.runSqlQuery(d,o.sql,{maxRows:f});if(p===`json`)process.stdout.write(JSON.stringify(e,null,2)),process.stdout.write(`
2
+ `);else if(p===`ndjson`)for(let t of e.rows)process.stdout.write(JSON.stringify(t)+`
3
+ `);else if(p===`csv`||p===`tsv`)process.stdout.write(i(e.rows,e.columns,p));else{let t=e.columns.map(t=>Math.max(t.length,...e.rows.map(e=>String(e[t]??``).length))),n=`+`+t.map(e=>`-`.repeat(e+2)).join(`+`)+`+`;process.stdout.write(n+`
4
+ `),process.stdout.write(`|`+e.columns.map((e,n)=>` ${e.padEnd(t[n]??0)} `).join(`|`)+`|
5
+ `),process.stdout.write(n+`
6
+ `);for(let n of e.rows.slice(0,200))process.stdout.write(`|`+e.columns.map((e,r)=>` ${String(n[e]??``).padEnd(t[r]??0)} `).join(`|`)+`|
7
+ `);process.stdout.write(n+`
8
+ `),process.stdout.write(`${e.row_count} rows · ${e.duration_ms}ms${e.truncated?` · truncated`:``}\n`)}return 0}catch(e){return process.stderr.write(`✗ ${e.message}\n`),1}let{render:m}=await import(`ink`);return await m(h.createElement(y,{api:u,siteId:d,maxRows:f})).waitUntilExit(),0}export{b as queryCommand};
@@ -0,0 +1,2 @@
1
+ import{readConfig as e,updateConfig as t}from"./config--JRu_jFq.js";import{Panel as n,useTheme as r}from"./panel-DB1HLxAw.js";import{Banner as i}from"./banner-MAYlzjcP.js";import{Select as a}from"./prompt-D7Ek9MYk.js";import{Box as o,Text as s,render as c}from"ink";import l from"react";async function u(n,r){if(r.explicit&&r.explicit.trim())return{siteId:r.explicit.trim(),saved:!1};let i=await e(),a;try{a=await n.getSites()}catch(e){if(i.defaultSiteId)return{siteId:i.defaultSiteId,saved:!1};throw Error(`Could not fetch your sites (${e.message}). Pass --site-id <ID> to bypass.`)}if(i.defaultSiteId){let e=a.find(e=>e.id===i.defaultSiteId);if(e)return{siteId:e.id,site:e,saved:!1};await t({defaultSiteId:void 0,defaultSiteName:void 0})}if(a.length===0)throw Error("No sites in your account. Run `zenovay init` to add one, or create one at app.zenovay.com.");if(a.length===1){let e=a[0];return await t({defaultSiteId:e.id,defaultSiteName:e.name}),{siteId:e.id,site:e,saved:!0}}if(r.headless||!process.stdout.isTTY){let e=a.map(e=>` ${e.name.padEnd(24)} ${e.url.padEnd(36)} ${e.id}`).join(`
2
+ `),t=a[0]?a[0].url.replace(/^https?:\/\//,``).replace(/\/$/,``):`<domain>`;throw Error(`Multiple sites found — pick one:\n${e}\n\nPass --site-id <ID>, set ZENOVAY_SITE=<ID>, or run \`zenovay use ${t}\` to set a default.`)}let o=await d(a,r.cliVersion);return await t({defaultSiteId:o.id,defaultSiteName:o.name}),{siteId:o.id,site:o,saved:!0}}function d(e,t=`0`){return new Promise((n,r)=>{let i,a=e=>{i?.(),n(e)},o=()=>{i?.(),r(Error(`Site selection cancelled`))},s=c(l.createElement(f,{sites:e,cliVersion:t,onPick:a,onCancel:o}));i=s.unmount})}const f=({sites:e,cliVersion:t,onPick:c})=>{let{theme:u}=r(),d=e.map(e=>({label:`${e.name.padEnd(28)} ${e.url.replace(/^https?:\/\//,``).padEnd(28)}`,value:e,description:e.trackingCode?`tracking: ${e.trackingCode}`:void 0}));return l.createElement(o,{flexDirection:`column`},l.createElement(i,{version:t,subtitle:`pick a site`}),l.createElement(n,{title:`Which site?`,state:`idle`},l.createElement(o,{marginBottom:1},l.createElement(s,{color:u.muted},"We'll save your pick as the default — re-run with `zenovay use --reset` to change it.")),l.createElement(a,{items:d,onSelect:c})))};export{u as resolveSiteId};
@@ -0,0 +1 @@
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{requireTier as r}from"./tier-BneaO4vD.js";import"./formatter-C4YSOKuq.js";import{emit$1 as i,isHeadless as a}from"./emit-D4YlMlzk.js";import{openInBrowser as o}from"./open-url-dPoDcwsm.js";import"./theme-Brz9wK0w.js";import{Panel as s,useTheme as c}from"./panel-DB1HLxAw.js";import{Banner as l}from"./banner-MAYlzjcP.js";import"./prompt-D7Ek9MYk.js";import{Keybar as u}from"./keybar-BcHUm3hI.js";import{resolveSiteId as d}from"./resolve-site-DYBsBK4c.js";import{EmptyState as f}from"./empty-state-DdLBcz4h.js";import{deepLinkFor as p}from"./keybar-deep-link-Dagnpllp.js";import{Box as m,Text as h,render as g,useApp as _,useInput as v}from"ink";import y,{useEffect as b,useState as x}from"react";import S from"ink-spinner";function C(e,t){return e>=.6?t.accent:e>=.4?t.muted:t.dim}function w(e){return!Number.isFinite(e)||e===0?` — `:` ${(e*100).toFixed(0).padStart(3)}% `}async function T(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 l=new n({config:s,cliVersion:o.cliVersion,token:c});try{await r(l,`pro`)}catch(e){return process.stderr.write(`${e.message}\n`),2}let u,f;try{({siteId:u,site:f}=await d(l,{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??u;if(a(o)){let e=await l.getRetention(u);return i({type:`retention.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=g(y.createElement(E,{api:l,siteId:u,siteLabel:p,cliVersion:o.cliVersion,onExit:n=>{t(),e(n)}}))})}const E=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:a}=_(),{theme:d}=c(),[g,T]=x(null),[E,D]=x(!0),[O,k]=x(null);return v(e=>{if(e===`o`||e===`O`){o(p(`retention`,{siteId:t}));return}e===`q`&&(a(),i(0))}),b(()=>{let n=!1;return(async()=>{try{let r=await e.getRetention(t);n||(T(r.cohorts),D(!1))}catch(e){n||(k(e.message),D(!1))}})(),()=>{n=!0}},[e,t]),E?y.createElement(m,{flexDirection:`column`},y.createElement(l,{version:r,subtitle:`retention · ${n}`}),y.createElement(s,{title:`Loading`,state:`busy`},y.createElement(m,null,y.createElement(h,{color:d.accent},y.createElement(S,{type:`dots`})),y.createElement(h,null,` Crunching cohorts…`)))):O?y.createElement(m,{flexDirection:`column`},y.createElement(l,{version:r,subtitle:`retention · ${n}`}),y.createElement(f,{reason:`error`,headline:`Failed to load`,hint:O})):!g||g.length===0?y.createElement(m,{flexDirection:`column`},y.createElement(l,{version:r,subtitle:`retention · ${n}`}),y.createElement(f,{reason:`no-data`,headline:`No retention data yet`,hint:`Retention needs at least 30 days of traffic`})):y.createElement(m,{flexDirection:`column`},y.createElement(l,{version:r,subtitle:`retention · ${n}`}),y.createElement(s,{title:`Cohort retention (D1 / D7 / D30)`},y.createElement(m,{flexDirection:`row`},y.createElement(h,{bold:!0},`cohort`.padEnd(12)),y.createElement(h,{bold:!0},` D1 `),y.createElement(h,{bold:!0},` D7 `),y.createElement(h,{bold:!0},` D30 `)),g.map(e=>y.createElement(m,{key:e.date,flexDirection:`row`},y.createElement(h,null,e.date.padEnd(12).slice(0,12)),y.createElement(h,{color:C(e.day1,d)},w(e.day1)),y.createElement(h,{color:C(e.day7,d)},w(e.day7)),y.createElement(h,{color:C(e.day30,d)},w(e.day30))))),y.createElement(u,{items:[{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}]}))};export{T as retentionCommand};
@@ -0,0 +1,2 @@
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import"./error-codes-C5caZH9p.js";import"./telemetry-DRh10SvO.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{formatTabular as r,selectFormat as i}from"./formatter-C4YSOKuq.js";import"./client-I4GTcUcm.js";import{openInBrowser as a}from"./open-url-dPoDcwsm.js";import"./theme-Brz9wK0w.js";import{useTheme as o}from"./panel-DB1HLxAw.js";import"./banner-MAYlzjcP.js";import"./progress-row-BS7fwhn_.js";import"./prompt-D7Ek9MYk.js";import"./keybar-BcHUm3hI.js";import{spark as s}from"./sparkline-8ucKVUV7.js";import"./chat-panel-dXLm3hUn.js";import{resolveSiteId as c}from"./resolve-site-DYBsBK4c.js";import"./data-table-BvnWCG-w.js";import"./bar-DG-MqgGx.js";import{deepLinkFor as l}from"./keybar-deep-link-Dagnpllp.js";import{runAnalyticalScreen as u}from"./analytical-screen-BrOFDrQ_.js";import"./ui-DXrdVAc-.js";import{Box as d,Text as f}from"ink";import p from"react";function m(e,t){let n=e/100,r=new Intl.NumberFormat(`en-US`,{minimumFractionDigits:0,maximumFractionDigits:0}).format(n),i=(t||`USD`).toUpperCase();return i===`USD`?`$${r}`:i===`EUR`?`€${r}`:i===`GBP`?`£${r}`:`${r} ${i}`}function h({data:e}){let{theme:t}=o();return p.createElement(d,{flexDirection:`column`},p.createElement(f,null,p.createElement(f,{color:t.accent,bold:!0},m(e.totalAmount,e.currency)),` `,p.createElement(f,{color:t.muted},`total · `,e.totalTransactions,` transactions`)),typeof e.mrr==`number`?p.createElement(f,null,p.createElement(f,{bold:!0},`MRR `),p.createElement(f,{color:t.accent},m(e.mrr,e.currency)),typeof e.arpu==`number`?p.createElement(f,{color:t.muted},` · ARPU `,m(e.arpu,e.currency)):null):null)}function g({data:e}){let{theme:t}=o(),n=e.series.map(e=>e.amount);if(n.length===0)return p.createElement(f,{color:t.muted},`— no transactions —`);let r=Math.max(...n,1);return p.createElement(d,{flexDirection:`column`},p.createElement(f,{color:t.accent},s(n,Math.min(60,n.length*2))),p.createElement(f,{color:t.muted},`peak: `,m(r,e.currency),` ·`,` `,`avg: `,m(e.totalAmount/Math.max(1,n.length),e.currency)))}function _({data:e}){let{theme:t}=o();return p.createElement(f,{color:t.muted},new Date(e.windowStart).toISOString().slice(0,10),` →`,` `,new Date(e.windowEnd).toISOString().slice(0,10))}async function v(o){let s=await e(),d=await t({strict:!1}),f=new n({config:s,cliVersion:o.cliVersion,token:d}),m,v;try{({siteId:m,site:v}=await c(f,{explicit:o.siteId,headless:!!(o.json||o.csv||o.tsv||o.ndjson),cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let y=i(o),b=o.range??`30d`;return u({cliVersion:o.cliVersion,title:`revenue · ${m} · ${b}`,commandName:`revenue`,ai:{api:f,siteId:m,siteLabel:v?.url?v.url.replace(/^https?:\/\//,``).replace(/\/$/,``):v?.name??m},authToken:d?.accessToken??null,refreshIntervalMs:o.watch?5*6e4:0,fetcher:e=>f.getRevenue(m,b,e),format:y,keybindings:{o:{label:`open in browser`,handler:()=>{a(l(`revenue`,{siteId:m}))}}},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
+ `);return}process.stdout.write(r(e.series,[`bucket`,`amount`,`currency`,`transactions`],t))},panels:[{id:`totals`,title:`Top line`,render:e=>p.createElement(h,{data:e})},{id:`series`,title:`Daily (${b})`,render:e=>p.createElement(g,{data:e})},{id:`window`,title:`Window`,render:e=>p.createElement(_,{data:e})}]})}export{v as revenueCommand};
@@ -0,0 +1 @@
1
+ import{SECRET_PATTERNS as e,scrubSecrets as t}from"./secrets-DzueUVGL.js";export{e as SECRET_PATTERNS,t as scrubSecrets};
@@ -0,0 +1,16 @@
1
+ import{mocha as e}from"./theme-Brz9wK0w.js";import{spawn as t}from"node:child_process";import n from"chalk";const r=3e4,i=4,a=1e3;function o(e,t){let n=e.requires;if(!n)return null;if(n.auth!==!1&&!t.authenticated)return`not authenticated`;if(n.tier&&t.currentTier){let e={free:0,pro:1,scale:2,enterprise:3},r=e[t.currentTier]??0,i=e[n.tier]??99}return n.multipleTeams&&!t.hasMultipleTeams?`requires 2+ teams`:n.freeTeam&&!t.hasFreeTeam?`requires a Free-tier team`:null}function s(e,n,r,i){return new Promise(a=>{let o=/\.[mc]?js$/.test(e),s=o?`node`:e,c=o?[e,...n]:n,l=t(s,c,{env:{...process.env,ZENOVAY_NO_UPDATE_CHECK:`1`,...i},stdio:[`ignore`,`pipe`,`pipe`]}),u=``,d=``,f=!1,p=setTimeout(()=>{f=!0;try{l.kill(`SIGKILL`)}catch{}},r);l.stdout?.on(`data`,e=>{u+=e.toString(`utf8`),u.length>1048576&&(u=u.slice(0,1048576))}),l.stderr?.on(`data`,e=>{d+=e.toString(`utf8`),d.length>1048576&&(d=d.slice(0,1048576))}),l.on(`error`,e=>{clearTimeout(p),a({stdout:u,stderr:d+`\n[spawn error: ${e.message}]`,exitCode:-1,timedOut:f})}),l.on(`close`,e=>{clearTimeout(p),a({stdout:u,stderr:d,exitCode:e??0,timedOut:f})})})}async function c(e,t){let n=Date.now(),i=o(e,t.env);if(i)return{name:e.name,category:e.category,status:`skip`,durationMs:0,reason:i};if(e.inProcess)try{let t=await e.inProcess(),r=Date.now()-n;return t.ok?{name:e.name,category:e.category,status:`pass`,durationMs:r,...t.detail?{detail:t.detail}:{}}:{name:e.name,category:e.category,status:`fail`,durationMs:r,reason:t.reason}}catch(t){return{name:e.name,category:e.category,status:`fail`,durationMs:Date.now()-n,reason:t.message}}let c=e.name===`stack-leak.bad-net`?{ZENOVAY_API_BASE:`http://127.0.0.1:1`}:void 0,l=t.timeoutMs??r,u=await s(t.binPath,e.command,l,c),d=Date.now()-n;if(u.timedOut)return{name:e.name,category:e.category,status:`fail`,durationMs:d,reason:`timeout (${Math.round(l/1e3)}s)`,...t.verbose?{rawStdout:u.stdout.slice(0,a),rawStderr:u.stderr.slice(0,a)}:{}};let f;try{f=e.assert(u.stdout,u.stderr,u.exitCode)}catch(n){return{name:e.name,category:e.category,status:`fail`,durationMs:d,reason:`assert threw: ${n.message}`,...t.verbose?{rawStdout:u.stdout.slice(0,a),rawStderr:u.stderr.slice(0,a)}:{}}}return f.ok?{name:e.name,category:e.category,status:`pass`,durationMs:d,...f.detail?{detail:f.detail}:{},...t.verbose?{rawStdout:u.stdout.slice(0,a),rawStderr:u.stderr.slice(0,a)}:{}}:{name:e.name,category:e.category,status:`fail`,durationMs:d,reason:f.reason,...t.verbose?{rawStdout:u.stdout.slice(0,a),rawStderr:u.stderr.slice(0,a)}:{}}}async function l(e,t){let n=Date.now(),r=Math.max(1,t.parallel??i),a=Array(e.length).fill(void 0),o=[];for(let n=0;n<e.length;n++){let r=e[n];r&&(t.quick&&!r.quick||o.push(n))}let s=0,l=[],u=async()=>{for(;;){let n=s;if(s+=1,n>=o.length)return;let r=o[n];if(r===void 0)return;let i=e[r];if(!i)continue;let l=await c(i,t);a[r]=l,t.onResult?.(l)}};for(let e=0;e<r;e++)l.push(u());await Promise.all(l);let d=[];for(let e of a)e&&d.push(e);let f=d.filter(e=>e.status===`pass`).length,p=d.filter(e=>e.status===`fail`).length,m=d.filter(e=>e.status===`skip`).length;return{results:d,total:d.length,pass:f,fail:p,skip:m,durationMs:Date.now()-n}}async function u(e){let t={currentTier:null,hasMultipleTeams:!1,hasFreeTeam:!1,authenticated:!1};try{let{readToken:n}=await import(`./token-store-TmBx42nv.js`),{readConfig:r}=await import(`./config-DB3jF5gG.js`),{ApiV2Client:i}=await import(`./api-v2-CTc_U2Gw.js`),a=await n({strict:!1}).catch(()=>null);if(!a)return t;t.authenticated=!0;let o=await r(),s=new i({config:o,cliVersion:e,token:a}),c=await s.me();if(c.team?.plan){let e=c.team.plan.toLowerCase();(e===`free`||e===`pro`||e===`scale`||e===`enterprise`)&&(t.currentTier=e)}c.teams&&c.teams.length>=2&&(t.hasMultipleTeams=!0),(c.teams&&c.teams.some(e=>e.plan?.toLowerCase()===`free`)||t.currentTier===`free`)&&(t.hasFreeTeam=!0)}catch{}return t}function d(e){let t=e.trim();if(!t)return{ok:!1,reason:`empty stdout`};try{return{ok:!0,value:JSON.parse(t)}}catch{let e=t.split(`
2
+ `).filter(e=>e.trim().startsWith(`{`)||e.trim().startsWith(`[`)).pop();if(e)try{return{ok:!0,value:JSON.parse(e)}}catch{}return{ok:!1,reason:`stdout not JSON (got ${t.length} bytes)`}}}function f(e,t,n){if(n!==0)return{ok:!1,reason:`exit ${n}`};let r=d(e);return r.ok?{ok:!0}:{ok:!1,reason:r.reason}}function p(e,t,n){if(n!==0){let r=[e,t];for(let e of r)if(e.includes(`tier_insufficient`))return{ok:!0,detail:{gated:!0}};return{ok:!1,reason:`exit ${n} — ${(t||e).slice(0,80)}`}}let r=d(e);return r.ok?{ok:!0}:{ok:!1,reason:r.reason}}function m(e){if(typeof e!=`object`||!e)return!1;let t=e;if(Array.isArray(t.items)||Array.isArray(t.rows)||Array.isArray(t.data))return!0;if(typeof t.data==`object`&&t.data!==null){let e=t.data;if(Array.isArray(e.items)||Array.isArray(e.rows))return!0}return!1}const h=[{name:`analytics`,category:`ANALYTICS`,command:[`analytics`,`--json`],assert:(e,t,n)=>{let r=f(e,t,n);if(!r.ok)return r;let i=d(e);if(!i.ok)return{ok:!1,reason:i.reason};let a=i.value,o=a.visitors??a.data?.visitors,s=a.pageviews??a.data?.pageviews;return{ok:!0,detail:{visitors:o??null,pageviews:s??null}}},quick:!0},{name:`overview`,category:`ANALYTICS`,command:[`overview`,`--json`],assert:f},{name:`pages`,category:`ANALYTICS`,command:[`pages`,`--json`],assert:(e,t,n)=>{let r=f(e,t,n);if(!r.ok)return r;let i=d(e);if(!i.ok)return{ok:!1,reason:i.reason};let a=i.value,o=a.items??a.data?.items;return{ok:!0,detail:{rows:o?.length??0}}},quick:!0},{name:`sources`,category:`ANALYTICS`,command:[`sources`,`--json`],assert:f,quick:!0},{name:`devices`,category:`ANALYTICS`,command:[`devices`,`--json`],assert:f},{name:`geo`,category:`ANALYTICS`,command:[`geo`,`--json`],assert:f},{name:`live`,category:`ANALYTICS`,command:[`live`,`--json`],assert:(e,t,n)=>{let r=f(e,t,n);if(!r.ok)return r;let i=d(e);if(i.ok&&typeof i.value==`object`&&i.value!==null){let e=i.value,t=e.bounceRate??e.data?.bounceRate;if(typeof t==`number`&&(t<0||t>1))return{ok:!1,reason:`bounceRate semantics violated (got ${t}, expected 0..1)`}}return{ok:!0}}},{name:`revenue`,category:`ANALYTICS`,command:[`revenue`,`--json`],assert:f},{name:`funnels`,category:`ANALYTICS`,command:[`funnels`,`--json`],assert:p,requires:{tier:`pro`}},{name:`home`,category:`ANALYTICS`,command:[`home`,`--json`],assert:f},{name:`usage`,category:`ANALYTICS`,command:[`usage`,`--json`],assert:f,quick:!0},{name:`stats`,category:`ANALYTICS`,command:[`stats`,`--json`],assert:f},{name:`retention`,category:`BEHAVIOR`,command:[`retention`,`--json`],assert:p,requires:{tier:`pro`}},{name:`uptime`,category:`BEHAVIOR`,command:[`uptime`,`--json`],assert:p,requires:{tier:`pro`}},{name:`sessions`,category:`BEHAVIOR`,command:[`sessions`,`--json`],assert:p,requires:{tier:`pro`}},{name:`heatmaps`,category:`BEHAVIOR`,command:[`heatmaps`,`--json`],assert:p,requires:{tier:`pro`}},{name:`journeys`,category:`BEHAVIOR`,command:[`journeys`,`--json`],assert:p,requires:{tier:`pro`}},{name:`insights`,category:`INTELLIGENCE`,command:[`insights`,`--json`],assert:p,requires:{tier:`pro`}},{name:`domains list`,category:`MANAGE`,command:[`domains`,`list`,`--json`],assert:(e,t,n)=>{let r=f(e,t,n);if(!r.ok)return r;let i=d(e);return!i.ok||!m(i.value)?{ok:!1,reason:`expected list shape ({items|rows|data})`}:{ok:!0}},quick:!0},{name:`api-keys list`,category:`MANAGE`,command:[`api-keys`,`list`,`--json`],assert:(e,t,n)=>{let r=f(e,t,n);if(!r.ok)return r;let i=d(e);return!i.ok||!m(i.value)?{ok:!1,reason:`expected list shape`}:{ok:!0}}},{name:`team list`,category:`MANAGE`,command:[`team`,`list`,`--json`],assert:p,requires:{tier:`pro`}},{name:`webhooks list`,category:`MANAGE`,command:[`webhooks`,`list`,`--json`],assert:f},{name:`profile show`,category:`ACCOUNT`,command:[`profile`,`show`,`--json`],assert:f,quick:!0},{name:`plans info`,category:`ACCOUNT`,command:[`plans`,`info`,`--json`],assert:f},{name:`settings get`,category:`ACCOUNT`,command:[`settings`,`get`,`--json`],assert:f},{name:`integrations list`,category:`ACCOUNT`,command:[`integrations`,`list`,`--json`],assert:f},{name:`goals list`,category:`ACCOUNT`,command:[`goals`,`list`,`--json`],assert:p,requires:{tier:`pro`}},{name:`notes list`,category:`ACCOUNT`,command:[`notes`,`list`,`--json`],assert:f},{name:`audit list`,category:`ACCOUNT`,command:[`audit`,`list`,`--json`],assert:p,requires:{tier:`pro`}},{name:`share url`,category:`ACCOUNT`,command:[`share`,`url`,`--json`],assert:(e,t,n)=>n!==0&&n!==1&&n!==2?{ok:!1,reason:`unexpected exit ${n}`}:{ok:!0}},{name:`teams list`,category:`ACCOUNT`,command:[`teams`,`list`,`--json`],assert:f},{name:`health`,category:`OPERATIONS`,command:[`health`,`--json`],assert:(e,t,n)=>{let r=d(e);return r.ok?{ok:!0}:{ok:!1,reason:r.reason}},quick:!0},{name:`commands`,category:`OPERATIONS`,command:[`commands`,`--json`],assert:(e,t,n)=>{let r=f(e,t,n);if(!r.ok)return r;let i=d(e);if(!i.ok)return{ok:!1,reason:i.reason};let a=i.value,o=a.commands;return!Array.isArray(o)||o.length===0?{ok:!1,reason:`commands tree empty`}:{ok:!0,detail:{commands:o.length}}}},{name:`themes`,category:`OPERATIONS`,command:[`themes`,`--json`],assert:f},{name:`projects`,category:`OPERATIONS`,command:[`projects`,`--json`],assert:f},{name:`idor.cross-team`,category:`SECURITY`,command:[`domains`,`list`,`--site-id`,`00000000-0000-0000-0000-000000000001`,`--json`],assert:(e,t,n)=>{let r=e+t;return/forbidden|not_found|tier_insufficient|auth_required|auth_invalid/.test(r)?{ok:!0,detail:{rejected:!0}}:r.includes(`"items"`)||r.includes(`"rows"`)?{ok:!1,reason:`expected forbidden/not_found, got data`}:{ok:!0,detail:{rejected:`empty`}}},requires:{multipleTeams:!0},dev:!0},{name:`idor.bad-uuid`,category:`SECURITY`,command:[`analytics`,`--site-id`,`00000000-0000-0000-0000-000000000000`,`--json`],assert:(e,t,n)=>{let r=e+t;return/not_found|forbidden|auth_/.test(r)?{ok:!0,detail:{rejected:!0}}:/error|invalid|"code":/i.test(r)?{ok:!0,detail:{rejected:`error-shaped`}}:{ok:!1,reason:`silent zeros — expected not_found`}},quick:!0,dev:!0},{name:`tier-gate.retention`,category:`SECURITY`,command:[`retention`,`--json`],assert:(e,t,n)=>{let r=e+t;return r.includes(`tier_insufficient`)?{ok:!0,detail:{gated:`tier_insufficient`}}:/upgrade_required|tier_required/.test(r)?{ok:!0,detail:{gated:`legacy-or-transitional`}}:/"code":\s*"forbidden"/.test(r)&&/tier|upgrade|plan/i.test(r)?{ok:!0,detail:{gated:`forbidden+tier-message`}}:n===0&&!/"type"\s*:\s*"error"/.test(r)?{ok:!0,detail:{gated:`pass-through (Pro+ access)`}}:{ok:!1,reason:`gate did not behave as expected (no tier envelope and no clean pass-through)`}},dev:!0},{name:`stack-leak.bad-net`,category:`SECURITY`,command:[`analytics`,`--json`],assert:(e,t,n)=>{let r=e+t;return/\/Users\//.test(r)||/node:internal\//.test(r)?{ok:!1,reason:`stack trace leaked filesystem path`}:{ok:!0}},quick:!0},{name:`token-perms`,category:`SECURITY`,command:[],assert:()=>({ok:!1,reason:`should run in-process`}),inProcess:async()=>{let{stat:e}=await import(`node:fs/promises`),t=await import(`node:path`),n=process.env.HOME??process.env.USERPROFILE??``,r=process.env.XDG_CONFIG_HOME??t.join(n,`.config`),i=process.platform===`win32`?t.join(process.env.APPDATA??t.join(n,`AppData`,`Roaming`),`zenovay`,`auth.json`):t.join(r,`zenovay`,`auth.json`);try{let t=await e(i);if(process.platform===`win32`)return{ok:!0,detail:{mode:`win32-skip`}};let n=t.mode&511;return n===384?{ok:!0,detail:{mode:`0600`}}:{ok:!1,reason:`auth.json mode ${n.toString(8)} != 0600`}}catch(e){let t=e.code;return t===`ENOENT`?{ok:!0,detail:{mode:`no-auth-file`}}:{ok:!1,reason:e.message}}},quick:!0},{name:`secret-scrub`,category:`SECURITY`,command:[],assert:()=>({ok:!1,reason:`should run in-process`}),inProcess:async()=>{let{SECRET_PATTERNS:e,scrubSecrets:t}=await import(`./secrets-BBaEWu03.js`),n=[{name:`openai-proj`,sample:`sk-proj-abcdefghijklmnopqrstuvwxyz0123456789`},{name:`anthropic`,sample:`sk-ant-abcdefghijklmnopqrstuvwxyz0123456789`},{name:`openai-sk`,sample:`sk-abcdefghijklmnopqrstuvwxyz0123`},{name:`github-pat-new`,sample:`github_pat_`+`a`.repeat(82)},{name:`github-pat`,sample:`ghp_`+`a`.repeat(36)},{name:`github-oauth`,sample:`gho_`+`a`.repeat(36)},{name:`aws-access-key`,sample:`AKIAABCDEFGHIJKLMNOP`},{name:`stripe-live`,sample:`sk_live_`+`a`.repeat(28)},{name:`stripe-test`,sample:`pk_test_`+`a`.repeat(28)},{name:`stripe-restricted`,sample:`rk_live_`+`a`.repeat(28)},{name:`stripe-webhook`,sample:`whsec_`+`a`.repeat(28)},{name:`slack-bot`,sample:`xoxb-1234567890-abcdef`},{name:`google-api`,sample:`AIza`+`a`.repeat(35)},{name:`jwt`,sample:`eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTYifQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c`},{name:`private-key-rsa`,sample:`-----BEGIN RSA PRIVATE KEY-----`},{name:`private-key-pkcs8`,sample:`-----BEGIN PRIVATE KEY-----`},{name:`supabase-jwt`,sample:`eyJhbGciOi`+`a`.repeat(40)},{name:`resend-api`,sample:`re_`+`a`.repeat(20)},{name:`gitlab-pat`,sample:`glpat-`+`a`.repeat(20)},{name:`shopify`,sample:`shpat_`+`a`.repeat(32)},{name:`service-role-key`,sample:`service_role: "`+`a`.repeat(40)+`"`}],r=n.map(e=>`${e.name}=${e.sample}`).join(`
3
+ `),i=t(r),a=n.filter(e=>i.includes(`[REDACTED:${e.name}]`)).length,o=e.length,s=Math.max(18,o-4);return a>=s?{ok:!0,detail:{matched:a,total:o}}:{ok:!1,reason:`${a}/${o} patterns redacted (need >= ${s})`}},quick:!0},{name:`help-line-count`,category:`DISCOVERABILITY`,command:[`--help`],assert:(e,t,n)=>{let r=e.split(`
4
+ `).length;return r<90?{ok:!0,detail:{lines:r}}:{ok:!1,reason:`${r} lines (target < 90)`}},dev:!0},{name:`help-no-wave-markers`,category:`DISCOVERABILITY`,command:[`--help`],assert:(e,t,n)=>{let r=/\b(?:Wave\s*\d|W\d|V2\.1)\b/i,i=e.match(r);return i?{ok:!1,reason:`found marker: ${i[0]}`}:{ok:!0}},dev:!0},{name:`help-has-groups`,category:`DISCOVERABILITY`,command:[`--help`],assert:(e,t,n)=>{let r=[`ANALYTICS`,`BEHAVIOR`,`MANAGE`,`ACCOUNT`,`OPERATIONS`],i=r.filter(t=>!e.includes(t));return i.length===0?{ok:!0,detail:{found:r}}:{ok:!1,reason:`missing groups: ${i.join(`, `)}`}},dev:!0},{name:`examples-coverage`,category:`DISCOVERABILITY`,command:[],assert:()=>({ok:!1,reason:`should run in-process`}),inProcess:async()=>{let{EXAMPLES:e}=await import(`./examples-C0LrZPUl.js`),t=Object.keys(e).length;return t>=25?{ok:!0,detail:{commands:t}}:{ok:!1,reason:`${t} commands have examples (need >= 25)`}},dev:!0},{name:`envelope-shape`,category:`DISCOVERABILITY`,command:[`commands`,`--json`],assert:(e,t,n)=>{if(n!==0)return{ok:!1,reason:`exit ${n}`};let r=d(e);if(!r.ok)return{ok:!1,reason:r.reason};let i=r.value,a=typeof i.version==`string`&&Array.isArray(i.commands);return a?{ok:!0,detail:{commands:i.commands.length}}:{ok:!1,reason:`commands payload missing version+commands`}},dev:!0}],g=h.length,_={accent:n.hex(e.accent),success:n.hex(e.success),error:n.hex(e.error),muted:n.hex(e.muted)};async function v(e){let t=(process.execPath||``).split(`/`).pop()||``,n=/^node(\.exe)?$/i.test(t),r=n?process.argv[1]??process.execPath:process.execPath,i=!!e.full||process.env.ZENOVAY_SELF_TEST_FULL===`1`,a=h.filter(e=>i||!e.dev);e.quick&&(a=a.filter(e=>e.quick));let o=await u(e.cliVersion);return e.json?y({...e,binPath:r,env:o,catalog:a}):S({...e,binPath:r,env:o,catalog:a})}async function y(e){let t=await l(e.catalog,{binPath:e.binPath,quick:e.quick??!1,verbose:e.verbose??!1,parallel:e.parallel,env:e.env,onResult:e=>{let t={type:`self-test.result`,name:e.name,category:e.category,status:e.status,durationMs:e.durationMs,...e.detail?{detail:e.detail}:{},...e.reason?{reason:e.reason}:{},...e.rawStdout?{rawStdout:e.rawStdout}:{},...e.rawStderr?{rawStderr:e.rawStderr}:{}};process.stdout.write(`${JSON.stringify(t)}\n`)}});return process.stdout.write(`${JSON.stringify({type:`self-test.summary`,total:t.total,pass:t.pass,fail:t.fail,skip:t.skip,durationMs:t.durationMs,cliVersion:e.cliVersion,env:e.env})}\n`),t.fail>0?1:0}const b=26,x=8;async function S(e){w(e.cliVersion,e.quick??!1,e.catalog.length);let t=new Map,n=0,r=null,i=new Map;for(let t of e.catalog)i.set(t.category,(i.get(t.category)??0)+1);let a=await l(e.catalog,{binPath:e.binPath,quick:e.quick??!1,verbose:e.verbose??!1,parallel:e.parallel,env:e.env,onResult:a=>{for(t.set(a.name,a);n<e.catalog.length;){let a=e.catalog[n];if(!a)break;let o=t.get(a.name);if(!o)break;r!==a.category&&(T(a.category,i.get(a.category)??0),r=a.category),E(a,o),t.delete(a.name),n+=1}}});return D(a),a.fail>0?1:0}function C(){return Math.max(60,process.stdout.columns??80)}function w(e,t,n){let r=Math.min(120,C()),i=r-2,a=`ZENOVAY · v${e}`,o=`self-test · ${t?`quick`:`full`} · ${n} test${n===1?``:`s`}`,s=`╭─ `+a+` `+`─`.repeat(Math.max(0,i-a.length-4))+`╮`,c=`│ `+o+` `.repeat(Math.max(0,i-o.length-2))+`│`,l=`╰`+`─`.repeat(i)+`╯`;process.stdout.write(_.accent(s)+`
5
+ `),process.stdout.write(_.accent(c)+`
6
+ `),process.stdout.write(_.accent(l)+`
7
+
8
+ `)}function T(e,t){let r=e.padEnd(16,` `),i=`· ${t} test${t===1?``:`s`}`;process.stdout.write(n.bold(r)+n.dim(i)+`
9
+ `)}function E(e,t){let r=t.status===`pass`?_.success(`✓`):t.status===`skip`?_.muted(`○`):_.error(`✗`),i=O(e.name,b),a=t.status===`pass`||t.status===`fail`?`${(t.durationMs/1e3).toFixed(2)}s`:`—`,o=a.padEnd(x,` `),s=M(t),c=t.status===`fail`?``:n.dim(s);process.stdout.write(` ${r} ${i}${o}${c}\n`);let l=N(t);if(l){let e=t.status===`fail`?_.error:n.dim;process.stdout.write(` `+n.dim(`→ `)+e(l)+`
10
+ `)}}function D(e){let t=Math.min(120,C()),r=t-2,i=`${(e.durationMs/1e3).toFixed(1)}s`,a=e.fail===0,o=a?`all checks passed`:`${e.fail} failure${e.fail===1?``:`s`}`,s=a?_.success(o):_.error(o),c=Math.max(0,r-3-o.length),l=n.dim(`╭─ `)+s+n.dim(` `+`─`.repeat(c)+`╮`);process.stdout.write(`
11
+ `+l+`
12
+ `);let u=n.bold(`${e.pass} / ${e.total}`)+n.dim(` pass · `)+(e.fail>0?_.error(`${e.fail} fail`):n.dim(`${e.fail} fail`))+n.dim(` · ${e.skip} skip · ${i}`),d=k(u);process.stdout.write(n.dim(`│ `)+u+` `.repeat(Math.max(0,r-d-2))+n.dim(` │`)+`
13
+ `),process.stdout.write(n.dim(`│`+` `.repeat(r)+`│`)+`
14
+ `);let f=`Run with --json for machine-readable output, --verbose for full traces.`;process.stdout.write(n.dim(`│ `+f+` `.repeat(Math.max(0,r-f.length-4))+` │`)+`
15
+ `),process.stdout.write(n.dim(`╰`+`─`.repeat(r)+`╯`)+`
16
+ `)}function O(e,t){return e.length>t?e.slice(0,t-1)+`…`:e.padEnd(t,` `)}function k(e){return e.replace(/\x1b\[[0-9;]*m/g,``).length}const A=40,j=240;function M(e){if(e.status===`fail`||e.status===`skip`&&!e.detail||!e.detail)return``;let t=Object.entries(e.detail).filter(([,e])=>e!=null);if(t.length===0)return``;let n=t.map(([e,t])=>`${e}=${P(t)}`).join(` `);return n.length>A?n.slice(0,A-1)+`…`:n}function N(e){if(e.status===`fail`){let t=e.reason??`failed`;return t.length>j?t.slice(0,j-1)+`…`:t}return e.status===`skip`&&e.reason?e.reason.length>j?e.reason.slice(0,j-1)+`…`:e.reason:``}function P(e){return typeof e==`string`?e:typeof e==`number`||typeof e==`boolean`?String(e):e===null?`null`:JSON.stringify(e)}export{v as selfTestCommand};
@@ -0,0 +1 @@
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{requireTier as r}from"./tier-BneaO4vD.js";import"./formatter-C4YSOKuq.js";import{emit$1 as i,isHeadless as a}from"./emit-D4YlMlzk.js";import{openInBrowser as o}from"./open-url-dPoDcwsm.js";import"./theme-Brz9wK0w.js";import{Panel as s,useTheme as c}from"./panel-DB1HLxAw.js";import{Banner as l}from"./banner-MAYlzjcP.js";import"./prompt-D7Ek9MYk.js";import{Keybar as u}from"./keybar-BcHUm3hI.js";import{resolveSiteId as d}from"./resolve-site-DYBsBK4c.js";import{DataTable as f}from"./data-table-BvnWCG-w.js";import{EmptyState as p}from"./empty-state-DdLBcz4h.js";import{deepLinkFor as m}from"./keybar-deep-link-Dagnpllp.js";import{Box as h,Text as g,render as _,useApp as v,useInput as y}from"ink";import b,{useEffect as x,useState as S}from"react";import C from"ink-spinner";function w(e){if(!e||e<=0)return`—`;let t=Math.floor(e/1e3);if(t<60)return`${t}s`;let n=Math.floor(t/60);return`${n}m ${(t%60).toString().padStart(2,`0`)}s`}function T(e){if(!e)return`—`;let t=Date.parse(e);if(Number.isNaN(t))return`—`;let n=Math.max(0,Math.floor((Date.now()-t)/1e3));return n<60?`${n}s`:n<3600?`${Math.floor(n/60)}m`:n<86400?`${Math.floor(n/3600)}h`:`${Math.floor(n/86400)}d`}async function E(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 l=new n({config:s,cliVersion:o.cliVersion,token:c});try{await r(l,`pro`)}catch(e){return process.stderr.write(`${e.message}\n`),2}let u,f;try{({siteId:u,site:f}=await d(l,{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??u;if(a(o)){let e=await l.getSessions(u);return i({type:`sessions.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=_(b.createElement(D,{api:l,siteId:u,siteLabel:p,cliVersion:o.cliVersion,onExit:n=>{t(),e(n)}}))})}const D=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:a}=v(),{theme:d}=c(),[_,E]=S(null),[D,O]=S(!0),[k,A]=S(null);if(y(e=>{if(e===`o`||e===`O`){o(m(`sessions`,{siteId:t}));return}e===`q`&&(a(),i(0))}),x(()=>{let n=!1;return(async()=>{try{let r=await e.getSessions(t);n||(E(r),O(!1))}catch(e){n||(A(e.message),O(!1))}})(),()=>{n=!0}},[e,t]),D)return b.createElement(h,{flexDirection:`column`},b.createElement(l,{version:r,subtitle:`sessions · ${n}`}),b.createElement(s,{title:`Loading`,state:`busy`},b.createElement(h,null,b.createElement(g,{color:d.accent},b.createElement(C,{type:`dots`})),b.createElement(g,null,` Fetching sessions…`))));if(k)return b.createElement(h,{flexDirection:`column`},b.createElement(l,{version:r,subtitle:`sessions · ${n}`}),b.createElement(p,{reason:`error`,headline:`Failed to load`,hint:k}));if(!_||_.length===0)return b.createElement(h,{flexDirection:`column`},b.createElement(l,{version:r,subtitle:`sessions · ${n}`}),b.createElement(p,{reason:`no-data`,headline:`No replays yet`,hint:`Enable session replay in your site settings`}));let j=[{key:`id`,label:`session id`,width:24},{key:`visitor`,label:`visitor`,width:18},{key:`duration`,label:`duration`,align:`right`,width:9,format:e=>w(e)},{key:`startedAt`,label:`when`,align:`right`,width:6,format:e=>T(String(e))},{key:`pageCount`,label:`events`,align:`right`,width:7},{key:`deviceType`,label:`device`,width:8,format:e=>String(e??`—`)}];return b.createElement(h,{flexDirection:`column`},b.createElement(l,{version:r,subtitle:`sessions · ${n}`}),b.createElement(s,{title:`Recent sessions (${_.length})`},b.createElement(f,{columns:j,data:_,zebra:!0})),b.createElement(h,{marginTop:1},b.createElement(g,{color:d.muted},`Open any session for replay at https://app.zenovay.com/replay`)),b.createElement(u,{items:[{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}]}))};export{E as sessionsCommand};
@@ -1,4 +1,4 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{confirmDestructive as r}from"./confirm-DS5wux0g.js";import"./panel-B_yDcIcn.js";import"./banner-3iSWTDFy.js";import"./prompt-D-Uzz_GF.js";import{resolveSiteId as i}from"./resolve-site-mj0esTrm.js";async function a(a){let o=await e(),s=await t({strict:!1}),c=new n({config:o,cliVersion:a.cliVersion,token:s}),l;try{({siteId:l}=await i(c,{explicit:a.siteId,headless:!!a.json,cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}try{switch(a.action){case`enable`:{let e=await c.enableShare(l);if(a.json)return process.stdout.write(JSON.stringify(e,null,2)+`
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{confirmDestructive as r}from"./confirm-DS5wux0g.js";import"./theme-Brz9wK0w.js";import"./panel-DB1HLxAw.js";import"./banner-MAYlzjcP.js";import"./prompt-D7Ek9MYk.js";import{resolveSiteId as i}from"./resolve-site-DYBsBK4c.js";async function a(a){let o=await e(),s=await t({strict:!1}),c=new n({config:o,cliVersion:a.cliVersion,token:s}),l;try{({siteId:l}=await i(c,{explicit:a.siteId,headless:!!a.json,cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}try{switch(a.action){case`enable`:{let e=await c.enableShare(l);if(a.json)return process.stdout.write(JSON.stringify(e,null,2)+`
2
2
  `),0;let t=`═`.repeat(72);return process.stdout.write(`\n${t}\n Public dashboard sharing enabled\n url: ${e.url}\n${t}\n\n Anyone with this link can view your dashboard. Disable with\n \`zenovay share disable\` to invalidate the link immediately.\n\n`),0}case`disable`:{let e=await r({resource:`public share link`,name:l.length>12?`${l.slice(0,8)}…${l.slice(-4)}`:l,yes:a.yes,destructive:!0});if(!e)return process.stdout.write(`Cancelled.
3
3
  `),1;let t=await c.disableShare(l);return a.json?(process.stdout.write(JSON.stringify(t)+`
4
4
  `),0):(process.stdout.write(`✔ Public sharing disabled. The previous link is no longer valid.
@@ -0,0 +1,2 @@
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import"./error-codes-C5caZH9p.js";import"./telemetry-DRh10SvO.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{formatTabular as r,selectFormat as i}from"./formatter-C4YSOKuq.js";import"./client-I4GTcUcm.js";import{openInBrowser as a}from"./open-url-dPoDcwsm.js";import"./theme-Brz9wK0w.js";import{useTheme as o}from"./panel-DB1HLxAw.js";import"./banner-MAYlzjcP.js";import"./prompt-D7Ek9MYk.js";import"./keybar-BcHUm3hI.js";import"./chat-panel-dXLm3hUn.js";import{resolveSiteId as s}from"./resolve-site-DYBsBK4c.js";import{DataTable as c}from"./data-table-BvnWCG-w.js";import{deepLinkFor as l}from"./keybar-deep-link-Dagnpllp.js";import{runAnalyticalScreen as u}from"./analytical-screen-BrOFDrQ_.js";import{Box as d,Text as f}from"ink";import p from"react";function m(e,t){let n=Math.round(e/100*t);return`█`.repeat(n)+`░`.repeat(Math.max(0,t-n))}function h(e){return e==null?{glyph:`·`,tone:`neutral`}:e>.5?{glyph:`▲`,tone:`up`}:e<-.5?{glyph:`▼`,tone:`down`}:{glyph:`→`,tone:`neutral`}}function g({data:e}){let{theme:t}=o();return p.createElement(f,null,p.createElement(f,{bold:!0},e.totalVisitors.toLocaleString()),` `,p.createElement(f,{color:t.muted},`visitors · `,e.sources.length,` sources`))}function _({data:e}){let{theme:t}=o();if(e.sources.length===0)return p.createElement(f,{color:t.muted},`— no source data —`);let n={up:t.success,down:t.accent2,neutral:t.muted},r=e.totalVisitors||1,i=[...e.sources].sort((e,t)=>t.visitors-e.visitors).slice(0,12);return p.createElement(d,{flexDirection:`column`},i.map((e,i)=>{let a=e.visitors/r*100,o=h(e.delta);return p.createElement(d,{key:`${e.source}-${i}`},p.createElement(f,null,p.createElement(f,{color:t.accent},e.source.padEnd(20).slice(0,20)),` `,p.createElement(f,{color:t.accent},m(a,30)),` `,p.createElement(f,null,e.visitors.toString().padStart(6),` `),p.createElement(f,{color:t.muted},`(`,a.toFixed(1),`%)`),` `,p.createElement(f,{color:n[o.tone]},o.glyph)))}))}function v({data:e,columns:t}){let{theme:n}=o();return e.sources.length===0?p.createElement(f,{color:n.muted},`— —`):p.createElement(c,{data:e.sources.slice(0,20),columns:t,headerStyle:`accent`})}async function y(o){let c=await e(),d=await t({strict:!1}),f=new n({config:c,cliVersion:o.cliVersion,token:d}),m,h;try{({siteId:m,site:h}=await s(f,{explicit:o.siteId,headless:!!(o.json||o.csv||o.tsv||o.ndjson),cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let y=i(o),b=o.period??`30d`,x=[{key:`source`,label:`source`,width:22},{key:`channel`,label:`channel`,width:10,format:e=>String(e??`—`)},{key:`visitors`,label:`visitors`,width:8,align:`right`},{key:`delta`,label:`Δ`,width:6,align:`right`,format:e=>typeof e==`number`?`${e>0?`+`:``}${(e*100).toFixed(1)}%`:`—`}];return u({cliVersion:o.cliVersion,title:`sources · ${m} · ${b}`,commandName:`sources`,authToken:d?.accessToken??null,refreshIntervalMs:6e4,fetcher:e=>f.getSources(m,b,o.compare,e),format:y,ai:{api:f,siteId:m,siteLabel:h?.url?h.url.replace(/^https?:\/\//,``).replace(/\/$/,``):h?.name??m},keybindings:{o:{label:`open in browser`,handler:()=>{a(l(`sources`,{siteId:m}))}}},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
+ `);return}process.stdout.write(r(e.sources,[`source`,`channel`,`visitors`,`conversions`,`revenue`,`delta`],t))},panels:[{id:`summary`,title:`Total`,render:e=>p.createElement(g,{data:e})},{id:`channels`,title:`By channel`,render:e=>p.createElement(_,{data:e})},{id:`table`,title:`Detail`,render:e=>p.createElement(v,{data:e,columns:x})}]})}export{y as sourcesCommand};
@@ -0,0 +1,2 @@
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import"./error-codes-C5caZH9p.js";import"./telemetry-DRh10SvO.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{formatTabular as r,selectFormat as i}from"./formatter-C4YSOKuq.js";import"./client-I4GTcUcm.js";import"./theme-Brz9wK0w.js";import{useTheme as a}from"./panel-DB1HLxAw.js";import"./banner-MAYlzjcP.js";import"./prompt-D7Ek9MYk.js";import"./keybar-BcHUm3hI.js";import"./chat-panel-dXLm3hUn.js";import{resolveSiteId as o}from"./resolve-site-DYBsBK4c.js";import{DataTable as s}from"./data-table-BvnWCG-w.js";import{runAnalyticalScreen as c}from"./analytical-screen-BrOFDrQ_.js";import{Box as l,Text as u}from"ink";import d from"react";function f(e){return`${(e*100).toFixed(1)}%`}function p(e){return e<60?`${Math.round(e)}s`:e<3600?`${Math.floor(e/60)}m ${Math.round(e%60)}s`:`${Math.floor(e/3600)}h ${Math.floor(e%3600/60)}m`}const m=({data:e})=>{let{theme:t}=a();return d.createElement(l,{flexDirection:`column`},d.createElement(u,null,d.createElement(u,{bold:!0},e.visitors.toLocaleString()),d.createElement(u,{color:t.muted},` visitors `),d.createElement(u,{bold:!0},e.pageviews.toLocaleString()),d.createElement(u,{color:t.muted},` pageviews `),d.createElement(u,{bold:!0},e.sessions.toLocaleString()),d.createElement(u,{color:t.muted},` sessions`)),d.createElement(u,{color:t.muted},`bounce `,f(e.bounceRate),` · avg session `,p(e.avgSessionSec)))},h=({label:e})=>{let{theme:t}=a();return d.createElement(u,{color:t.dim},e)};async function g(a){let l=await e(),u=await t({strict:!1}),g=new n({config:l,cliVersion:a.cliVersion,token:u}),_,v;try{({siteId:_,site:v}=await o(g,{explicit:a.siteId,headless:!!(a.json||a.csv||a.tsv||a.ndjson),cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let y=i(a),b=a.range??`24h`,x=[{key:`url`,label:`page`,width:40,format:e=>String(e??`—`)},{key:`views`,label:`views`,width:8,align:`right`}],S=[{key:`country`,label:`country`,width:8},{key:`visitors`,label:`visitors`,width:8,align:`right`}];return c({cliVersion:a.cliVersion,title:`stats · ${_} · ${b}`,commandName:`stats`,ai:{api:g,siteId:_,siteLabel:v?.url?v.url.replace(/^https?:\/\//,``).replace(/\/$/,``):v?.name??_},authToken:u?.accessToken??null,refreshIntervalMs:a.watch?6e4:0,fetcher:e=>g.getStats(_,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(`
2
+ `);return}process.stdout.write(r([{range:b,visitors:e.visitors,pageviews:e.pageviews,sessions:e.sessions,bounceRate:f(e.bounceRate),avgSession:p(e.avgSessionSec)}],[`range`,`visitors`,`pageviews`,`sessions`,`bounceRate`,`avgSession`],t))},panels:[{id:`summary`,title:`Summary`,render:e=>d.createElement(m,{data:e})},{id:`pages`,title:`Top pages`,render:e=>e.topPages.length===0?d.createElement(h,{label:`— no pages —`}):d.createElement(s,{data:e.topPages.slice(0,10),columns:x,headerStyle:`accent`})},{id:`countries`,title:`Top countries`,render:e=>e.topCountries.length===0?d.createElement(h,{label:`— no country data —`}):d.createElement(s,{data:e.topCountries.slice(0,10),columns:S,headerStyle:`accent`})}]})}export{g as statsCommand};
@@ -1,5 +1,5 @@
1
1
  import{configPath as e,readConfig as t,writeConfig as n}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as r}from"./token-store-BQuGH0z2.js";import{emit as i}from"./telemetry-DRh10SvO.js";import{ApiV2Client as a}from"./api-v2-CI5hxW-O.js";import{spawn as o}from"node:child_process";import s from"node:path";import{existsSync as c,mkdirSync as l,readFileSync as u,renameSync as d,unlinkSync as f,writeFileSync as p}from"node:fs";import{homedir as m}from"node:os";const h=6e4;function g(){return s.join(m(),`.zenovay`)}function _(){return s.join(g(),`status-agent.pid`)}function v(){return s.join(g(),`tmux-status`)}function y(){l(g(),{recursive:!0,mode:448})}function b(e){let t=_(),n=`${t}.tmp.${process.pid}`;p(n,String(e),{mode:384}),d(n,t)}function x(e){try{return process.kill(e,0),!0}catch{return!1}}function S(e){if(!e)return[];let t=[];for(let n of e.split(`,`).map(e=>e.trim()).filter(Boolean)){let e=n.match(/^([a-z_]+)\s*(>|<)\s*(-?\d+(?:\.\d+)?)$/i);if(!e)continue;t.push({key:(e[1]??``).toLowerCase(),op:e[2]??`>`,value:Number(e[3]??0)})}return t}function C(e,t,n,r=!1){let i=(t/1e5).toFixed(1),a=[`#[fg=colour141]● ${e} live`,`#[fg=colour114]▲ MRR $${i}k`,`#[fg=colour203]✗ ${n.toFixed(0)} err/s`].join(` `);return r?`#[reverse]${a}#[noreverse]`:a}const w=3e4,T=5*60*1e3,E=new Map;function D(e,t){let n=Math.floor(t/10),r=`${e}:${n}`,i=Date.now(),a=E.get(r);return a&&i-a<T?!1:(E.set(r,i),!0)}async function O(e,t){let n=process.platform;try{if(n===`darwin`){await new Promise((n,r)=>{let i=o(`terminal-notifier`,[`-title`,e,`-message`,t,`-group`,`zenovay`],{stdio:`ignore`});i.on(`error`,r),i.on(`exit`,()=>n())});return}if(n===`linux`){await new Promise((n,r)=>{let i=o(`notify-send`,[e,t],{stdio:`ignore`});i.on(`error`,r),i.on(`exit`,()=>n())});return}}catch{}process.stdout.write(`\x1b]9;${e} — ${t}\x07`)}function k(e,t){let n=[];for(let r of e){let e=t[r.key];if(typeof e!=`number`)continue;r.op===`>`&&e>r.value&&n.push({rule:r,actual:e}),r.op===`<`&&e<r.value&&n.push({rule:r,actual:e})}return n}async function A(e){let n=await t(),o=await r({strict:!1});if(!o)return process.stderr.write(`status-agent: not logged in
2
- `),2;let s=new a({config:n,cliVersion:e.cliVersion,token:o}),c=e.siteId??n.defaultSiteId??``;if(!c)return process.stderr.write("status-agent: no site selected — pass --site-id or run `zenovay use <site>`\n"),2;y();let l=n.statusAgent?.notifyOn,u=n.statusAgent?.refreshIntervalMs,d=S(e.notifyOn??l),m=e.intervalMs??u??h,g=Date.now(),b=0;i(`status_agent.start`,{properties:{rule_count:d.length,interval_ms:m}});let x=null,T=!1,E=0,A=null,j=()=>{T=!0,A&&A()};for(process.on(`SIGTERM`,j),process.on(`SIGINT`,j);!T;){try{let[e,t,n]=await Promise.all([s.getLive(c).catch(()=>({activeVisitors:0,recentEvents:[]})),s.getErrors(c,{window:`24h`}).catch(()=>({errors:[],total:0})),s.getRevenue(c,`24h`).catch(()=>null)]),r=e.activeVisitors,a=n?.mrr??n?.totalAmount??0,o=t.total/86400,l=x&&x>0?(x-a)/x*100:0,u=k(d,{error_rate:o,revenue_drop:l}),f=!1;for(let e of u){if(!D(e.rule.key,e.actual))continue;f=!0,i(`status_agent.alert_fired`,{properties:{rule_key:e.rule.key,op:e.rule.op,threshold:e.rule.value,actual:e.actual}}),await O(`Zenovay alert`,`${e.rule.key} ${e.rule.op} ${e.rule.value} (got ${e.actual.toFixed(2)})`)}f&&(E=Date.now());let m=E>0&&Date.now()-E<w;p(v(),C(r,a,o,m),{mode:420}),b+=1,b%10==0&&i(`status_agent.tick`,{properties:{visitors:r,error_rate_24h_avg:o,mrr_cents:a,tick:b}}),x=a}catch(e){process.stderr.write(`status-agent tick failed: ${e.message}\n`)}await new Promise(e=>{let t=setTimeout(e,m);A=()=>{clearTimeout(t),e()}}),A=null}i(`status_agent.stop`,{duration_ms:Date.now()-g,properties:{ticks:b}});try{f(_())}catch{}return 0}function j(){return[`# Add to ~/.tmux.conf:`,`set -g status-right "#(cat ~/.zenovay/tmux-status) %H:%M"`,``,`# Then reload:`,`# $ tmux source ~/.tmux.conf`].join(`
2
+ `),2;let s=new a({config:n,cliVersion:e.cliVersion,token:o}),c=e.siteId??n.defaultSiteId??``;if(!c)return process.stderr.write("status-agent: no site selected — pass --site-id or run `zenovay use <site>`\n"),2;y();let l=n.statusAgent?.notifyOn,u=n.statusAgent?.refreshIntervalMs,d=S(e.notifyOn??l),m=e.intervalMs??u??h,g=Date.now(),b=0;i(`status_agent.start`,{properties:{rule_count:d.length,interval_ms:m}});let x=null,T=!1,E=0,A=null,j=()=>{T=!0,A&&A()};for(process.on(`SIGTERM`,j),process.on(`SIGINT`,j);!T;){try{let[e,t,n]=await Promise.all([s.getLive(c).catch(()=>({activeVisitors:0,recentEvents:[]})),s.getErrors(c,{window:`24h`}).catch(()=>({errors:[],total:0})),s.getRevenue(c,`24h`).catch(()=>null)]),r=e.activeVisitors,a=n?.mrr??n?.totalAmount??0,o=t.total/86400,l=x&&x>0?(x-a)/x*100:0,u=k(d,{error_rate:o,revenue_drop:l}),f=!1;for(let e of u){if(!D(e.rule.key,e.actual))continue;f=!0,i(`status_agent.alert_fired`,{properties:{rule_key:e.rule.key,op:e.rule.op}}),await O(`Zenovay alert`,`${e.rule.key} ${e.rule.op} ${e.rule.value} (got ${e.actual.toFixed(2)})`)}f&&(E=Date.now());let m=E>0&&Date.now()-E<w;p(v(),C(r,a,o,m),{mode:420}),b+=1,b%10==0&&i(`status_agent.tick`,{properties:{tick:b,has_revenue:a>0,has_visitors:r>0,had_errors:o>0}}),x=a}catch(e){process.stderr.write(`status-agent tick failed: ${e.message}\n`)}await new Promise(e=>{let t=setTimeout(e,m);A=()=>{clearTimeout(t),e()}}),A=null}i(`status_agent.stop`,{duration_ms:Date.now()-g,properties:{ticks:b}});try{f(_())}catch{}return 0}function j(){return[`# Add to ~/.tmux.conf:`,`set -g status-right "#(cat ~/.zenovay/tmux-status) %H:%M"`,``,`# Then reload:`,`# $ tmux source ~/.tmux.conf`].join(`
3
3
  `)}function M(){let e=process.argv[0]??`zenovay`;return[`[Unit]`,`Description=Zenovay status agent`,`After=network.target`,``,`[Service]`,`Type=simple`,`ExecStart=${e} status-agent --child`,`Restart=on-failure`,`RestartSec=10`,``,`[Install]`,`WantedBy=default.target`,``,`# Save as ~/.config/systemd/user/zenovay-status.service`,`# systemctl --user enable --now zenovay-status`].join(`
4
4
  `)}function N(){let e=process.argv[0]??`zenovay`;return[`<?xml version="1.0" encoding="UTF-8"?>`,`<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">`,`<plist version="1.0">`,`<dict>`,` <key>Label</key><string>com.zenovay.status-agent</string>`,` <key>ProgramArguments</key>`,` <array>`,` <string>${e}</string>`,` <string>status-agent</string>`,` <string>--child</string>`,` </array>`,` <key>RunAtLoad</key><true/>`,` <key>KeepAlive</key><true/>`,`</dict>`,`</plist>`,``,`<!-- Save as ~/Library/LaunchAgents/com.zenovay.status-agent.plist -->`,`<!-- launchctl load ~/Library/LaunchAgents/com.zenovay.status-agent.plist -->`].join(`
5
5
  `)}async function P(r){if(r.installTmux)return process.stdout.write(j()+`
@@ -1,4 +1,4 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{requireTier as r}from"./tier-BneaO4vD.js";import{confirmDestructive as i}from"./confirm-DS5wux0g.js";import{fmtDate as a,formatTable as o,shortId as s}from"./fmt-gMsty5jy.js";async function c(c){let l=await e(),u=await t({strict:!1}),d=new n({config:l,cliVersion:c.cliVersion,token:u});try{await r(d,`pro`)}catch(e){return process.stderr.write(`✗ ${e.message}\n`),2}try{switch(c.action){case`list`:{let e=await d.listTeam();if(c.json)return process.stdout.write(JSON.stringify(e,null,2)+`
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{requireTier as r}from"./tier-BneaO4vD.js";import{confirmDestructive as i}from"./confirm-DS5wux0g.js";import{fmtDate as a,formatTable as o,shortId as s}from"./fmt-iR2sYwsO.js";async function c(c){let l=await e(),u=await t({strict:!1}),d=new n({config:l,cliVersion:c.cliVersion,token:u});try{await r(d,`pro`)}catch(e){return process.stderr.write(`✗ ${e.message}\n`),2}try{switch(c.action){case`list`:{let e=await d.listTeam();if(c.json)return process.stdout.write(JSON.stringify(e,null,2)+`
2
2
  `),0;let t=[{key:`userId`,header:`user id`,width:14,format:e=>s(String(e))},{key:`email`,header:`email`,width:32,format:e=>String(e??`—`)},{key:`role`,header:`role`,width:8},{key:`joinedAt`,header:`joined`,width:10,format:e=>a(e)}],n=[{key:`id`,header:`invite id`,width:14,format:e=>s(String(e))},{key:`email`,header:`email`,width:32},{key:`role`,header:`role`,width:8},{key:`expiresAt`,header:`expires`,width:10,format:e=>a(e)}];return process.stdout.write(`\nMEMBERS (${e.members.length})\n`),e.members.length===0?process.stdout.write(` — none —
3
3
  `):process.stdout.write(o({rows:e.members,cols:t})),process.stdout.write(`\nPENDING INVITES (${e.invites.length})\n`),e.invites.length===0?process.stdout.write(` — none —
4
4
  `):process.stdout.write(o({rows:e.invites,cols:n})),process.stdout.write(`
@@ -0,0 +1 @@
1
+ const e={xs:1,sm:2,md:3,lg:5,xl:8},t=e=>({headline:{color:e.fg,bold:!0},title:{color:e.fg,bold:!0},body:{color:e.fg},label:{color:e.dim,dim:!0,uppercase:!0},mono:{color:e.fg},caption:{color:e.muted}}),n={name:`mocha`,bg:`#1F1D1A`,fg:`#F4F1EC`,muted:`#A8A39B`,accent:`#6E9CE8`,accent2:`#FDA4AF`,success:`#54C896`,warn:`#E4AE3A`,error:`#DC2626`,info:`#6BB1D4`,border:`#2E2C29`,dim:`#7C7770`,spacing:e,radius:`round`,typography:t({fg:`#F4F1EC`,muted:`#A8A39B`,accent:`#6E9CE8`,dim:`#7C7770`})},r={name:`latte`,bg:`#FAF8F5`,fg:`#1F1D1A`,muted:`#6F6B66`,accent:`#3B6FD4`,accent2:`#D9648A`,success:`#2E9E6B`,warn:`#C9920E`,error:`#DC2626`,info:`#3F8FB8`,border:`#E8E4DE`,dim:`#9A968F`,spacing:e,radius:`round`,typography:t({fg:`#1F1D1A`,muted:`#6F6B66`,accent:`#3B6FD4`,dim:`#9A968F`})},i={name:`dracula`,bg:`#282A36`,fg:`#F8F8F2`,muted:`#6272A4`,accent:`#BD93F9`,accent2:`#FF79C6`,success:`#50FA7B`,warn:`#F1FA8C`,error:`#FF5555`,info:`#8BE9FD`,border:`#44475A`,dim:`#6272A4`,spacing:e,radius:`round`,typography:t({fg:`#F8F8F2`,muted:`#6272A4`,accent:`#BD93F9`,dim:`#6272A4`})},a={name:`tokyoNight`,bg:`#1A1B26`,fg:`#C0CAF5`,muted:`#565F89`,accent:`#7AA2F7`,accent2:`#BB9AF7`,success:`#9ECE6A`,warn:`#E0AF68`,error:`#F7768E`,info:`#7DCFFF`,border:`#3B4261`,dim:`#414868`,spacing:e,radius:`round`,typography:t({fg:`#C0CAF5`,muted:`#565F89`,accent:`#7AA2F7`,dim:`#414868`})},o={name:`nord`,bg:`#2E3440`,fg:`#D8DEE9`,muted:`#4C566A`,accent:`#88C0D0`,accent2:`#81A1C1`,success:`#A3BE8C`,warn:`#EBCB8B`,error:`#BF616A`,info:`#81A1C1`,border:`#3B4252`,dim:`#434C5E`,spacing:e,radius:`round`,typography:t({fg:`#D8DEE9`,muted:`#4C566A`,accent:`#88C0D0`,dim:`#434C5E`})};export{i as dracula,r as latte,n as mocha,o as nord,a as tokyoNight};
@@ -0,0 +1,4 @@
1
+ import{dracula as e,latte as t,mocha as n,nord as r,tokyoNight as i}from"./theme-Brz9wK0w.js";import{useTheme as a}from"./panel-DB1HLxAw.js";import{Banner as o}from"./banner-MAYlzjcP.js";import"./progress-row-BS7fwhn_.js";import"./prompt-D7Ek9MYk.js";import"./keybar-BcHUm3hI.js";import"./sparkline-8ucKVUV7.js";import"./data-table-BvnWCG-w.js";import"./bar-DG-MqgGx.js";import"./ui-DXrdVAc-.js";import{promises as s}from"node:fs";import{Box as c,Text as l,render as u}from"ink";import d from"react";const f=[{name:`mocha`,theme:n,mode:`dark`},{name:`latte`,theme:t,mode:`light`},{name:`dracula`,theme:e,mode:`dark`},{name:`tokyoNight`,theme:i,mode:`dark`},{name:`nord`,theme:r,mode:`dark`}],p=[`name`,`bg`,`fg`,`muted`,`accent`,`accent2`,`success`,`warn`,`error`,`border`,`dim`];function m({name:e,theme:t,mode:n}){let{theme:r}=a(),i=[t.accent,t.accent2,t.success,t.warn,t.error];return d.createElement(c,{flexDirection:`row`},d.createElement(l,{bold:!0},e.padEnd(14)),d.createElement(l,{color:r.muted},n.padEnd(7)),i.map((e,t)=>d.createElement(l,{key:t,color:e},`████`,` `)),d.createElement(l,{color:r.muted},t.bg))}function h({themes:e}){let{theme:t}=a();return d.createElement(c,{flexDirection:`column`},d.createElement(o,{version:`themes`}),d.createElement(c,{marginTop:1,marginBottom:1},d.createElement(l,{color:t.muted},e.length,` themes — pass --theme <name> to any command, or set in your config.`)),d.createElement(c,{flexDirection:`column`},d.createElement(c,null,d.createElement(l,{bold:!0},`name`.padEnd(14)),d.createElement(l,{bold:!0},`mode`.padEnd(7)),d.createElement(l,{bold:!0},`swatch`.padEnd(28)),d.createElement(l,{bold:!0},`bg`)),e.map(({name:e,theme:t,mode:n})=>d.createElement(m,{key:e,name:e,theme:t,mode:n}))))}async function g(e){if(e.validate){let t;try{let n=await s.readFile(e.validate,`utf8`);t=JSON.parse(n)}catch(t){return process.stderr.write(`✗ Failed to read ${e.validate}: ${t.message}\n`),1}let n=p.filter(e=>t[e]==null);return n.length>0?(process.stderr.write(`✗ Missing required tokens: ${n.join(`, `)}\n`),e.json&&process.stdout.write(JSON.stringify({ok:!1,missing:n},null,2)+`
2
+ `),1):(process.stdout.write(`✔ Valid theme (${p.length} tokens present).\n`),e.json&&process.stdout.write(JSON.stringify({ok:!0,theme:t},null,2)+`
3
+ `),0)}if(e.json)return process.stdout.write(JSON.stringify({themes:f.map(({name:e,theme:t,mode:n})=>({name:e,mode:n,background:t.bg,foreground:t.fg,accent:t.accent}))},null,2)+`
4
+ `),0;let{waitUntilExit:t}=u(d.createElement(h,{themes:f}));return await t(),0}export{g as themesCommand};
@@ -1,4 +1,4 @@
1
- import{Panel as e,useTheme as t}from"./panel-B_yDcIcn.js";import{Banner as n}from"./banner-3iSWTDFy.js";import{spawn as r}from"node:child_process";import{Box as i,Text as a,render as o,useApp as s,useInput as c}from"ink";import l,{useEffect as u,useState as d}from"react";import f from"ink-spinner";const p=[{title:`Identify`,explainer:"Who you are and which team you’re acting on. CLI uses your saved bearer token from `zenovay login`.",command:`profile show`},{title:`Tracked sites`,explainer:`The websites your account can read.`,command:`domains list`},{title:`Today's analytics`,explainer:`What visitors did on your sites in the last 24 hours.`,command:`analytics`},{title:`Traffic sources`,explainer:`Where visitors come from — direct, organic, referrals.`,command:`sources --period 7d`},{title:`Recent sessions`,explainer:`Replay-style listing of recorded sessions (Pro+).`,command:`sessions`,tierGated:!0},{title:`Alert configs`,explainer:`Threshold-based alerts you’ve set up.`,command:`alerts list`,tierGated:!0},{title:`Export today`,explainer:`Bulk-export analytics data to CSV.`,command:`export analytics --range 7d --format csv`,csvPreview:!0},{title:`Self-test`,explainer:`One-command verification that everything works.`,command:`self-test --quick`,maxLines:24}],m=p.length;async function h(e){let t=process.argv[1]??process.execPath;return e.nonInteractive?g(t,e.cliVersion):new Promise(n=>{let{unmount:r}=o(l.createElement(y,{cliVersion:e.cliVersion,binPath:t,onDone:e=>{r(),n(e)}}))})}async function g(e,t){process.stdout.write(`Zenovay CLI v${t} — tour (non-interactive)\n`),process.stdout.write(`────────────────────────────────────────────────────
1
+ import"./theme-Brz9wK0w.js";import{Panel as e,useTheme as t}from"./panel-DB1HLxAw.js";import{Banner as n}from"./banner-MAYlzjcP.js";import{spawn as r}from"node:child_process";import{Box as i,Text as a,render as o,useApp as s,useInput as c}from"ink";import l,{useEffect as u,useState as d}from"react";import f from"ink-spinner";const p=[{title:`Identify`,explainer:"Who you are and which team you’re acting on. CLI uses your saved bearer token from `zenovay login`.",command:`profile show`},{title:`Tracked sites`,explainer:`The websites your account can read.`,command:`domains list`},{title:`Today's analytics`,explainer:`What visitors did on your sites in the last 24 hours.`,command:`analytics`},{title:`Traffic sources`,explainer:`Where visitors come from — direct, organic, referrals.`,command:`sources --period 7d`},{title:`Recent sessions`,explainer:`Replay-style listing of recorded sessions (Pro+).`,command:`sessions`,tierGated:!0},{title:`Alert configs`,explainer:`Threshold-based alerts you’ve set up.`,command:`alerts list`,tierGated:!0},{title:`Export today`,explainer:`Bulk-export analytics data to CSV.`,command:`export analytics --range 7d --format csv`,csvPreview:!0},{title:`Self-test`,explainer:`One-command verification that everything works.`,command:`self-test --quick`,maxLines:24}],m=p.length;async function h(e){let t=process.argv[1]??process.execPath;return e.nonInteractive?g(t,e.cliVersion):new Promise(n=>{let{unmount:r}=o(l.createElement(y,{cliVersion:e.cliVersion,binPath:t,onDone:e=>{r(),n(e)}}))})}async function g(e,t){process.stdout.write(`Zenovay CLI v${t} — tour (non-interactive)\n`),process.stdout.write(`────────────────────────────────────────────────────
2
2
 
3
3
  `);for(let t=0;t<p.length;t++){let n=p[t];process.stdout.write(`[${t+1}/${m}] ${n.title}\n`),process.stdout.write(` ${n.explainer}\n`),process.stdout.write(` $ zenovay ${n.command}\n\n`);let r=await v(e,n);if(r.tierSkipped){process.stdout.write(` → Skipping (requires Pro plan)
4
4
 
@@ -0,0 +1 @@
1
+ import{Text as e}from"ink";import t from"react";
@@ -1 +1 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import{classifyBump as t,fetchManifest as n}from"./check-D9G0N7NB.js";import{applyUpdate as r}from"./apply-B19bFTz0.js";import"./formatter-DutfcQAc.js";import{emit$1 as i,isHeadless as a}from"./emit-DBYk96TD.js";async function o(o){let s=await e(),c=await n({cliBase:s.cliBase}),l=t(o.cliVersion,c.latest);if(o.check)return a({json:o.json})?i({type:`info`,message:`latest=${c.latest} current=${o.cliVersion} bump=${l}`}):process.stdout.write(`Current: ${o.cliVersion}\nLatest: ${c.latest}\nBump: ${l}\n`),{updated:!1,from:o.cliVersion,to:c.latest};if(l===`none`)return a({json:o.json})||process.stdout.write(`Already on latest (${o.cliVersion}).\n`),{updated:!1,from:o.cliVersion,to:c.latest};if(l===`downgrade`&&!o.forceDowngrade)throw Error(`Refused to downgrade ${o.cliVersion} → ${c.latest}. Pass --force-downgrade if you really want this.`);let u=await r({currentVersion:o.cliVersion,cliBase:s.cliBase,binaryPath:o.binaryPath,forceDowngrade:o.forceDowngrade});return a({json:o.json})?u.updated&&i({type:`update.applied`,from:u.from,to:u.to}):u.updated?process.stdout.write(`Updated ${u.from} → ${u.to}\n`):process.stdout.write(`Not updated (${u.reason??`unknown`}).\n`),u}export{o as updateCommand};
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import{classifyBump as t,fetchManifest as n}from"./check-D9G0N7NB.js";import{applyUpdate as r}from"./apply-oUMOH7u2.js";import"./formatter-C4YSOKuq.js";import{emit$1 as i,isHeadless as a}from"./emit-D4YlMlzk.js";async function o(o){let s=await e(),c=await n({cliBase:s.cliBase}),l=t(o.cliVersion,c.latest);if(o.check)return a({json:o.json})?i({type:`info`,message:`latest=${c.latest} current=${o.cliVersion} bump=${l}`}):process.stdout.write(`Current: ${o.cliVersion}\nLatest: ${c.latest}\nBump: ${l}\n`),{updated:!1,from:o.cliVersion,to:c.latest};if(l===`none`)return a({json:o.json})||process.stdout.write(`Already on latest (${o.cliVersion}).\n`),{updated:!1,from:o.cliVersion,to:c.latest};if(l===`downgrade`&&!o.forceDowngrade)throw Error(`Refused to downgrade ${o.cliVersion} → ${c.latest}. Pass --force-downgrade if you really want this.`);let u=await r({currentVersion:o.cliVersion,cliBase:s.cliBase,binaryPath:o.binaryPath,forceDowngrade:o.forceDowngrade});return a({json:o.json})?u.updated&&i({type:`update.applied`,from:u.from,to:u.to}):u.updated?process.stdout.write(`Updated ${u.from} → ${u.to}\n`):process.stdout.write(`Not updated (${u.reason??`unknown`}).\n`),u}export{o as updateCommand};
@@ -0,0 +1 @@
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{requireTier as r}from"./tier-BneaO4vD.js";import"./formatter-C4YSOKuq.js";import{emit$1 as i,isHeadless as a}from"./emit-D4YlMlzk.js";import{openInBrowser as o}from"./open-url-dPoDcwsm.js";import"./theme-Brz9wK0w.js";import{Panel as s,useTheme as c}from"./panel-DB1HLxAw.js";import{Banner as l}from"./banner-MAYlzjcP.js";import"./prompt-D7Ek9MYk.js";import{Keybar as u}from"./keybar-BcHUm3hI.js";import{resolveSiteId as d}from"./resolve-site-DYBsBK4c.js";import{DataTable as f}from"./data-table-BvnWCG-w.js";import{EmptyState as p}from"./empty-state-DdLBcz4h.js";import{deepLinkFor as m}from"./keybar-deep-link-Dagnpllp.js";import{Box as h,Text as g,render as _,useApp as v,useInput as y}from"ink";import b,{useEffect as x,useState as S}from"react";import C from"ink-spinner";function w(e){return e===`up`?{glyph:`● up`,color:`green`}:e===`down`?{glyph:`● down`,color:`red`}:{glyph:`○ unknown`,color:`gray`}}function T(e){if(!e)return`—`;let t=Date.parse(e);if(Number.isNaN(t))return`—`;let n=Math.round((t-Date.now())/(1e3*60*60*24));return`${n}d`}async function E(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 l=new n({config:s,cliVersion:o.cliVersion,token:c});try{await r(l,`pro`)}catch(e){return process.stderr.write(`${e.message}\n`),2}let u,f;try{({siteId:u,site:f}=await d(l,{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??u;if(a(o)){let e=await l.getUptime(u);return i({type:`uptime.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=_(b.createElement(D,{api:l,siteId:u,siteLabel:p,cliVersion:o.cliVersion,onExit:n=>{t(),e(n)}}))})}const D=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:a}=v(),{theme:d}=c(),[_,E]=S(null),[D,O]=S(!0),[k,A]=S(null);if(y(e=>{if(e===`o`||e===`O`){o(m(`uptime`,{siteId:t}));return}e===`q`&&(a(),i(0))}),x(()=>{let n=!1;return(async()=>{try{let r=await e.getUptime(t);n||(E(r.monitors),O(!1))}catch(e){n||(A(e.message),O(!1))}})(),()=>{n=!0}},[e,t]),D)return b.createElement(h,{flexDirection:`column`},b.createElement(l,{version:r,subtitle:`uptime · ${n}`}),b.createElement(s,{title:`Loading`,state:`busy`},b.createElement(h,null,b.createElement(g,{color:d.accent},b.createElement(C,{type:`dots`})),b.createElement(g,null,` Fetching monitors…`))));if(k)return b.createElement(h,{flexDirection:`column`},b.createElement(l,{version:r,subtitle:`uptime · ${n}`}),b.createElement(p,{reason:`error`,headline:`Failed to load`,hint:k}));if(!_||_.length===0)return b.createElement(h,{flexDirection:`column`},b.createElement(l,{version:r,subtitle:`uptime · ${n}`}),b.createElement(p,{reason:`no-data`,headline:`No monitors configured`,hint:`Add one at app.zenovay.com/uptime`}));let j=[{key:`url`,label:`monitor`,width:36},{key:`status`,label:`status`,width:12,format:e=>w(String(e)).glyph},{key:`p95ms`,label:`p95 ms`,align:`right`,width:8,format:e=>typeof e==`number`?String(e):`—`},{key:`sslExpiry`,label:`ssl exp`,align:`right`,width:7,format:e=>T(e)}];return b.createElement(h,{flexDirection:`column`},b.createElement(l,{version:r,subtitle:`uptime · ${n}`}),b.createElement(s,{title:`Monitors (${_.length})`},b.createElement(f,{columns:j,data:_,zebra:!0})),b.createElement(u,{items:[{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}]}))};export{E as uptimeCommand};
@@ -1,3 +1,3 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{fmtDate as r,fmtNumber as i}from"./fmt-gMsty5jy.js";const a=1e8,o=e=>e<=0||e>=a;function s(e,t,n=24){if(o(t))return`─`.repeat(n);let r=Math.min(1,e/t),i=Math.round(r*n);return`█`.repeat(i)+`░`.repeat(Math.max(0,n-i))}function c(e,t){if(o(t))return`—`;let n=e/t*100;return`${n.toFixed(0)}%`}function l(e,t){if(o(t))return``;let n=e/t;return n>=1?`⚠ over limit`:n>=.8?`⚠ near limit`:``}function u(e,t){return o(e)?`∞`:t(e)}async function d(a){let o=await e(),d=await t({strict:!1});if(!d)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let f=new n({config:o,cliVersion:a.cliVersion,token:d}),p;try{p=await f.getUsage()}catch(e){return process.stderr.write(`✗ ${e.message}\n`),1}if(a.json)return process.stdout.write(JSON.stringify(p,null,2)+`
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{fmtDate as r,fmtNumber as i}from"./fmt-iR2sYwsO.js";const a=1e8,o=e=>e<=0||e>=a;function s(e,t,n=24){if(o(t))return`─`.repeat(n);let r=Math.min(1,e/t),i=Math.round(r*n);return`█`.repeat(i)+`░`.repeat(Math.max(0,n-i))}function c(e,t){if(o(t))return`—`;let n=e/t*100;return`${n.toFixed(0)}%`}function l(e,t){if(o(t))return``;let n=e/t;return n>=1?`⚠ over limit`:n>=.8?`⚠ near limit`:``}function u(e,t){return o(e)?`∞`:t(e)}async function d(a){let o=await e(),d=await t({strict:!1});if(!d)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let f=new n({config:o,cliVersion:a.cliVersion,token:d}),p;try{p=await f.getUsage()}catch(e){return process.stderr.write(`✗ ${e.message}\n`),1}if(a.json)return process.stdout.write(JSON.stringify(p,null,2)+`
2
2
  `),0;let m=[{label:`events this month`,used:p.events.thisMonth,limit:p.events.monthlyLimit,format:i},{label:`events today`,used:p.events.today,limit:p.events.dailyLimit,format:i},{label:`websites`,used:p.websites.used,limit:p.websites.limit},{label:`team members`,used:p.teamMembers.used,limit:p.teamMembers.limit}],h=18,g=8,_=9,v=[];v.push(``),v.push(` plan: ${p.plan}`),v.push(``);for(let e of m){let t=e.format??i,n=t(e.used).padStart(g),r=u(e.limit,t).padStart(_),a=s(e.used,e.limit),o=c(e.used,e.limit).padStart(5),d=l(e.used,e.limit);v.push(` ${e.label.padEnd(h)} ${n} / ${r} ${a} ${o} ${d}`.trimEnd())}return v.push(` ${`api keys`.padEnd(h)} ${i(p.apiKeys.used).padStart(g)} / ${`—`.padStart(_)} ${`─`.repeat(24)} ${`—`.padStart(5)}`),v.push(``),v.push(` data retention: ${p.dataRetentionDays} days`),v.push(` last event: ${r(p.events.lastEventAt,`datetime`)}`),v.push(``),process.stdout.write(v.join(`
3
3
  `)),0}export{d as usageCommand};
@@ -1,3 +1,3 @@
1
- import{readConfig as e,updateConfig as t}from"./config--JRu_jFq.js";import{ApiClient as n}from"./api-FCanTxsb.js";import{readToken as r}from"./token-store-BQuGH0z2.js";import"./formatter-DutfcQAc.js";import{emitEnvelope as i,wrapSnapshot as a}from"./emit-DBYk96TD.js";async function o(o){if(o.reset)return await t({defaultSiteId:void 0,defaultSiteName:void 0}),o.json?(i(a({reset:!0,defaultSiteId:null},`use.reset`)),0):(process.stdout.write(`Default site cleared.
1
+ import{readConfig as e,updateConfig as t}from"./config--JRu_jFq.js";import{ApiClient as n}from"./api-FCanTxsb.js";import{readToken as r}from"./token-store-BQuGH0z2.js";import"./formatter-C4YSOKuq.js";import{emitEnvelope as i,wrapSnapshot as a}from"./emit-D4YlMlzk.js";async function o(o){if(o.reset)return await t({defaultSiteId:void 0,defaultSiteName:void 0}),o.json?(i(a({reset:!0,defaultSiteId:null},`use.reset`)),0):(process.stdout.write(`Default site cleared.
2
2
  `),0);if(!o.match||!o.match.trim()){let t=await e();if(t.defaultSiteId){let e={siteId:t.defaultSiteId,name:t.defaultSiteName??null,domain:t.defaultSiteName??null};return o.json?(i(a(e,`use.current`,{siteId:t.defaultSiteId})),0):(process.stdout.write(`Default site: ${e.name??e.siteId} (${t.defaultSiteId})\n`),0)}return o.json?(i(a(null,`use.current`,{})),0):(process.stdout.write("No default site set. Run `zenovay use <domain>` to set one.\n"),0)}let c=await e(),l=await r({strict:!1});if(!l&&!process.env.ZENOVAY_API_TOKEN)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let u=new n({config:c,cliVersion:o.cliVersion,token:l}),d=o.match.trim().toLowerCase(),f=await u.getSites(),p=f.find(e=>e.id===o.match||e.trackingCode===o.match||e.url===o.match),m=p??f.find(e=>s(e.url).includes(d)||e.name.toLowerCase().includes(d));return m?(await t({defaultSiteId:m.id,defaultSiteName:m.name}),o.json?(i(a({siteId:m.id,name:m.name,domain:s(m.url)},`use.set`,{siteId:m.id})),0):(process.stdout.write(`Default site → ${m.name} (${m.url})\n`),0)):(process.stderr.write(`No site matched "${o.match}". Your sites:\n${f.map(e=>` ${e.name} — ${e.url} — ${e.id}`).join(`
3
3
  `)}\n`),2)}function s(e){return e.toLowerCase().replace(/^https?:\/\//,``).replace(/\/.*$/,``)}export{o as useCommand};
@@ -0,0 +1,2 @@
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import"./error-codes-C5caZH9p.js";import"./telemetry-DRh10SvO.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{formatTabular as r,selectFormat as i}from"./formatter-C4YSOKuq.js";import"./client-I4GTcUcm.js";import{openInBrowser as a}from"./open-url-dPoDcwsm.js";import"./theme-Brz9wK0w.js";import{useTheme as o}from"./panel-DB1HLxAw.js";import"./banner-MAYlzjcP.js";import"./prompt-D7Ek9MYk.js";import"./keybar-BcHUm3hI.js";import{brailleSpark as s,spark as c}from"./sparkline-8ucKVUV7.js";import"./chat-panel-dXLm3hUn.js";import{resolveSiteId as l}from"./resolve-site-DYBsBK4c.js";import{DataTable as u}from"./data-table-BvnWCG-w.js";import{deepLinkFor as d}from"./keybar-deep-link-Dagnpllp.js";import{runAnalyticalScreen as f}from"./analytical-screen-BrOFDrQ_.js";import{Box as p,Text as m}from"ink";import h from"react";function g(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`}function _(e){let t=e,n=t.events??t.timeseries;return Array.isArray(n)&&n.length>0?c(n,8):`▁▁▁▁▁▁▁▁`}function v(e){let t=e;if(typeof t.sessionDurationSec==`number`)return t.sessionDurationSec;if(typeof t.sessionDurationMs==`number`)return Math.floor(t.sessionDurationMs/1e3);if(typeof t.durationMs==`number`)return Math.floor(t.durationMs/1e3);if(typeof t.duration==`number`)return Math.floor(t.duration/1e3);let n=Date.parse(e.startedAt);return Number.isNaN(n)?0:Math.max(0,Math.floor((Date.now()-n)/1e3))}async function y(o){let s=await e(),c=await t({strict:!1}),u=new n({config:s,cliVersion:o.cliVersion,token:c}),p,m;try{({siteId:p,site:m}=await l(u,{explicit:o.siteId,headless:!!(o.json||o.csv||o.tsv||o.ndjson),cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let y=i(o),S=o.limit??50,C=typeof o.minDuration==`number`&&o.minDuration>0?o.minDuration:0,w=e=>C<=0?e:e.filter(e=>v(e)>=C),T=6e4,E=e=>{let t=Date.parse(e.startedAt);return Number.isFinite(t)&&Date.now()-t<T},D=[{key:`startedAt`,label:``,width:5,format:(e,t)=>E(t)?`● new`:``},{key:`startedAt`,label:`when`,width:6,format:e=>g(String(e))},{key:`country`,label:`country`,width:7,format:e=>String(e??`—`)},{key:`city`,label:`city`,width:14,format:e=>String(e??`—`)},{key:`device`,label:`device`,width:7,format:e=>String(e??`—`)},{key:`page`,label:`page`,width:26,format:e=>String(e??`—`)},{key:`id`,label:`24h`,width:8,format:(e,t)=>_(t)}];return f({cliVersion:o.cliVersion,title:`visitors · ${p}`,commandName:`visitors`,ai:{api:u,siteId:p,siteLabel:m?.url?m.url.replace(/^https?:\/\//,``).replace(/\/$/,``):m?.name??p},authToken:c?.accessToken??null,refreshIntervalMs:1e4,fetcher:e=>u.getVisitors(p,{limit:S},e),format:y,keybindings:{o:{label:`open in browser`,handler:()=>{a(d(`visitors`,{siteId:p}))}}},headlessEmit:(e,t)=>{let n={...e,visitors:w(e.visitors)};if(t===`json`||t===`ndjson`){process.stdout.write(JSON.stringify(n,null,t===`json`?2:0)),t===`ndjson`&&process.stdout.write(`
2
+ `);return}let i=[`startedAt`,`country`,`city`,`device`,`page`];process.stdout.write(r(n.visitors,i,t))},panels:[{id:`live`,title:`Now`,render:e=>h.createElement(b,{visitors:w(e.visitors)})},{id:`visitors`,title:`Active sessions`,render:e=>h.createElement(x,{visitors:w(e.visitors),limit:S,columns:D})}]})}const b=({visitors:e})=>{let{theme:t}=o(),n=[...e].sort((e,t)=>Date.parse(t.startedAt)-Date.parse(e.startedAt)),r=n[0],i=Array(24*6).fill(0),a=Date.now();for(let t of e){let e=a-new Date(t.startedAt).getTime(),n=Math.floor(e/(10*60*1e3));n>=0&&n<i.length&&(i[i.length-1-n]+=1)}return h.createElement(p,{flexDirection:`column`},h.createElement(m,{bold:!0},e.length,` live`),h.createElement(m,{color:t.muted},s(i,40)),r?h.createElement(m,{color:t.muted},`top: `,r.city??r.country??`—`,` · `,r.page??`—`):null)},x=({visitors:e,limit:t,columns:n})=>{let{theme:r}=o(),i=[...e].sort((e,t)=>Date.parse(t.startedAt)-Date.parse(e.startedAt)).slice(0,t);return i.length===0?h.createElement(m,{color:r.dim},`— no visitors yet —`):h.createElement(u,{columns:n,data:i,headerStyle:`accent`})};export{y as visitorsCommand};
@@ -0,0 +1,2 @@
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import"./error-codes-C5caZH9p.js";import"./telemetry-DRh10SvO.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{formatTabular as r,selectFormat as i}from"./formatter-C4YSOKuq.js";import"./client-I4GTcUcm.js";import{openInBrowser as a}from"./open-url-dPoDcwsm.js";import"./theme-Brz9wK0w.js";import{useTheme as o}from"./panel-DB1HLxAw.js";import"./banner-MAYlzjcP.js";import"./prompt-D7Ek9MYk.js";import"./keybar-BcHUm3hI.js";import"./chat-panel-dXLm3hUn.js";import{resolveSiteId as s}from"./resolve-site-DYBsBK4c.js";import{DataTable as c}from"./data-table-BvnWCG-w.js";import{deepLinkFor as l}from"./keybar-deep-link-Dagnpllp.js";import{runAnalyticalScreen as u}from"./analytical-screen-BrOFDrQ_.js";import{Box as d,Text as f}from"ink";import p from"react";const m={lcp:{good:2500,poor:4e3},inp:{good:200,poor:500},cls:{good:.1,poor:.25},ttfb:{good:800,poor:1800},fcp:{good:1800,poor:3e3}};function h(e,t){let n=m[e];return t<=n.good?{label:`good`,tone:`good`}:t<=n.poor?{label:`needs`,tone:`needs`}:{label:`poor`,tone:`poor`}}function g(e,t){return e===`cls`?t.toFixed(3):t<1e3?`${Math.round(t)}ms`:`${(t/1e3).toFixed(2)}s`}function _({data:e}){let{theme:t}=o(),n={good:t.success,needs:t.warn,poor:t.error},r=t=>{let n=0,r=0;for(let i of e.vitals){let e=i[t]?.p75;typeof e==`number`&&(n+=e*i.samples,r+=i.samples)}return r>0?n/r:0},i=[`lcp`,`inp`,`cls`,`ttfb`,`fcp`];return p.createElement(d,{flexDirection:`column`},i.map(e=>{let t=r(e),i=h(e,t);return p.createElement(f,{key:e},p.createElement(f,{color:n[i.tone]},`● `),p.createElement(f,{bold:!0},e.toUpperCase().padEnd(5)),` `,p.createElement(f,null,g(e,t).padStart(8)),` `,p.createElement(f,{color:n[i.tone]},i.label))}))}function v({data:e,columns:t}){let{theme:n}=o();return e.vitals.length===0?p.createElement(f,{color:n.muted},`— no vitals data yet —`):p.createElement(c,{data:e.vitals.slice(0,15),columns:t,headerStyle:`accent`})}async function y(o){let c=await e(),d=await t({strict:!1}),f=new n({config:c,cliVersion:o.cliVersion,token:d}),m,h;try{({siteId:m,site:h}=await s(f,{explicit:o.siteId,headless:!!(o.json||o.csv||o.tsv||o.ndjson),cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let y=i(o),b=[{key:`url`,label:`url`,width:32},{key:`device`,label:`device`,width:7,format:e=>String(e??`—`)},{key:`lcp`,label:`LCP p75`,width:9,align:`right`,format:e=>e&&typeof e==`object`&&`p75`in e?g(`lcp`,e.p75):`—`},{key:`inp`,label:`INP p75`,width:9,align:`right`,format:e=>e&&typeof e==`object`&&`p75`in e?g(`inp`,e.p75):`—`},{key:`cls`,label:`CLS p75`,width:9,align:`right`,format:e=>e&&typeof e==`object`&&`p75`in e?g(`cls`,e.p75):`—`},{key:`samples`,label:`n`,width:6,align:`right`}];return u({cliVersion:o.cliVersion,title:`vitals · ${m}`,commandName:`vitals`,ai:{api:f,siteId:m,siteLabel:h?.url?h.url.replace(/^https?:\/\//,``).replace(/\/$/,``):h?.name??m},authToken:d?.accessToken??null,refreshIntervalMs:o.watch?5*6e4:0,fetcher:e=>f.getVitals(m,{url:o.url,device:o.device,window:o.window},e),format:y,keybindings:{o:{label:`open in browser`,handler:()=>{a(l(`vitals`,{siteId:m}))}}},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
+ `);return}process.stdout.write(r(e.vitals,[`url`,`device`,`samples`],t))},panels:[{id:`summary`,title:`Site-wide p75`,render:e=>p.createElement(_,{data:e})},{id:`pages`,title:`Per-page`,render:e=>p.createElement(v,{data:e,columns:b})}]})}export{y as vitalsCommand};
@@ -0,0 +1 @@
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import"./formatter-C4YSOKuq.js";import{emit$1 as r,isHeadless as i}from"./emit-D4YlMlzk.js";import{parseSseStream as a}from"./client-I4GTcUcm.js";import{openInBrowser as o}from"./open-url-dPoDcwsm.js";import"./theme-Brz9wK0w.js";import{Panel as s,useTheme as c}from"./panel-DB1HLxAw.js";import{Banner as l}from"./banner-MAYlzjcP.js";import"./prompt-D7Ek9MYk.js";import{Keybar as u}from"./keybar-BcHUm3hI.js";import{spark as d}from"./sparkline-8ucKVUV7.js";import{resolveSiteId as f}from"./resolve-site-DYBsBK4c.js";import{EmptyState as p}from"./empty-state-DdLBcz4h.js";import{deepLinkFor as m}from"./keybar-deep-link-Dagnpllp.js";import{z as h}from"zod";import{Box as g,Text as _,render as v,useApp as y,useInput as b}from"ink";import x,{useEffect as S,useState as C}from"react";import w from"ink-spinner";import T from"ink-text-input";const E=Math.PI*2;function D(e){let t=e,n=Math.PI*Math.sin(e);for(let e=0;e<6;e++){let e=2*t+Math.sin(2*t)-n,r=2+2*Math.cos(2*t);if(r===0)break;t-=e/r}return t}function O(e,t){if(e<-90||e>90||t<-180||t>180)return null;let n=e*Math.PI/180,r=t*Math.PI/180,i=D(n),a=r*Math.cos(i)/Math.PI,o=Math.sin(i);return{x:a,y:o}}function k(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 A(e,t){let n=e*2,r=t*4;return{dw:n,dh:r,bits:new Uint8Array(n*r)}}function j(e,t,n){t<0||t>=e.dw||n<0||n>=e.dh||(e.bits[n*e.dw+t]=1)}function M(e){let t=e.dw/2,n=e.dh/2,r=e.dw/2-1,i=e.dh/2-1,a=Math.max(e.dw,e.dh)*2;for(let o=0;o<a;o++){let s=o/a*E,c=Math.round(t+r*Math.cos(s)),l=Math.round(n+i*Math.sin(s));j(e,c,l)}}function N(e){let t=Math.floor(e.dh/2);for(let n=0;n<e.dw;n+=4)j(e,n,t)}function P(e,t){let n=e.dw/2,r=e.dh/2,i=e.dw/2-1,a=e.dh/2-1;for(let o of t){let t=O(o.lat,o.lng);if(!t)continue;let s=Math.round(n+t.x*i),c=Math.round(r-t.y*a);j(e,s,c),j(e,s+1,c),j(e,s,c+1),j(e,s+1,c+1)}}const F=[[0,0],[0,1],[0,2],[1,0],[1,1],[1,2],[0,3],[1,3]];function I(e,t,n){let r=0;for(let i=0;i<F.length;i++){let[a,o]=F[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 L(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<=4?`:`:r<=6?`*`:`#`}function R({data:e,width:t=80,height:n=20,asciiOnly:r}){let{theme:i}=c(),a=k(r),o=A(t,n);M(o),N(o),P(o,e);let s=[];for(let e=0;e<n;e++){let n=``;for(let r=0;r<t;r++)n+=a?L(o,r,e):I(o,r,e);s.push(n)}return x.createElement(g,{flexDirection:`column`},s.map((e,t)=>x.createElement(_,{key:t,color:i.accent},e)),x.createElement(_,{color:i.muted},e.length,` live · `,a?`ascii mode`:`braille mode`))}const z=h.object({siteId:h.string().optional(),window:h.string().optional(),totalVisitors:h.number().optional(),visitors:h.object({count:h.number().optional(),series:h.array(h.number()).optional()}).optional(),topPages:h.array(h.object({path:h.string(),views:h.number().optional(),count:h.number().optional()})).optional(),sources:h.array(h.object({source:h.string(),visitors:h.number()})).optional()}).passthrough();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 c=new n({config:o,cliVersion:a.cliVersion,token:s}),l;try{({siteId:l}=await f(c,{explicit:a.siteId,headless:!!a.json,cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}if(i(a)){let e=await c.getDashboardSnapshot(l);return r({type:`watch.tick`,snapshot:e}),0}return new Promise(e=>{let{unmount:t}=v(x.createElement(V,{api:c,siteId:l,intervalMs:a.intervalMs??15e3,cliVersion:a.cliVersion,onExit:n=>{t(),e(n)}}))})}const V=({api:e,siteId:t,intervalMs:n,cliVersion:r,onExit:i})=>{let{theme:d}=c(),{exit:f}=y(),[h,v]=C(null),[T,E]=C(null),[D,O]=C(null),[k,A]=C([]),[j,M]=C(!0),[N,P]=C(null),[F,I]=C(1),[L,B]=C(!1),[V,Y]=C(!1);b((e,n)=>{if(e===`o`||e===`O`){o(m(`watch`,{siteId:t}));return}if(e===`q`){f(),i(0);return}if(e===`?`||e===`/`){Y(e=>!e);return}if(e===`g`){B(e=>!e);return}if(n.tab){I(e=>{let t=n.shift?(e+4)%6+1:e%6+1;return t});return}(e===`1`||e===`2`||e===`3`||e===`4`||e===`5`||e===`6`)&&I(Number(e))});let[X,Z]=C(!1);if(S(()=>{let r=!1,i=async()=>{try{let n=await e.getDashboardSnapshot(t);if(r)return;let i=z.safeParse(n);if(!i.success){Z(!0),M(!1);return}Z(!1);let a=i.data,o={visitors:a.visitors??(typeof a.totalVisitors==`number`?{count:a.totalVisitors}:void 0),topPages:a.topPages?.map(e=>({path:e.path,views:e.views??e.count??0})),sources:a.sources};v(o),e.getVitals(t).then(e=>{r||E(e)},()=>{}),e.getGoals(t).then(e=>{r||O(e)},()=>{}),M(!1),P(null)}catch(e){r||P(e.message)}};i();let a=setInterval(i,n);return()=>{r=!0,clearInterval(a)}},[e,t,n]),S(()=>{let n=new AbortController;return(async()=>{try{let r=await e.openEventsStream(t,n.signal);for await(let e of a(r))e.type===`error`&&A(t=>[...t,`[ERR ${e.code}] ${e.message}`].slice(-10))}catch{}})(),()=>n.abort()},[e,t]),j)return x.createElement(g,{flexDirection:`column`},x.createElement(l,{version:r,subtitle:`watch · ${t}`}),x.createElement(s,{title:`Loading`,state:`busy`},x.createElement(g,null,x.createElement(_,{color:d.accent},x.createElement(w,{type:`dots`})),x.createElement(_,null,` Fetching snapshot…`))));if(N&&!h)return x.createElement(g,{flexDirection:`column`},x.createElement(l,{version:r,subtitle:`watch · ${t}`}),x.createElement(s,{title:`Error`,state:`err`},x.createElement(_,{color:d.error},N)));if(X&&!h)return x.createElement(g,{flexDirection:`column`},x.createElement(l,{version:r,subtitle:`watch · ${t}`}),x.createElement(p,{reason:`error`,headline:`Couldn't load dashboard`,hint:"The server returned an unexpected shape. Try `zenovay update` to refresh the CLI."}));let Q=process.stdout.columns??80,$=Math.max(20,Math.floor(Q/3)-1),ee=[];return x.createElement(g,{flexDirection:`column`},x.createElement(l,{version:r,subtitle:`watch · ${t}${L?` · globe`:``}`}),x.createElement(g,{flexDirection:`row`},x.createElement(g,{flexDirection:`column`},L?x.createElement(s,{title:`Live globe`,focused:F===1,width:$},x.createElement(R,{data:ee,width:Math.max(40,$-4),height:12})):x.createElement(U,{snapshot:h,focused:F===1,width:$}),x.createElement(K,{events:k,focused:F===4,width:$})),x.createElement(g,{flexDirection:`column`},x.createElement(W,{snapshot:h,focused:F===2,width:$}),x.createElement(q,{vitals:T,focused:F===5,width:$})),x.createElement(g,{flexDirection:`column`},x.createElement(G,{snapshot:h,focused:F===3,width:$}),x.createElement(J,{goals:D,focused:F===6,width:$}))),V?x.createElement(H,{api:e,siteId:t,width:Q-2}):null,x.createElement(u,{items:[{key:`tab`,label:`next`},{key:`1-6`,label:`jump`},{key:`g`,label:L?`panels`:`globe`},{key:`?/`,label:V?`close chat`:`ai chat`},{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}]}))},H=({api:e,siteId:t,width:n})=>{let{theme:r}=c(),[i,o]=C(``),[l,u]=C([]),[d,f]=C(!1),[p,m]=C(``),[h,v]=C(null),y=async n=>{let r=n.trim();if(!r||d)return;v(null),o(``);let i=[...l,{role:`user`,content:r}];u(i),f(!0),m(``);try{let n=i.map(e=>({role:e.role,content:e.content})),r=await e.openAiStream(`chat`,{messages:n,siteId:t},void 0),o=``;for await(let e of a(r))if(e.type===`delta`)o+=e.content,m(o);else if(e.type===`error`)v(`${e.code}: ${e.message}`);else if(e.type===`done`)break;u([...i,{role:`assistant`,content:o}]),m(``)}catch(e){v(e instanceof Error?e.message:`chat failed`)}finally{f(!1)}};return x.createElement(g,{marginTop:1},x.createElement(s,{title:`AI chat (esc / ?/ to close)`,focused:!0,width:n},x.createElement(g,{flexDirection:`column`},l.slice(-6).map((e,t)=>x.createElement(g,{key:t,flexDirection:`column`,marginBottom:1},x.createElement(_,{color:e.role===`user`?r.accent:r.info,bold:!0},e.role===`user`?`you`:`zenovay`),x.createElement(_,null,e.content))),d&&p?x.createElement(g,{flexDirection:`column`,marginBottom:1},x.createElement(_,{color:r.info,bold:!0},`zenovay`),x.createElement(_,null,p)):null,h?x.createElement(_,{color:r.error},`✗ `,h):null,x.createElement(g,null,x.createElement(_,{color:r.accent},d?`⠋ `:`▸ `),x.createElement(T,{value:i,onChange:o,onSubmit:y,placeholder:d?`streaming…`:`ask anything about your analytics`})))))},U=({snapshot:e,focused:t,width:n})=>{let{theme:r}=c(),i=e?.visitors?.count??0,a=e?.visitors?.series??[];return x.createElement(s,{title:`Visitors`,focused:t,width:n},x.createElement(_,{bold:!0},i.toString()),x.createElement(_,{color:r.muted},a.length>0?d(a,Math.max(8,n-6)):`— no data —`))},W=({snapshot:e,focused:t,width:n})=>{let{theme:r}=c(),i=e?.topPages?.slice(0,5)??[];return x.createElement(s,{title:`Top pages`,focused:t,width:n},i.length===0?x.createElement(_,{color:r.muted},`— no data —`):i.map(e=>x.createElement(g,{key:e.path},x.createElement(_,null,e.path.padEnd(n-10).slice(0,n-10)),x.createElement(_,{color:r.muted},` `,e.views))))},G=({snapshot:e,focused:t,width:n})=>{let{theme:r}=c(),i=e?.sources?.slice(0,5)??[];return x.createElement(s,{title:`Sources`,focused:t,width:n},i.length===0?x.createElement(_,{color:r.muted},`— no data —`):i.map(e=>x.createElement(g,{key:e.source},x.createElement(_,null,e.source.padEnd(n-10).slice(0,n-10)),x.createElement(_,{color:r.muted},` `,e.visitors))))},K=({events:e,focused:t,width:n})=>{let{theme:r}=c();return x.createElement(s,{title:`Events`,focused:t,width:n},e.length===0?x.createElement(_,{color:r.muted},`— waiting —`):e.slice(-10).map((e,t)=>x.createElement(_,{key:t},e.slice(0,n-4))))},q=({vitals:e,focused:t,width:n})=>{let{theme:r}=c(),i=(e,t,n)=>x.createElement(g,{key:e},x.createElement(_,{bold:!0},e.padEnd(6)),x.createElement(_,{color:r.muted},typeof t==`number`?`${t.toFixed(0)}${n}`:`—`));return x.createElement(s,{title:`Vitals`,focused:t,width:n},i(`LCP`,e?.lcpP75,`ms`),i(`INP`,e?.inpP75,`ms`),i(`CLS`,e?.clsP75?e.clsP75*1e3:void 0,`/1k`),i(`TTFB`,e?.ttfbP75,`ms`),i(`FCP`,e?.fcpP75,`ms`))},J=({goals:e,focused:t,width:n})=>{let{theme:r}=c(),i=e?.goals?.slice(0,5)??[];return x.createElement(s,{title:`Goals`,focused:t,width:n},i.length===0?x.createElement(_,{color:r.muted},`— no data —`):i.map(e=>x.createElement(g,{key:e.name},x.createElement(_,null,e.name.padEnd(n-10).slice(0,n-10)),x.createElement(_,{color:r.muted},` `,e.completions))))};export{B as watchCommand};
@@ -1,4 +1,4 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{emitErrorEnvelope as n}from"./error-codes-C5caZH9p.js";import{ApiV2Client as r}from"./api-v2-CI5hxW-O.js";import{confirmDestructive as i}from"./confirm-DS5wux0g.js";import"./formatter-DutfcQAc.js";import{emitEnvelope as a,wrapItem as o,wrapList as s}from"./emit-DBYk96TD.js";function c(e){return e.length>12?`${e.slice(0,8)}…${e.slice(-4)}`:e}function l(e){return e?new Date(e).toISOString().slice(0,10):`—`}async function u(u){let d=await e(),f=await t({strict:!1}),p=new r({config:d,cliVersion:u.cliVersion,token:f});try{switch(u.action){case`list`:{let{webhooks:e}=await p.listWebhooks();if(u.json)return a(s(e,`webhooks.list`),{legacyKey:`webhooks`,legacyValue:e}),0;if(e.length===0)return process.stdout.write("No webhooks yet. Add one with `zenovay webhooks add <https-url> --events <e1,e2>`.\n"),0;let t=[``,`id`,`url`,`events`,`created`],n=[1,14,40,28,10],r=e=>e.map((e,t)=>(e??``).padEnd(n[t])).join(` `);process.stdout.write(r(t)+`
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{emitErrorEnvelope as n}from"./error-codes-C5caZH9p.js";import{ApiV2Client as r}from"./api-v2-CI5hxW-O.js";import{confirmDestructive as i}from"./confirm-DS5wux0g.js";import"./formatter-C4YSOKuq.js";import{emitEnvelope as a,wrapItem as o,wrapList as s}from"./emit-D4YlMlzk.js";function c(e){return e.length>12?`${e.slice(0,8)}…${e.slice(-4)}`:e}function l(e){return e?new Date(e).toISOString().slice(0,10):`—`}async function u(u){let d=await e(),f=await t({strict:!1}),p=new r({config:d,cliVersion:u.cliVersion,token:f});try{switch(u.action){case`list`:{let{webhooks:e}=await p.listWebhooks();if(u.json)return a(s(e,`webhooks.list`),{legacyKey:`webhooks`,legacyValue:e}),0;if(e.length===0)return process.stdout.write("No webhooks yet. Add one with `zenovay webhooks add <https-url> --events <e1,e2>`.\n"),0;let t=[``,`id`,`url`,`events`,`created`],n=[1,14,40,28,10],r=e=>e.map((e,t)=>(e??``).padEnd(n[t])).join(` `);process.stdout.write(r(t)+`
2
2
  `),process.stdout.write(r(n.map(e=>`─`.repeat(e)))+`
3
3
  `);for(let t of e){let e=t.status===`disabled`?`○`:`●`,i=t.url.length>n[2]?`${t.url.slice(0,n[2]-1)}…`:t.url,a=t.events.join(`,`),o=a.length>n[3]?`${a.slice(0,n[3]-1)}…`:a;process.stdout.write(r([e,c(t.id),i,o,l(t.createdAt)])+`
4
4
  `)}return process.stdout.write(`
@@ -0,0 +1,3 @@
1
+ import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import"./theme-Brz9wK0w.js";import{Panel as r,useTheme as i}from"./panel-DB1HLxAw.js";import{Banner as a}from"./banner-MAYlzjcP.js";import"./progress-row-BS7fwhn_.js";import"./prompt-D7Ek9MYk.js";import"./keybar-BcHUm3hI.js";import"./sparkline-8ucKVUV7.js";import"./data-table-BvnWCG-w.js";import"./bar-DG-MqgGx.js";import"./ui-DXrdVAc-.js";import{Box as o,Text as s,render as c,useApp as l,useInput as u}from"ink";import d,{useEffect as f,useState as p}from"react";async function m(e,t){let n=new TextEncoder,r=await crypto.subtle.importKey(`raw`,n.encode(e),{name:`HMAC`,hash:`SHA-256`},!1,[`sign`]),i=await crypto.subtle.sign(`HMAC`,r,n.encode(t));return Array.from(new Uint8Array(i),e=>e.toString(16).padStart(2,`0`)).join(``)}function h({stats:e}){let{theme:t}=i();return d.createElement(r,{title:`webhooks forward`,state:e.connected?`ok`:`busy`},d.createElement(o,{flexDirection:`column`},d.createElement(s,null,d.createElement(s,{color:t.muted},`public URL `),d.createElement(s,{color:t.accent},e.publicUrl)),d.createElement(s,null,d.createElement(s,{color:t.muted},`→ forwarding to `),d.createElement(s,{color:t.accent},e.wsUrl)),d.createElement(s,null,e.connected?d.createElement(s,{color:t.success},`● connected`):d.createElement(s,{color:t.warn},`○ connecting…`),d.createElement(s,{color:t.muted},` · `,e.total,` requests · `,e.ok,` ok · `),d.createElement(s,{color:e.err>0?t.error:t.muted},e.err,` err`),e.lastStatus===null?null:d.createElement(s,{color:t.muted},` · last: HTTP `,e.lastStatus)),e.lastError?d.createElement(s,{color:t.error},`last error: `,e.lastError.slice(0,80)):null))}async function g(r){let g=await e(),_=await t({strict:!1});if(!_?.accessToken)return process.stderr.write("Not authenticated. Run `zenovay login` first.\n"),2;let v=r.siteId??_.teamId??``;if(!v)return process.stderr.write(`No site selected — pass --site-id or set ZENOVAY_SITE.
2
+ `),2;if(!r.to)return process.stderr.write(`Missing --to <url> (e.g. --to localhost:3000/webhook).
3
+ `),2;let y=r.to.match(/^https?:\/\//)?r.to:`http://${r.to}`,b=new n({config:g,cliVersion:r.cliVersion,token:_}),x;try{x=await b.createTunnel(v,r.to)}catch(e){return process.stderr.write(`Failed to register tunnel: ${e.message}\n`),1}let S=r.sign?r.secret??x.tunnelKey:null,C=()=>{let{theme:e}=i(),{exit:t}=l(),[n,c]=p({total:0,ok:0,err:0,lastStatus:null,lastError:null,publicUrl:x.publicUrl,wsUrl:x.wsUrl,connected:!1});return u((e,n)=>{(e===`q`||n.escape)&&t()}),f(()=>{let e=new AbortController,t=async e=>{try{let t={...e.headers};delete t.host,delete t[`content-length`],S&&(t[`X-Zenovay-Signature`]=`sha256=${await m(S,e.body)}`);let n=await fetch(y,{method:e.method,headers:t,body:e.method===`GET`||e.method===`HEAD`?void 0:e.body}),r=await n.text(),i={};return n.headers.forEach((e,t)=>{i[t]=e}),c(e=>({...e,total:e.total+1,ok:e.ok+(n.ok?1:0),err:e.err+(n.ok?0:1),lastStatus:n.status,lastError:n.ok?null:`HTTP ${n.status}`})),{status:n.status,headers:i,body:r}}catch(e){let t=e instanceof Error?e.message:String(e);return c(e=>({...e,total:e.total+1,err:e.err+1,lastError:t})),{status:502,body:JSON.stringify({error:`cli_local_failed`,detail:t})}}};return(async()=>{let n=b.tunnelClient(x.wsUrl);c(e=>({...e,connected:!0}));try{await n.start(t,e.signal)}catch(e){c(t=>({...t,connected:!1,lastError:e.message}))}})(),()=>{e.abort()}},[]),d.createElement(o,{flexDirection:`column`},d.createElement(a,{version:`webhooks forward`}),d.createElement(h,{stats:n}),d.createElement(s,{color:e.muted},`target: `,y,` `,r.sign?`· HMAC-signed`:``),d.createElement(s,{color:e.muted},`[q | Esc] quit`))},{waitUntilExit:w}=c(d.createElement(C,null));return await w(),0}export{g as webhooksForwardCommand};
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import(`./init-BhfcLbDE.js`).then(async({initCommand:e})=>{let{readFileSync:t}=await import(`node:fs`),n=await import(`node:path`),{fileURLToPath:r}=await import(`node:url`),i=n.dirname(r(import.meta.url)),a=JSON.parse(t(n.join(i,`..`,`package.json`),`utf8`)),o=process.argv.slice(2),s=o.includes(`--json`),c=o.includes(`--yes`),l=o.includes(`--skip-mcp`),u=o.includes(`--skip-verify`),d=await e({cliVersion:a.version,cwd:process.cwd(),json:s,yes:c,skipMcp:l,skipVerify:u});process.exit(d)});
2
+ import(`./init-awEnG3zC.js`).then(async({initCommand:e})=>{let{readFileSync:t}=await import(`node:fs`),n=await import(`node:path`),{fileURLToPath:r}=await import(`node:url`),i=n.dirname(r(import.meta.url)),a=JSON.parse(t(n.join(i,`..`,`package.json`),`utf8`)),o=process.argv.slice(2),s=o.includes(`--json`),c=o.includes(`--yes`),l=o.includes(`--skip-mcp`),u=o.includes(`--skip-verify`),d=await e({cliVersion:a.version,cwd:process.cwd(),json:s,yes:c,skipMcp:l,skipVerify:u});process.exit(d)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenovay/cli",
3
- "version": "0.1.64",
3
+ "version": "0.1.65",
4
4
  "description": "Zenovay CLI — AI install wizard + full terminal analytics dashboard",
5
5
  "type": "module",
6
6
  "bin": {
@@ -20,7 +20,7 @@
20
20
  "build": "tsdown",
21
21
  "build:binaries": "tsx scripts/build-binaries.ts",
22
22
  "typecheck": "tsc --noEmit",
23
- "lint": "node -e \"console.log('lint: TypeScript ESLint v9 setup pending — see eslint.config.mjs');\"",
23
+ "lint": "eslint 'src/**/*.{ts,tsx}'",
24
24
  "test": "vitest run",
25
25
  "test:watch": "vitest",
26
26
  "test:all": "vitest run tests/unit tests/integration tests/security",
@@ -54,6 +54,7 @@
54
54
  "@types/node": "^22.10.0",
55
55
  "@types/react": "^18.3.12",
56
56
  "@types/semver": "^7.5.8",
57
+ "@typescript-eslint/parser": "^8.61.0",
57
58
  "@vitest/coverage-v8": "^2.1.8",
58
59
  "csv-parse": "^6.2.1",
59
60
  "eslint": "^9.16.0",
@@ -1,7 +0,0 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import{ApiClient as t}from"./api-FCanTxsb.js";import{readToken as n}from"./token-store-BQuGH0z2.js";import"./telemetry-DRh10SvO.js";import{ApiV2Client as r}from"./api-v2-CI5hxW-O.js";import{detectInstalled as i,initCommand as a}from"./init-BIJkCrgc.js";import{parseSseStream as o}from"./client-DTXWADkX.js";import"./formatter-DutfcQAc.js";import{emit$1 as s,isHeadless as c}from"./emit-DBYk96TD.js";import"./secrets-ApB7yh2A.js";import"./login-yhuXiFqh.js";import{Panel as l}from"./panel-B_yDcIcn.js";import"./banner-3iSWTDFy.js";import"./progress-row-BpAXjJPL.js";import{Select as u}from"./prompt-D-Uzz_GF.js";import"./keybar-DsYTkKZX.js";import"./sparkline-BZ0eMB-w.js";import{ChatPanel as d}from"./chat-panel-CqJaCIg3.js";import{Box as f,Text as p,render as m}from"ink";import h from"react";async function g(e){let t=await i(e.cwd),n;if(e.mode)n=e.mode;else if(!t.installed)n=`install`;else if(c(e))return s({type:`error`,code:`no_mode`,message:`Headless mode requires --mode chat|mcp|install`}),2;else n=await _(t);return n===`install`?a({cliVersion:e.cliVersion,cwd:e.cwd,json:e.json}):n===`chat`?v(e):y(e)}async function _(e){return new Promise(t=>{let n=[{label:`Chat with your analytics`,value:`chat`,description:`Ask natural-language questions about your data`},{label:`Manage via MCP`,value:`mcp`,description:`Create goals, funnels, sites, etc. in plain English`},{label:`Re-run install / repair`,value:`install`,description:`Run the install wizard again`}],{unmount:r}=m(h.createElement(f,{flexDirection:`column`},h.createElement(l,{title:`Zenovay detected${e.packageMarker?` (${e.packageMarker})`:``}`,state:`idle`},h.createElement(p,null,`What do you want to do?`)),h.createElement(u,{items:n,onSelect:e=>{r(),t(e)}})))})}async function v(t){let i=await e(),a=await n({strict:!1});if(!a)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let o=i.defaultSiteId,s=i.defaultSiteName,c=new r({config:i,cliVersion:t.cliVersion,token:a});return new Promise(e=>{let{unmount:n}=m(h.createElement(d,{cliVersion:t.cliVersion,api:c,dashboardContext:{commandName:`ai chat`,siteId:o,siteLabel:s,metricsSnapshot:null},onClose:()=>{n(),e(0)}}))})}async function y(r){let i=await e(),a=await n({strict:!1});if(!a)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let s=new t({config:i,cliVersion:r.cliVersion,token:a});process.stdout.write(`
2
- Zenovay · MCP mode — describe what you want to create or change. Ctrl-C to exit.
3
-
4
- > `);let c=await b();if(!c)return 0;let l=await s.openAiStream(`mcp`,{messages:[{role:`user`,content:c}]});for await(let e of o(l)){if(e.type===`delta`&&process.stdout.write(e.content),e.type===`tool_start`&&process.stdout.write(`\n[tool: ${e.name}] `),e.type===`tool_result`&&process.stdout.write(`
5
- [result]`),e.type===`done`){process.stdout.write(`
6
- `);break}if(e.type===`error`)return process.stderr.write(`\n[${e.code}] ${e.message}\n`),1}return 0}function b(){return new Promise(e=>{let t=``,n=r=>{let i=r.toString(`utf8`);i.includes(`
7
- `)||i.includes(`\r`)?(t+=i.replace(/[\r\n]/g,``),process.stdin.off(`data`,n),process.stdin.pause(),e(t)):t+=i};process.stdin.resume(),process.stdin.on(`data`,n)})}export{g as aiCommand};
@@ -1,3 +0,0 @@
1
- import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{emitErrorEnvelope as n}from"./error-codes-C5caZH9p.js";import{ApiV2Client as r}from"./api-v2-CI5hxW-O.js";import{confirmDestructive as i}from"./confirm-DS5wux0g.js";import"./formatter-DutfcQAc.js";import{emitEnvelope as a,wrapItem as o,wrapList as s}from"./emit-DBYk96TD.js";import{Panel as c}from"./panel-B_yDcIcn.js";import{Banner as l}from"./banner-3iSWTDFy.js";import"./prompt-D-Uzz_GF.js";import{resolveSiteId as u}from"./resolve-site-mj0esTrm.js";import{fmtDate as d,shortId as f}from"./fmt-gMsty5jy.js";import{DataTable as p}from"./data-table-BpbyyNSA.js";import{Box as m,Text as h,render as g}from"ink";import _ from"react";const v=new Set([`visitors`,`pageviews`,`bounce_rate`,`avg_session_duration`,`errors`,`lcp`,`inp`,`cls`,`uptime`,`revenue`]),y=/^\d+(m|h|d)$/;function b(e){let t=e.metric;if(!t)return{errorMessage:"--metric is required for `alerts create`."};if(!v.has(t))return{errorMessage:`--metric must be one of: ${[...v].join(`, `)}. Got: ${t}.`};let n=e.op;if(n!==`gt`&&n!==`lt`)return{errorMessage:"--op must be `gt` or `lt`."};let r=e.threshold,i=typeof r==`number`?r:Number(r);if(!Number.isFinite(i))return{errorMessage:`--threshold must be a number.`};let a=e.window;if(!a||!y.test(a))return{errorMessage:"--window must match `<n>m|h|d` (e.g. 5m, 1h, 7d)."};let o=e.channel,s=`email`;if(o!==void 0){if(o!==`email`&&o!==`webhook`)return{errorMessage:`--channel must be 'email' or 'webhook'. Got: ${o}.`};s=o}return s===`email`&&!e.email?{errorMessage:`--email <addr> is required when --channel email (the default).`}:{body:{metric:t,op:n,threshold:i,window:a,...e.name?{name:e.name}:{},channel:s,...e.email?{email:e.email}:{}}}}async function x(c){let l=await e(),d=await t({strict:!1}),p=new r({config:l,cliVersion:c.cliVersion,token:d}),m;try{({siteId:m}=await u(p,{explicit:c.siteId,headless:!!c.json,cliVersion:c.cliVersion}))}catch(e){return c.json?n(e,{command:`alerts`,cliVersion:c.cliVersion}):(process.stderr.write(`${e.message}\n`),2)}try{switch(c.action){case`list`:{let e=await p.listAlerts(m);return c.json?(a(s(e,`alerts.list`,{siteId:m,cliVersion:c.cliVersion,command:`alerts list`})),0):e.length===0?(process.stdout.write("No alerts yet. Create one with `zenovay alerts create --metric <m> --op <gt|lt> --threshold <n> --window <1h>`.\n"),0):w(e,m,c.cliVersion)}case`create`:{let e=b(c);if(`errorMessage`in e)return c.json?n(new S(e.errorMessage),{command:`alerts create`,cliVersion:c.cliVersion}):(process.stderr.write(`Error: ${e.errorMessage}\n`),2);let t=await p.createAlert(m,e.body);return c.json?(a(o(t,`alerts.created`,{siteId:m,cliVersion:c.cliVersion,command:`alerts create`})),0):(process.stdout.write(`\n ✓ Alert created: ${t.metric} ${t.op} ${t.threshold} over ${t.window}\n id: ${t.id}\n\n`),0)}case`delete`:{if(!c.id){let e="alert id is required for `alerts delete`.";return c.json?n(new S(e),{command:`alerts delete`,cliVersion:c.cliVersion}):(process.stderr.write(`Error: ${e}\n`),2)}let e;try{let t=await p.listAlerts(m);e=t.find(e=>e.id===c.id)}catch{}let t=e?`${e.metric} ${e.op} ${e.threshold} (${f(c.id)})`:f(c.id),r=await i({resource:`alert`,name:t,yes:c.yes,destructive:!0});return r?(await p.deleteAlert(m,c.id),c.json?(a(o({deleted:!0,id:c.id},`alerts.deleted`,{siteId:m,cliVersion:c.cliVersion,command:`alerts delete`})),0):(process.stdout.write(`✓ Alert deleted (${f(c.id)}). Notifications stopped immediately.\n`),0)):c.json?(process.stdout.write(JSON.stringify({cancelled:!0})+`
2
- `),1):(process.stdout.write(`Cancelled.
3
- `),1)}}}catch(e){return c.json?n(e,{command:`alerts ${c.action}`,cliVersion:c.cliVersion}):(process.stderr.write(`✗ ${e.message}\n`),1)}}var S=class extends Error{constructor(e){super(e),this.name=`ValidationError`}};const C=({items:e,siteId:t,cliVersion:n})=>{let r=[{key:`id`,label:`id`,width:14,format:e=>f(String(e))},{key:`metric`,label:`metric`,width:18},{key:`op`,label:`op`,width:3},{key:`threshold`,label:`threshold`,width:10,align:`right`,format:e=>String(e??``)},{key:`window`,label:`window`,width:7},{key:`createdAt`,label:`created`,width:10,format:e=>d(e)}];return _.createElement(m,{flexDirection:`column`},_.createElement(l,{version:n,subtitle:`alerts · ${t}`}),_.createElement(c,{title:`${e.length} alert${e.length===1?``:`s`}`,state:`idle`},_.createElement(p,{columns:r,data:e,headerStyle:`accent`}),_.createElement(m,{marginTop:1},_.createElement(h,{color:`gray`},`Create: zenovay alerts create --metric <m> --op <gt|lt> --threshold <n> --window <1h>`))))};function w(e,t,n){return new Promise(r=>{let i=g(_.createElement(C,{items:e,siteId:t,cliVersion:n}));setTimeout(()=>{i.unmount(),r(0)},50)})}export{x as alertsCommand};
@@ -1 +0,0 @@
1
- import{ApiError as e}from"./api-FCanTxsb.js";import{formatEvent as t}from"./formatter-DutfcQAc.js";import{Panel as n}from"./panel-B_yDcIcn.js";import{Banner as r}from"./banner-3iSWTDFy.js";import{Keybar as i}from"./keybar-DsYTkKZX.js";import{ChatPanel as a}from"./chat-panel-CqJaCIg3.js";import{Box as o,Text as s,render as c,useApp as l,useInput as u}from"ink";import d,{useEffect as f,useMemo as p,useReducer as m,useRef as h,useState as g}from"react";import _ from"ink-spinner";function v(e,t){switch(t.type){case`set`:return{...e,data:t.data,status:`ready`,error:null};case`merge`:{let n=e.data?{...e.data,...t.partial}:t.partial;return{...e,data:n,status:`ready`,error:null}}case`error`:return{...e,status:`error`,error:{message:t.message,status:t.status,upgradeUrl:t.upgradeUrl}};case`refresh`:return{...e,refreshTick:e.refreshTick+1};case`focus`:return{...e,focusIndex:t.index};case`help-toggle`:return{...e,showHelp:!e.showHelp};default:return e}}async function y(e,n){let r=new AbortController,i=()=>r.abort();process.on(`SIGINT`,i);try{let i=await e.fetcher(r.signal);if(e.headlessEmit?e.headlessEmit(i,n):process.stdout.write(t(i,n)),e.streamer)for await(let i of e.streamer(r.signal))process.stdout.write(t(i,n));return 0}catch(e){if(e.name===`AbortError`)return 0;let t=e.message;return process.stderr.write(`${t}\n`),1}finally{process.off(`SIGINT`,i)}}const b=({cliVersion:e})=>d.createElement(o,{flexDirection:`column`},d.createElement(r,{version:e,subtitle:`login required`}),d.createElement(n,{title:`Not logged in`,state:`warn`},d.createElement(s,null,`You need to authenticate before running this command.`),d.createElement(s,null,` `),d.createElement(s,{color:`gray`},`Run `),d.createElement(s,{color:`cyan`},`zenovay login`),d.createElement(s,{color:`gray`},` to start the device-flow.`)));function x(t){let{exit:c}=l(),[y,b]=m(v,{data:null,status:`loading`,error:null,refreshTick:0,focusIndex:0,showHelp:!1}),[x,S]=g(!1),C=h(b);C.current=b;let w=p(()=>{let e={q:{label:`quit`,handler:()=>{c(),t.onExit(0)}},r:{label:`refresh`,handler:()=>C.current({type:`refresh`})},"?":{label:`help`,handler:()=>C.current({type:`help-toggle`})}};return t.ai&&(e[`/`]={label:`ask AI`,handler:()=>S(!0)}),e},[c,t]),T=p(()=>({...t.keybindings??{},...w}),[t.keybindings,w]);if(u((e,n)=>{if(x)return;if(n.tab&&n.shift){b({type:`focus`,index:(y.focusIndex-1+t.panels.length)%t.panels.length});return}if(n.tab){b({type:`focus`,index:(y.focusIndex+1)%t.panels.length});return}if(e>=`1`&&e<=`9`){let n=Number(e)-1;n<t.panels.length&&b({type:`focus`,index:n});return}let r=T[e];r&&r.handler()}),f(()=>{let n=new AbortController,r=!1,i=async()=>{try{let e=await t.fetcher(n.signal);r||C.current({type:`set`,data:e})}catch(t){if(r)return;if(t instanceof e){if(t.status===402){let e=t.body,n=typeof e==`object`&&e&&`upgradeUrl`in e?e.upgradeUrl:void 0;C.current({type:`error`,message:`This command requires a higher plan.`,status:402,upgradeUrl:n});return}C.current({type:`error`,message:t.message,status:t.status});return}if(t.name===`AbortError`)return;C.current({type:`error`,message:t.message})}};i();let a=null,o=t.refreshIntervalMs??15e3;return o>0&&!t.streamer&&(a=setInterval(i,o)),()=>{r=!0,n.abort(),a&&clearInterval(a)}},[t.fetcher,t.refreshIntervalMs,t.streamer,y.refreshTick]),f(()=>{if(!t.streamer)return;let e=new AbortController,n=!1;return(async()=>{try{for await(let r of t.streamer(e.signal)){if(n)return;C.current({type:`merge`,partial:r})}}catch(e){if(n||e.name===`AbortError`)return;C.current({type:`error`,message:e.message})}})(),()=>{n=!0,e.abort()}},[t.streamer]),x&&t.ai)return d.createElement(a,{cliVersion:t.cliVersion,api:t.ai.api,dashboardContext:{commandName:t.commandName,siteId:t.ai.siteId,siteLabel:t.ai.siteLabel,metricsSnapshot:y.data},onClose:()=>S(!1)});if(y.status===`loading`&&y.data===null)return d.createElement(o,{flexDirection:`column`},d.createElement(r,{version:t.cliVersion,subtitle:t.title}),d.createElement(n,{title:`Loading`,state:`busy`},d.createElement(o,null,d.createElement(s,{color:`magenta`},d.createElement(_,{type:`dots`})),d.createElement(s,null,` Fetching `,t.commandName,`…`))),d.createElement(i,{items:[{key:`q`,label:`quit`}]}));if(y.status===`error`&&y.error){let e=y.error.status===402;return d.createElement(o,{flexDirection:`column`},d.createElement(r,{version:t.cliVersion,subtitle:t.title}),d.createElement(n,{title:e?`Upgrade required`:`Error`,state:e?`warn`:`err`},d.createElement(s,{color:e?`yellow`:`red`},y.error.message),e&&y.error.upgradeUrl?d.createElement(d.Fragment,null,d.createElement(s,null,` `),d.createElement(s,{color:`gray`},`Upgrade: `),d.createElement(s,{color:`cyan`},y.error.upgradeUrl)):null),d.createElement(i,{items:[{key:`r`,label:`retry`},{key:`q`,label:`quit`}]}))}let E=y.data,D=Object.entries(T).map(([e,t])=>({key:e,label:t.label})),O=Math.ceil(t.panels.length/2),k=t.panels.slice(0,O),A=t.panels.slice(O);return d.createElement(o,{flexDirection:`column`},d.createElement(r,{version:t.cliVersion,subtitle:t.title}),d.createElement(o,{flexDirection:`row`},k.map((e,t)=>{let r=y.focusIndex===t;return d.createElement(o,{key:e.id,flexDirection:`column`,marginRight:1,flexGrow:1},d.createElement(n,{title:e.title,state:r?`busy`:`idle`},e.render(E,r)))})),A.length>0?d.createElement(o,{flexDirection:`row`},A.map((e,t)=>{let r=t+O,i=y.focusIndex===r;return d.createElement(o,{key:e.id,flexDirection:`column`,marginRight:1,flexGrow:1},d.createElement(n,{title:e.title,state:i?`busy`:`idle`},e.render(E,i)))})):null,y.showHelp?d.createElement(n,{title:`Help`,state:`idle`},Object.entries(T).map(([e,t])=>d.createElement(s,{key:e},`[`,e,`] `,t.label)),d.createElement(s,{color:`gray`},`[tab/shift+tab] cycle focus [1-9] focus panel`)):null,d.createElement(i,{items:D}))}async function S(e){return e.authToken===null?e.format?(process.stderr.write("Not logged in — run `zenovay login` first.\n"),2):new Promise(t=>{let{unmount:n}=c(d.createElement(b,{cliVersion:e.cliVersion}));setTimeout(()=>{n(),t(2)},50)}):e.format?y(e,e.format):new Promise(t=>{let{unmount:n}=c(d.createElement(x,{...e,onExit:e=>{n(),t(e)}}))})}export{S as runAnalyticalScreen};