@zenovay/cli 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{agency-DHAyzKd-.js → agency-cNkRWBOo.js} +1 -1
- package/dist/{ai-xhCcy02q.js → ai-DDefS75j.js} +1 -1
- package/dist/{alerts-Be0XKEUX.js → alerts-BQ0EMdBT.js} +1 -1
- package/dist/{analytical-screen-BU2yCSg_.js → analytical-screen-B4xo6sII.js} +1 -1
- package/dist/{analytics-D7vhDrdG.js → analytics-ZCtpMy4v.js} +2 -2
- package/dist/{annotation-dveH657H.js → annotation-aMzsv1oV.js} +1 -1
- package/dist/{api-hWp9s3Y8.js → api-CdcB84ie.js} +1 -1
- package/dist/{api-keys-DKQX5aL9.js → api-keys-x_GGL61a.js} +1 -1
- package/dist/api-v2-Co0dWAP5.js +1 -0
- package/dist/{api-v2-DqKh6FgZ.js → api-v2-D0mvt__4.js} +1 -1
- package/dist/{audit-DgHopH-O.js → audit-VHsZwYPM.js} +1 -1
- package/dist/bin.js +7 -7
- package/dist/{chat-panel-PSN5hjlF.js → chat-panel-D9IjovCR.js} +1 -1
- package/dist/{companies-uScE2uHf.js → companies-BFUFJkEM.js} +1 -1
- package/dist/{completions-DKyjFPMK.js → completions-suqE20Pu.js} +1 -1
- package/dist/{config-DB3jF5gG.js → config-B72_Kfe0.js} +1 -1
- package/dist/{config--JRu_jFq.js → config-JVhBplSX.js} +1 -1
- package/dist/{deploys-BqQmCzVb.js → deploys-DLvmc21H.js} +1 -1
- package/dist/{devices-CUgpkbAC.js → devices-BMdSSO0o.js} +1 -1
- package/dist/{doctor-D1bGGwtN.js → doctor-BI6TF72T.js} +1 -1
- package/dist/{domains-iRmYn9G7.js → domains-CNv8-i1K.js} +1 -1
- package/dist/error-codes-BiKo9PGm.js +1 -0
- package/dist/{error-codes-D4XO4okw.js → error-codes-ByhvHx2M.js} +1 -1
- package/dist/{errors-CEIyrEgF.js → errors-DTs33lNs.js} +1 -1
- package/dist/{events-tail-CRgba_gO.js → events-tail-CzYtpjey.js} +1 -1
- package/dist/{export-Csl7rWLW.js → export-BAFQahzg.js} +1 -1
- package/dist/{funnel-B36lGX2i.js → funnel-CnkLL8HX.js} +1 -1
- package/dist/{geo-CPt2etQd.js → geo-B9TL_gUX.js} +1 -1
- package/dist/{globe-yy_-G4K8.js → globe-CnpFQ9iU.js} +1 -1
- package/dist/{goals-BTzgvDOK.js → goals-DQqxuANi.js} +1 -1
- package/dist/{health-RsLcvYTb.js → health-C6ZK4ZDk.js} +1 -1
- package/dist/{health-D26VB-iZ.js → health-Cg5Vtq-A.js} +1 -1
- package/dist/{heatmaps-D4o0Ghjn.js → heatmaps-BLVXNROm.js} +1 -1
- package/dist/{home-B8CoN9Hd.js → home-CcQ7J4RY.js} +1 -1
- package/dist/{init-Cee2-8Kd.js → init-CczZwsQf.js} +2 -2
- package/dist/init-DJbtwhvX.js +1 -0
- package/dist/{insights-B0L6kIxY.js → insights-J4kYprJu.js} +1 -1
- package/dist/{integrations-CJ9Pa-II.js → integrations-C3z-N73K.js} +1 -1
- package/dist/{journeys--jjaTA3C.js → journeys-BRqDOAqs.js} +1 -1
- package/dist/{live-CuVd6yRs.js → live-DJsNJ-fo.js} +1 -1
- package/dist/login-CDAP0iKS.js +1 -0
- package/dist/{login-CsQ7fPVu.js → login-DU1fY88U.js} +1 -1
- package/dist/{logout-C3KOOdIM.js → logout-u6BpGCg6.js} +1 -1
- package/dist/{notes-jV1DYMp_.js → notes-sFga-5H5.js} +1 -1
- package/dist/{pages-0DLiuGYc.js → pages-DXd2DGo6.js} +1 -1
- package/dist/{plans-D4o6-tbv.js → plans-BhicnNJA.js} +1 -1
- package/dist/{profile-Cm5RFs_L.js → profile-DsSj1vSw.js} +1 -1
- package/dist/{projects-BTTgnjOZ.js → projects-CTXvqzN8.js} +1 -1
- package/dist/{query-yn10M321.js → query-Ds3hjKZ8.js} +1 -1
- package/dist/{resolve-site-BLrtFOyW.js → resolve-site-BTVBMF1C.js} +1 -1
- package/dist/{retention-DpBuavgY.js → retention-DWQML_Jo.js} +1 -1
- package/dist/{revenue-Bv1Cqzjr.js → revenue-Dm4wls0K.js} +1 -1
- package/dist/{self-test-Cml0QXeA.js → self-test-CEclBRpu.js} +1 -1
- package/dist/{sessions-B0RwtHvP.js → sessions-KmEQ4zZp.js} +1 -1
- package/dist/{settings-i4TqMmAY.js → settings-1kdqZcWp.js} +1 -1
- package/dist/{share-DTHFqTzp.js → share-BsCpBNTV.js} +1 -1
- package/dist/{site-switcher-D_JBKFaR.js → site-switcher-B2L1-Pjd.js} +1 -1
- package/dist/{sources-B39BFFKF.js → sources-CJQtexqb.js} +1 -1
- package/dist/{stats-Dh9MQAXx.js → stats-ctt0SOlE.js} +1 -1
- package/dist/{status-agent-C3q7fOEs.js → status-agent-CMpp3zEX.js} +1 -1
- package/dist/{team-DZtvClMF.js → team-CyzZCg--.js} +1 -1
- package/dist/{teams-CqJFecKB.js → teams-DnOLx5tK.js} +1 -1
- package/dist/{telemetry-DRh10SvO.js → telemetry-BV-xvfdt.js} +1 -1
- package/dist/telemetry-Bbh6Vtst.js +1 -0
- package/dist/{telemetry-BdWnMaJC.js → telemetry-C-0DECLq.js} +1 -1
- package/dist/{tier-BneaO4vD.js → tier-DDIroQbc.js} +1 -1
- package/dist/{token-store-BQuGH0z2.js → token-store-BvSCse1t.js} +1 -1
- package/dist/token-store-QTNSg4TT.js +1 -0
- package/dist/{update-CoZzBsMu.js → update-C72vyFU1.js} +1 -1
- package/dist/{uptime-Ck1GdjRR.js → uptime-Dgi5KItw.js} +1 -1
- package/dist/{usage-BN_mEsal.js → usage-BOlapdBM.js} +1 -1
- package/dist/{use-NGqXzASp.js → use-DBiMOOkB.js} +1 -1
- package/dist/{visitors-BCz-O9rK.js → visitors-CbU2tXXG.js} +1 -1
- package/dist/{vitals-Dx_eY6tW.js → vitals-3NBHzH_m.js} +1 -1
- package/dist/{watch-CP-Klikt.js → watch-GUa_JTOS.js} +1 -1
- package/dist/{webhooks-BR1D3o5S.js → webhooks-CrE9paQf.js} +1 -1
- package/dist/{webhooks-forward-CpXm4GHn.js → webhooks-forward-CCd-RyJc.js} +1 -1
- package/dist/wizard-bin.js +1 -1
- package/package.json +1 -1
- package/dist/api-v2-C7-5GPx8.js +0 -1
- package/dist/error-codes-DpKbL-uM.js +0 -1
- package/dist/init-BrxmKAnU.js +0 -1
- package/dist/login-DeznxBjS.js +0 -1
- package/dist/telemetry-C1045t6Q.js +0 -1
- package/dist/token-store-TmBx42nv.js +0 -1
package/README.md
CHANGED
|
@@ -63,7 +63,7 @@ Notification platforms (auto-detected, with graceful fallback to OSC 9 bell):
|
|
|
63
63
|
|
|
64
64
|
## Documentation
|
|
65
65
|
|
|
66
|
-
- CLI reference: https://docs.zenovay.com/cli
|
|
66
|
+
- CLI reference: https://docs.zenovay.com/en/integrations/cli
|
|
67
67
|
- Changelog: https://cli.zenovay.com/changelog
|
|
68
68
|
- Feedback: https://cli.zenovay.com/feedback
|
|
69
69
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config-JVhBplSX.js";import"./api-CdcB84ie.js";import{readToken as t}from"./token-store-BvSCse1t.js";import{ApiV2Client as n}from"./api-v2-D0mvt__4.js";import{requireTier as r}from"./tier-DDIroQbc.js";import{confirmDestructive as i}from"./confirm-DS5wux0g.js";function a(e){return e.length>12?`${e.slice(0,8)}…${e.slice(-4)}`:e}function o(e){return e?new Date(e).toISOString().slice(0,10):`—`}async function s(s){let c=await e(),l=await t({strict:!1}),u=new n({config:c,cliVersion:s.cliVersion,token:l});try{await r(u,`scale`)}catch(e){return process.stderr.write(`✗ ${e.message}\n`),2}try{switch(s.action){case`clients-list`:{let{clients:e}=await u.listAgencyClients();if(s.json)return process.stdout.write(JSON.stringify({clients:e},null,2)+`
|
|
2
2
|
`),0;if(e.length===0)return process.stdout.write("No clients yet. Add one with `zenovay agency clients add --name <n> --email <e>`.\n"),0;let t=[14,30,30,12],n=e=>e.map((e,n)=>(e??``).padEnd(t[n])).join(` `);process.stdout.write(`
|
|
3
3
|
`+n([`id`,`name`,`domain`,`created`])+`
|
|
4
4
|
`),process.stdout.write(n(t.map(e=>`─`.repeat(e)))+`
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config-JVhBplSX.js";import"./api-CdcB84ie.js";import{readToken as t}from"./token-store-BvSCse1t.js";import{emit as n}from"./telemetry-BV-xvfdt.js";import{ApiV2Client as r}from"./api-v2-D0mvt__4.js";import{detectInstalled as i,initCommand as a}from"./init-CczZwsQf.js";import"./formatter-C4YSOKuq.js";import{emit$1 as o,isHeadless as s}from"./emit-D4YlMlzk.js";import"./open-url-BtI5aLgL.js";import"./secrets-ApB7yh2A.js";import{parseSseStream as c}from"./client-ntsEXSVC.js";import"./login-DU1fY88U.js";import"./theme-Brz9wK0w.js";import{Banner as l,Panel as u,useTheme as d}from"./panel-CTtQ2ue6.js";import"./progress-row-Afnt5Ng8.js";import{Select as f}from"./prompt-BXvg2B4R.js";import"./keybar-DO5OoZy9.js";import"./sparkline-CpoBjjlc.js";import{ChatPanel as p}from"./chat-panel-D9IjovCR.js";import{resolveSiteId as m}from"./resolve-site-BTVBMF1C.js";import{Box as h,Static as g,Text as _,render as v,useApp as y,useInput as ee}from"ink";import b,{useEffect as x,useRef as S,useState as C}from"react";import w from"ink-spinner";import T from"ink-text-input";const E=30,D=9e4;function O(e){return e.replace(/_/g,` `)}function k(e){if(!e)return``;let t=Object.entries(e).map(([e,t])=>`${e}: ${JSON.stringify(t)}`).join(`, `);return t.length>80?t.slice(0,77)+`…`:t}function A(e,t,n){if(t<=0)return{body:``,clipped:0};let r=e.split(`
|
|
2
2
|
`),i=[];for(let e of r)if(e.length<=n||n<=0)i.push(e);else for(let t=0;t<e.length;t+=n)i.push(e.slice(t,t+n));if(i.length<=t)return{body:e,clipped:0};let a=i.slice(i.length-t);return{body:a.join(`
|
|
3
3
|
`),clipped:i.length-t}}const j=({cliVersion:e,api:t,siteId:r,siteLabel:i,initialAllowAll:a=!1,onClose:o})=>{let{theme:s}=d(),{exit:f}=y(),[p,m]=C([]),[v,j]=C(``),[M,N]=C(!1),[P,F]=C(``),[I,L]=C([]),[R,z]=C(null),[B,V]=C(a),[H,U]=C(!1),[W,G]=C(0),K=S(``),q=S(null),J=S(Date.now());x(()=>{if(!M)return;let e=setInterval(()=>{K.current!==P&&F(K.current)},Math.floor(1e3/E));return()=>clearInterval(e)},[M,P]),x(()=>(n(`mcp.open`,{properties:{has_site:!!r}}),()=>{n(`mcp.close`,{duration_ms:Date.now()-J.current})}),[r]),ee((e,t)=>{if(t.escape||t.ctrl&&e===`c`){q.current?.abort(),o();return}if(e===`a`||e===`A`){V(!0),H&&U(!1);return}if(e===`x`||e===`X`){q.current?.abort(),z(`Cancelled.`),U(!1),N(!1);return}if((t.return||e===`y`||e===`Y`)&&H){U(!1);return}if((e===`n`||e===`N`)&&H){q.current?.abort(),z(`Cancelled by user.`),U(!1),N(!1);return}});let Y=async e=>{let i=e.trim();if(!i||M||H)return;j(``),z(null),m(e=>[...e,{role:`user`,content:i}]),K.current=``,F(``),L([]),G(0),N(!0),q.current=new AbortController;let a=setTimeout(()=>{q.current?.abort(),z(`Request timed out after ${D/1e3}s`)},D);try{let e=p.map(e=>({role:e.role,content:e.content}));e.push({role:`user`,content:i});let a=await t.openAiStream(`mcp`,{messages:e,siteId:r},q.current.signal);if(!a.ok){z(`MCP request failed (${a.status})`);return}let o=0,s=new Map;for await(let e of c(a))if(e.type===`delta`)K.current+=e.content;else if(e.type===`tool_call`)s.set(e.id,e.arguments),o+=1,G(o),n(`mcp.tool_call`,{properties:{tool_name:e.name}}),L(t=>[...t,{id:e.id,name:e.name,argsPreview:k(e.arguments),status:`running`}]);else if(e.type===`tool_start`){let t=s.get(e.id);L(r=>r.some(t=>t.id===e.id)?r:(o+=1,G(o),n(`mcp.tool_call`,{properties:{tool_name:e.name}}),[...r,{id:e.id,name:e.name,argsPreview:k(t),status:`running`}]))}else if(e.type===`tool_result`)L(t=>t.map(t=>t.id===e.id?{...t,status:e.error?`error`:`done`,result:e.summary,error:e.error,name:e.name??t.name}:t));else if(e.type===`done`){let e=K.current;m(t=>[...t,{role:`assistant`,content:e||``}]),o>0&&!B&&U(!0);break}else if(e.type===`error`){z(e.message);break}}catch(e){e.name!==`AbortError`&&z(e.message??`unknown error`)}finally{clearTimeout(a),K.current=``,F(``),N(!1),q.current=null}},X=[`mcp`,i].filter(Boolean).join(` · `),Z=process.stdout.rows??40,Q=Math.max(4,Z-16),te=Math.max(20,(process.stdout.columns??80)-4),$=A(P,Q,te);return b.createElement(h,{flexDirection:`column`},b.createElement(l,{version:e,subtitle:X}),p.length===0&&!M?b.createElement(h,{marginTop:1,marginLeft:2,flexDirection:`column`},b.createElement(_,{color:s.muted},`Describe what you want to create or change. Examples:`),b.createElement(h,{marginTop:0,flexDirection:`column`},b.createElement(_,{color:s.dim},` · "Create a goal for newsletter signups"`),b.createElement(_,{color:s.dim},` · "Add a funnel: landing page → signup → dashboard"`),b.createElement(_,{color:s.dim},` · "Annotate today with our product launch"`),b.createElement(_,{color:s.dim},` · "Set up uptime monitoring for /api/health"`)),b.createElement(h,{marginTop:1},b.createElement(_,{color:s.dim},`MCP actions execute server-side. `),b.createElement(_,{color:s.warn},`Review each turn before continuing.`)),b.createElement(h,{marginTop:0,flexDirection:`row`},b.createElement(_,{color:s.accent},`[a]`),b.createElement(_,{color:s.dim},` allow-all · `),b.createElement(_,{color:s.accent},`[Esc]`),b.createElement(_,{color:s.dim},` close`))):null,b.createElement(g,{items:p},(e,t)=>b.createElement(h,{key:t,marginTop:1},b.createElement(u,{title:e.role===`user`?`you`:`Zenovay MCP`,pillColor:e.role===`user`?s.accent:s.info,state:`idle`},b.createElement(_,{color:s.fg,wrap:`wrap`},e.content)))),M?b.createElement(h,{flexDirection:`column`},I.length>0?b.createElement(h,{marginTop:1},b.createElement(u,{title:`Actions${B?` (allow-all)`:``}`,state:I.some(e=>e.status===`running`)?`busy`:`ok`},I.map(e=>b.createElement(h,{key:e.id,flexDirection:`column`,marginBottom:0},b.createElement(h,{flexDirection:`row`},b.createElement(_,{color:e.status===`error`?s.error:e.status===`done`?s.success:s.accent},e.status===`done`?`✓ `:e.status===`error`?`✗ `:`⋯ `),b.createElement(_,{color:s.fg,bold:!0},O(e.name))),e.argsPreview?b.createElement(h,{marginLeft:2},b.createElement(_,{color:s.dim},e.argsPreview)):null,e.status===`done`&&e.result?b.createElement(h,{marginLeft:2},b.createElement(_,{color:s.dim},`→ `,e.result.slice(0,80))):null,e.status===`error`&&e.error?b.createElement(h,{marginLeft:2},b.createElement(_,{color:s.error},`✗ `,e.error.slice(0,80))):null)))):null,P.length>0?b.createElement(h,{marginTop:1},b.createElement(u,{title:`Zenovay MCP`,pillColor:s.info,state:`busy`},$.clipped>0?b.createElement(_,{color:s.dim},` …${$.clipped} earlier line${$.clipped===1?``:`s`} above`):null,b.createElement(_,{color:s.fg,wrap:`wrap`},$.body))):I.every(e=>e.status!==`running`)||I.length===0?b.createElement(h,{marginTop:1,marginLeft:2,flexDirection:`row`},b.createElement(_,{color:s.accent},b.createElement(w,{type:`dots`})),b.createElement(_,{color:s.muted},` Planning actions…`)):null):null,H&&!M?b.createElement(h,{marginTop:1},b.createElement(u,{title:`Continue?`,state:`warn`,pillColor:s.warn},b.createElement(_,{color:s.muted},W,` action`,W===1?``:`s`,` executed this turn. Send another message?`),b.createElement(h,{marginTop:1,flexDirection:`row`},b.createElement(_,{color:s.success},`[Enter / y] `),b.createElement(_,{color:s.dim},`continue `),b.createElement(_,{color:s.error},`[n] `),b.createElement(_,{color:s.dim},`cancel `),b.createElement(_,{color:s.accent},`[a] `),b.createElement(_,{color:s.dim},`allow-all this session `),b.createElement(_,{color:s.warn},`[x] `),b.createElement(_,{color:s.dim},`abort`)))):null,R?b.createElement(h,{marginTop:1,marginLeft:2},b.createElement(_,{color:s.error},`✗ `,R)):null,b.createElement(h,{marginTop:1,marginLeft:2,flexDirection:`column`},b.createElement(h,{flexDirection:`row`},b.createElement(_,{color:M||H?s.dim:s.accent},M?`⋯ `:H?`? `:`> `),b.createElement(T,{value:v,onChange:j,onSubmit:e=>void Y(e),placeholder:M?`executing…`:H?`press Enter to continue, n to cancel…`:`describe what to create or change…`})),b.createElement(h,{marginTop:1,flexDirection:`row`},b.createElement(_,{color:s.dim},`[Enter] send [a] allow-all [x] abort [Esc] close`),B?b.createElement(_,{color:s.success},` ● allow-all`):null)))};async function M(e){if((s(e)||!process.stdin.isTTY)&&e.mode!==`install`)return o({type:`error`,code:`interactive_only`,message:`zenovay ai is interactive; run without --json in a TTY`}),2;let t=await i(e.cwd),n;if(e.mode)n=e.mode;else if(!t.installed)n=`install`;else if(s(e))return o({type:`error`,code:`no_mode`,message:`Headless mode requires --mode chat|mcp|install`}),2;else n=await N(t,e.cliVersion);return n===`install`?a({cliVersion:e.cliVersion,cwd:e.cwd,json:e.json}):n===`chat`?P(e):F(e)}async function N(e,t){return new Promise(n=>{let r=[{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`}],i=e.packageMarker?`detected · ${e.packageMarker}`:`detected`,{unmount:a}=v(b.createElement(h,{flexDirection:`column`},b.createElement(l,{version:t,subtitle:`ai · ${i}`,live:!1}),b.createElement(h,{marginTop:1},b.createElement(u,{title:`Zenovay AI assistant`,state:`idle`},b.createElement(_,null,`What do you want to do?`))),b.createElement(h,{marginTop:1},b.createElement(f,{items:r,onSelect:e=>{a(),n(e)}}))))})}async function P(n){let i=await e(),a=await t({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:n.cliVersion,token:a});return new Promise(e=>{let{unmount:t}=v(b.createElement(p,{cliVersion:n.cliVersion,api:c,dashboardContext:{commandName:`ai chat`,siteId:o,siteLabel:s,metricsSnapshot:null},onClose:()=>{t(),e(0)}}))})}async function F(n){let i=await e(),a=await t({strict:!1});if(!a)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let o=new r({config:i,cliVersion:n.cliVersion,token:a}),s,c;try{let e=await m(o,{explicit:void 0,headless:!1,cliVersion:n.cliVersion});s=e.siteId,c=e.site?.url?e.site.url.replace(/^https?:\/\//,``).replace(/\/$/,``):e.site?.name??s}catch{}return new Promise(e=>{let{unmount:t}=v(b.createElement(j,{cliVersion:n.cliVersion,api:o,siteId:s,siteLabel:c,onClose:()=>{t(),e(0)}}))})}export{M as aiCommand};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config-JVhBplSX.js";import"./api-CdcB84ie.js";import{readToken as t}from"./token-store-BvSCse1t.js";import{emitErrorEnvelope as n}from"./error-codes-ByhvHx2M.js";import{ApiV2Client as r}from"./api-v2-D0mvt__4.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";import"./theme-Brz9wK0w.js";import{Banner as c,Panel as l,useTheme as u}from"./panel-CTtQ2ue6.js";import"./prompt-BXvg2B4R.js";import{resolveSiteId as d}from"./resolve-site-BTVBMF1C.js";import{fmtDate as f,shortId as p}from"./fmt-xxIPQJX-.js";import{DataTable as m}from"./data-table-BhKjjiOS.js";import{EmptyState as h}from"./empty-state-D-krMX62.js";import{Box as g,Text as _,render as v}from"ink";import y from"react";const b=new Set([`visitors`,`pageviews`,`bounce_rate`,`avg_session_duration`,`errors`,`lcp`,`inp`,`cls`,`uptime`,`revenue`]),x=/^\d+(m|h|d)$/;function S(e){let t=e.metric;if(!t)return{errorMessage:"--metric is required for `alerts create`."};if(!b.has(t))return{errorMessage:`--metric must be one of: ${[...b].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||!x.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 C(c){let l=await e(),u=await t({strict:!1}),f=new r({config:l,cliVersion:c.cliVersion,token:u}),m,h;try{({siteId:m,site:h}=await d(f,{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)}let g=h?.url?h.url.replace(/^https?:\/\//,``).replace(/\/$/,``):h?.name??m;try{switch(c.action){case`list`:{let e=await f.listAlerts(m);return c.json?(a(s(e,`alerts.list`,{siteId:m,cliVersion:c.cliVersion,command:`alerts list`})),0):E(e,g,c.cliVersion)}case`create`:{let e=S(c);if(`errorMessage`in e)return c.json?n(new w(e.errorMessage),{command:`alerts create`,cliVersion:c.cliVersion}):(process.stderr.write(`Error: ${e.errorMessage}\n`),2);let t=await f.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 w(e),{command:`alerts delete`,cliVersion:c.cliVersion}):(process.stderr.write(`Error: ${e}\n`),2)}let e;try{let t=await f.listAlerts(m);e=t.find(e=>e.id===c.id)}catch{}let t=e?`${e.metric} ${e.op} ${e.threshold} (${p(c.id)})`:p(c.id),r=await i({resource:`alert`,name:t,yes:c.yes,destructive:!0});return r?(await f.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 (${p(c.id)}). Notifications stopped immediately.\n`),0)):c.json?(process.stdout.write(JSON.stringify({cancelled:!0})+`
|
|
2
2
|
`),1):(process.stdout.write(`Cancelled.
|
|
3
3
|
`),1)}}}catch(e){return c.json?n(e,{command:`alerts ${c.action}`,cliVersion:c.cliVersion}):(process.stderr.write(`✗ ${e.message}\n`),1)}}var w=class extends Error{constructor(e){super(e),this.name=`ValidationError`}};const T=({items:e,siteLabel:t,cliVersion:n})=>{let{theme:r}=u(),i=[{key:`id`,label:`id`,width:14,format:e=>p(String(e))},{key:`metric`,label:`metric`,width:18},{key:`op`,label:`op`,width:4,format:e=>e===`gt`?`>`:e===`lt`?`<`:String(e??``)},{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=>f(e)}];if(e.length===0)return y.createElement(g,{flexDirection:`column`},y.createElement(c,{version:n,subtitle:`alerts · ${t}`,live:!1}),y.createElement(h,{reason:`no-data`,headline:`No alerts yet`,hint:"Create one with `zenovay alerts create --metric <m> --op <gt|lt> --threshold <n> --window <1h>`."}));let a=process.stdout.rows??40,o=Math.max(5,a-10),s=e.slice(0,o),d=e.length-s.length;return y.createElement(g,{flexDirection:`column`},y.createElement(c,{version:n,subtitle:`alerts · ${t}`,live:!0}),y.createElement(l,{title:`${e.length} alert${e.length===1?``:`s`}`,state:`idle`},y.createElement(m,{columns:i,data:s,zebra:!0}),d>0?y.createElement(_,{color:r.dim},` +${d} more · run with --json for all`):null))};function E(e,t,n){return new Promise(r=>{let i=v(y.createElement(T,{items:e,siteLabel:t,cliVersion:n}));setTimeout(()=>{i.unmount(),r(0)},50)})}export{C as alertsCommand};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ApiError as e}from"./api-
|
|
1
|
+
import{ApiError as e}from"./api-CdcB84ie.js";import{buildErrorEnvelope as t}from"./error-codes-ByhvHx2M.js";import{formatEvent as n}from"./formatter-C4YSOKuq.js";import{Banner as r,Panel as i,useTheme as a}from"./panel-CTtQ2ue6.js";import{Keybar as o}from"./keybar-DO5OoZy9.js";import{ChatPanel as s}from"./chat-panel-D9IjovCR.js";import{ResponsiveGrid as c}from"./grid-CMwhs-Ms.js";import{useFullscreen as l}from"./use-fullscreen-ucSyZkjO.js";import{DEFAULT_WINDOWS as u,RangeTabs as d,rangeForKey as f}from"./range-tabs-BbJdVWNV.js";import{Box as p,Text as m,render as h,useApp as g,useInput as _}from"ink";import v,{useEffect as y,useMemo as b,useReducer as x,useRef as S,useState as C}from"react";import w from"ink-spinner";function T(e,t){switch(t.type){case`set`:return{...e,data:t.data,status:`ready`,error:null,refreshing:!1,lastFetched:Date.now()};case`merge`:{let n=e.data?{...e.data,...t.partial}:t.partial;return{...e,data:n,status:`ready`,error:null,refreshing:!1,lastFetched:Date.now()}}case`fetching`:return e.data===null?e:{...e,refreshing:!0};case`error`:return{...e,status:`error`,error:{message:t.message,status:t.status,upgradeUrl:t.upgradeUrl},refreshing:!1};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}}function E(e,t){let n=Math.max(0,Math.round((t-e)/1e3));if(n<5)return`just now`;if(n<60)return`${n}s ago`;let r=Math.floor(n/60);return r<60?`${r}m ago`:`${Math.floor(r/60)}h ago`}function D(e){return e.replace(/\b[A-Z]+\s+\/v1\/cli\/\S*(?:\s+→\s+\d{3})?/g,``).replace(/\/v1\/cli\/\S*/g,``).replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi,``).replace(/\s{2,}/g,` `).trim()}function O(n,r){let i=t(n,{command:r});if(n instanceof e){let e={400:{message:`The request was rejected — check the command flags and arguments.`},404:{message:`The requested site or resource was not found.`,hint:"Run `zenovay domains` to list available domains."}},t=e[n.status];if(t)return i.message=t.message,t.hint?i.hint=t.hint:i.code===`validation_failed`&&!i.hint&&(i.hint=`Check the command flags and arguments.`),i}return i.message=D(i.message)||`The request failed.`,i.hint&&=D(i.hint),i}async function k(e,t){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,t):process.stdout.write(n(i,t)),e.streamer)for await(let i of e.streamer(r.signal))process.stdout.write(n(i,t));return 0}catch(r){if(r.name===`AbortError`)return 0;let i=O(r,e.commandName);return t===`json`?process.stdout.write(JSON.stringify(i,null,2)+`
|
|
2
2
|
`):process.stdout.write(n(i,t)),1}finally{process.off(`SIGINT`,i)}}const A=({cliVersion:e})=>{let{theme:t}=a();return v.createElement(p,{flexDirection:`column`},v.createElement(r,{version:e,subtitle:`login required`}),v.createElement(i,{title:`Not logged in`,state:`warn`},v.createElement(m,null,`You need to authenticate before running this command.`),v.createElement(m,null,` `),v.createElement(m,{color:t.muted},`Run `),v.createElement(m,{color:t.accent},`zenovay login`),v.createElement(m,{color:t.muted},` to start the device-flow.`)))};function j(t){l();let{exit:n}=g(),{theme:h}=a(),[O,k]=x(T,{data:null,status:`loading`,error:null,refreshTick:0,focusIndex:0,showHelp:!1,refreshing:!1,lastFetched:null}),[A,j]=C(()=>Date.now()),[M,N]=C(!1),P=typeof t.ranges==`object`?t.ranges.windows:u,[F,I]=C(P[0]??`24h`),L=S(k);L.current=k;let R=b(()=>{let e={q:{label:`quit`,handler:()=>{n(),t.onExit(0)}},r:{label:`refresh`,handler:()=>L.current({type:`refresh`})},"?":{label:`help`,handler:()=>L.current({type:`help-toggle`})}};return t.ai&&(e[`/`]={label:`ask AI`,handler:()=>N(!0)}),e},[n,t]),z=b(()=>({...t.keybindings??{},...R}),[t.keybindings,R]);_((e,n)=>{if(M)return;if(n.tab&&n.shift){k({type:`focus`,index:(O.focusIndex-1+t.panels.length)%t.panels.length});return}if(n.tab){k({type:`focus`,index:(O.focusIndex+1)%t.panels.length});return}if(t.ranges){let t=f(e,P);if(t){I(t);return}}if(e>=`1`&&e<=`9`){let n=Number(e)-1;n<t.panels.length&&k({type:`focus`,index:n});return}let r=z[e];r&&r.handler()}),y(()=>{let n=new AbortController,r=!1,i=async()=>{L.current({type:`fetching`});try{let e=await t.fetcher(n.signal,F);r||L.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;L.current({type:`error`,message:`This command requires a higher plan.`,status:402,upgradeUrl:n});return}L.current({type:`error`,message:D(t.message)||`The request failed.`,status:t.status});return}if(t.name===`AbortError`)return;L.current({type:`error`,message:D(t.message)||`The request failed.`})}};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,O.refreshTick,F]),y(()=>{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;L.current({type:`merge`,partial:r})}}catch(e){if(n||e.name===`AbortError`)return;L.current({type:`error`,message:D(e.message)||`The request failed.`})}})(),()=>{n=!0,e.abort()}},[t.streamer]);let B=(t.refreshIntervalMs??15e3)>0&&!t.streamer;y(()=>{if(M||!B)return;let e=setInterval(()=>j(Date.now()),5e3);return()=>clearInterval(e)},[M,B]);let V=t.ranges?`${t.title} · ${F}`:t.title;if(M&&t.ai)return v.createElement(s,{cliVersion:t.cliVersion,api:t.ai.api,dashboardContext:{commandName:t.commandName,siteId:t.ai.siteId,siteLabel:t.ai.siteLabel,metricsSnapshot:O.data},onClose:()=>N(!1)});if(O.status===`loading`&&O.data===null)return v.createElement(p,{flexDirection:`column`},v.createElement(r,{version:t.cliVersion,subtitle:V}),v.createElement(i,{title:`Loading`,state:`busy`},v.createElement(p,null,v.createElement(m,{color:h.accent},v.createElement(w,{type:`dots`})),v.createElement(m,null,` Fetching `,t.commandName,`…`))),v.createElement(o,{items:[{key:`q`,label:`quit`}]}));if(O.status===`error`&&O.error){let e=O.error.status===402;return v.createElement(p,{flexDirection:`column`},v.createElement(r,{version:t.cliVersion,subtitle:V}),v.createElement(i,{title:e?`Upgrade required`:`Error`,state:e?`warn`:`err`},v.createElement(m,{color:e?h.warn:h.error},O.error.message),e&&O.error.upgradeUrl?v.createElement(v.Fragment,null,v.createElement(m,null,` `),v.createElement(m,{color:h.muted},`Upgrade: `),v.createElement(m,{color:h.accent},O.error.upgradeUrl)):null),v.createElement(o,{items:[{key:`r`,label:`retry`},{key:`q`,label:`quit`}]}))}let H=O.data,U=Object.entries(z).map(([e,t])=>({key:e,label:t.label})),W=process.stdout.columns??80,G=t.panels.map((e,t)=>({key:e.id,title:e.title,state:O.focusIndex===t?`busy`:`idle`,render:()=>e.render(H,O.focusIndex===t)}));return v.createElement(p,{flexDirection:`column`},v.createElement(r,{version:t.cliVersion,subtitle:V}),t.ranges?v.createElement(d,{range:F,windows:P}):null,v.createElement(p,{marginTop:1},v.createElement(c,{totalWidth:W,panels:G,minColWidth:36,maxCols:2,gap:2})),O.showHelp?v.createElement(i,{title:`Help`,state:`idle`},Object.entries(z).map(([e,t])=>v.createElement(m,{key:e},`[`,e,`] `,t.label)),v.createElement(m,{color:h.muted},`[tab/shift+tab] cycle focus [1-9] focus panel`)):null,v.createElement(p,{marginTop:1},v.createElement(m,{color:h.dim},O.refreshing?`↻ refreshing…`:O.lastFetched===null?``:`↻ updated ${E(O.lastFetched,A)} · [r] refresh`)),v.createElement(o,{items:U,active:`r`}))}async function M(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}=h(v.createElement(A,{cliVersion:e.cliVersion}));setTimeout(()=>{n(),t(2)},50)}):e.format?k(e,e.format):new Promise(t=>{let{unmount:n}=h(v.createElement(j,{...e,onExit:e=>{n(),t(e)}}))})}export{M as runAnalyticalScreen};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{readConfig as e,updateConfig as t}from"./config
|
|
2
|
-
`);return 0}return a({type:`overview.snapshot`,data:e}),0}catch(e){let{emitErrorEnvelope:n}=await import(`./error-codes-DpKbL-uM.js`);return n(e,{command:`analytics`,cliVersion:t.cliVersion})}return new Promise(e=>{let{unmount:n}=b(x.createElement(D,{api:c,siteId:l,siteLabel:d,siteSlug:u?.slug??null,cliVersion:t.cliVersion,onExit:t=>{n(),e(t)}}))})}const de=[{key:`1`,value:`24h`},{key:`2`,value:`7d`},{key:`3`,value:`30d`},{key:`4`,value:`90d`}];function fe(e,t){let n=Math.max(0,Math.round((t-e)/1e3));if(n<5)return`just now`;if(n<60)return`${n}s ago`;let r=Math.floor(n/60);return r<60?`${r}m ago`:`${Math.floor(r/60)}h ago`}function E(e){return e===`24h`?`7d`:e}async function pe(e,t,n){let[r,i,a,o,s]=await Promise.all([w(e.getStats(t,n),null),w(e.getPages(t,n),[]),e.getSources(t,E(n),`prev`).catch(()=>null),w(e.getGeo(t,n),null),w(e.getDevices(t,n),null)]),c=i.reduce((e,t)=>e+t.views,0),l=(r?.daily??[]).map(e=>e.visitors),u=(r?.daily??[]).map(e=>e.pageviews),d=(r?.daily??[]).map(e=>typeof e.bounceRate==`number`?e.bounceRate*100:0),f=(r?.daily??[]).map(e=>typeof e.avgSession==`number`?e.avgSession:0),p=Math.floor(l.length/2),m=l.slice(0,p).reduce((e,t)=>e+t,0),ee=u.slice(0,p).reduce((e,t)=>e+t,0),h=e=>[...e].sort((e,t)=>t.visitors-e.visitors),g=h((a?.sources??[]).filter(e=>e.channel!==`other`||!e.source.includes(`/`))).slice(0,50).map(e=>({name:e.source,visitors:e.visitors,delta:e.delta??null}));return{visitors:r?.visitors??0,pageviews:r?.pageviews??c,bounceRate:r?.bounceRate??null,avgSession:r?.avgSessionSec??null,series:l,pageviewsSeries:u,bounceSeries:d,sessionSeries:f,prevVisitors:m,prevPageviews:ee,topPages:i.slice(0,100),channels:g,countries:h(o?.countries??[]).slice(0,50),browsers:h(s?.browsers??[]).slice(0,50),devices:h(s?.devices??[]).slice(0,50)}}const D=({api:e,siteId:n,siteLabel:r,siteSlug:i,cliVersion:a,onExit:o})=>{oe();let{exit:m}=se(),{theme:b}=u(),[C,w]=S(null),[T,E]=S(!0),[D,me]=S(null),[O,k]=S(`24h`),[A,j]=S(!1),[M,he]=S(n),[N,ge]=S(r),[_e,ve]=S(i??null),[P,F]=S(!1),[I,ye]=S([]),[be,L]=S(0),[xe,R]=S(!1),[z,Se]=S(null),[Ce,we]=S(()=>Date.now()),[B,V]=S(null),[Te,H]=S(0),[U,Ee]=S(!1);le(()=>{if(U)return;let e=setInterval(()=>we(Date.now()),5e3),t=setInterval(()=>L(e=>e+1),15e3);return()=>{clearInterval(e),clearInterval(t)}},[U]),ce(async(t,n)=>{if(!U){if(P){(n.escape||t===`s`)&&F(!1);return}if(B){if(n.escape||t===`q`){V(null),H(0);return}if(n.upArrow||t===`k`){H(e=>Math.max(0,e-1));return}if(n.downArrow||t===`j`){H(e=>e+1);return}if(n.pageUp){H(e=>Math.max(0,e-10));return}if(n.pageDown){H(e=>e+10);return}return}if(t===`/`){Ee(!0);return}if(t===`r`||t===`R`){L(e=>e+1);return}if(t===`o`||t===`O`){s(ae(`overview`,{siteId:M,siteSlug:_e}));return}if(t===`q`){m(),o(0);return}if(t===`1`){j(!1),k(`24h`);return}if(t===`2`){j(!1),k(`7d`);return}if(t===`3`){j(!1),k(`30d`);return}if(t===`4`){j(!1),k(`90d`);return}if(!P){if(t===`c`){H(0),V(`channels`);return}if(t===`g`){H(0),V(`countries`);return}if(t===`b`){H(0),V(`browsers`);return}if(t===`d`){H(0),V(`devices`);return}if(t===`p`){H(0),V(`pages`);return}}if(t===`s`){if(I.length===0)try{let t=await e.getSites();ye(t)}catch{}F(e=>!e);return}}}),le(()=>{let t=!1;return C===null?E(!0):R(!0),(async()=>{try{let n=await pe(e,M,O);if(t)return;let r=n.visitors===0&&n.pageviews===0&&n.topPages.length===0;if(r&&O===`24h`&&!A){j(!0),k(`7d`);return}w(n),E(!1),R(!1),Se(Date.now())}catch(e){t||(me(e.message),E(!1),R(!1))}})(),()=>{t=!0}},[e,M,O,be]);let De=e=>{he(e.id),ge(e.url.replace(/^https?:\/\//,``).replace(/\/$/,``)),ve(e.slug??null),F(!1),w(null),t({defaultSiteId:e.id,defaultSiteName:e.name})},W=()=>x.createElement(l,{title:`Switch site`,state:`idle`},I.length===0?x.createElement(y,{color:b.muted},`Loading your sites…`):x.createElement(d,{items:I.map(e=>({label:`${e.name} · ${e.url.replace(/^https?:\/\//,``).replace(/\/$/,``)}${e.id===M?` (current)`:``}`,value:e})),onSelect:De}),x.createElement(v,{marginTop:1},x.createElement(y,{color:b.dim},`[↑↓ navigate] · [enter] select · [s/esc] close`))),G=`overview · ${N} · ${O}${A?` (auto)`:``}`,K=[{key:`/`,label:`AI chat`},{key:`r`,label:`refresh`},{key:`s`,label:`site`},{key:`o`,label:`browser`},{key:`q`,label:`quit`}];if(U)return x.createElement(p,{cliVersion:a,api:e,dashboardContext:{commandName:`overview`,siteId:M,siteLabel:N,metricsSnapshot:C},onClose:()=>Ee(!1)});if(T)return x.createElement(v,{flexDirection:`column`},x.createElement(c,{version:a,subtitle:G,live:!1}),x.createElement(l,{title:`Loading`,state:`busy`},x.createElement(v,null,x.createElement(y,{color:b.accent},x.createElement(ue,{type:`dots`})),x.createElement(y,null,` Fetching dashboard…`))),P?W():null);if(D)return x.createElement(v,{flexDirection:`column`},x.createElement(c,{version:a,subtitle:G,live:!1}),x.createElement(g,{reason:`error`,headline:`Failed to load`,hint:D}),P?W():null,x.createElement(f,{items:K}));if(!C||C.visitors===0&&C.pageviews===0&&C.topPages.length===0)return x.createElement(v,{flexDirection:`column`},x.createElement(c,{version:a,subtitle:G,live:!1}),x.createElement(g,{reason:`no-data`,headline:`No data yet`,hint:A?`No data in 7d either. Visit your site to send the first event — press [s] to switch site.`:`Visit your site to send the first event, or press [3] for 30d / [4] for 90d to widen the window.`}),P?W():null,x.createElement(f,{items:K}));let q=process.stdout.columns??80,J=re(q,4,2),Y=process.stdout.rows??40,Oe=Math.max(10,Y-32),X=Math.max(3,Math.min(7,Math.floor((Oe-4)/2))),Z=Math.max(4,Math.min(14,Oe-2*X)),ke=[{key:`path`,label:`path`,width:32,format:e=>ee(String(e??``))},{key:`views`,label:`views`,align:`right`,width:8},{key:`uniqueVisitors`,label:`visitors`,align:`right`,width:8},{key:`avgTime`,label:`avg time`,align:`right`,width:9,format:e=>typeof e==`number`?`${Math.round(e)}s`:`—`},{key:`bounceRate`,label:`bounce`,align:`right`,width:7,format:e=>typeof e==`number`?`${(e*100).toFixed(0)}%`:`—`}],Ae=C.prevVisitors>0?(C.visitors-C.prevVisitors)/C.prevVisitors:void 0,je=C.prevPageviews>0?(C.pageviews-C.prevPageviews)/C.prevPageviews:void 0,Me=Math.max(1,...C.channels.map(e=>e.visitors)),Ne=Math.max(1,...C.countries.map(e=>e.visitors)),Pe=Math.max(1,...C.browsers.map(e=>e.visitors)),Fe=Math.max(1,...C.devices.map(e=>e.visitors)),Ie=(e,t,n,r,i,a)=>{let o=Math.max(6,a-n-1-9);return x.createElement(v,{key:e,flexDirection:`row`},x.createElement(v,{width:n,marginRight:1},x.createElement(y,{wrap:`truncate`},t)),x.createElement(ie,{value:r,max:i,width:o,showPercent:!1,track:!0}),x.createElement(v,{flexGrow:1,justifyContent:`flex-end`},x.createElement(y,{color:b.fg},r.toLocaleString())))},Le=[{key:`channels`,hotkey:`c`,title:`Channels`,labelWidth:16,display:X,max:Me,rows:C.channels.map(e=>({label:e.name,value:e.visitors}))},{key:`countries`,hotkey:`g`,title:`Top countries`,labelWidth:5,display:X,max:Ne,rows:C.countries.map(e=>({label:e.country,value:e.visitors}))},{key:`browsers`,hotkey:`b`,title:`Top browsers`,labelWidth:16,display:X,max:Pe,rows:C.browsers.map(e=>({label:e.name,value:e.visitors}))},{key:`devices`,hotkey:`d`,title:`Top devices`,labelWidth:16,display:X,max:Fe,rows:C.devices.map(e=>({label:e.name,value:e.visitors}))}],Re=Le.filter(e=>e.rows.length>0).map(e=>({key:e.key,title:e.title,render:t=>{let n=e.rows.slice(0,X),r=e.rows.length-n.length,i=Math.max(0,X-n.length);return x.createElement(x.Fragment,null,n.map((n,r)=>Ie(`${e.key}-${r}`,n.label,e.labelWidth,n.value,e.max,t)),Array.from({length:i},(e,t)=>x.createElement(v,{key:`pad-${t}`,height:1})),x.createElement(y,{color:b.dim},r>0?` +${r} more · [${e.hotkey}] expand`:` `))}})),Q=Math.max(5,Y-9),$=e=>{let t=Math.max(0,e-Q),n=Math.min(Te,t),r=Math.min(e,n+Q);return{from:n,window:Q,label:e>Q?` ${n+1}-${r} of ${e} · ↑↓ scroll`:` ${e} total`}};if(B===`pages`){let e=C.topPages.length,t=$(e);return x.createElement(v,{flexDirection:`column`},x.createElement(c,{version:a,subtitle:`pages · ${N} · ${O}`,live:!1}),x.createElement(v,{marginTop:1},x.createElement(l,{title:`Top pages — all ${e}`},e===0?x.createElement(y,{color:b.muted},`No pages with data in this window yet.`):x.createElement(x.Fragment,null,x.createElement(h,{columns:ke,data:C.topPages.slice(t.from,t.from+t.window),zebra:!0}),x.createElement(y,{color:b.dim},t.label)))),x.createElement(f,{items:[{key:`↑↓`,label:`scroll`},{key:`esc`,label:`back`},{key:`q`,label:`quit`}],active:`↑↓`}))}if(B){let e=Le.find(e=>e.key===B);if(e){let t=Math.min(q,84),n=$(e.rows.length);return x.createElement(v,{flexDirection:`column`},x.createElement(c,{version:a,subtitle:`${e.title.toLowerCase()} · ${N} · ${O}`,live:!1}),x.createElement(v,{marginTop:1},x.createElement(l,{title:`${e.title} — all ${e.rows.length}`,width:t},e.rows.length===0?x.createElement(y,{color:b.muted},`No data.`):x.createElement(x.Fragment,null,e.rows.slice(n.from,n.from+n.window).map((r,i)=>Ie(`x-${n.from+i}`,r.label,e.labelWidth,r.value,e.max,ne(t))),x.createElement(y,{color:b.dim},n.label)))),x.createElement(f,{items:[{key:`↑↓`,label:`scroll`},{key:`esc`,label:`back`},{key:`q`,label:`quit`}],active:`↑↓`}))}}return x.createElement(v,{flexDirection:`column`},x.createElement(c,{version:a,subtitle:G,live:!0}),x.createElement(v,{flexDirection:`row`,marginTop:1},de.map(e=>{let t=e.value===O;return x.createElement(v,{key:e.value,flexDirection:`row`,marginRight:3},x.createElement(y,{color:b.dim},e.key,` `),x.createElement(y,{color:t?b.accent:b.muted,bold:t},e.value))}),A?x.createElement(y,{color:b.dim},` (auto)`):null),x.createElement(v,{flexDirection:`row`,marginTop:1},x.createElement(_,{title:`Visitors`,value:C.visitors,format:`number`,width:J[0],gap:2,series:C.series,...typeof Ae==`number`?{delta:Ae}:{}}),x.createElement(_,{title:`Pageviews`,value:C.pageviews,format:`number`,width:J[1],gap:2,series:C.pageviewsSeries,...typeof je==`number`?{delta:je}:{}}),x.createElement(_,{title:`Bounce rate`,value:C.bounceRate??``,emptyHint:`—`,format:`percent`,width:J[2],gap:2,series:C.bounceSeries}),x.createElement(_,{title:`Avg session`,value:C.avgSession??``,emptyHint:`—`,format:`duration`,width:J[3],gap:0,series:C.sessionSeries})),Re.length>0&&x.createElement(v,{marginTop:1},x.createElement(te,{totalWidth:q,panels:Re,minColWidth:40,maxCols:2,gap:2})),x.createElement(v,{marginTop:1},x.createElement(l,{title:`Top pages (${O})`},C.topPages.length===0?x.createElement(y,{color:b.muted},`No pages with data in this window yet.`):x.createElement(x.Fragment,null,x.createElement(h,{columns:ke,data:C.topPages.slice(0,Z),zebra:!0}),C.topPages.length>Z?x.createElement(y,{color:b.dim},` +${C.topPages.length-Z} more · [p] expand`):null))),P?W():null,x.createElement(v,{marginTop:1},x.createElement(y,{color:b.dim},xe?`↻ refreshing…`:z===null?``:`↻ updated ${fe(z,Ce)} · [r] refresh`)),x.createElement(f,{items:K}))};async function me(e){return T(e)}export{me as analyticsCommand};
|
|
1
|
+
import{readConfig as e,updateConfig as t}from"./config-JVhBplSX.js";import{ApiError as n}from"./api-CdcB84ie.js";import{readToken as r}from"./token-store-BvSCse1t.js";import"./telemetry-BV-xvfdt.js";import{ApiV2Client as i}from"./api-v2-D0mvt__4.js";import"./formatter-C4YSOKuq.js";import{emit$1 as a,isHeadless as o}from"./emit-D4YlMlzk.js";import{openInBrowser as s}from"./open-url-BtI5aLgL.js";import"./client-ntsEXSVC.js";import"./theme-Brz9wK0w.js";import{Banner as c,Panel as l,useTheme as u}from"./panel-CTtQ2ue6.js";import{Select as d}from"./prompt-BXvg2B4R.js";import{Keybar as f}from"./keybar-DO5OoZy9.js";import"./sparkline-CpoBjjlc.js";import{ChatPanel as p}from"./chat-panel-D9IjovCR.js";import{resolveSiteId as m}from"./resolve-site-BTVBMF1C.js";import{stripUrlPrefix as ee}from"./fmt-xxIPQJX-.js";import{DataTable as h}from"./data-table-BhKjjiOS.js";import{EmptyState as g}from"./empty-state-D-krMX62.js";import{ResponsiveGrid as te,panelInnerWidth as ne,tileWidths as re}from"./grid-CMwhs-Ms.js";import{MetricCard as _}from"./metric-card-C4iqxdww.js";import{Bar as ie}from"./bar-NfgovYHe.js";import{deepLinkFor as ae}from"./keybar-deep-link-B4VJn2ko.js";import{useFullscreen as oe}from"./use-fullscreen-ucSyZkjO.js";import{Box as v,Text as y,render as b,useApp as se,useInput as ce}from"ink";import x,{useEffect as le,useState as S}from"react";import ue from"ink-spinner";function C(e){if(!(e instanceof n))return!1;let t=e.status;if(t===401||t===403||t===404)return!0;let r=e.body,i=r?.code;return i===`forbidden`||i===`not_found`||i===`auth_required`||i===`auth_invalid`||i===`tier_insufficient`}function w(e,t){return e.catch(e=>{if(C(e))throw e;return t})}async function T(t){let n=await e(),s=await r({strict:!1});if(!s)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let c=new i({config:n,cliVersion:t.cliVersion,token:s}),l,u;try{({siteId:l,site:u}=await m(c,{explicit:t.siteId,headless:!!t.json,cliVersion:t.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let d=u?.url?u.url.replace(/^https?:\/\//,``).replace(/\/$/,``):u?.name??l;if(o(t))try{let e=await pe(c,l,`24h`);if(t.csv||t.tsv){let{writeCsv:n}=await import(`./csv-emit-CmlDBfbA.js`);return n(e.topPages,[`path`,`views`,`uniqueVisitors`,`avgTime`,`bounceRate`],t.tsv?`tsv`:`csv`)}if(t.ndjson){for(let t of e.topPages)process.stdout.write(JSON.stringify(t)+`
|
|
2
|
+
`);return 0}return a({type:`overview.snapshot`,data:e}),0}catch(e){let{emitErrorEnvelope:n}=await import(`./error-codes-BiKo9PGm.js`);return n(e,{command:`analytics`,cliVersion:t.cliVersion})}return new Promise(e=>{let{unmount:n}=b(x.createElement(D,{api:c,siteId:l,siteLabel:d,siteSlug:u?.slug??null,cliVersion:t.cliVersion,onExit:t=>{n(),e(t)}}))})}const de=[{key:`1`,value:`24h`},{key:`2`,value:`7d`},{key:`3`,value:`30d`},{key:`4`,value:`90d`}];function fe(e,t){let n=Math.max(0,Math.round((t-e)/1e3));if(n<5)return`just now`;if(n<60)return`${n}s ago`;let r=Math.floor(n/60);return r<60?`${r}m ago`:`${Math.floor(r/60)}h ago`}function E(e){return e===`24h`?`7d`:e}async function pe(e,t,n){let[r,i,a,o,s]=await Promise.all([w(e.getStats(t,n),null),w(e.getPages(t,n),[]),e.getSources(t,E(n),`prev`).catch(()=>null),w(e.getGeo(t,n),null),w(e.getDevices(t,n),null)]),c=i.reduce((e,t)=>e+t.views,0),l=(r?.daily??[]).map(e=>e.visitors),u=(r?.daily??[]).map(e=>e.pageviews),d=(r?.daily??[]).map(e=>typeof e.bounceRate==`number`?e.bounceRate*100:0),f=(r?.daily??[]).map(e=>typeof e.avgSession==`number`?e.avgSession:0),p=Math.floor(l.length/2),m=l.slice(0,p).reduce((e,t)=>e+t,0),ee=u.slice(0,p).reduce((e,t)=>e+t,0),h=e=>[...e].sort((e,t)=>t.visitors-e.visitors),g=h((a?.sources??[]).filter(e=>e.channel!==`other`||!e.source.includes(`/`))).slice(0,50).map(e=>({name:e.source,visitors:e.visitors,delta:e.delta??null}));return{visitors:r?.visitors??0,pageviews:r?.pageviews??c,bounceRate:r?.bounceRate??null,avgSession:r?.avgSessionSec??null,series:l,pageviewsSeries:u,bounceSeries:d,sessionSeries:f,prevVisitors:m,prevPageviews:ee,topPages:i.slice(0,100),channels:g,countries:h(o?.countries??[]).slice(0,50),browsers:h(s?.browsers??[]).slice(0,50),devices:h(s?.devices??[]).slice(0,50)}}const D=({api:e,siteId:n,siteLabel:r,siteSlug:i,cliVersion:a,onExit:o})=>{oe();let{exit:m}=se(),{theme:b}=u(),[C,w]=S(null),[T,E]=S(!0),[D,me]=S(null),[O,k]=S(`24h`),[A,j]=S(!1),[M,he]=S(n),[N,ge]=S(r),[_e,ve]=S(i??null),[P,F]=S(!1),[I,ye]=S([]),[be,L]=S(0),[xe,R]=S(!1),[z,Se]=S(null),[Ce,we]=S(()=>Date.now()),[B,V]=S(null),[Te,H]=S(0),[U,Ee]=S(!1);le(()=>{if(U)return;let e=setInterval(()=>we(Date.now()),5e3),t=setInterval(()=>L(e=>e+1),15e3);return()=>{clearInterval(e),clearInterval(t)}},[U]),ce(async(t,n)=>{if(!U){if(P){(n.escape||t===`s`)&&F(!1);return}if(B){if(n.escape||t===`q`){V(null),H(0);return}if(n.upArrow||t===`k`){H(e=>Math.max(0,e-1));return}if(n.downArrow||t===`j`){H(e=>e+1);return}if(n.pageUp){H(e=>Math.max(0,e-10));return}if(n.pageDown){H(e=>e+10);return}return}if(t===`/`){Ee(!0);return}if(t===`r`||t===`R`){L(e=>e+1);return}if(t===`o`||t===`O`){s(ae(`overview`,{siteId:M,siteSlug:_e}));return}if(t===`q`){m(),o(0);return}if(t===`1`){j(!1),k(`24h`);return}if(t===`2`){j(!1),k(`7d`);return}if(t===`3`){j(!1),k(`30d`);return}if(t===`4`){j(!1),k(`90d`);return}if(!P){if(t===`c`){H(0),V(`channels`);return}if(t===`g`){H(0),V(`countries`);return}if(t===`b`){H(0),V(`browsers`);return}if(t===`d`){H(0),V(`devices`);return}if(t===`p`){H(0),V(`pages`);return}}if(t===`s`){if(I.length===0)try{let t=await e.getSites();ye(t)}catch{}F(e=>!e);return}}}),le(()=>{let t=!1;return C===null?E(!0):R(!0),(async()=>{try{let n=await pe(e,M,O);if(t)return;let r=n.visitors===0&&n.pageviews===0&&n.topPages.length===0;if(r&&O===`24h`&&!A){j(!0),k(`7d`);return}w(n),E(!1),R(!1),Se(Date.now())}catch(e){t||(me(e.message),E(!1),R(!1))}})(),()=>{t=!0}},[e,M,O,be]);let De=e=>{he(e.id),ge(e.url.replace(/^https?:\/\//,``).replace(/\/$/,``)),ve(e.slug??null),F(!1),w(null),t({defaultSiteId:e.id,defaultSiteName:e.name})},W=()=>x.createElement(l,{title:`Switch site`,state:`idle`},I.length===0?x.createElement(y,{color:b.muted},`Loading your sites…`):x.createElement(d,{items:I.map(e=>({label:`${e.name} · ${e.url.replace(/^https?:\/\//,``).replace(/\/$/,``)}${e.id===M?` (current)`:``}`,value:e})),onSelect:De}),x.createElement(v,{marginTop:1},x.createElement(y,{color:b.dim},`[↑↓ navigate] · [enter] select · [s/esc] close`))),G=`overview · ${N} · ${O}${A?` (auto)`:``}`,K=[{key:`/`,label:`AI chat`},{key:`r`,label:`refresh`},{key:`s`,label:`site`},{key:`o`,label:`browser`},{key:`q`,label:`quit`}];if(U)return x.createElement(p,{cliVersion:a,api:e,dashboardContext:{commandName:`overview`,siteId:M,siteLabel:N,metricsSnapshot:C},onClose:()=>Ee(!1)});if(T)return x.createElement(v,{flexDirection:`column`},x.createElement(c,{version:a,subtitle:G,live:!1}),x.createElement(l,{title:`Loading`,state:`busy`},x.createElement(v,null,x.createElement(y,{color:b.accent},x.createElement(ue,{type:`dots`})),x.createElement(y,null,` Fetching dashboard…`))),P?W():null);if(D)return x.createElement(v,{flexDirection:`column`},x.createElement(c,{version:a,subtitle:G,live:!1}),x.createElement(g,{reason:`error`,headline:`Failed to load`,hint:D}),P?W():null,x.createElement(f,{items:K}));if(!C||C.visitors===0&&C.pageviews===0&&C.topPages.length===0)return x.createElement(v,{flexDirection:`column`},x.createElement(c,{version:a,subtitle:G,live:!1}),x.createElement(g,{reason:`no-data`,headline:`No data yet`,hint:A?`No data in 7d either. Visit your site to send the first event — press [s] to switch site.`:`Visit your site to send the first event, or press [3] for 30d / [4] for 90d to widen the window.`}),P?W():null,x.createElement(f,{items:K}));let q=process.stdout.columns??80,J=re(q,4,2),Y=process.stdout.rows??40,Oe=Math.max(10,Y-32),X=Math.max(3,Math.min(7,Math.floor((Oe-4)/2))),Z=Math.max(4,Math.min(14,Oe-2*X)),ke=[{key:`path`,label:`path`,width:32,format:e=>ee(String(e??``))},{key:`views`,label:`views`,align:`right`,width:8},{key:`uniqueVisitors`,label:`visitors`,align:`right`,width:8},{key:`avgTime`,label:`avg time`,align:`right`,width:9,format:e=>typeof e==`number`?`${Math.round(e)}s`:`—`},{key:`bounceRate`,label:`bounce`,align:`right`,width:7,format:e=>typeof e==`number`?`${(e*100).toFixed(0)}%`:`—`}],Ae=C.prevVisitors>0?(C.visitors-C.prevVisitors)/C.prevVisitors:void 0,je=C.prevPageviews>0?(C.pageviews-C.prevPageviews)/C.prevPageviews:void 0,Me=Math.max(1,...C.channels.map(e=>e.visitors)),Ne=Math.max(1,...C.countries.map(e=>e.visitors)),Pe=Math.max(1,...C.browsers.map(e=>e.visitors)),Fe=Math.max(1,...C.devices.map(e=>e.visitors)),Ie=(e,t,n,r,i,a)=>{let o=Math.max(6,a-n-1-9);return x.createElement(v,{key:e,flexDirection:`row`},x.createElement(v,{width:n,marginRight:1},x.createElement(y,{wrap:`truncate`},t)),x.createElement(ie,{value:r,max:i,width:o,showPercent:!1,track:!0}),x.createElement(v,{flexGrow:1,justifyContent:`flex-end`},x.createElement(y,{color:b.fg},r.toLocaleString())))},Le=[{key:`channels`,hotkey:`c`,title:`Channels`,labelWidth:16,display:X,max:Me,rows:C.channels.map(e=>({label:e.name,value:e.visitors}))},{key:`countries`,hotkey:`g`,title:`Top countries`,labelWidth:5,display:X,max:Ne,rows:C.countries.map(e=>({label:e.country,value:e.visitors}))},{key:`browsers`,hotkey:`b`,title:`Top browsers`,labelWidth:16,display:X,max:Pe,rows:C.browsers.map(e=>({label:e.name,value:e.visitors}))},{key:`devices`,hotkey:`d`,title:`Top devices`,labelWidth:16,display:X,max:Fe,rows:C.devices.map(e=>({label:e.name,value:e.visitors}))}],Re=Le.filter(e=>e.rows.length>0).map(e=>({key:e.key,title:e.title,render:t=>{let n=e.rows.slice(0,X),r=e.rows.length-n.length,i=Math.max(0,X-n.length);return x.createElement(x.Fragment,null,n.map((n,r)=>Ie(`${e.key}-${r}`,n.label,e.labelWidth,n.value,e.max,t)),Array.from({length:i},(e,t)=>x.createElement(v,{key:`pad-${t}`,height:1})),x.createElement(y,{color:b.dim},r>0?` +${r} more · [${e.hotkey}] expand`:` `))}})),Q=Math.max(5,Y-9),$=e=>{let t=Math.max(0,e-Q),n=Math.min(Te,t),r=Math.min(e,n+Q);return{from:n,window:Q,label:e>Q?` ${n+1}-${r} of ${e} · ↑↓ scroll`:` ${e} total`}};if(B===`pages`){let e=C.topPages.length,t=$(e);return x.createElement(v,{flexDirection:`column`},x.createElement(c,{version:a,subtitle:`pages · ${N} · ${O}`,live:!1}),x.createElement(v,{marginTop:1},x.createElement(l,{title:`Top pages — all ${e}`},e===0?x.createElement(y,{color:b.muted},`No pages with data in this window yet.`):x.createElement(x.Fragment,null,x.createElement(h,{columns:ke,data:C.topPages.slice(t.from,t.from+t.window),zebra:!0}),x.createElement(y,{color:b.dim},t.label)))),x.createElement(f,{items:[{key:`↑↓`,label:`scroll`},{key:`esc`,label:`back`},{key:`q`,label:`quit`}],active:`↑↓`}))}if(B){let e=Le.find(e=>e.key===B);if(e){let t=Math.min(q,84),n=$(e.rows.length);return x.createElement(v,{flexDirection:`column`},x.createElement(c,{version:a,subtitle:`${e.title.toLowerCase()} · ${N} · ${O}`,live:!1}),x.createElement(v,{marginTop:1},x.createElement(l,{title:`${e.title} — all ${e.rows.length}`,width:t},e.rows.length===0?x.createElement(y,{color:b.muted},`No data.`):x.createElement(x.Fragment,null,e.rows.slice(n.from,n.from+n.window).map((r,i)=>Ie(`x-${n.from+i}`,r.label,e.labelWidth,r.value,e.max,ne(t))),x.createElement(y,{color:b.dim},n.label)))),x.createElement(f,{items:[{key:`↑↓`,label:`scroll`},{key:`esc`,label:`back`},{key:`q`,label:`quit`}],active:`↑↓`}))}}return x.createElement(v,{flexDirection:`column`},x.createElement(c,{version:a,subtitle:G,live:!0}),x.createElement(v,{flexDirection:`row`,marginTop:1},de.map(e=>{let t=e.value===O;return x.createElement(v,{key:e.value,flexDirection:`row`,marginRight:3},x.createElement(y,{color:b.dim},e.key,` `),x.createElement(y,{color:t?b.accent:b.muted,bold:t},e.value))}),A?x.createElement(y,{color:b.dim},` (auto)`):null),x.createElement(v,{flexDirection:`row`,marginTop:1},x.createElement(_,{title:`Visitors`,value:C.visitors,format:`number`,width:J[0],gap:2,series:C.series,...typeof Ae==`number`?{delta:Ae}:{}}),x.createElement(_,{title:`Pageviews`,value:C.pageviews,format:`number`,width:J[1],gap:2,series:C.pageviewsSeries,...typeof je==`number`?{delta:je}:{}}),x.createElement(_,{title:`Bounce rate`,value:C.bounceRate??``,emptyHint:`—`,format:`percent`,width:J[2],gap:2,series:C.bounceSeries}),x.createElement(_,{title:`Avg session`,value:C.avgSession??``,emptyHint:`—`,format:`duration`,width:J[3],gap:0,series:C.sessionSeries})),Re.length>0&&x.createElement(v,{marginTop:1},x.createElement(te,{totalWidth:q,panels:Re,minColWidth:40,maxCols:2,gap:2})),x.createElement(v,{marginTop:1},x.createElement(l,{title:`Top pages (${O})`},C.topPages.length===0?x.createElement(y,{color:b.muted},`No pages with data in this window yet.`):x.createElement(x.Fragment,null,x.createElement(h,{columns:ke,data:C.topPages.slice(0,Z),zebra:!0}),C.topPages.length>Z?x.createElement(y,{color:b.dim},` +${C.topPages.length-Z} more · [p] expand`):null))),P?W():null,x.createElement(v,{marginTop:1},x.createElement(y,{color:b.dim},xe?`↻ refreshing…`:z===null?``:`↻ updated ${fe(z,Ce)} · [r] refresh`)),x.createElement(f,{items:K}))};async function me(e){return T(e)}export{me as analyticsCommand};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config-JVhBplSX.js";import{ensureFreshToken as t}from"./api-CdcB84ie.js";import{readToken as n}from"./token-store-BvSCse1t.js";import{ApiV2Client as r}from"./api-v2-D0mvt__4.js";import"./theme-Brz9wK0w.js";import"./panel-CTtQ2ue6.js";import"./prompt-BXvg2B4R.js";import{resolveSiteId as i}from"./resolve-site-BTVBMF1C.js";const a=[`deploy`,`release`,`campaign`,`incident`,`custom`];function o(e){return a.includes(e)}async function s(s){if(!s.message||s.message.length<1||s.message.length>500)return process.stderr.write(`Error: --message is required and must be 1–500 chars.
|
|
2
2
|
`),2;if(!o(s.type))return process.stderr.write(`Error: --type must be one of: ${a.join(`, `)}\n`),2;if(s.occurredAt&&Number.isNaN(Date.parse(s.occurredAt)))return process.stderr.write(`Error: --occurred-at must be a valid ISO 8601 timestamp.
|
|
3
3
|
`),2;let c=await e(),l=await n({strict:!1});if(!l)return process.stderr.write(`Error: not logged in. Run: zenovay login
|
|
4
4
|
`),3;let u=new r({config:c,cliVersion:s.cliVersion,token:l}),d,f;try{({siteId:d,site:f}=await i(u,{explicit:s.siteId,headless:!!s.json,cliVersion:s.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let p=f?.url?f.url.replace(/^https?:\/\//,``).replace(/\/$/,``):f?.name??d,m=await t({apiBase:c.apiBase});if(!m)return process.stderr.write(`Error: token expired and refresh failed. Run: zenovay login
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{clearToken as e,isExpired as t,readToken as n,writeToken as r}from"./token-store-
|
|
1
|
+
import{clearToken as e,isExpired as t,readToken as n,writeToken as r}from"./token-store-BvSCse1t.js";import{z as i}from"zod";const a=i.object({device_code:i.string(),user_code:i.string(),verification_uri:i.string().url(),verification_uri_complete:i.string().url().optional(),expires_in:i.number().int().positive(),interval:i.number().int().positive().default(5)}),o=i.object({access_token:i.string(),refresh_token:i.string(),token_type:i.literal(`Bearer`).default(`Bearer`),expires_in:i.number().int().positive(),scope:i.string().optional()}),s=i.object({error:i.enum([`authorization_pending`,`slow_down`,`access_denied`,`expired_token`,`invalid_client`,`invalid_grant`,`invalid_scope`]),error_description:i.string().optional()});async function c(e){let{apiBase:t,clientId:n=`cli-zenovay`,scope:r=`cli:full`}=e,i=e.fetchImpl??fetch,o=new URLSearchParams({client_id:n,scope:r}),s=await i(`${t}/oauth/device_authorization`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:o.toString()});if(!s.ok){let e=await s.text();throw Error(`Device authorization failed: ${s.status} ${e}`)}let c=await s.json();return a.parse(c)}async function l(e){let{apiBase:t,deviceCode:n,clientId:r=`cli-zenovay`,expiresIn:i}=e,a=e.fetchImpl??fetch,c=e.sleep??(e=>new Promise(t=>setTimeout(t,e))),l=e.interval,u=Date.now(),d=u+i*1e3;for(;Date.now()<d;){if(e.signal?.aborted)throw Error(`Polling aborted`);await c(l*1e3),e.onTick?.(Date.now()-u);let i=new URLSearchParams({grant_type:`urn:ietf:params:oauth:grant-type:device_code`,device_code:n,client_id:r}),d=await a(`${t}/oauth/token`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:i.toString()}),f=await d.json().catch(()=>({}));if(d.ok){let e=o.parse(f);return{accessToken:e.access_token,refreshToken:e.refresh_token,expiresAt:Date.now()+e.expires_in*1e3,tokenType:`Bearer`,scope:e.scope}}let p=s.safeParse(f);if(!p.success)throw Error(`Token poll failed (${d.status}): ${JSON.stringify(f)}`);let{error:m}=p.data;if(m!==`authorization_pending`){if(m===`slow_down`){l=Math.min(l*2,30);continue}throw m===`access_denied`?Error(`Device authorization denied by user.`):m===`expired_token`?Error("Device code expired — run `zenovay login` again."):Error(`Device token error: ${m}`)}}throw Error("Device code expired — run `zenovay login` again.")}async function u(e){let r=await n({strict:!0});return r?t(r)?d(r,e):r:null}async function d(t,n){let{apiBase:i,clientId:a=`cli-zenovay`}=n,s=n.fetchImpl??fetch,c=new URLSearchParams({grant_type:`refresh_token`,refresh_token:t.refreshToken,client_id:a}),l=await s(`${i}/oauth/token`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:c.toString()}),u=await l.json().catch(()=>({}));if(!l.ok){let t=u&&typeof u==`object`&&`error`in u?u.error:String(u);throw t===`invalid_grant`?(await e(),Error("Refresh token rejected by server — your session has been revoked. Run `zenovay login` again.")):Error(`Token refresh failed (${l.status}): ${JSON.stringify(u)}`)}let d=o.parse(u),f={...t,accessToken:d.access_token,refreshToken:d.refresh_token,expiresAt:Date.now()+d.expires_in*1e3,tokenType:`Bearer`,scope:d.scope??t.scope};return await r(f),f}const f=i.object({id:i.string(),slug:i.string().nullable().optional(),name:i.string(),url:i.string().url(),trackingCode:i.string().optional(),lastActiveAt:i.string().nullable().optional()});function p(e,t=`https://app.zenovay.com`){return`${t}/domains/${encodeURIComponent(e.slug??e.id)}`}const m=i.object({user:i.object({id:i.string(),email:i.string().email(),name:i.string().optional().nullable()}),team:i.object({id:i.string(),name:i.string(),plan:i.string()}).optional().nullable(),teams:i.array(i.object({id:i.string(),name:i.string(),plan:i.string(),role:i.string(),siteCount:i.number().int(),isCurrent:i.boolean()})).optional()});var h=class extends Error{constructor(e,t,n){super(n),this.status=e,this.body=t,this.name=`ApiError`}},g=class{fetchImpl;token;constructor(e){this.opts=e,this.fetchImpl=e.fetchImpl??fetch,this.token=e.token??null}get apiBase(){return this.opts.config.apiBase}async authedHeaders(e={}){let t=process.env.ZENOVAY_TEAM_ID,n=t&&t.trim()?{"X-Zenovay-Team-Id":t.trim()}:{},r=process.env.ZENOVAY_API_TOKEN;if(r&&r.trim())return{Accept:`application/json`,"User-Agent":`zenovay-cli/${this.opts.cliVersion}`,"X-Zenovay-CLI-Version":this.opts.cliVersion,Authorization:`Bearer ${r.trim()}`,...n,...e};this.token||=await u({apiBase:this.apiBase});let i={Accept:`application/json`,"User-Agent":`zenovay-cli/${this.opts.cliVersion}`,"X-Zenovay-CLI-Version":this.opts.cliVersion,...n,...e};return this.token&&(i.Authorization=`${this.token.tokenType} ${this.token.accessToken}`),i}async request(e,t){let n=`${this.apiBase}${e}`,r=await this.fetchImpl(n,{...t,headers:{...await this.authedHeaders(),...t.headers}});if(r.status===401&&this.token&&(this.token=null,r=await this.fetchImpl(n,{...t,headers:{...await this.authedHeaders(),...t.headers}})),!r.ok){let n=await r.text().catch(()=>``);throw new h(r.status,n,`${t.method??`GET`} ${e} → ${r.status}`)}let i=await r.json();return t.schema.parse(i)}async getSites(){return this.request(`/v1/cli/sites`,{schema:i.array(f)})}async createSite(e){return this.request(`/v1/cli/sites`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e),schema:i.object({id:i.string()})})}async getFirstEvent(e){let t=new URLSearchParams({site_id:e.siteId,since:String(e.since)});return this.request(`/v1/cli/first-event?${t.toString()}`,{schema:i.object({received:i.boolean(),event:i.unknown().optional()})})}async me(){return this.request(`/v1/cli/me`,{schema:m})}async revokeCurrentToken(){this.token&&await this.fetchImpl(`${this.apiBase}/oauth/revoke`,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`,...await this.authedHeaders()},body:new URLSearchParams({token:this.token.refreshToken,token_type_hint:`refresh_token`,client_id:`cli-zenovay`}).toString()})}async openAiStream(e,t,n){let r=await this.authedHeaders({"Content-Type":`application/json`,Accept:`text/event-stream`}),i=await this.fetchImpl(`${this.apiBase}/ai/cli/${e}`,{method:`POST`,headers:r,body:JSON.stringify(t),signal:n});if(!i.ok){let t=await i.text().catch(()=>``);throw new h(i.status,t,`POST /ai/cli/${e} → ${i.status}`)}return i}async openEventsStream(e,t){let n=await this.authedHeaders({Accept:`text/event-stream`}),r=await this.fetchImpl(`${this.apiBase}/v1/cli/events/tail?site_id=${e}`,{method:`GET`,headers:n,signal:t});if(!r.ok){let e=await r.text().catch(()=>``);throw new h(r.status,e,`GET events tail → ${r.status}`)}return r}async getDashboardSnapshot(e){return this.request(`/v1/cli/dashboard?site_id=${e}`,{schema:i.unknown()})}async ping(){let e=Date.now(),t=await this.fetchImpl(`${this.apiBase}/v1/cli/ping`,{headers:await this.authedHeaders()});if(!t.ok)throw new h(t.status,await t.text().catch(()=>``),`ping failed`);return{ok:!0,latencyMs:Date.now()-e}}};export{g as ApiClient,h as ApiError,p as dashboardUrlForSite,u as ensureFreshToken,l as pollDeviceToken,c as startDeviceAuthorization};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config-JVhBplSX.js";import"./api-CdcB84ie.js";import{readToken as t}from"./token-store-BvSCse1t.js";import{emitErrorEnvelope as n}from"./error-codes-ByhvHx2M.js";import{ApiV2Client as r}from"./api-v2-D0mvt__4.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";import{fmtDate as c,formatTable as l,shortId as u}from"./fmt-xxIPQJX-.js";async function d(d){let f=await e(),p=await t({strict:!1}),m=new r({config:f,cliVersion:d.cliVersion,token:p});try{switch(d.action){case`list`:{let{keys:e}=await m.listApiKeys();if(d.json)return a(s(e,`api-keys.list`),{legacyKey:`keys`,legacyValue:e}),0;if(e.length===0)return process.stdout.write("No API keys yet. Create one with `zenovay api-keys create --name <n>`.\n"),0;let t=[{key:`isCurrent`,header:``,width:1,format:e=>e?`*`:` `},{key:`id`,header:`id`,width:14,format:e=>u(String(e))},{key:`name`,header:`name`,width:24,format:e=>String(e??``)},{key:`scope`,header:`scope`,width:6},{key:`createdAt`,header:`created`,width:10,format:e=>c(e)},{key:`lastUsedAt`,header:`last used`,width:19,format:e=>c(e,`datetime`)}];return process.stdout.write(l({rows:e,cols:t})),process.stdout.write(`
|
|
2
2
|
* = current CLI key
|
|
3
3
|
`),0}case`create`:{if(!d.name)return process.stderr.write("Error: --name is required for `api-keys create`.\n"),2;let e=d.scope===`write`?`write`:`read`,t=await m.createApiKey({name:d.name,scope:e});if(d.json)return a(o(t,`api-keys.item`)),0;let n=`═`.repeat(64);return process.stdout.write(`\n${n}\n API key created: ${t.name} (${t.scope})\n id: ${t.id}\n token: ${t.token}\n${n}\n\n ⚠ Save this token NOW — it will not be shown again.\n Use it via the Authorization header: "Bearer ${t.token}"\n\n`),0}case`delete`:{if(!d.id)return process.stderr.write("Error: api-key id is required for `api-keys delete`.\n"),2;let e=await i({resource:`API key`,name:u(d.id),yes:d.yes,destructive:!0});if(!e)return process.stdout.write(`Cancelled.
|
|
4
4
|
`),1;let t=await m.deleteApiKey(d.id);return d.json?(a(o(t,`api-keys.deleted`)),0):(process.stdout.write(`✔ Deleted API key ${u(d.id)}.\n`),0)}}}catch(e){return n(e,{command:`api-keys ${d.action}`})}}export{d as apiKeysCommand};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./config-JVhBplSX.js";import{ApiError as e}from"./api-CdcB84ie.js";import"./token-store-BvSCse1t.js";import{ApiV2Client as t}from"./api-v2-D0mvt__4.js";export{t as ApiV2Client};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ApiClient as e,ApiError as t,ensureFreshToken as n}from"./api-hWp9s3Y8.js";import{z as r}from"zod";const i=r.object({id:r.string(),startedAt:r.string(),country:r.string().nullable().optional(),city:r.string().nullable().optional(),device:r.enum([`mobile`,`desktop`,`tablet`,`unknown`]).optional(),os:r.string().nullable().optional(),browser:r.string().nullable().optional(),page:r.string().optional(),referrer:r.string().nullable().optional(),utmSource:r.string().nullable().optional(),utmMedium:r.string().nullable().optional(),utmCampaign:r.string().nullable().optional(),aiScore:r.number().min(0).max(100).nullable().optional()}),a=r.object({visitors:r.array(i),total:r.number().int(),windowStart:r.string(),windowEnd:r.string()}),o=r.object({type:r.enum([`visitor.started`,`visitor.ended`,`visitor.heartbeat`]),visitor:i}),s=r.object({source:r.string(),channel:r.enum([`direct`,`organic`,`paid`,`social`,`referral`,`email`,`other`]).optional(),visitors:r.number().int(),conversions:r.number().int().optional(),revenue:r.number().int().optional(),delta:r.number().nullable().optional()}),c=r.object({sources:r.array(s),totalVisitors:r.number().int(),windowStart:r.string(),windowEnd:r.string()}),l=r.object({bucket:r.string(),amount:r.number().int(),currency:r.string(),transactions:r.number().int()}),u=r.object({series:r.array(l),totalAmount:r.number().int(),currency:r.string(),totalTransactions:r.number().int(),mrr:r.number().int().optional(),arpu:r.number().int().optional(),windowStart:r.string(),windowEnd:r.string()}),d=r.object({url:r.string(),device:r.enum([`mobile`,`desktop`]).optional(),lcp:r.object({p50:r.number(),p75:r.number(),p90:r.number()}).optional(),inp:r.object({p50:r.number(),p75:r.number(),p90:r.number()}).optional(),cls:r.object({p50:r.number(),p75:r.number(),p90:r.number()}).optional(),ttfb:r.object({p50:r.number(),p75:r.number(),p90:r.number()}).optional(),fcp:r.object({p50:r.number(),p75:r.number(),p90:r.number()}).optional(),samples:r.number().int()}),f=r.object({vitals:r.array(d),windowStart:r.string(),windowEnd:r.string()}),p=r.object({id:r.string(),name:r.string(),visitors:r.number().int(),conversions:r.number().int(),dropOff:r.number().min(0).max(1).optional()}),m=r.object({funnelId:r.string(),name:r.string(),steps:r.array(p),totalEntries:r.number().int(),totalCompletions:r.number().int(),conversionRate:r.number().min(0).max(1),windowStart:r.string(),windowEnd:r.string()}),h=r.object({id:r.string(),name:r.string(),stepCount:r.number().int(),lastEvaluatedAt:r.string().nullable().optional()}),g=r.object({funnels:r.array(h)}),_=r.object({visitors:r.number().int(),pageviews:r.number().int(),sessions:r.number().int(),bounceRate:r.number().min(0).max(1),avgSessionSec:r.number(),topPages:r.array(r.object({url:r.string(),views:r.number().int()})),topCountries:r.array(r.object({country:r.string(),visitors:r.number().int()})),windowStart:r.string(),windowEnd:r.string(),daily:r.array(r.object({date:r.string(),visitors:r.number().int(),pageviews:r.number().int(),bounceRate:r.number().optional(),avgSession:r.number().optional()})).optional()}),v=r.object({id:r.string(),name:r.string(),type:r.enum([`event`,`pageview`,`revenue`]),conversions24h:r.number().int(),conversions7d:r.number().int()}),y=r.object({goals:r.array(v)}),b=r.object({id:r.string(),name:r.string(),domain:r.string().nullable().optional(),industry:r.string().nullable().optional(),employeeCount:r.number().int().nullable().optional(),visitorCount:r.number().int(),firstSeenAt:r.string(),lastSeenAt:r.string()}),x=r.object({type:r.enum([`company.identified`,`company.returning`]),company:b}),S=r.object({companies:r.array(b),total:r.number().int()}),C=r.object({type:r.literal(`error.captured`),id:r.string(),message:r.string(),stack:r.string().optional(),url:r.string().optional(),occurredAt:r.string(),count:r.number().int().optional(),spike:r.number().optional()}),w=r.object({id:r.string(),ts:r.string(),class:r.string(),message:r.string(),page:r.string().nullable(),device:r.string().nullable(),fingerprint:r.string().nullable()}),T=r.object({errors:r.array(w),total:r.number().int()}),E=r.object({id:r.string(),name:r.string(),domain:r.string().nullable(),industry:r.string().nullable(),employeeCount:r.number().int().nullable(),visitCount:r.number().int(),firstSeenAt:r.string(),lastSeenAt:r.string(),isNew:r.boolean()}),D=r.object({companies:r.array(E),total:r.number().int()}),O=r.object({columns:r.array(r.string()),rows:r.array(r.record(r.unknown())),row_count:r.number(),duration_ms:r.number(),truncated:r.boolean()}),k=r.object({id:r.string(),provider:r.literal(`github`),commit_sha:r.string(),commit_message:r.string().nullable(),commit_author:r.string().nullable(),branch:r.string().nullable(),repository:r.string().nullable(),commit_url:r.string().nullable(),pushed_at:r.string(),show_on_chart:r.boolean()}),A=r.object({deploys:r.array(k),total:r.number().int()}),j=r.object({id:r.string(),name:r.string(),domain:r.string().nullable(),tier:r.string(),pageviews24h:r.number().int(),isCurrent:r.boolean()}),M=r.object({projects:r.array(j)}),N=r.object({type:r.string(),bucket:r.string(),count:r.number().int()}),P=r.object({events:r.array(N),windowStart:r.string(),windowEnd:r.string()}),F=r.object({id:r.string(),receivedAt:r.string(),url:r.string(),method:r.string(),headers:r.record(r.string(),r.string()),body:r.string()}),I=r.object({columns:r.array(r.string()),rows:r.array(r.array(r.unknown())),rowCount:r.number().int(),durationMs:r.number(),truncated:r.boolean().optional()}),L=r.object({resource:r.string(),values:r.array(r.string()),cachedAt:r.string().optional()});function R(e,t){throw Error(`api-v2: ${e} not yet implemented; awaiting backend Wave ${t}`)}async function*z(e,t){R(e,t)}function B(e){switch(e){case`24h`:return 1;case`7d`:return 7;case`30d`:return 30;case`90d`:return 90;case`1y`:return 365;default:return 7}}var V=class extends e{v2Opts;v2Fetch;v2Token;constructor(e){super(e),this.v2Opts=e,this.v2Fetch=e.fetchImpl??fetch,this.v2Token=e.token??null}get v2ApiBase(){return this.v2Opts.config.apiBase}async v2Headers(e={}){let t=process.env.ZENOVAY_TEAM_ID,r=t&&t.trim()?{"X-Zenovay-Team-Id":t.trim()}:{},i=process.env.ZENOVAY_API_TOKEN;if(i&&i.trim())return{Accept:`application/json`,"User-Agent":`zenovay-cli/${this.v2Opts.cliVersion}`,"X-Zenovay-CLI-Version":this.v2Opts.cliVersion,Authorization:`Bearer ${i.trim()}`,...r,...e};this.v2Token||=await n({apiBase:this.v2ApiBase});let a={Accept:`application/json`,"User-Agent":`zenovay-cli/${this.v2Opts.cliVersion}`,"X-Zenovay-CLI-Version":this.v2Opts.cliVersion,...r,...e};return this.v2Token&&(a.Authorization=`${this.v2Token.tokenType} ${this.v2Token.accessToken}`),a}async v2Request(e,n,r={},i){let a=`${this.v2ApiBase}${e}`,o=await this.v2Headers(r.headers??{}),s=await this.v2Fetch(a,{...r,headers:o,signal:i});if(s.status===401&&this.v2Token){this.v2Token=null;let e=await this.v2Headers(r.headers??{});s=await this.v2Fetch(a,{...r,headers:e,signal:i})}if(!s.ok){let n=await s.text().catch(()=>``),i=n;try{i=JSON.parse(n)}catch{}throw new t(s.status,i,`${r.method??`GET`} ${e} → ${s.status}`)}let c=await s.json();return n.parse(c)}async v2RequestRaw(e,n={},r){let i=`${this.v2ApiBase}${e}`,a=await this.v2Headers(n.headers??{}),o=await this.v2Fetch(i,{...n,headers:a,signal:r});if(o.status===401&&this.v2Token){this.v2Token=null;let e=await this.v2Headers(n.headers??{});o=await this.v2Fetch(i,{...n,headers:e,signal:r})}if(!o.ok){let r=await o.text().catch(()=>``),i=r;try{i=JSON.parse(r)}catch{}throw new t(o.status,i,`${n.method??`GET`} ${e} → ${o.status}`)}let s=await o.json();return s?.data??s}async getVisitors(e,t,n){let r=new URLSearchParams({site_id:e});t?.since&&r.set(`since`,t.since),typeof t?.limit==`number`&&r.set(`limit`,String(t.limit));let i=await this.v2RequestRaw(`/v1/cli/visitors?${r.toString()}`,{},n),o=new Date,s=new Date(Date.now()-24*3600*1e3),c=e=>{if(!e)return`unknown`;let t=e.toLowerCase();return t.includes(`mobile`)?`mobile`:t.includes(`tablet`)?`tablet`:t.includes(`desktop`)?`desktop`:`unknown`};return a.parse({total:i.liveCount??i.visitors?.length??0,visitors:(i.visitors??[]).map(e=>({id:e.sessionId,startedAt:e.lastSeen,country:e.country,city:null,device:c(e.device??null),page:e.currentPath??void 0,aiScore:typeof e.valueScore==`number`?Math.max(0,Math.min(100,e.valueScore)):null})),windowStart:s.toISOString(),windowEnd:o.toISOString()})}streamVisitors(e,t){return this.streamChannel(e,`visitors`,t)}async getSources(e,t=`30d`,n,r){let i=new URLSearchParams({site_id:e,period:t});n&&i.set(`compare`,n);let a=await this.v2RequestRaw(`/v1/cli/sources?${i.toString()}`,{},r),o=a.channels??[],s=a.top_utm_sources??[],l=o.reduce((e,t)=>e+t.visitors,0),u=new Set([`direct`,`organic`,`paid`,`social`,`referral`,`email`]),d=[...o.map(e=>({source:e.name,channel:u.has(e.name)?e.name:`other`,visitors:e.visitors,delta:typeof e.delta==`number`?e.delta/100:null})),...s.map(e=>({source:e.medium?`${e.source}/${e.medium}`:e.source,channel:`other`,visitors:e.visitors}))],f=new Date,p=new Date(Date.now()-B(t)*24*3600*1e3);return c.parse({sources:d,totalVisitors:l,windowStart:p.toISOString(),windowEnd:f.toISOString()})}async getRevenue(e,t=`30d`,n){let r=new URLSearchParams({site_id:e,window:t}),i=await this.v2RequestRaw(`/v1/cli/revenue?${r.toString()}`,{},n),a=(i.daily??[]).map(e=>({bucket:e.date,amount:e.cents,currency:i.currency??`USD`,transactions:e.transactions})),o=a.reduce((e,t)=>e+t.amount,0),s=a.reduce((e,t)=>e+t.transactions,0),c=new Date,l=new Date(Date.now()-B(t)*24*3600*1e3),d={series:a,totalAmount:o,currency:i.currency??`USD`,totalTransactions:s,windowStart:l.toISOString(),windowEnd:c.toISOString()};return typeof i.mrr_cents==`number`&&(d.mrr=i.mrr_cents),u.parse(d)}async getVitals(e,t,n){let r=new URLSearchParams({site_id:e});t?.url&&r.set(`url`,t.url),t?.device&&r.set(`device`,t.device),t?.window&&r.set(`window`,t.window);let i=await this.v2RequestRaw(`/v1/cli/vitals?${r.toString()}`,{},n),a=[];if(i.p75&&(i.sample_count??0)>0){let e=i.p75,n={url:`— site-wide aggregate —`,device:t?.device??void 0,samples:i.sample_count??0,...typeof e.lcp==`number`?{lcp:{p50:e.lcp,p75:e.lcp,p90:e.lcp}}:{},...typeof e.inp==`number`?{inp:{p50:e.inp,p75:e.inp,p90:e.inp}}:{},...typeof e.cls==`number`?{cls:{p50:e.cls,p75:e.cls,p90:e.cls}}:{},...typeof e.fcp==`number`?{fcp:{p50:e.fcp,p75:e.fcp,p90:e.fcp}}:{},...typeof e.ttfb==`number`?{ttfb:{p50:e.ttfb,p75:e.ttfb,p90:e.ttfb}}:{}};a.push(n)}for(let e of i.worst_pages??[])a.push({url:e.path,device:t?.device??void 0,samples:e.sample_count,lcp:{p50:e.lcp_p75,p75:e.lcp_p75,p90:e.lcp_p75}});let o=new Date,s=new Date(Date.now()-B(t?.window??`7d`)*24*3600*1e3);return f.parse({vitals:a,windowStart:s.toISOString(),windowEnd:o.toISOString()})}async getFunnel(e,t,n=`30d`,r){let i=new URLSearchParams({site_id:e,window:n}),a=await this.v2RequestRaw(`/v1/cli/funnels/${encodeURIComponent(t)}?${i.toString()}`,{},r),o=a.total_entries??0,s=(a.steps??[]).map(e=>({id:`step-${e.order}`,name:e.name,visitors:e.visitors,conversions:e.visitors,dropOff:Math.max(0,Math.min(1,e.dropoffPct/100))})),c=s[s.length-1],l=c?.visitors??0,u=o>0?Math.min(1,l/o):0,d=new Date,f=new Date(Date.now()-B(n)*24*3600*1e3);return m.parse({funnelId:a.id??t,name:a.name??t,steps:s,totalEntries:o,totalCompletions:l,conversionRate:u,windowStart:f.toISOString(),windowEnd:d.toISOString()})}async listFunnels(e,t){let n=new URLSearchParams({site_id:e}),r=await this.v2RequestRaw(`/v1/cli/funnels?${n.toString()}`,{},t);return g.parse({funnels:(r.funnels??[]).map(e=>({id:e.id,name:e.name,stepCount:e.step_count}))})}async getStats(e,t=`24h`,n){let r=new URLSearchParams({site_id:e,range:t}),i=await this.v2RequestRaw(`/v1/cli/stats?${r.toString()}`,{},n),a=i.visitors??0,o=i.pageviews??0,s=a,c=s>0?o/s:0,l=typeof i.bounceRate==`number`?Math.max(0,Math.min(1,i.bounceRate)):c>0?Math.max(0,Math.min(1,1/Math.max(1,c))):0,u=i.avgSessionSec??0,d=new Date,f=new Date(Date.now()-B(t)*24*3600*1e3);return _.parse({visitors:a,pageviews:o,sessions:s,bounceRate:l,avgSessionSec:u,topPages:i.topPage?[{url:i.topPage.path,views:i.topPage.views}]:[],topCountries:i.topSource?[{country:i.topSource.channel,visitors:i.topSource.visitors}]:[],windowStart:f.toISOString(),windowEnd:d.toISOString(),daily:i.daily})}async getGoals(e,t){let n=new URLSearchParams({site_id:e});return this.v2Request(`/v1/cli/goals?${n.toString()}`,y,{},t)}async getLive(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/live?${n.toString()}`,t)}async getPages(e,t,n){let r=new URLSearchParams({site_id:e});return t&&r.set(`range`,t),await this.v2RawJson(`/v1/cli/pages?${r.toString()}`,n)}async getDevices(e,t,n){let r=new URLSearchParams({site_id:e});return t&&r.set(`range`,t),await this.v2RawJson(`/v1/cli/devices?${r.toString()}`,n)}async getGeo(e,t,n){let r=new URLSearchParams({site_id:e});return t&&r.set(`range`,t),await this.v2RawJson(`/v1/cli/geo?${r.toString()}`,n)}async getRetention(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/retention?${n.toString()}`,t)}async getUptime(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/uptime?${n.toString()}`,t)}async getSessions(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/sessions?${n.toString()}`,t)}async getHeatmaps(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/heatmaps?${n.toString()}`,t)}async getJourneys(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/journeys?${n.toString()}`,t)}async getInsights(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/insights?${n.toString()}`,t)}async v2RawJson(e,n){let r=`${this.v2ApiBase}${e}`,i=await this.v2Headers(),a=await this.v2Fetch(r,{headers:i,signal:n});if(a.status===401&&this.v2Token){this.v2Token=null;let e=await this.v2Headers();a=await this.v2Fetch(r,{headers:e,signal:n})}if(!a.ok){let n=await a.text().catch(()=>``),r=n;try{r=JSON.parse(n)}catch{}throw new t(a.status,r,`GET ${e} → ${a.status}`)}return a.json()}streamCompaniesV2(e,t){return this.streamChannel(e,`companies`,t)}streamCompanies(e,t){return z(`streamCompanies`,2)}async getCompanies(e){R(`getCompanies`,2)}async getCompaniesSnapshot(e,t,n){let r=new URLSearchParams({site_id:e});t?.window&&r.set(`window`,t.window),typeof t?.limit==`number`&&r.set(`limit`,String(t.limit));let i=await this.v2RequestRaw(`/v1/cli/companies?${r.toString()}`,{},n);return D.parse(i)}async runSqlQuery(e,n,r,i){let a=`${this.v2ApiBase}/v1/cli/query`,o=await this.v2Headers({"Content-Type":`application/json`}),s=await this.v2Fetch(a,{method:`POST`,headers:o,signal:i,body:JSON.stringify({site_id:e,sql:n,...r?.maxRows?{max_rows:r.maxRows}:{}})});if(!s.ok){let e=await s.text().catch(()=>``),n=e;try{n=JSON.parse(e)}catch{}throw new t(s.status,n,`POST /v1/cli/query → ${s.status}`)}let c=await s.json();return O.parse(c.data??c)}async getDeploys(e,t,n){let r=new URLSearchParams({site_id:e});t?.since&&r.set(`since`,t.since),typeof t?.limit==`number`&&r.set(`limit`,String(t.limit)),t?.branch&&r.set(`branch`,t.branch),t?.onChartOnly&&r.set(`on_chart_only`,`true`);let i=await this.v2RequestRaw(`/v1/cli/deploys?${r.toString()}`,{},n);return A.parse(i)}async getProjects(e,t){let n=new URLSearchParams({site_id:e}),r=await this.v2RequestRaw(`/v1/cli/projects?${n.toString()}`,{},t);return M.parse(r)}async getErrors(e,t,n){let r=new URLSearchParams({site_id:e});t?.window&&r.set(`window`,t.window),typeof t?.limit==`number`&&r.set(`limit`,String(t.limit));let i=await this.v2RequestRaw(`/v1/cli/errors?${r.toString()}`,{},n);return T.parse(i)}streamErrorsV2(e,t){return this.streamChannel(e,`errors`,t)}streamErrors(e,t){return z(`streamErrors`,2)}async getEventsHistory(e,t){R(`getEventsHistory`,2)}forwardWebhook(e,t){return z(`forwardWebhook`,2)}async registerTunnel(e,t){R(`registerTunnel`,2)}async queryRaw(e,t,n){R(`queryRaw`,3)}async getCompletions(e,t){R(`getCompletions`,3)}async listApiKeys(e){return await this.v2RawJson(`/v1/cli/mutate/keys`,e)}async createApiKey(e,t){return await this.v2Mutate(`/v1/cli/mutate/keys`,`POST`,e,t)}async deleteApiKey(e,t){return await this.v2Mutate(`/v1/cli/mutate/keys/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async addDomain(e,t){return await this.v2Mutate(`/v1/cli/mutate/domains`,`POST`,e,t)}async deleteDomain(e,t){return await this.v2Mutate(`/v1/cli/mutate/domains/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async listTeam(e){return await this.v2RawJson(`/v1/cli/mutate/team`,e)}async inviteTeamMember(e,t){return await this.v2Mutate(`/v1/cli/mutate/team/invite`,`POST`,e,t)}async removeTeamMember(e,t){return await this.v2Mutate(`/v1/cli/mutate/team/members/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async updateTeamMemberRole(e,t,n){return await this.v2Mutate(`/v1/cli/mutate/team/members/${encodeURIComponent(e)}/role`,`PATCH`,{role:t},n)}async updateProfile(e,t){return await this.v2Mutate(`/v1/cli/mutate/profile`,`POST`,e,t)}async getPlanInfo(e){return await this.v2RawJson(`/v1/cli/mutate/plans/info`,e)}async upgradePlan(e,t){return await this.v2Mutate(`/v1/cli/mutate/plans/upgrade`,`POST`,{targetPlan:e},t)}async cancelPlan(e){return await this.v2Mutate(`/v1/cli/mutate/plans/cancel`,`POST`,{},e)}async getSettings(e){return await this.v2RawJson(`/v1/cli/mutate/settings`,e)}async getUsage(e){return await this.v2RawJson(`/v1/cli/mutate/usage`,e)}async setSetting(e,t,n){return await this.v2Mutate(`/v1/cli/mutate/settings`,`POST`,{key:e,value:t},n)}async listIntegrations(e){return await this.v2RawJson(`/v1/cli/mutate/integrations`,e)}async disconnectIntegration(e,t){return await this.v2Mutate(`/v1/cli/mutate/integrations/disconnect`,`POST`,{name:e},t)}async listGoals(e){return await this.v2RawJson(`/v1/cli/mutate/goals`,e)}async createGoal(e,t){return await this.v2Mutate(`/v1/cli/mutate/goals`,`POST`,e,t)}async deleteGoal(e,t){return await this.v2Mutate(`/v1/cli/mutate/goals/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async listNotes(e){return await this.v2RawJson(`/v1/cli/mutate/notes`,e)}async createNote(e,t){return await this.v2Mutate(`/v1/cli/mutate/notes`,`POST`,e,t)}async deleteNote(e,t){return await this.v2Mutate(`/v1/cli/mutate/notes/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async listAgencyClients(e){return await this.v2RawJson(`/v1/cli/mutate/agency/clients`,e)}async addAgencyClient(e,t){return await this.v2Mutate(`/v1/cli/mutate/agency/clients`,`POST`,e,t)}async removeAgencyClient(e,t){return await this.v2Mutate(`/v1/cli/mutate/agency/clients/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async sendAgencyReport(e,t){return await this.v2Mutate(`/v1/cli/mutate/agency/report/${encodeURIComponent(e)}`,`POST`,{},t)}async listWebhooks(e){return await this.v2RawJson(`/v1/cli/mutate/webhooks`,e)}async createWebhook(e,t){return await this.v2Mutate(`/v1/cli/mutate/webhooks`,`POST`,e,t)}async deleteWebhook(e,t){return await this.v2Mutate(`/v1/cli/mutate/webhooks/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async rotateWebhookSecret(e,t){return await this.v2Mutate(`/v1/cli/mutate/webhooks/${encodeURIComponent(e)}/rotate`,`POST`,{},t)}async testWebhook(e,t){return await this.v2Mutate(`/v1/cli/mutate/webhooks/${encodeURIComponent(e)}/test`,`POST`,{},t)}async getAuditLogs(e,t){let n=new URLSearchParams;e.since&&n.set(`since`,e.since),e.action&&n.set(`action`,e.action),e.actor&&n.set(`actor`,e.actor);let r=n.toString()?`/v1/cli/mutate/audit/logs?${n.toString()}`:`/v1/cli/mutate/audit/logs`;return await this.v2RawJson(r,t)}async exportAudit(e,n){let r=`${this.v2ApiBase}/v1/cli/mutate/audit/export?format=${encodeURIComponent(e.format)}`,i=await this.v2Headers(),a=await this.v2Fetch(r,{headers:i,signal:n});if(a.status===401&&this.v2Token){this.v2Token=null;let e=await this.v2Headers();a=await this.v2Fetch(r,{headers:e,signal:n})}if(!a.ok){let e=await a.text().catch(()=>``),n=e;try{n=JSON.parse(e)}catch{}throw new t(a.status,n,`GET /v1/cli/mutate/audit/export → ${a.status}`)}return a.text()}async getShare(e,t){let n=new URLSearchParams({siteId:e});return await this.v2RawJson(`/v1/cli/mutate/share?${n.toString()}`,t)}async enableShare(e,t){return await this.v2Mutate(`/v1/cli/mutate/share/enable`,`POST`,{siteId:e},t)}async disableShare(e,t){return await this.v2Mutate(`/v1/cli/mutate/share/disable`,`POST`,{siteId:e},t)}async v2Mutate(e,n,r,i){let a=`${this.v2ApiBase}${e}`,o=await this.v2Headers(r===void 0?{}:{"Content-Type":`application/json`}),s={method:n,headers:o,signal:i};r!==void 0&&(s.body=JSON.stringify(r));let c=await this.v2Fetch(a,s);if(c.status===401&&this.v2Token){this.v2Token=null;let e=await this.v2Headers(r===void 0?{}:{"Content-Type":`application/json`});c=await this.v2Fetch(a,{...s,headers:e})}if(!c.ok){let r=await c.text().catch(()=>``),i=r;try{i=JSON.parse(r)}catch{}throw new t(c.status,i,`${n} ${e} → ${c.status}`)}let l=c.headers.get(`content-type`)??``;return l.includes(`application/json`)?c.json():{}}async*streamChannel(e,t,n){let{connectWs:r}=await import(`./ws-client-MoEdfqAO.js`),i=this.v2ApiBase.replace(/^https:\/\//,`wss://`).replace(/^http:\/\//,`ws://`),a=`${i}/v1/cli/stream/${encodeURIComponent(e)}?channels=${t}`,o=this.v2Token?.accessToken;for await(let e of r({url:a,bearer:o,signal:n})){if(e.type!==`message`)continue;let t=e.data;if(t&&typeof t==`object`){let e=t;yield e.event??t}}}async createTunnel(e,n,r){let i=`${this.v2ApiBase}/v1/cli/tunnels`,a=await this.v2Headers({"Content-Type":`application/json`}),o=await this.v2Fetch(i,{method:`POST`,headers:a,signal:r,body:JSON.stringify({site_id:e,target_pattern:n})});if(!o.ok){let e=await o.text().catch(()=>``);throw new t(o.status,e,`POST /v1/cli/tunnels → ${o.status}`)}let s=await o.json(),c=s.data??{};if(!c.tunnel_key||!c.public_url||!c.ws_url)throw new t(500,s,`createTunnel: malformed response`);return{tunnelKey:c.tunnel_key,publicUrl:c.public_url,wsUrl:c.ws_url,siteId:c.site_id??e}}tunnelClient(e){let t=this.v2Token?.accessToken;return{start:async(n,r)=>{let{WsTunnelClient:i}=await import(`./ws-client-MoEdfqAO.js`),a=new i({url:e,bearer:t,signal:r});await a.start(n)}}}async listAlerts(e,t){let n=new URLSearchParams({site_id:e}),r=await this.v2RawJson(`/v1/cli/alerts?${n.toString()}`,t),i=(()=>{if(Array.isArray(r))return r;let e=r;if(Array.isArray(e?.alerts))return e.alerts;if(e?.data&&typeof e.data==`object`){let t=e.data;if(Array.isArray(t.alerts))return t.alerts;if(Array.isArray(e.data))return e.data}return[]})();return i.map(H)}async createAlert(e,t,n){let r=t.op===`gt`?`greater_than`:(t.op,`less_than`),i=t.channel===`webhook`?`webhook`:`email`;if(i===`email`&&!t.email){let e=Error(`--channel email requires --email <addr>`);throw e.name=`ValidationError`,e}let a={site_id:e,name:t.name??`${t.metric} ${t.op} ${t.threshold}`,metric:t.metric,threshold:t.threshold,comparator:r,window:t.window,channel:i,email:t.email??``},o=await this.v2Mutate(`/v1/cli/alerts`,`POST`,a,n),s=`data`in o&&o.data?o.data:o;return H(s)}async deleteAlert(e,t,n){let r=new URLSearchParams({site_id:e});await this.v2Mutate(`/v1/cli/alerts/${encodeURIComponent(t)}?${r.toString()}`,`DELETE`,void 0,n)}};function H(e){let t=(()=>e.op===`gt`||e.op===`lt`?e.op:e.comparator===`greater_than`?`gt`:e.comparator===`less_than`?`lt`:`gt`)();return{id:String(e.id),metric:e.metric,op:t,threshold:e.threshold,window:e.window,createdAt:e.createdAt??e.created_at??null}}export{V as ApiV2Client};
|
|
1
|
+
import{ApiClient as e,ApiError as t,ensureFreshToken as n}from"./api-CdcB84ie.js";import{z as r}from"zod";const i=r.object({id:r.string(),startedAt:r.string(),country:r.string().nullable().optional(),city:r.string().nullable().optional(),device:r.enum([`mobile`,`desktop`,`tablet`,`unknown`]).optional(),os:r.string().nullable().optional(),browser:r.string().nullable().optional(),page:r.string().optional(),referrer:r.string().nullable().optional(),utmSource:r.string().nullable().optional(),utmMedium:r.string().nullable().optional(),utmCampaign:r.string().nullable().optional(),aiScore:r.number().min(0).max(100).nullable().optional()}),a=r.object({visitors:r.array(i),total:r.number().int(),windowStart:r.string(),windowEnd:r.string()}),o=r.object({type:r.enum([`visitor.started`,`visitor.ended`,`visitor.heartbeat`]),visitor:i}),s=r.object({source:r.string(),channel:r.enum([`direct`,`organic`,`paid`,`social`,`referral`,`email`,`other`]).optional(),visitors:r.number().int(),conversions:r.number().int().optional(),revenue:r.number().int().optional(),delta:r.number().nullable().optional()}),c=r.object({sources:r.array(s),totalVisitors:r.number().int(),windowStart:r.string(),windowEnd:r.string()}),l=r.object({bucket:r.string(),amount:r.number().int(),currency:r.string(),transactions:r.number().int()}),u=r.object({series:r.array(l),totalAmount:r.number().int(),currency:r.string(),totalTransactions:r.number().int(),mrr:r.number().int().optional(),arpu:r.number().int().optional(),windowStart:r.string(),windowEnd:r.string()}),d=r.object({url:r.string(),device:r.enum([`mobile`,`desktop`]).optional(),lcp:r.object({p50:r.number(),p75:r.number(),p90:r.number()}).optional(),inp:r.object({p50:r.number(),p75:r.number(),p90:r.number()}).optional(),cls:r.object({p50:r.number(),p75:r.number(),p90:r.number()}).optional(),ttfb:r.object({p50:r.number(),p75:r.number(),p90:r.number()}).optional(),fcp:r.object({p50:r.number(),p75:r.number(),p90:r.number()}).optional(),samples:r.number().int()}),f=r.object({vitals:r.array(d),windowStart:r.string(),windowEnd:r.string()}),p=r.object({id:r.string(),name:r.string(),visitors:r.number().int(),conversions:r.number().int(),dropOff:r.number().min(0).max(1).optional()}),m=r.object({funnelId:r.string(),name:r.string(),steps:r.array(p),totalEntries:r.number().int(),totalCompletions:r.number().int(),conversionRate:r.number().min(0).max(1),windowStart:r.string(),windowEnd:r.string()}),h=r.object({id:r.string(),name:r.string(),stepCount:r.number().int(),lastEvaluatedAt:r.string().nullable().optional()}),g=r.object({funnels:r.array(h)}),_=r.object({visitors:r.number().int(),pageviews:r.number().int(),sessions:r.number().int(),bounceRate:r.number().min(0).max(1),avgSessionSec:r.number(),topPages:r.array(r.object({url:r.string(),views:r.number().int()})),topCountries:r.array(r.object({country:r.string(),visitors:r.number().int()})),windowStart:r.string(),windowEnd:r.string(),daily:r.array(r.object({date:r.string(),visitors:r.number().int(),pageviews:r.number().int(),bounceRate:r.number().optional(),avgSession:r.number().optional()})).optional()}),v=r.object({id:r.string(),name:r.string(),type:r.enum([`event`,`pageview`,`revenue`]),conversions24h:r.number().int(),conversions7d:r.number().int()}),y=r.object({goals:r.array(v)}),b=r.object({id:r.string(),name:r.string(),domain:r.string().nullable().optional(),industry:r.string().nullable().optional(),employeeCount:r.number().int().nullable().optional(),visitorCount:r.number().int(),firstSeenAt:r.string(),lastSeenAt:r.string()}),x=r.object({type:r.enum([`company.identified`,`company.returning`]),company:b}),S=r.object({companies:r.array(b),total:r.number().int()}),C=r.object({type:r.literal(`error.captured`),id:r.string(),message:r.string(),stack:r.string().optional(),url:r.string().optional(),occurredAt:r.string(),count:r.number().int().optional(),spike:r.number().optional()}),w=r.object({id:r.string(),ts:r.string(),class:r.string(),message:r.string(),page:r.string().nullable(),device:r.string().nullable(),fingerprint:r.string().nullable()}),T=r.object({errors:r.array(w),total:r.number().int()}),E=r.object({id:r.string(),name:r.string(),domain:r.string().nullable(),industry:r.string().nullable(),employeeCount:r.number().int().nullable(),visitCount:r.number().int(),firstSeenAt:r.string(),lastSeenAt:r.string(),isNew:r.boolean()}),D=r.object({companies:r.array(E),total:r.number().int()}),O=r.object({columns:r.array(r.string()),rows:r.array(r.record(r.unknown())),row_count:r.number(),duration_ms:r.number(),truncated:r.boolean()}),k=r.object({id:r.string(),provider:r.literal(`github`),commit_sha:r.string(),commit_message:r.string().nullable(),commit_author:r.string().nullable(),branch:r.string().nullable(),repository:r.string().nullable(),commit_url:r.string().nullable(),pushed_at:r.string(),show_on_chart:r.boolean()}),A=r.object({deploys:r.array(k),total:r.number().int()}),j=r.object({id:r.string(),name:r.string(),domain:r.string().nullable(),tier:r.string(),pageviews24h:r.number().int(),isCurrent:r.boolean()}),M=r.object({projects:r.array(j)}),N=r.object({type:r.string(),bucket:r.string(),count:r.number().int()}),P=r.object({events:r.array(N),windowStart:r.string(),windowEnd:r.string()}),F=r.object({id:r.string(),receivedAt:r.string(),url:r.string(),method:r.string(),headers:r.record(r.string(),r.string()),body:r.string()}),I=r.object({columns:r.array(r.string()),rows:r.array(r.array(r.unknown())),rowCount:r.number().int(),durationMs:r.number(),truncated:r.boolean().optional()}),L=r.object({resource:r.string(),values:r.array(r.string()),cachedAt:r.string().optional()});function R(e,t){throw Error(`api-v2: ${e} not yet implemented; awaiting backend Wave ${t}`)}async function*z(e,t){R(e,t)}function B(e){switch(e){case`24h`:return 1;case`7d`:return 7;case`30d`:return 30;case`90d`:return 90;case`1y`:return 365;default:return 7}}var V=class extends e{v2Opts;v2Fetch;v2Token;constructor(e){super(e),this.v2Opts=e,this.v2Fetch=e.fetchImpl??fetch,this.v2Token=e.token??null}get v2ApiBase(){return this.v2Opts.config.apiBase}async v2Headers(e={}){let t=process.env.ZENOVAY_TEAM_ID,r=t&&t.trim()?{"X-Zenovay-Team-Id":t.trim()}:{},i=process.env.ZENOVAY_API_TOKEN;if(i&&i.trim())return{Accept:`application/json`,"User-Agent":`zenovay-cli/${this.v2Opts.cliVersion}`,"X-Zenovay-CLI-Version":this.v2Opts.cliVersion,Authorization:`Bearer ${i.trim()}`,...r,...e};this.v2Token||=await n({apiBase:this.v2ApiBase});let a={Accept:`application/json`,"User-Agent":`zenovay-cli/${this.v2Opts.cliVersion}`,"X-Zenovay-CLI-Version":this.v2Opts.cliVersion,...r,...e};return this.v2Token&&(a.Authorization=`${this.v2Token.tokenType} ${this.v2Token.accessToken}`),a}async v2Request(e,n,r={},i){let a=`${this.v2ApiBase}${e}`,o=await this.v2Headers(r.headers??{}),s=await this.v2Fetch(a,{...r,headers:o,signal:i});if(s.status===401&&this.v2Token){this.v2Token=null;let e=await this.v2Headers(r.headers??{});s=await this.v2Fetch(a,{...r,headers:e,signal:i})}if(!s.ok){let n=await s.text().catch(()=>``),i=n;try{i=JSON.parse(n)}catch{}throw new t(s.status,i,`${r.method??`GET`} ${e} → ${s.status}`)}let c=await s.json();return n.parse(c)}async v2RequestRaw(e,n={},r){let i=`${this.v2ApiBase}${e}`,a=await this.v2Headers(n.headers??{}),o=await this.v2Fetch(i,{...n,headers:a,signal:r});if(o.status===401&&this.v2Token){this.v2Token=null;let e=await this.v2Headers(n.headers??{});o=await this.v2Fetch(i,{...n,headers:e,signal:r})}if(!o.ok){let r=await o.text().catch(()=>``),i=r;try{i=JSON.parse(r)}catch{}throw new t(o.status,i,`${n.method??`GET`} ${e} → ${o.status}`)}let s=await o.json();return s?.data??s}async getVisitors(e,t,n){let r=new URLSearchParams({site_id:e});t?.since&&r.set(`since`,t.since),typeof t?.limit==`number`&&r.set(`limit`,String(t.limit));let i=await this.v2RequestRaw(`/v1/cli/visitors?${r.toString()}`,{},n),o=new Date,s=new Date(Date.now()-24*3600*1e3),c=e=>{if(!e)return`unknown`;let t=e.toLowerCase();return t.includes(`mobile`)?`mobile`:t.includes(`tablet`)?`tablet`:t.includes(`desktop`)?`desktop`:`unknown`};return a.parse({total:i.liveCount??i.visitors?.length??0,visitors:(i.visitors??[]).map(e=>({id:e.sessionId,startedAt:e.lastSeen,country:e.country,city:null,device:c(e.device??null),page:e.currentPath??void 0,aiScore:typeof e.valueScore==`number`?Math.max(0,Math.min(100,e.valueScore)):null})),windowStart:s.toISOString(),windowEnd:o.toISOString()})}streamVisitors(e,t){return this.streamChannel(e,`visitors`,t)}async getSources(e,t=`30d`,n,r){let i=new URLSearchParams({site_id:e,period:t});n&&i.set(`compare`,n);let a=await this.v2RequestRaw(`/v1/cli/sources?${i.toString()}`,{},r),o=a.channels??[],s=a.top_utm_sources??[],l=o.reduce((e,t)=>e+t.visitors,0),u=new Set([`direct`,`organic`,`paid`,`social`,`referral`,`email`]),d=[...o.map(e=>({source:e.name,channel:u.has(e.name)?e.name:`other`,visitors:e.visitors,delta:typeof e.delta==`number`?e.delta/100:null})),...s.map(e=>({source:e.medium?`${e.source}/${e.medium}`:e.source,channel:`other`,visitors:e.visitors}))],f=new Date,p=new Date(Date.now()-B(t)*24*3600*1e3);return c.parse({sources:d,totalVisitors:l,windowStart:p.toISOString(),windowEnd:f.toISOString()})}async getRevenue(e,t=`30d`,n){let r=new URLSearchParams({site_id:e,window:t}),i=await this.v2RequestRaw(`/v1/cli/revenue?${r.toString()}`,{},n),a=(i.daily??[]).map(e=>({bucket:e.date,amount:e.cents,currency:i.currency??`USD`,transactions:e.transactions})),o=a.reduce((e,t)=>e+t.amount,0),s=a.reduce((e,t)=>e+t.transactions,0),c=new Date,l=new Date(Date.now()-B(t)*24*3600*1e3),d={series:a,totalAmount:o,currency:i.currency??`USD`,totalTransactions:s,windowStart:l.toISOString(),windowEnd:c.toISOString()};return typeof i.mrr_cents==`number`&&(d.mrr=i.mrr_cents),u.parse(d)}async getVitals(e,t,n){let r=new URLSearchParams({site_id:e});t?.url&&r.set(`url`,t.url),t?.device&&r.set(`device`,t.device),t?.window&&r.set(`window`,t.window);let i=await this.v2RequestRaw(`/v1/cli/vitals?${r.toString()}`,{},n),a=[];if(i.p75&&(i.sample_count??0)>0){let e=i.p75,n={url:`— site-wide aggregate —`,device:t?.device??void 0,samples:i.sample_count??0,...typeof e.lcp==`number`?{lcp:{p50:e.lcp,p75:e.lcp,p90:e.lcp}}:{},...typeof e.inp==`number`?{inp:{p50:e.inp,p75:e.inp,p90:e.inp}}:{},...typeof e.cls==`number`?{cls:{p50:e.cls,p75:e.cls,p90:e.cls}}:{},...typeof e.fcp==`number`?{fcp:{p50:e.fcp,p75:e.fcp,p90:e.fcp}}:{},...typeof e.ttfb==`number`?{ttfb:{p50:e.ttfb,p75:e.ttfb,p90:e.ttfb}}:{}};a.push(n)}for(let e of i.worst_pages??[])a.push({url:e.path,device:t?.device??void 0,samples:e.sample_count,lcp:{p50:e.lcp_p75,p75:e.lcp_p75,p90:e.lcp_p75}});let o=new Date,s=new Date(Date.now()-B(t?.window??`7d`)*24*3600*1e3);return f.parse({vitals:a,windowStart:s.toISOString(),windowEnd:o.toISOString()})}async getFunnel(e,t,n=`30d`,r){let i=new URLSearchParams({site_id:e,window:n}),a=await this.v2RequestRaw(`/v1/cli/funnels/${encodeURIComponent(t)}?${i.toString()}`,{},r),o=a.total_entries??0,s=(a.steps??[]).map(e=>({id:`step-${e.order}`,name:e.name,visitors:e.visitors,conversions:e.visitors,dropOff:Math.max(0,Math.min(1,e.dropoffPct/100))})),c=s[s.length-1],l=c?.visitors??0,u=o>0?Math.min(1,l/o):0,d=new Date,f=new Date(Date.now()-B(n)*24*3600*1e3);return m.parse({funnelId:a.id??t,name:a.name??t,steps:s,totalEntries:o,totalCompletions:l,conversionRate:u,windowStart:f.toISOString(),windowEnd:d.toISOString()})}async listFunnels(e,t){let n=new URLSearchParams({site_id:e}),r=await this.v2RequestRaw(`/v1/cli/funnels?${n.toString()}`,{},t);return g.parse({funnels:(r.funnels??[]).map(e=>({id:e.id,name:e.name,stepCount:e.step_count}))})}async getStats(e,t=`24h`,n){let r=new URLSearchParams({site_id:e,range:t}),i=await this.v2RequestRaw(`/v1/cli/stats?${r.toString()}`,{},n),a=i.visitors??0,o=i.pageviews??0,s=a,c=s>0?o/s:0,l=typeof i.bounceRate==`number`?Math.max(0,Math.min(1,i.bounceRate)):c>0?Math.max(0,Math.min(1,1/Math.max(1,c))):0,u=i.avgSessionSec??0,d=new Date,f=new Date(Date.now()-B(t)*24*3600*1e3);return _.parse({visitors:a,pageviews:o,sessions:s,bounceRate:l,avgSessionSec:u,topPages:i.topPage?[{url:i.topPage.path,views:i.topPage.views}]:[],topCountries:i.topSource?[{country:i.topSource.channel,visitors:i.topSource.visitors}]:[],windowStart:f.toISOString(),windowEnd:d.toISOString(),daily:i.daily})}async getGoals(e,t){let n=new URLSearchParams({site_id:e});return this.v2Request(`/v1/cli/goals?${n.toString()}`,y,{},t)}async getLive(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/live?${n.toString()}`,t)}async getPages(e,t,n){let r=new URLSearchParams({site_id:e});return t&&r.set(`range`,t),await this.v2RawJson(`/v1/cli/pages?${r.toString()}`,n)}async getDevices(e,t,n){let r=new URLSearchParams({site_id:e});return t&&r.set(`range`,t),await this.v2RawJson(`/v1/cli/devices?${r.toString()}`,n)}async getGeo(e,t,n){let r=new URLSearchParams({site_id:e});return t&&r.set(`range`,t),await this.v2RawJson(`/v1/cli/geo?${r.toString()}`,n)}async getRetention(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/retention?${n.toString()}`,t)}async getUptime(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/uptime?${n.toString()}`,t)}async getSessions(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/sessions?${n.toString()}`,t)}async getHeatmaps(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/heatmaps?${n.toString()}`,t)}async getJourneys(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/journeys?${n.toString()}`,t)}async getInsights(e,t){let n=new URLSearchParams({site_id:e});return await this.v2RawJson(`/v1/cli/insights?${n.toString()}`,t)}async v2RawJson(e,n){let r=`${this.v2ApiBase}${e}`,i=await this.v2Headers(),a=await this.v2Fetch(r,{headers:i,signal:n});if(a.status===401&&this.v2Token){this.v2Token=null;let e=await this.v2Headers();a=await this.v2Fetch(r,{headers:e,signal:n})}if(!a.ok){let n=await a.text().catch(()=>``),r=n;try{r=JSON.parse(n)}catch{}throw new t(a.status,r,`GET ${e} → ${a.status}`)}return a.json()}streamCompaniesV2(e,t){return this.streamChannel(e,`companies`,t)}streamCompanies(e,t){return z(`streamCompanies`,2)}async getCompanies(e){R(`getCompanies`,2)}async getCompaniesSnapshot(e,t,n){let r=new URLSearchParams({site_id:e});t?.window&&r.set(`window`,t.window),typeof t?.limit==`number`&&r.set(`limit`,String(t.limit));let i=await this.v2RequestRaw(`/v1/cli/companies?${r.toString()}`,{},n);return D.parse(i)}async runSqlQuery(e,n,r,i){let a=`${this.v2ApiBase}/v1/cli/query`,o=await this.v2Headers({"Content-Type":`application/json`}),s=await this.v2Fetch(a,{method:`POST`,headers:o,signal:i,body:JSON.stringify({site_id:e,sql:n,...r?.maxRows?{max_rows:r.maxRows}:{}})});if(!s.ok){let e=await s.text().catch(()=>``),n=e;try{n=JSON.parse(e)}catch{}throw new t(s.status,n,`POST /v1/cli/query → ${s.status}`)}let c=await s.json();return O.parse(c.data??c)}async getDeploys(e,t,n){let r=new URLSearchParams({site_id:e});t?.since&&r.set(`since`,t.since),typeof t?.limit==`number`&&r.set(`limit`,String(t.limit)),t?.branch&&r.set(`branch`,t.branch),t?.onChartOnly&&r.set(`on_chart_only`,`true`);let i=await this.v2RequestRaw(`/v1/cli/deploys?${r.toString()}`,{},n);return A.parse(i)}async getProjects(e,t){let n=new URLSearchParams({site_id:e}),r=await this.v2RequestRaw(`/v1/cli/projects?${n.toString()}`,{},t);return M.parse(r)}async getErrors(e,t,n){let r=new URLSearchParams({site_id:e});t?.window&&r.set(`window`,t.window),typeof t?.limit==`number`&&r.set(`limit`,String(t.limit));let i=await this.v2RequestRaw(`/v1/cli/errors?${r.toString()}`,{},n);return T.parse(i)}streamErrorsV2(e,t){return this.streamChannel(e,`errors`,t)}streamErrors(e,t){return z(`streamErrors`,2)}async getEventsHistory(e,t){R(`getEventsHistory`,2)}forwardWebhook(e,t){return z(`forwardWebhook`,2)}async registerTunnel(e,t){R(`registerTunnel`,2)}async queryRaw(e,t,n){R(`queryRaw`,3)}async getCompletions(e,t){R(`getCompletions`,3)}async listApiKeys(e){return await this.v2RawJson(`/v1/cli/mutate/keys`,e)}async createApiKey(e,t){return await this.v2Mutate(`/v1/cli/mutate/keys`,`POST`,e,t)}async deleteApiKey(e,t){return await this.v2Mutate(`/v1/cli/mutate/keys/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async addDomain(e,t){return await this.v2Mutate(`/v1/cli/mutate/domains`,`POST`,e,t)}async deleteDomain(e,t){return await this.v2Mutate(`/v1/cli/mutate/domains/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async listTeam(e){return await this.v2RawJson(`/v1/cli/mutate/team`,e)}async inviteTeamMember(e,t){return await this.v2Mutate(`/v1/cli/mutate/team/invite`,`POST`,e,t)}async removeTeamMember(e,t){return await this.v2Mutate(`/v1/cli/mutate/team/members/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async updateTeamMemberRole(e,t,n){return await this.v2Mutate(`/v1/cli/mutate/team/members/${encodeURIComponent(e)}/role`,`PATCH`,{role:t},n)}async updateProfile(e,t){return await this.v2Mutate(`/v1/cli/mutate/profile`,`POST`,e,t)}async getPlanInfo(e){return await this.v2RawJson(`/v1/cli/mutate/plans/info`,e)}async upgradePlan(e,t){return await this.v2Mutate(`/v1/cli/mutate/plans/upgrade`,`POST`,{targetPlan:e},t)}async cancelPlan(e){return await this.v2Mutate(`/v1/cli/mutate/plans/cancel`,`POST`,{},e)}async getSettings(e){return await this.v2RawJson(`/v1/cli/mutate/settings`,e)}async getUsage(e){return await this.v2RawJson(`/v1/cli/mutate/usage`,e)}async setSetting(e,t,n){return await this.v2Mutate(`/v1/cli/mutate/settings`,`POST`,{key:e,value:t},n)}async listIntegrations(e){return await this.v2RawJson(`/v1/cli/mutate/integrations`,e)}async disconnectIntegration(e,t){return await this.v2Mutate(`/v1/cli/mutate/integrations/disconnect`,`POST`,{name:e},t)}async listGoals(e){return await this.v2RawJson(`/v1/cli/mutate/goals`,e)}async createGoal(e,t){return await this.v2Mutate(`/v1/cli/mutate/goals`,`POST`,e,t)}async deleteGoal(e,t){return await this.v2Mutate(`/v1/cli/mutate/goals/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async listNotes(e){return await this.v2RawJson(`/v1/cli/mutate/notes`,e)}async createNote(e,t){return await this.v2Mutate(`/v1/cli/mutate/notes`,`POST`,e,t)}async deleteNote(e,t){return await this.v2Mutate(`/v1/cli/mutate/notes/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async listAgencyClients(e){return await this.v2RawJson(`/v1/cli/mutate/agency/clients`,e)}async addAgencyClient(e,t){return await this.v2Mutate(`/v1/cli/mutate/agency/clients`,`POST`,e,t)}async removeAgencyClient(e,t){return await this.v2Mutate(`/v1/cli/mutate/agency/clients/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async sendAgencyReport(e,t){return await this.v2Mutate(`/v1/cli/mutate/agency/report/${encodeURIComponent(e)}`,`POST`,{},t)}async listWebhooks(e){return await this.v2RawJson(`/v1/cli/mutate/webhooks`,e)}async createWebhook(e,t){return await this.v2Mutate(`/v1/cli/mutate/webhooks`,`POST`,e,t)}async deleteWebhook(e,t){return await this.v2Mutate(`/v1/cli/mutate/webhooks/${encodeURIComponent(e)}`,`DELETE`,void 0,t)}async rotateWebhookSecret(e,t){return await this.v2Mutate(`/v1/cli/mutate/webhooks/${encodeURIComponent(e)}/rotate`,`POST`,{},t)}async testWebhook(e,t){return await this.v2Mutate(`/v1/cli/mutate/webhooks/${encodeURIComponent(e)}/test`,`POST`,{},t)}async getAuditLogs(e,t){let n=new URLSearchParams;e.since&&n.set(`since`,e.since),e.action&&n.set(`action`,e.action),e.actor&&n.set(`actor`,e.actor);let r=n.toString()?`/v1/cli/mutate/audit/logs?${n.toString()}`:`/v1/cli/mutate/audit/logs`;return await this.v2RawJson(r,t)}async exportAudit(e,n){let r=`${this.v2ApiBase}/v1/cli/mutate/audit/export?format=${encodeURIComponent(e.format)}`,i=await this.v2Headers(),a=await this.v2Fetch(r,{headers:i,signal:n});if(a.status===401&&this.v2Token){this.v2Token=null;let e=await this.v2Headers();a=await this.v2Fetch(r,{headers:e,signal:n})}if(!a.ok){let e=await a.text().catch(()=>``),n=e;try{n=JSON.parse(e)}catch{}throw new t(a.status,n,`GET /v1/cli/mutate/audit/export → ${a.status}`)}return a.text()}async getShare(e,t){let n=new URLSearchParams({siteId:e});return await this.v2RawJson(`/v1/cli/mutate/share?${n.toString()}`,t)}async enableShare(e,t){return await this.v2Mutate(`/v1/cli/mutate/share/enable`,`POST`,{siteId:e},t)}async disableShare(e,t){return await this.v2Mutate(`/v1/cli/mutate/share/disable`,`POST`,{siteId:e},t)}async v2Mutate(e,n,r,i){let a=`${this.v2ApiBase}${e}`,o=await this.v2Headers(r===void 0?{}:{"Content-Type":`application/json`}),s={method:n,headers:o,signal:i};r!==void 0&&(s.body=JSON.stringify(r));let c=await this.v2Fetch(a,s);if(c.status===401&&this.v2Token){this.v2Token=null;let e=await this.v2Headers(r===void 0?{}:{"Content-Type":`application/json`});c=await this.v2Fetch(a,{...s,headers:e})}if(!c.ok){let r=await c.text().catch(()=>``),i=r;try{i=JSON.parse(r)}catch{}throw new t(c.status,i,`${n} ${e} → ${c.status}`)}let l=c.headers.get(`content-type`)??``;return l.includes(`application/json`)?c.json():{}}async*streamChannel(e,t,n){let{connectWs:r}=await import(`./ws-client-MoEdfqAO.js`),i=this.v2ApiBase.replace(/^https:\/\//,`wss://`).replace(/^http:\/\//,`ws://`),a=`${i}/v1/cli/stream/${encodeURIComponent(e)}?channels=${t}`,o=this.v2Token?.accessToken;for await(let e of r({url:a,bearer:o,signal:n})){if(e.type!==`message`)continue;let t=e.data;if(t&&typeof t==`object`){let e=t;yield e.event??t}}}async createTunnel(e,n,r){let i=`${this.v2ApiBase}/v1/cli/tunnels`,a=await this.v2Headers({"Content-Type":`application/json`}),o=await this.v2Fetch(i,{method:`POST`,headers:a,signal:r,body:JSON.stringify({site_id:e,target_pattern:n})});if(!o.ok){let e=await o.text().catch(()=>``);throw new t(o.status,e,`POST /v1/cli/tunnels → ${o.status}`)}let s=await o.json(),c=s.data??{};if(!c.tunnel_key||!c.public_url||!c.ws_url)throw new t(500,s,`createTunnel: malformed response`);return{tunnelKey:c.tunnel_key,publicUrl:c.public_url,wsUrl:c.ws_url,siteId:c.site_id??e}}tunnelClient(e){let t=this.v2Token?.accessToken;return{start:async(n,r)=>{let{WsTunnelClient:i}=await import(`./ws-client-MoEdfqAO.js`),a=new i({url:e,bearer:t,signal:r});await a.start(n)}}}async listAlerts(e,t){let n=new URLSearchParams({site_id:e}),r=await this.v2RawJson(`/v1/cli/alerts?${n.toString()}`,t),i=(()=>{if(Array.isArray(r))return r;let e=r;if(Array.isArray(e?.alerts))return e.alerts;if(e?.data&&typeof e.data==`object`){let t=e.data;if(Array.isArray(t.alerts))return t.alerts;if(Array.isArray(e.data))return e.data}return[]})();return i.map(H)}async createAlert(e,t,n){let r=t.op===`gt`?`greater_than`:(t.op,`less_than`),i=t.channel===`webhook`?`webhook`:`email`;if(i===`email`&&!t.email){let e=Error(`--channel email requires --email <addr>`);throw e.name=`ValidationError`,e}let a={site_id:e,name:t.name??`${t.metric} ${t.op} ${t.threshold}`,metric:t.metric,threshold:t.threshold,comparator:r,window:t.window,channel:i,email:t.email??``},o=await this.v2Mutate(`/v1/cli/alerts`,`POST`,a,n),s=`data`in o&&o.data?o.data:o;return H(s)}async deleteAlert(e,t,n){let r=new URLSearchParams({site_id:e});await this.v2Mutate(`/v1/cli/alerts/${encodeURIComponent(t)}?${r.toString()}`,`DELETE`,void 0,n)}};function H(e){let t=(()=>e.op===`gt`||e.op===`lt`?e.op:e.comparator===`greater_than`?`gt`:e.comparator===`less_than`?`lt`:`gt`)();return{id:String(e.id),metric:e.metric,op:t,threshold:e.threshold,window:e.window,createdAt:e.createdAt??e.created_at??null}}export{V as ApiV2Client};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config-JVhBplSX.js";import"./api-CdcB84ie.js";import{readToken as t}from"./token-store-BvSCse1t.js";import{ApiV2Client as n}from"./api-v2-D0mvt__4.js";import{requireTier as r}from"./tier-DDIroQbc.js";import{resolve as i}from"node:path";import{writeFile as a}from"node:fs/promises";function o(e){return e?e.length>12?`${e.slice(0,8)}…${e.slice(-4)}`:e:`—`}function s(e){return e?new Date(e).toISOString().slice(0,19).replace(`T`,` `):`—`}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.getAuditLogs({since:c.since??`7d`,action:c.filterAction,actor:c.actor});if(c.json)return process.stdout.write(JSON.stringify(e,null,2)+`
|
|
2
2
|
`),0;if(e.logs.length===0)return process.stdout.write(`No audit log entries in the last ${c.since??`7d`}. Try --since 30d for a wider window.\n`),0;let t=[`when`,`action`,`resource`,`actor`],n=[19,32,28,14],r=e=>e.map((e,t)=>(e??``).padEnd(n[t])).join(` `);process.stdout.write(`
|
|
3
3
|
`+r(t)+`
|
|
4
4
|
`),process.stdout.write(r(n.map(e=>`─`.repeat(e)))+`
|