@zenovay/cli 1.0.0 → 1.0.2
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-BkP3oeh2.js} +1 -1
- package/dist/{alerts-Be0XKEUX.js → alerts-BQ0EMdBT.js} +1 -1
- package/dist/{analytical-screen-BU2yCSg_.js → analytical-screen-BvQa8oH6.js} +1 -1
- package/dist/analytics-S6AFt20R.js +1 -0
- package/dist/{annotation-dveH657H.js → annotation-CZ2bEuyD.js} +1 -1
- package/dist/{api-hWp9s3Y8.js → api-CdcB84ie.js} +1 -1
- package/dist/{api-keys-DKQX5aL9.js → api-keys-CLol-4YC.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-CFlSb0g5.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-Cpb3yv2Q.js} +1 -1
- package/dist/{completions-DKyjFPMK.js → completions-XLznfo7H.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/{csv-emit-CmlDBfbA.js → csv-emit-B-5km-O-.js} +1 -1
- package/dist/{deploys-BqQmCzVb.js → deploys-DZ0IR9Re.js} +1 -1
- package/dist/{devices-CUgpkbAC.js → devices-C_NjBY89.js} +1 -1
- package/dist/{doctor-D1bGGwtN.js → doctor-BsEuqZTb.js} +1 -1
- package/dist/{domains-iRmYn9G7.js → domains-ByXV1O4R.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-DPRcy7WT.js} +1 -1
- package/dist/{events-tail-CRgba_gO.js → events-tail-DEdVkmT0.js} +1 -1
- package/dist/{export-Csl7rWLW.js → export-DhSRfpg_.js} +1 -1
- package/dist/{funnel-B36lGX2i.js → funnel-Cb4-3RJB.js} +1 -1
- package/dist/{geo-CPt2etQd.js → geo-ReUNKl3F.js} +1 -1
- package/dist/{globe-yy_-G4K8.js → globe-DwaTDQns.js} +1 -1
- package/dist/{goals-BTzgvDOK.js → goals-Ds0QZ4H6.js} +1 -1
- package/dist/{health-D26VB-iZ.js → health-D6w7hF5q.js} +1 -1
- package/dist/{health-RsLcvYTb.js → health-DTR77eQW.js} +1 -1
- package/dist/{heatmaps-D4o0Ghjn.js → heatmaps-B-As729q.js} +1 -1
- package/dist/{home-B8CoN9Hd.js → home-DGYBSPWi.js} +1 -1
- package/dist/{init-Cee2-8Kd.js → init-igNlvq0N.js} +6 -6
- package/dist/init-x1CXZTzr.js +1 -0
- package/dist/{insights-B0L6kIxY.js → insights-BiqMftak.js} +1 -1
- package/dist/{integrations-CJ9Pa-II.js → integrations-CCvt4xb_.js} +1 -1
- package/dist/{journeys--jjaTA3C.js → journeys-CogDUObU.js} +1 -1
- package/dist/{live-CuVd6yRs.js → live-BNX4HBCf.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-BoUfEnN9.js} +1 -1
- package/dist/{notes-jV1DYMp_.js → notes-BrY4efpr.js} +1 -1
- package/dist/{analytics-D7vhDrdG.js → overview-CmTIumZy.js} +2 -2
- package/dist/overview-L8jqiSuU.js +1 -0
- package/dist/{pages-0DLiuGYc.js → pages-BYVz90uO.js} +1 -1
- package/dist/{plans-D4o6-tbv.js → plans-DT8hilXl.js} +1 -1
- package/dist/{profile-Cm5RFs_L.js → profile-CDY3kFEq.js} +1 -1
- package/dist/{projects-BTTgnjOZ.js → projects-BdRZaLg8.js} +1 -1
- package/dist/{query-yn10M321.js → query-DLC0vi-K.js} +1 -1
- package/dist/{resolve-site-BLrtFOyW.js → resolve-site-BTVBMF1C.js} +1 -1
- package/dist/{retention-DpBuavgY.js → retention-DQHXVSG0.js} +1 -1
- package/dist/{revenue-Bv1Cqzjr.js → revenue-CitFZ4DN.js} +1 -1
- package/dist/{self-test-Cml0QXeA.js → self-test-BcCqMRQ9.js} +2 -2
- package/dist/{sessions-B0RwtHvP.js → sessions-dPZ32wpz.js} +1 -1
- package/dist/{settings-i4TqMmAY.js → settings-DO8UOasX.js} +1 -1
- package/dist/{share-DTHFqTzp.js → share-BkvKZuPo.js} +1 -1
- package/dist/{site-switcher-D_JBKFaR.js → site-switcher-BAoYWp18.js} +1 -1
- package/dist/{sources-B39BFFKF.js → sources-lvpcvTTz.js} +1 -1
- package/dist/{stats-Dh9MQAXx.js → stats-EeSDu70A.js} +1 -1
- package/dist/{status-agent-C3q7fOEs.js → status-agent-BLIJc81G.js} +1 -1
- package/dist/{team-DZtvClMF.js → team-Bw6dcpI2.js} +1 -1
- package/dist/{teams-CqJFecKB.js → teams-cwzXaqBH.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-CgyMy4hV.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-DkMxLJbM.js} +1 -1
- package/dist/{uptime-Ck1GdjRR.js → uptime-BA8vRzJQ.js} +1 -1
- package/dist/{usage-BN_mEsal.js → usage-CkyXScnm.js} +1 -1
- package/dist/{use-NGqXzASp.js → use-BW8rVPgW.js} +1 -1
- package/dist/{visitors-BCz-O9rK.js → visitors-mjvSIKkI.js} +1 -1
- package/dist/{vitals-Dx_eY6tW.js → vitals-D3sMQksQ.js} +1 -1
- package/dist/{webhooks-BR1D3o5S.js → webhooks-D1PNfhgJ.js} +1 -1
- package/dist/{webhooks-forward-CpXm4GHn.js → webhooks-forward-B8nnKB4f.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/dist/watch-CP-Klikt.js +0 -1
- /package/dist/{commands-BE8-kQ9U.js → commands-DVRYYbbn.js} +0 -0
- /package/dist/{csv-emit-C-9o-imN.js → csv-emit-BiRGo6SK.js} +0 -0
- /package/dist/{examples-DikBW-H2.js → examples-CsQBLv9W.js} +0 -0
- /package/dist/{range-tabs-BbJdVWNV.js → range-tabs-CH2cEXOf.js} +0 -0
- /package/dist/{themes-6H0KlK3b.js → themes-BC8U4Od4.js} +0 -0
- /package/dist/{tour-fOYY-mK0.js → tour-ChHRo89U.js} +0 -0
- /package/dist/{ui-C5Te-OTJ.js → ui-BTnLAro-.js} +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
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"./formatter-C4YSOKuq.js";import{emit$1 as r,isHeadless as i}from"./emit-D4YlMlzk.js";import{openInBrowser as a}from"./open-url-BtI5aLgL.js";import"./theme-Brz9wK0w.js";import{Banner as o,Panel as s,useTheme as c}from"./panel-CTtQ2ue6.js";import"./prompt-BXvg2B4R.js";import{Keybar as l}from"./keybar-DO5OoZy9.js";import{resolveSiteId as u}from"./resolve-site-BTVBMF1C.js";import{DataTable as d}from"./data-table-BhKjjiOS.js";import{EmptyState as f}from"./empty-state-D-krMX62.js";import{deepLinkFor as p}from"./keybar-deep-link-B4VJn2ko.js";import{useFullscreen as m}from"./use-fullscreen-ucSyZkjO.js";import{RangeTabs as h,rangeForKey as g}from"./range-tabs-CH2cEXOf.js";import{useSiteSwitcher as _}from"./site-switcher-BAoYWp18.js";import{Box as v,Text as y,render as b,useApp as x,useInput as S}from"ink";import C,{useEffect as w,useState as T}from"react";import E from"ink-spinner";async function D(a){let o=await e(),s=await t({strict:!1});if(!s)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let c=new n({config:o,cliVersion:a.cliVersion,token:s}),l,d;try{({siteId:l,site:d}=await u(c,{explicit:a.siteId,headless:!!(a.json||a.csv||a.tsv||a.ndjson),cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let f=d?.url?d.url.replace(/^https?:\/\//,``).replace(/\/$/,``):d?.name??l;if(i(a)){let e=await c.getPages(l);if(a.csv||a.tsv){let{writeCsv:t}=await import(`./csv-emit-B-5km-O-.js`);return t(e,[`path`,`views`,`uniqueVisitors`,`avgTime`,`bounceRate`],a.tsv?`tsv`:`csv`)}if(a.ndjson){for(let t of e)process.stdout.write(JSON.stringify(t)+`
|
|
2
2
|
`);return 0}return r({type:`pages.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=b(C.createElement(O,{api:c,siteId:l,siteLabel:f,cliVersion:a.cliVersion,onExit:n=>{t(),e(n)}}))})}const O=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{m();let{exit:u}=x(),{theme:b}=c(),[D,O]=T(null),[k,A]=T(!0),[j,M]=T(null),[N,P]=T(`24h`),[F,I]=T(t),[L,R]=T(n),z=_(e,F,e=>{I(e.id),R(e.url.replace(/^https?:\/\//,``).replace(/\/$/,``)),O(null)});S((e,t)=>{if(z.open){(t.escape||e===`s`)&&z.close();return}if(e===`o`||e===`O`){a(p(`pages`,{siteId:F}));return}if(e===`s`){z.toggle();return}let n=g(e);if(n){P(n);return}e===`q`&&(u(),i(0))}),w(()=>{let t=!1;return D===null&&A(!0),(async()=>{try{let n=await e.getPages(F,N);t||(O(n),A(!1))}catch(e){t||(M(e.message),A(!1))}})(),()=>{t=!0}},[e,F,N]);let B=`pages · ${L} · ${N}`;if(k)return C.createElement(v,{flexDirection:`column`},C.createElement(o,{version:r,subtitle:B}),C.createElement(h,{range:N}),C.createElement(s,{title:`Loading`,state:`busy`},C.createElement(v,null,C.createElement(y,{color:b.accent},C.createElement(E,{type:`dots`})),C.createElement(y,null,` Fetching pages…`))));if(j)return C.createElement(v,{flexDirection:`column`},C.createElement(o,{version:r,subtitle:B}),C.createElement(h,{range:N}),C.createElement(f,{reason:`error`,headline:`Failed to load`,hint:j}));if(!D||D.length===0)return C.createElement(v,{flexDirection:`column`},C.createElement(o,{version:r,subtitle:B}),C.createElement(h,{range:N}),C.createElement(f,{reason:`no-data`,headline:`No pages in this window`,hint:`Press 1-4 to widen the range, [s] to switch site, or visit your site to send an event`}),z.overlay,C.createElement(l,{items:[{key:`1-4`,label:`range`},{key:`s`,label:`site`},{key:`q`,label:`quit`}],active:`s`}));let V=[{key:`path`,label:`path`,width:36},{key:`views`,label:`views`,align:`right`,width:8},{key:`uniqueVisitors`,label:`unique`,align:`right`,width:8},{key:`avgTime`,label:`avg time`,align:`right`,width:9,format:e=>typeof e==`number`?`${Math.round(e)}s`:`—`},{key:`bounceRate`,label:`bounce`,align:`right`,width:7,format:e=>typeof e==`number`?`${(e*100).toFixed(0)}%`:`—`}],H=process.stdout.rows??40,U=Math.max(5,H-15),W=D.slice(0,U),G=D.length-W.length;return C.createElement(v,{flexDirection:`column`},C.createElement(o,{version:r,subtitle:B}),C.createElement(h,{range:N}),C.createElement(s,{title:`Top pages (${D.length})`},C.createElement(d,{columns:V,data:W,zebra:!0}),G>0?C.createElement(y,{color:b.dim},` +${G} more · run with --json for all`):null),z.overlay,C.createElement(l,{items:[{key:`1-4`,label:`range`},{key:`s`,label:`site`},{key:`o`,label:`browser`},{key:`q`,label:`quit`}],active:`o`}))};export{D as pagesCommand};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config-JVhBplSX.js";import{ApiError 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{openInBrowser as i}from"./open-url-BtI5aLgL.js";import{fmtCurrency as a,formatTable as o}from"./fmt-xxIPQJX-.js";async function s(s){let c=await e(),l=await n({strict:!1}),u=new r({config:c,cliVersion:s.cliVersion,token:l});try{switch(s.action){case`info`:{let e=await u.getPlanInfo();if(s.json)return process.stdout.write(JSON.stringify(e,null,2)+`
|
|
2
2
|
`),0;let t=[{key:`plan`,value:e.plan},{key:`status`,value:`${e.status}${e.cancelAtPeriodEnd?` (cancels at period end)`:``}`},{key:`current period`,value:`${e.currentPeriodStart??`—`} → ${e.currentPeriodEnd??`—`}`},{key:`websites in use`,value:String(e.usage.websites)}];e.nextInvoice&&t.push({key:`next invoice`,value:`${a(e.nextInvoice.amountDue,e.nextInvoice.currency)} on ${e.nextInvoice.periodEnd??`—`}`});let n=[{key:`key`,header:`field`,width:18},{key:`value`,header:`value`,width:48}];return process.stdout.write(`
|
|
3
3
|
`),process.stdout.write(o({rows:t,cols:n})),process.stdout.write(`
|
|
4
4
|
`),0}case`upgrade`:if(!s.targetPlan)return process.stderr.write("Error: pass <plan> (pro | scale | enterprise) — e.g. `zenovay plans upgrade pro`.\n"),2;try{let e=await u.upgradePlan(s.targetPlan);return s.json?(process.stdout.write(JSON.stringify(e,null,2)+`
|
|
@@ -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";async function r(r){let i=await e(),a=await t({strict:!1}),o=new n({config:i,cliVersion:r.cliVersion,token:a});try{switch(r.action){case`show`:{let e=await o.me();if(r.json)return process.stdout.write(JSON.stringify(e,null,2)+`
|
|
2
2
|
`),0;let t=[``,` email: ${e.user.email}`,` name: ${e.user.name??`—`}`,` user id: ${e.user.id}`,``];if(e.teams&&e.teams.length>0){t.push(` TEAMS (${e.teams.length})`),t.push(` name plan role sites`),t.push(` ─ ──────────────────────────── ─────────── ─────── ─────`);for(let n of e.teams){let e=n.isCurrent?`*`:` `,r=(n.name??`—`).padEnd(28).slice(0,28),i=n.plan.padEnd(11),a=n.role.padEnd(7),o=String(n.siteCount).padStart(5);t.push(` ${e} ${r} ${i} ${a} ${o}`)}t.push(``),t.push(" * = current team. Switch with `zenovay teams switch <name>` or pass `--team <name>` per command.")}else e.team&&(t.push(` team: ${e.team.name} (${e.team.id})`),t.push(` plan: ${e.team.plan}`));return t.push(``),process.stdout.write(t.join(`
|
|
3
3
|
`)),0}case`edit`:{if(r.name===void 0&&r.notifications===void 0)return process.stderr.write("Error: pass --name <n> or --notifications <email|none> for `profile edit`.\n"),2;let e={};r.name!==void 0&&(e.name=r.name),r.notifications!==void 0&&(e.notifications=r.notifications);let t=await o.updateProfile(e);return r.json?(process.stdout.write(JSON.stringify(t,null,2)+`
|
|
4
4
|
`),0):(process.stdout.write(`✔ Profile updated.${t.name?` name → ${t.name}`:``}${t.notifications?` notifications → ${t.notifications}`:``}\n`),0)}}}catch(e){return process.stderr.write(`✗ ${e.message}\n`),1}}export{r as profileCommand};
|
|
@@ -1,2 +1,2 @@
|
|
|
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"./error-codes-ByhvHx2M.js";import"./telemetry-BV-xvfdt.js";import{ApiV2Client as n}from"./api-v2-D0mvt__4.js";import{formatTabular as r,selectFormat as i}from"./formatter-C4YSOKuq.js";import"./client-ntsEXSVC.js";import"./theme-Brz9wK0w.js";import"./panel-CTtQ2ue6.js";import"./prompt-BXvg2B4R.js";import"./keybar-DO5OoZy9.js";import"./chat-panel-D9IjovCR.js";import{resolveSiteId as a}from"./resolve-site-BTVBMF1C.js";import{DataTable as o}from"./data-table-BhKjjiOS.js";import{EmptyState as s}from"./empty-state-D-krMX62.js";import"./grid-CMwhs-Ms.js";import"./use-fullscreen-ucSyZkjO.js";import"./range-tabs-CH2cEXOf.js";import{runAnalyticalScreen as c}from"./analytical-screen-BvQa8oH6.js";import l from"react";async function u(u){let d=await e(),f=await t({strict:!1}),p=new n({config:d,cliVersion:u.cliVersion,token:f}),m,h;try{({siteId:m,site:h}=await a(p,{explicit:u.siteId,headless:!!(u.json||u.csv||u.tsv||u.ndjson),cliVersion:u.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let g=i(u),_=h?.url?h.url.replace(/^https?:\/\//,``).replace(/\/$/,``):h?.name??m,v=[{key:`isCurrent`,label:``,width:1,format:e=>e?`*`:` `},{key:`name`,label:`project`},{key:`domain`,label:`domain`,format:e=>String(e??`—`)},{key:`tier`,label:`tier`},{key:`pageviews24h`,label:`24h pv`,width:8,align:`right`},{key:`id`,label:`id`}];return c({cliVersion:u.cliVersion,title:`projects · ${_}`,commandName:`projects`,authToken:f?.accessToken??null,refreshIntervalMs:0,fetcher:e=>p.getProjects(m,e),format:g,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){if(t===`ndjson`)for(let t of e.projects)process.stdout.write(JSON.stringify(t)+`
|
|
2
2
|
`);else process.stdout.write(JSON.stringify(e,null,2));return}process.stdout.write(r(e.projects,[`id`,`name`,`domain`,`tier`,`pageviews24h`,`isCurrent`],t))},keybindings:{s:{label:`switch project (logout + login)`,handler:()=>{process.stderr.write("To switch project: run `zenovay logout` then `zenovay login`.\n")}}},panels:[{id:`projects`,title:`Projects`,render:e=>e.projects.length===0?l.createElement(s,{reason:`no-data`,headline:`No projects yet`,hint:"Add a site in the dashboard, then run `zenovay init` to install tracking."}):l.createElement(o,{data:e.projects,columns:v,headerStyle:`accent`})}]})}export{u as projectsCommand};
|
|
@@ -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{formatTabular as i,selectFormat as a}from"./formatter-C4YSOKuq.js";import"./theme-Brz9wK0w.js";import{Banner as o,Panel as s,useTheme as c}from"./panel-CTtQ2ue6.js";import"./prompt-BXvg2B4R.js";import{Keybar as l}from"./keybar-DO5OoZy9.js";import{resolveSiteId as u}from"./resolve-site-BTVBMF1C.js";import{DataTable as d}from"./data-table-BhKjjiOS.js";import{EmptyState as f}from"./empty-state-D-krMX62.js";import{useFullscreen as p}from"./use-fullscreen-ucSyZkjO.js";import{Box as m,Text as h,useApp as g,useInput as _}from"ink";import v,{useMemo as y,useState as b}from"react";import x from"ink-text-input";function S({api:e,siteId:t,siteLabel:n,cliVersion:r,maxRows:i}){p();let{theme:a}=c(),{exit:u}=g(),[S,C]=b(``),[w,T]=b(null),[E,D]=b(null),[O,k]=b(!1),[A,j]=b([]);_((e,t)=>{t.escape&&u()});let M=async n=>{if(n.trim()){if(n.trim()===`\\q`||n.trim()===`exit`||n.trim()===`quit`){u();return}j(e=>[...e,n]),k(!0),D(null);try{let r=await e.runSqlQuery(t,n,{maxRows:i});T(r)}catch(e){D(e.message)}finally{k(!1),C(``)}}},N=y(()=>w?w.columns.map(e=>({key:e,label:e,width:18,format:e=>e==null?`∅`:String(e)})):[],[w]),P=process.stdout.rows??40,F=Math.max(8,P-16),I=Math.min(5,Math.max(2,Math.floor(F*.3))),L=Math.max(4,F-I),R=A.slice(-I),z=w?w.rows.slice(0,L):[],B=w?w.row_count-z.length:0;return v.createElement(m,{flexDirection:`column`},v.createElement(o,{version:r,subtitle:`query · ${n}`,live:w!==null}),v.createElement(m,{marginTop:1},v.createElement(s,{title:`History`,state:`idle`},A.length===0?v.createElement(h,{color:a.dim},`Type SQL below and press enter. \\q or Esc to exit.`):R.map((e,t)=>v.createElement(h,{key:t,color:a.muted,wrap:`truncate`},`› ${e}`)))),v.createElement(m,null,v.createElement(h,{color:a.accent},`sql`,`>`,` `),v.createElement(x,{value:S,onChange:C,onSubmit:M})),E?v.createElement(m,{marginTop:1},v.createElement(s,{title:`Query error`,state:`err`},v.createElement(h,{color:a.error,wrap:`truncate`},E))):null,w?v.createElement(m,{marginTop:1},v.createElement(s,{title:`${w.row_count.toLocaleString()} rows · ${w.duration_ms}ms${w.truncated?` · truncated`:``}`,state:`ok`},w.row_count===0?v.createElement(f,{reason:`no-data`,headline:`0 rows`,hint:`The query ran fine but returned nothing — widen the WHERE clause or the time window.`}):v.createElement(v.Fragment,null,v.createElement(d,{data:z,columns:N,headerStyle:`accent`,zebra:!0}),B>0?v.createElement(h,{color:a.dim},` +${B.toLocaleString()} more · re-run with --json / --csv for all`):null))):null,v.createElement(m,{marginTop:1},v.createElement(h,{color:a.dim},O?`↻ running…`:``)),v.createElement(l,{items:[{key:`enter`,label:`run`},{key:`\\q`,label:`exit`},{key:`esc`,label:`quit`}],active:`enter`}))}async function C(o){let s=await e(),c=await t({strict:!1}),l=new n({config:s,cliVersion:o.cliVersion,token:c});try{await r(l,`scale`)}catch(e){return process.stderr.write(`${e.message}\n`),2}let d,f;try{({siteId:d,site:f}=await u(l,{explicit:o.siteId,headless:!!(o.json||o.csv||o.tsv||o.ndjson),cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let p=f?.url?f.url.replace(/^https?:\/\//,``).replace(/\/$/,``):f?.name??d,m=o.maxRows??1e3,h=a(o);if(o.sql)try{let e=await l.runSqlQuery(d,o.sql,{maxRows:m});if(h===`json`)process.stdout.write(JSON.stringify(e,null,2)),process.stdout.write(`
|
|
2
2
|
`);else if(h===`ndjson`)for(let t of e.rows)process.stdout.write(JSON.stringify(t)+`
|
|
3
3
|
`);else if(h===`csv`||h===`tsv`)process.stdout.write(i(e.rows,e.columns,h));else{let t=e.columns.map(t=>Math.max(t.length,...e.rows.map(e=>String(e[t]??``).length))),n=`+`+t.map(e=>`-`.repeat(e+2)).join(`+`)+`+`;process.stdout.write(n+`
|
|
4
4
|
`),process.stdout.write(`|`+e.columns.map((e,n)=>` ${e.padEnd(t[n]??0)} `).join(`|`)+`|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{readConfig as e,updateConfig as t}from"./config
|
|
1
|
+
import{readConfig as e,updateConfig as t}from"./config-JVhBplSX.js";import{Banner as n,Panel as r,useTheme as i}from"./panel-CTtQ2ue6.js";import{Select as a}from"./prompt-BXvg2B4R.js";import{Box as o,Text as s,render as c}from"ink";import l from"react";async function u(n,r){if(r.explicit&&r.explicit.trim()){let e=r.explicit.trim();if(!r.headless)try{let t=await n.getSites(),r=t.find(t=>t.id===e);if(r)return{siteId:e,site:r,saved:!1}}catch{}return{siteId:e,saved:!1}}let i=await e(),a;try{a=await n.getSites()}catch(e){if(i.defaultSiteId)return{siteId:i.defaultSiteId,saved:!1};throw Error(`Could not fetch your sites (${e.message}). Pass --site-id <ID> to bypass.`)}if(i.defaultSiteId){let e=a.find(e=>e.id===i.defaultSiteId);if(e)return{siteId:e.id,site:e,saved:!1};await t({defaultSiteId:void 0,defaultSiteName:void 0})}if(a.length===0)throw Error("No sites in your account. Run `zenovay init` to add one, or create one at app.zenovay.com.");if(a.length===1){let e=a[0];return await t({defaultSiteId:e.id,defaultSiteName:e.name}),{siteId:e.id,site:e,saved:!0}}if(r.headless||!process.stdout.isTTY){let e=a.map(e=>` ${e.name.padEnd(24)} ${e.url.padEnd(36)} ${e.id}`).join(`
|
|
2
2
|
`),t=a[0]?a[0].url.replace(/^https?:\/\//,``).replace(/\/$/,``):`<domain>`;throw Error(`Multiple sites found — pick one:\n${e}\n\nPass --site-id <ID>, set ZENOVAY_SITE=<ID>, or run \`zenovay use ${t}\` to set a default.`)}let o=await d(a,r.cliVersion);return await t({defaultSiteId:o.id,defaultSiteName:o.name}),{siteId:o.id,site:o,saved:!0}}function d(e,t=`0`){return new Promise((n,r)=>{let i,a=e=>{i?.(),n(e)},o=()=>{i?.(),r(Error(`Site selection cancelled`))},s=c(l.createElement(f,{sites:e,cliVersion:t,onPick:a,onCancel:o}));i=s.unmount})}const f=({sites:e,cliVersion:t,onPick:c})=>{let{theme:u}=i(),d=e.map(e=>({label:`${e.name.padEnd(28)} ${e.url.replace(/^https?:\/\//,``).padEnd(28)}`,value:e,description:e.trackingCode?`tracking: ${e.trackingCode}`:void 0}));return l.createElement(o,{flexDirection:`column`},l.createElement(n,{version:t,subtitle:`pick a site`}),l.createElement(r,{title:`Which site?`,state:`idle`},l.createElement(o,{marginBottom:1},l.createElement(s,{color:u.muted},"We'll save your pick as the default — re-run with `zenovay use --reset` to change it.")),l.createElement(a,{items:d,onSelect:c})))};export{u as resolveSiteId};
|
|
@@ -1 +1 @@
|
|
|
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"./formatter-C4YSOKuq.js";import{emit$1 as i,isHeadless as a}from"./emit-D4YlMlzk.js";import{openInBrowser as o}from"./open-url-BtI5aLgL.js";import"./theme-Brz9wK0w.js";import{Banner as s,Panel as c,useTheme as l}from"./panel-CTtQ2ue6.js";import"./prompt-BXvg2B4R.js";import{Keybar as u}from"./keybar-DO5OoZy9.js";import{resolveSiteId as d}from"./resolve-site-BTVBMF1C.js";import{EmptyState as f}from"./empty-state-D-krMX62.js";import{deepLinkFor as p}from"./keybar-deep-link-B4VJn2ko.js";import{useFullscreen as m}from"./use-fullscreen-ucSyZkjO.js";import{useSiteSwitcher as h}from"./site-switcher-BAoYWp18.js";import{Box as g,Text as _,render as v,useApp as y,useInput as b}from"ink";import x,{useEffect as S,useState as C}from"react";import w from"ink-spinner";function T(e,t){return!Number.isFinite(e)||e<=0?t.dim:e>=.6?t.accent:e>=.4?t.fg:e>=.2?t.muted:t.dim}function E(e){return!Number.isFinite(e)||e===0?`—`:`${(e*100).toFixed(0)}%`}async function D(o){let s=await e(),c=await t({strict:!1});if(!c)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let l=new n({config:s,cliVersion:o.cliVersion,token:c});try{await r(l,`pro`)}catch(e){return process.stderr.write(`${e.message}\n`),2}let u,f;try{({siteId:u,site:f}=await d(l,{explicit:o.siteId,headless:!!o.json,cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let p=f?.url?f.url.replace(/^https?:\/\//,``).replace(/\/$/,``):f?.name??u;if(a(o)){let e=await l.getRetention(u);return i({type:`retention.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=v(x.createElement(O,{api:l,siteId:u,siteLabel:p,cliVersion:o.cliVersion,onExit:n=>{t(),e(n)}}))})}const O=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{m();let{exit:a}=y(),{theme:d}=l(),[v,D]=C(null),[O,k]=C(!0),[A,j]=C(null),[M,N]=C(t),[P,F]=C(n),I=h(e,M,e=>{N(e.id),F(e.url.replace(/^https?:\/\//,``).replace(/\/$/,``)),D(null)});if(b((e,t)=>{if(I.open){(t.escape||e===`s`)&&I.close();return}if(e===`o`||e===`O`){o(p(`retention`,{siteId:M}));return}if(e===`s`){I.toggle();return}e===`q`&&(a(),i(0))}),S(()=>{let t=!1;return v===null&&(k(!0),j(null)),(async()=>{try{let n=await e.getRetention(M);t||(D(n.cohorts),k(!1))}catch(e){t||(j(e.message),k(!1))}})(),()=>{t=!0}},[e,M]),O)return x.createElement(g,{flexDirection:`column`},x.createElement(s,{version:r,subtitle:`retention · ${P}`}),x.createElement(c,{title:`Loading`,state:`busy`},x.createElement(g,null,x.createElement(_,{color:d.accent},x.createElement(w,{type:`dots`})),x.createElement(_,null,` Crunching cohorts…`))));if(A)return x.createElement(g,{flexDirection:`column`},x.createElement(s,{version:r,subtitle:`retention · ${P}`}),x.createElement(f,{reason:`error`,headline:`Failed to load`,hint:A}),I.overlay,x.createElement(u,{items:[{key:`s`,label:`site`},{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}]}));if(!v||v.length===0)return x.createElement(g,{flexDirection:`column`},x.createElement(s,{version:r,subtitle:`retention · ${P}`}),x.createElement(f,{reason:`no-data`,headline:`No retention data yet`,hint:`Retention needs at least 30 days of traffic — press [s] to switch site, or check back once your site has run for a month.`}),I.overlay,x.createElement(u,{items:[{key:`s`,label:`site`},{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}]}));let L=process.stdout.rows??40,R=Math.max(4,L-14),z=[...v].reverse(),B=z.slice(0,R),V=z.length-B.length,H=12,U=7,W=H+3*U,G=(e,t,n)=>x.createElement(g,{key:n,width:U,flexShrink:0,justifyContent:`flex-end`},x.createElement(_,{wrap:`truncate`,color:T(t,d)},e));return x.createElement(g,{flexDirection:`column`},x.createElement(s,{version:r,subtitle:`retention · ${P}`}),x.createElement(c,{title:`Cohort retention (D1 / D7 / D30)`},x.createElement(g,{flexDirection:`row`,width:W},x.createElement(g,{width:H,flexShrink:0},x.createElement(_,{color:d.dim},`COHORT`)),[`D1`,`D7`,`D30`].map(e=>x.createElement(g,{key:e,width:U,flexShrink:0,justifyContent:`flex-end`},x.createElement(_,{color:d.dim},e)))),B.map(e=>x.createElement(g,{key:e.date,flexDirection:`row`,width:W},x.createElement(g,{width:H,flexShrink:0},x.createElement(_,{wrap:`truncate`,color:d.fg},e.date)),G(E(e.day1),e.day1,`${e.date}-1`),G(E(e.day7),e.day7,`${e.date}-7`),G(E(e.day30),e.day30,`${e.date}-30`))),V>0?x.createElement(_,{color:d.dim},` +${V} older cohorts · run with --json for all`):null),I.overlay,x.createElement(u,{items:[{key:`s`,label:`site`},{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}],active:`o`}))};export{D as retentionCommand};
|
|
@@ -1,2 +1,2 @@
|
|
|
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"./error-codes-ByhvHx2M.js";import"./telemetry-BV-xvfdt.js";import{ApiV2Client as n}from"./api-v2-D0mvt__4.js";import{formatTabular as r,selectFormat as i}from"./formatter-C4YSOKuq.js";import{openInBrowser as a}from"./open-url-BtI5aLgL.js";import"./client-ntsEXSVC.js";import"./theme-Brz9wK0w.js";import{useTheme as o}from"./panel-CTtQ2ue6.js";import"./progress-row-Afnt5Ng8.js";import"./prompt-BXvg2B4R.js";import"./keybar-DO5OoZy9.js";import{spark as s}from"./sparkline-CpoBjjlc.js";import"./chat-panel-D9IjovCR.js";import{resolveSiteId as c}from"./resolve-site-BTVBMF1C.js";import"./data-table-BhKjjiOS.js";import{EmptyState as l}from"./empty-state-D-krMX62.js";import"./grid-CMwhs-Ms.js";import"./bar-NfgovYHe.js";import{deepLinkFor as u}from"./keybar-deep-link-B4VJn2ko.js";import"./use-fullscreen-ucSyZkjO.js";import"./range-tabs-CH2cEXOf.js";import{runAnalyticalScreen as d}from"./analytical-screen-BvQa8oH6.js";import"./ui-BTnLAro-.js";import{Box as f,Text as p}from"ink";import m from"react";function h(e,t){let n=e/100,r=new Intl.NumberFormat(`en-US`,{minimumFractionDigits:0,maximumFractionDigits:0}).format(n),i=(t||`USD`).toUpperCase();return i===`USD`?`$${r}`:i===`EUR`?`€${r}`:i===`GBP`?`£${r}`:`${r} ${i}`}function g({data:e}){let{theme:t}=o();return m.createElement(f,{flexDirection:`column`},m.createElement(p,null,m.createElement(p,{color:t.accent,bold:!0},h(e.totalAmount,e.currency)),` `,m.createElement(p,{color:t.muted},`total · `,e.totalTransactions,` transactions`)),typeof e.mrr==`number`?m.createElement(p,null,m.createElement(p,{bold:!0},`MRR `),m.createElement(p,{color:t.accent},h(e.mrr,e.currency)),typeof e.arpu==`number`?m.createElement(p,{color:t.muted},` · ARPU `,h(e.arpu,e.currency)):null):null)}function _({data:e}){let{theme:t}=o(),n=e.series.map(e=>e.amount);if(n.length===0)return m.createElement(l,{reason:`no-data`,headline:`No transactions yet`,hint:`Connect a payment provider or widen the window with the 30d / 90d tabs.`});let r=Math.max(...n,1);return m.createElement(f,{flexDirection:`column`},m.createElement(p,{color:t.accent},s(n,Math.min(60,n.length*2))),m.createElement(p,{color:t.muted},`peak: `,h(r,e.currency),` ·`,` `,`avg: `,h(e.totalAmount/Math.max(1,n.length),e.currency)))}function v({data:e}){let{theme:t}=o();return m.createElement(p,{color:t.muted},new Date(e.windowStart).toISOString().slice(0,10),` →`,` `,new Date(e.windowEnd).toISOString().slice(0,10))}async function y(o){let s=await e(),l=await t({strict:!1}),f=new n({config:s,cliVersion:o.cliVersion,token:l}),p,h;try{({siteId:p,site:h}=await c(f,{explicit:o.siteId,headless:!!(o.json||o.csv||o.tsv||o.ndjson),cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let y=i(o),b=o.range??`30d`;return d({cliVersion:o.cliVersion,title:`revenue · ${h?.url?h.url.replace(/^https?:\/\//,``).replace(/\/$/,``):h?.name??p}`,commandName:`revenue`,ai:{api:f,siteId:p,siteLabel:h?.url?h.url.replace(/^https?:\/\//,``).replace(/\/$/,``):h?.name??p},authToken:l?.accessToken??null,refreshIntervalMs:o.watch?5*6e4:0,ranges:{windows:[`7d`,`30d`,`90d`]},fetcher:(e,t)=>f.getRevenue(p,t?t===`90d`?`1y`:t:b,e),format:y,keybindings:{o:{label:`open in browser`,handler:()=>{a(u(`revenue`,{siteId:p}))}}},headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){process.stdout.write(JSON.stringify(e,null,t===`json`?2:0)),t===`ndjson`&&process.stdout.write(`
|
|
2
2
|
`);return}process.stdout.write(r(e.series,[`bucket`,`amount`,`currency`,`transactions`],t))},panels:[{id:`totals`,title:`Top line`,render:e=>m.createElement(g,{data:e})},{id:`series`,title:`Daily`,render:e=>m.createElement(_,{data:e})},{id:`window`,title:`Window`,render:e=>m.createElement(v,{data:e})}]})}export{y as revenueCommand};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{mocha as e}from"./theme-Brz9wK0w.js";import{spawn as t}from"node:child_process";import n from"chalk";const r=3e4,i=4,a=1e3;function o(e,t){let n=e.requires;if(!n)return null;if(n.auth!==!1&&!t.authenticated)return`not authenticated`;if(n.tier&&t.currentTier){let e={free:0,pro:1,scale:2,enterprise:3},r=e[t.currentTier]??0,i=e[n.tier]??99}return n.multipleTeams&&!t.hasMultipleTeams?`requires 2+ teams`:n.freeTeam&&!t.hasFreeTeam?`requires a Free-tier team`:null}function s(e,n,r,i){return new Promise(a=>{let o=/\.[mc]?js$/.test(e),s=o?`node`:e,c=o?[e,...n]:n,l=t(s,c,{env:{...process.env,ZENOVAY_NO_UPDATE_CHECK:`1`,...i},stdio:[`ignore`,`pipe`,`pipe`]}),u=``,d=``,f=!1,p=setTimeout(()=>{f=!0;try{l.kill(`SIGKILL`)}catch{}},r);l.stdout?.on(`data`,e=>{u+=e.toString(`utf8`),u.length>1048576&&(u=u.slice(0,1048576))}),l.stderr?.on(`data`,e=>{d+=e.toString(`utf8`),d.length>1048576&&(d=d.slice(0,1048576))}),l.on(`error`,e=>{clearTimeout(p),a({stdout:u,stderr:d+`\n[spawn error: ${e.message}]`,exitCode:-1,timedOut:f})}),l.on(`close`,e=>{clearTimeout(p),a({stdout:u,stderr:d,exitCode:e??0,timedOut:f})})})}async function c(e,t){let n=Date.now(),i=o(e,t.env);if(i)return{name:e.name,category:e.category,status:`skip`,durationMs:0,reason:i};if(e.inProcess)try{let t=await e.inProcess(),r=Date.now()-n;return t.ok?{name:e.name,category:e.category,status:`pass`,durationMs:r,...t.detail?{detail:t.detail}:{}}:{name:e.name,category:e.category,status:`fail`,durationMs:r,reason:t.reason}}catch(t){return{name:e.name,category:e.category,status:`fail`,durationMs:Date.now()-n,reason:t.message}}let c=e.name===`stack-leak.bad-net`?{ZENOVAY_API_BASE:`http://127.0.0.1:1`}:void 0,l=t.timeoutMs??r,u=await s(t.binPath,e.command,l,c),d=Date.now()-n;if(u.timedOut)return{name:e.name,category:e.category,status:`fail`,durationMs:d,reason:`timeout (${Math.round(l/1e3)}s)`,...t.verbose?{rawStdout:u.stdout.slice(0,a),rawStderr:u.stderr.slice(0,a)}:{}};let f;try{f=e.assert(u.stdout,u.stderr,u.exitCode)}catch(n){return{name:e.name,category:e.category,status:`fail`,durationMs:d,reason:`assert threw: ${n.message}`,...t.verbose?{rawStdout:u.stdout.slice(0,a),rawStderr:u.stderr.slice(0,a)}:{}}}return f.ok?{name:e.name,category:e.category,status:`pass`,durationMs:d,...f.detail?{detail:f.detail}:{},...t.verbose?{rawStdout:u.stdout.slice(0,a),rawStderr:u.stderr.slice(0,a)}:{}}:{name:e.name,category:e.category,status:`fail`,durationMs:d,reason:f.reason,...t.verbose?{rawStdout:u.stdout.slice(0,a),rawStderr:u.stderr.slice(0,a)}:{}}}async function l(e,t){let n=Date.now(),r=Math.max(1,t.parallel??i),a=Array(e.length).fill(void 0),o=[];for(let n=0;n<e.length;n++){let r=e[n];r&&(t.quick&&!r.quick||o.push(n))}let s=0,l=[],u=async()=>{for(;;){let n=s;if(s+=1,n>=o.length)return;let r=o[n];if(r===void 0)return;let i=e[r];if(!i)continue;let l=await c(i,t);a[r]=l,t.onResult?.(l)}};for(let e=0;e<r;e++)l.push(u());await Promise.all(l);let d=[];for(let e of a)e&&d.push(e);let f=d.filter(e=>e.status===`pass`).length,p=d.filter(e=>e.status===`fail`).length,m=d.filter(e=>e.status===`skip`).length;return{results:d,total:d.length,pass:f,fail:p,skip:m,durationMs:Date.now()-n}}async function u(e){let t={currentTier:null,hasMultipleTeams:!1,hasFreeTeam:!1,authenticated:!1};try{let{readToken:n}=await import(`./token-store-
|
|
1
|
+
import{mocha as e}from"./theme-Brz9wK0w.js";import{spawn as t}from"node:child_process";import n from"chalk";const r=3e4,i=4,a=1e3;function o(e,t){let n=e.requires;if(!n)return null;if(n.auth!==!1&&!t.authenticated)return`not authenticated`;if(n.tier&&t.currentTier){let e={free:0,pro:1,scale:2,enterprise:3},r=e[t.currentTier]??0,i=e[n.tier]??99}return n.multipleTeams&&!t.hasMultipleTeams?`requires 2+ teams`:n.freeTeam&&!t.hasFreeTeam?`requires a Free-tier team`:null}function s(e,n,r,i){return new Promise(a=>{let o=/\.[mc]?js$/.test(e),s=o?`node`:e,c=o?[e,...n]:n,l=t(s,c,{env:{...process.env,ZENOVAY_NO_UPDATE_CHECK:`1`,...i},stdio:[`ignore`,`pipe`,`pipe`]}),u=``,d=``,f=!1,p=setTimeout(()=>{f=!0;try{l.kill(`SIGKILL`)}catch{}},r);l.stdout?.on(`data`,e=>{u+=e.toString(`utf8`),u.length>1048576&&(u=u.slice(0,1048576))}),l.stderr?.on(`data`,e=>{d+=e.toString(`utf8`),d.length>1048576&&(d=d.slice(0,1048576))}),l.on(`error`,e=>{clearTimeout(p),a({stdout:u,stderr:d+`\n[spawn error: ${e.message}]`,exitCode:-1,timedOut:f})}),l.on(`close`,e=>{clearTimeout(p),a({stdout:u,stderr:d,exitCode:e??0,timedOut:f})})})}async function c(e,t){let n=Date.now(),i=o(e,t.env);if(i)return{name:e.name,category:e.category,status:`skip`,durationMs:0,reason:i};if(e.inProcess)try{let t=await e.inProcess(),r=Date.now()-n;return t.ok?{name:e.name,category:e.category,status:`pass`,durationMs:r,...t.detail?{detail:t.detail}:{}}:{name:e.name,category:e.category,status:`fail`,durationMs:r,reason:t.reason}}catch(t){return{name:e.name,category:e.category,status:`fail`,durationMs:Date.now()-n,reason:t.message}}let c=e.name===`stack-leak.bad-net`?{ZENOVAY_API_BASE:`http://127.0.0.1:1`}:void 0,l=t.timeoutMs??r,u=await s(t.binPath,e.command,l,c),d=Date.now()-n;if(u.timedOut)return{name:e.name,category:e.category,status:`fail`,durationMs:d,reason:`timeout (${Math.round(l/1e3)}s)`,...t.verbose?{rawStdout:u.stdout.slice(0,a),rawStderr:u.stderr.slice(0,a)}:{}};let f;try{f=e.assert(u.stdout,u.stderr,u.exitCode)}catch(n){return{name:e.name,category:e.category,status:`fail`,durationMs:d,reason:`assert threw: ${n.message}`,...t.verbose?{rawStdout:u.stdout.slice(0,a),rawStderr:u.stderr.slice(0,a)}:{}}}return f.ok?{name:e.name,category:e.category,status:`pass`,durationMs:d,...f.detail?{detail:f.detail}:{},...t.verbose?{rawStdout:u.stdout.slice(0,a),rawStderr:u.stderr.slice(0,a)}:{}}:{name:e.name,category:e.category,status:`fail`,durationMs:d,reason:f.reason,...t.verbose?{rawStdout:u.stdout.slice(0,a),rawStderr:u.stderr.slice(0,a)}:{}}}async function l(e,t){let n=Date.now(),r=Math.max(1,t.parallel??i),a=Array(e.length).fill(void 0),o=[];for(let n=0;n<e.length;n++){let r=e[n];r&&(t.quick&&!r.quick||o.push(n))}let s=0,l=[],u=async()=>{for(;;){let n=s;if(s+=1,n>=o.length)return;let r=o[n];if(r===void 0)return;let i=e[r];if(!i)continue;let l=await c(i,t);a[r]=l,t.onResult?.(l)}};for(let e=0;e<r;e++)l.push(u());await Promise.all(l);let d=[];for(let e of a)e&&d.push(e);let f=d.filter(e=>e.status===`pass`).length,p=d.filter(e=>e.status===`fail`).length,m=d.filter(e=>e.status===`skip`).length;return{results:d,total:d.length,pass:f,fail:p,skip:m,durationMs:Date.now()-n}}async function u(e){let t={currentTier:null,hasMultipleTeams:!1,hasFreeTeam:!1,authenticated:!1};try{let{readToken:n}=await import(`./token-store-QTNSg4TT.js`),{readConfig:r}=await import(`./config-B72_Kfe0.js`),{ApiV2Client:i}=await import(`./api-v2-Co0dWAP5.js`),a=await n({strict:!1}).catch(()=>null);if(!a)return t;t.authenticated=!0;let o=await r(),s=new i({config:o,cliVersion:e,token:a}),c=await s.me();if(c.team?.plan){let e=c.team.plan.toLowerCase();(e===`free`||e===`pro`||e===`scale`||e===`enterprise`)&&(t.currentTier=e)}c.teams&&c.teams.length>=2&&(t.hasMultipleTeams=!0),(c.teams&&c.teams.some(e=>e.plan?.toLowerCase()===`free`)||t.currentTier===`free`)&&(t.hasFreeTeam=!0)}catch{}return t}function d(e){let t=e.trim();if(!t)return{ok:!1,reason:`empty stdout`};try{return{ok:!0,value:JSON.parse(t)}}catch{let e=t.split(`
|
|
2
2
|
`).filter(e=>e.trim().startsWith(`{`)||e.trim().startsWith(`[`)).pop();if(e)try{return{ok:!0,value:JSON.parse(e)}}catch{}return{ok:!1,reason:`stdout not JSON (got ${t.length} bytes)`}}}function f(e,t,n){if(n!==0)return{ok:!1,reason:`exit ${n}`};let r=d(e);return r.ok?{ok:!0}:{ok:!1,reason:r.reason}}function p(e,t,n){if(n!==0){let r=[e,t];for(let e of r)if(e.includes(`tier_insufficient`))return{ok:!0,detail:{gated:!0}};return{ok:!1,reason:`exit ${n} — ${(t||e).slice(0,80)}`}}let r=d(e);return r.ok?{ok:!0}:{ok:!1,reason:r.reason}}function m(e){if(typeof e!=`object`||!e)return!1;let t=e;if(Array.isArray(t.items)||Array.isArray(t.rows)||Array.isArray(t.data))return!0;if(typeof t.data==`object`&&t.data!==null){let e=t.data;if(Array.isArray(e.items)||Array.isArray(e.rows))return!0}return!1}const h=[{name:`analytics`,category:`ANALYTICS`,command:[`analytics`,`--json`],assert:(e,t,n)=>{let r=f(e,t,n);if(!r.ok)return r;let i=d(e);if(!i.ok)return{ok:!1,reason:i.reason};let a=i.value,o=a.visitors??a.data?.visitors,s=a.pageviews??a.data?.pageviews;return{ok:!0,detail:{visitors:o??null,pageviews:s??null}}},quick:!0},{name:`overview`,category:`ANALYTICS`,command:[`overview`,`--json`],assert:f},{name:`pages`,category:`ANALYTICS`,command:[`pages`,`--json`],assert:(e,t,n)=>{let r=f(e,t,n);if(!r.ok)return r;let i=d(e);if(!i.ok)return{ok:!1,reason:i.reason};let a=i.value,o=a.items??a.data?.items;return{ok:!0,detail:{rows:o?.length??0}}},quick:!0},{name:`sources`,category:`ANALYTICS`,command:[`sources`,`--json`],assert:f,quick:!0},{name:`devices`,category:`ANALYTICS`,command:[`devices`,`--json`],assert:f},{name:`geo`,category:`ANALYTICS`,command:[`geo`,`--json`],assert:f},{name:`live`,category:`ANALYTICS`,command:[`live`,`--json`],assert:(e,t,n)=>{let r=f(e,t,n);if(!r.ok)return r;let i=d(e);if(i.ok&&typeof i.value==`object`&&i.value!==null){let e=i.value,t=e.bounceRate??e.data?.bounceRate;if(typeof t==`number`&&(t<0||t>1))return{ok:!1,reason:`bounceRate semantics violated (got ${t}, expected 0..1)`}}return{ok:!0}}},{name:`revenue`,category:`ANALYTICS`,command:[`revenue`,`--json`],assert:f},{name:`funnels`,category:`ANALYTICS`,command:[`funnels`,`--json`],assert:p,requires:{tier:`pro`}},{name:`home`,category:`ANALYTICS`,command:[`home`,`--json`],assert:f},{name:`usage`,category:`ANALYTICS`,command:[`usage`,`--json`],assert:f,quick:!0},{name:`stats`,category:`ANALYTICS`,command:[`stats`,`--json`],assert:f},{name:`retention`,category:`BEHAVIOR`,command:[`retention`,`--json`],assert:p,requires:{tier:`pro`}},{name:`uptime`,category:`BEHAVIOR`,command:[`uptime`,`--json`],assert:p,requires:{tier:`pro`}},{name:`sessions`,category:`BEHAVIOR`,command:[`sessions`,`--json`],assert:p,requires:{tier:`pro`}},{name:`heatmaps`,category:`BEHAVIOR`,command:[`heatmaps`,`--json`],assert:p,requires:{tier:`pro`}},{name:`journeys`,category:`BEHAVIOR`,command:[`journeys`,`--json`],assert:p,requires:{tier:`pro`}},{name:`insights`,category:`INTELLIGENCE`,command:[`insights`,`--json`],assert:p,requires:{tier:`pro`}},{name:`domains list`,category:`MANAGE`,command:[`domains`,`list`,`--json`],assert:(e,t,n)=>{let r=f(e,t,n);if(!r.ok)return r;let i=d(e);return!i.ok||!m(i.value)?{ok:!1,reason:`expected list shape ({items|rows|data})`}:{ok:!0}},quick:!0},{name:`api-keys list`,category:`MANAGE`,command:[`api-keys`,`list`,`--json`],assert:(e,t,n)=>{let r=f(e,t,n);if(!r.ok)return r;let i=d(e);return!i.ok||!m(i.value)?{ok:!1,reason:`expected list shape`}:{ok:!0}}},{name:`team list`,category:`MANAGE`,command:[`team`,`list`,`--json`],assert:p,requires:{tier:`pro`}},{name:`webhooks list`,category:`MANAGE`,command:[`webhooks`,`list`,`--json`],assert:f},{name:`profile show`,category:`ACCOUNT`,command:[`profile`,`show`,`--json`],assert:f,quick:!0},{name:`plans info`,category:`ACCOUNT`,command:[`plans`,`info`,`--json`],assert:f},{name:`settings get`,category:`ACCOUNT`,command:[`settings`,`get`,`--json`],assert:f},{name:`integrations list`,category:`ACCOUNT`,command:[`integrations`,`list`,`--json`],assert:f},{name:`goals list`,category:`ACCOUNT`,command:[`goals`,`list`,`--json`],assert:p,requires:{tier:`pro`}},{name:`notes list`,category:`ACCOUNT`,command:[`notes`,`list`,`--json`],assert:f},{name:`audit list`,category:`ACCOUNT`,command:[`audit`,`list`,`--json`],assert:p,requires:{tier:`pro`}},{name:`share url`,category:`ACCOUNT`,command:[`share`,`url`,`--json`],assert:(e,t,n)=>n!==0&&n!==1&&n!==2?{ok:!1,reason:`unexpected exit ${n}`}:{ok:!0}},{name:`teams list`,category:`ACCOUNT`,command:[`teams`,`list`,`--json`],assert:f},{name:`health`,category:`OPERATIONS`,command:[`health`,`--json`],assert:(e,t,n)=>{let r=d(e);return r.ok?{ok:!0}:{ok:!1,reason:r.reason}},quick:!0},{name:`commands`,category:`OPERATIONS`,command:[`commands`,`--json`],assert:(e,t,n)=>{let r=f(e,t,n);if(!r.ok)return r;let i=d(e);if(!i.ok)return{ok:!1,reason:i.reason};let a=i.value,o=a.commands;return!Array.isArray(o)||o.length===0?{ok:!1,reason:`commands tree empty`}:{ok:!0,detail:{commands:o.length}}}},{name:`themes`,category:`OPERATIONS`,command:[`themes`,`--json`],assert:f},{name:`projects`,category:`OPERATIONS`,command:[`projects`,`--json`],assert:f},{name:`idor.cross-team`,category:`SECURITY`,command:[`domains`,`list`,`--site-id`,`00000000-0000-0000-0000-000000000001`,`--json`],assert:(e,t,n)=>{let r=e+t;return/forbidden|not_found|tier_insufficient|auth_required|auth_invalid/.test(r)?{ok:!0,detail:{rejected:!0}}:r.includes(`"items"`)||r.includes(`"rows"`)?{ok:!1,reason:`expected forbidden/not_found, got data`}:{ok:!0,detail:{rejected:`empty`}}},requires:{multipleTeams:!0},dev:!0},{name:`idor.bad-uuid`,category:`SECURITY`,command:[`analytics`,`--site-id`,`00000000-0000-0000-0000-000000000000`,`--json`],assert:(e,t,n)=>{let r=e+t;return/not_found|forbidden|auth_/.test(r)?{ok:!0,detail:{rejected:!0}}:/error|invalid|"code":/i.test(r)?{ok:!0,detail:{rejected:`error-shaped`}}:{ok:!1,reason:`silent zeros — expected not_found`}},quick:!0,dev:!0},{name:`tier-gate.retention`,category:`SECURITY`,command:[`retention`,`--json`],assert:(e,t,n)=>{let r=e+t;return r.includes(`tier_insufficient`)?{ok:!0,detail:{gated:`tier_insufficient`}}:/upgrade_required|tier_required/.test(r)?{ok:!0,detail:{gated:`legacy-or-transitional`}}:/"code":\s*"forbidden"/.test(r)&&/tier|upgrade|plan/i.test(r)?{ok:!0,detail:{gated:`forbidden+tier-message`}}:n===0&&!/"type"\s*:\s*"error"/.test(r)?{ok:!0,detail:{gated:`pass-through (Pro+ access)`}}:{ok:!1,reason:`gate did not behave as expected (no tier envelope and no clean pass-through)`}},dev:!0},{name:`stack-leak.bad-net`,category:`SECURITY`,command:[`analytics`,`--json`],assert:(e,t,n)=>{let r=e+t;return/\/Users\//.test(r)||/node:internal\//.test(r)?{ok:!1,reason:`stack trace leaked filesystem path`}:{ok:!0}},quick:!0},{name:`token-perms`,category:`SECURITY`,command:[],assert:()=>({ok:!1,reason:`should run in-process`}),inProcess:async()=>{let{stat:e}=await import(`node:fs/promises`),t=await import(`node:path`),n=process.env.HOME??process.env.USERPROFILE??``,r=process.env.XDG_CONFIG_HOME??t.join(n,`.config`),i=process.platform===`win32`?t.join(process.env.APPDATA??t.join(n,`AppData`,`Roaming`),`zenovay`,`auth.json`):t.join(r,`zenovay`,`auth.json`);try{let t=await e(i);if(process.platform===`win32`)return{ok:!0,detail:{mode:`win32-skip`}};let n=t.mode&511;return n===384?{ok:!0,detail:{mode:`0600`}}:{ok:!1,reason:`auth.json mode ${n.toString(8)} != 0600`}}catch(e){let t=e.code;return t===`ENOENT`?{ok:!0,detail:{mode:`no-auth-file`}}:{ok:!1,reason:e.message}}},quick:!0},{name:`secret-scrub`,category:`SECURITY`,command:[],assert:()=>({ok:!1,reason:`should run in-process`}),inProcess:async()=>{let{SECRET_PATTERNS:e,scrubSecrets:t}=await import(`./secrets-c-NB_plk.js`),n=[{name:`openai-proj`,sample:`sk-proj-abcdefghijklmnopqrstuvwxyz0123456789`},{name:`anthropic`,sample:`sk-ant-abcdefghijklmnopqrstuvwxyz0123456789`},{name:`openai-sk`,sample:`sk-abcdefghijklmnopqrstuvwxyz0123`},{name:`github-pat-new`,sample:`github_pat_`+`a`.repeat(82)},{name:`github-pat`,sample:`ghp_`+`a`.repeat(36)},{name:`github-oauth`,sample:`gho_`+`a`.repeat(36)},{name:`aws-access-key`,sample:`AKIAABCDEFGHIJKLMNOP`},{name:`stripe-live`,sample:`sk_live_`+`a`.repeat(28)},{name:`stripe-test`,sample:`pk_test_`+`a`.repeat(28)},{name:`stripe-restricted`,sample:`rk_live_`+`a`.repeat(28)},{name:`stripe-webhook`,sample:`whsec_`+`a`.repeat(28)},{name:`slack-bot`,sample:`xoxb-1234567890-abcdef`},{name:`google-api`,sample:`AIza`+`a`.repeat(35)},{name:`jwt`,sample:`eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTYifQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c`},{name:`private-key-rsa`,sample:`-----BEGIN RSA PRIVATE KEY-----`},{name:`private-key-pkcs8`,sample:`-----BEGIN PRIVATE KEY-----`},{name:`supabase-jwt`,sample:`eyJhbGciOi`+`a`.repeat(40)},{name:`resend-api`,sample:`re_`+`a`.repeat(20)},{name:`gitlab-pat`,sample:`glpat-`+`a`.repeat(20)},{name:`shopify`,sample:`shpat_`+`a`.repeat(32)},{name:`service-role-key`,sample:`service_role: "`+`a`.repeat(40)+`"`}],r=n.map(e=>`${e.name}=${e.sample}`).join(`
|
|
3
3
|
`),i=t(r),a=n.filter(e=>i.includes(`[REDACTED:${e.name}]`)).length,o=e.length,s=Math.max(18,o-4);return a>=s?{ok:!0,detail:{matched:a,total:o}}:{ok:!1,reason:`${a}/${o} patterns redacted (need >= ${s})`}},quick:!0},{name:`help-line-count`,category:`DISCOVERABILITY`,command:[`--help`],assert:(e,t,n)=>{let r=e.split(`
|
|
4
|
-
`).length;return r<90?{ok:!0,detail:{lines:r}}:{ok:!1,reason:`${r} lines (target < 90)`}},dev:!0},{name:`help-no-wave-markers`,category:`DISCOVERABILITY`,command:[`--help`],assert:(e,t,n)=>{let r=/\b(?:Wave\s*\d|W\d|V2\.1)\b/i,i=e.match(r);return i?{ok:!1,reason:`found marker: ${i[0]}`}:{ok:!0}},dev:!0},{name:`help-has-groups`,category:`DISCOVERABILITY`,command:[`--help`],assert:(e,t,n)=>{let r=[`ANALYTICS`,`BEHAVIOR`,`MANAGE`,`ACCOUNT`,`OPERATIONS`],i=r.filter(t=>!e.includes(t));return i.length===0?{ok:!0,detail:{found:r}}:{ok:!1,reason:`missing groups: ${i.join(`, `)}`}},dev:!0},{name:`examples-coverage`,category:`DISCOVERABILITY`,command:[],assert:()=>({ok:!1,reason:`should run in-process`}),inProcess:async()=>{let{EXAMPLES:e}=await import(`./examples-
|
|
4
|
+
`).length;return r<90?{ok:!0,detail:{lines:r}}:{ok:!1,reason:`${r} lines (target < 90)`}},dev:!0},{name:`help-no-wave-markers`,category:`DISCOVERABILITY`,command:[`--help`],assert:(e,t,n)=>{let r=/\b(?:Wave\s*\d|W\d|V2\.1)\b/i,i=e.match(r);return i?{ok:!1,reason:`found marker: ${i[0]}`}:{ok:!0}},dev:!0},{name:`help-has-groups`,category:`DISCOVERABILITY`,command:[`--help`],assert:(e,t,n)=>{let r=[`ANALYTICS`,`BEHAVIOR`,`MANAGE`,`ACCOUNT`,`OPERATIONS`],i=r.filter(t=>!e.includes(t));return i.length===0?{ok:!0,detail:{found:r}}:{ok:!1,reason:`missing groups: ${i.join(`, `)}`}},dev:!0},{name:`examples-coverage`,category:`DISCOVERABILITY`,command:[],assert:()=>({ok:!1,reason:`should run in-process`}),inProcess:async()=>{let{EXAMPLES:e}=await import(`./examples-CsQBLv9W.js`),t=Object.keys(e).length;return t>=25?{ok:!0,detail:{commands:t}}:{ok:!1,reason:`${t} commands have examples (need >= 25)`}},dev:!0},{name:`envelope-shape`,category:`DISCOVERABILITY`,command:[`commands`,`--json`],assert:(e,t,n)=>{if(n!==0)return{ok:!1,reason:`exit ${n}`};let r=d(e);if(!r.ok)return{ok:!1,reason:r.reason};let i=r.value,a=typeof i.version==`string`&&Array.isArray(i.commands);return a?{ok:!0,detail:{commands:i.commands.length}}:{ok:!1,reason:`commands payload missing version+commands`}},dev:!0}],g=h.length,_={accent:n.hex(e.accent),success:n.hex(e.success),error:n.hex(e.error),muted:n.hex(e.muted)};async function v(e){let t=(process.execPath||``).split(`/`).pop()||``,n=/^node(\.exe)?$/i.test(t),r=n?process.argv[1]??process.execPath:process.execPath,i=!!e.full||process.env.ZENOVAY_SELF_TEST_FULL===`1`,a=h.filter(e=>i||!e.dev);e.quick&&(a=a.filter(e=>e.quick));let o=await u(e.cliVersion);return e.json?y({...e,binPath:r,env:o,catalog:a}):S({...e,binPath:r,env:o,catalog:a})}async function y(e){let t=await l(e.catalog,{binPath:e.binPath,quick:e.quick??!1,verbose:e.verbose??!1,parallel:e.parallel,env:e.env,onResult:e=>{let t={type:`self-test.result`,name:e.name,category:e.category,status:e.status,durationMs:e.durationMs,...e.detail?{detail:e.detail}:{},...e.reason?{reason:e.reason}:{},...e.rawStdout?{rawStdout:e.rawStdout}:{},...e.rawStderr?{rawStderr:e.rawStderr}:{}};process.stdout.write(`${JSON.stringify(t)}\n`)}});return process.stdout.write(`${JSON.stringify({type:`self-test.summary`,total:t.total,pass:t.pass,fail:t.fail,skip:t.skip,durationMs:t.durationMs,cliVersion:e.cliVersion,env:e.env})}\n`),t.fail>0?1:0}const b=26,x=8;async function S(e){w(e.cliVersion,e.quick??!1,e.catalog.length);let t=new Map,n=0,r=null,i=new Map;for(let t of e.catalog)i.set(t.category,(i.get(t.category)??0)+1);let a=await l(e.catalog,{binPath:e.binPath,quick:e.quick??!1,verbose:e.verbose??!1,parallel:e.parallel,env:e.env,onResult:a=>{for(t.set(a.name,a);n<e.catalog.length;){let a=e.catalog[n];if(!a)break;let o=t.get(a.name);if(!o)break;r!==a.category&&(T(a.category,i.get(a.category)??0),r=a.category),E(a,o),t.delete(a.name),n+=1}}});return D(a),a.fail>0?1:0}function C(){return Math.max(60,process.stdout.columns??80)}function w(e,t,n){let r=Math.min(120,C()),i=r-2,a=`ZENOVAY · v${e}`,o=`self-test · ${t?`quick`:`full`} · ${n} test${n===1?``:`s`}`,s=`╭─ `+a+` `+`─`.repeat(Math.max(0,i-a.length-4))+`╮`,c=`│ `+o+` `.repeat(Math.max(0,i-o.length-2))+`│`,l=`╰`+`─`.repeat(i)+`╯`;process.stdout.write(_.accent(s)+`
|
|
5
5
|
`),process.stdout.write(_.accent(c)+`
|
|
6
6
|
`),process.stdout.write(_.accent(l)+`
|
|
7
7
|
|
|
@@ -1 +1 @@
|
|
|
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"./formatter-C4YSOKuq.js";import{emit$1 as i,isHeadless as a}from"./emit-D4YlMlzk.js";import{openInBrowser as o}from"./open-url-BtI5aLgL.js";import"./theme-Brz9wK0w.js";import{Banner as s,Panel as c,useTheme as l}from"./panel-CTtQ2ue6.js";import"./prompt-BXvg2B4R.js";import{Keybar as u}from"./keybar-DO5OoZy9.js";import{resolveSiteId as d}from"./resolve-site-BTVBMF1C.js";import{DataTable as f}from"./data-table-BhKjjiOS.js";import{EmptyState as p}from"./empty-state-D-krMX62.js";import{deepLinkFor as m}from"./keybar-deep-link-B4VJn2ko.js";import{useFullscreen as h}from"./use-fullscreen-ucSyZkjO.js";import{useSiteSwitcher as g}from"./site-switcher-BAoYWp18.js";import{Box as _,Text as v,render as y,useApp as b,useInput as x}from"ink";import S,{useEffect as C,useState as w}from"react";import T from"ink-spinner";function E(e){if(!e||e<=0)return`—`;let t=Math.floor(e/1e3);if(t<60)return`${t}s`;let n=Math.floor(t/60);return`${n}m ${(t%60).toString().padStart(2,`0`)}s`}function D(e){if(!e)return`—`;let t=Date.parse(e);if(Number.isNaN(t))return`—`;let n=Math.max(0,Math.floor((Date.now()-t)/1e3));return n<60?`${n}s`:n<3600?`${Math.floor(n/60)}m`:n<86400?`${Math.floor(n/3600)}h`:`${Math.floor(n/86400)}d`}async function O(o){let s=await e(),c=await t({strict:!1});if(!c)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let l=new n({config:s,cliVersion:o.cliVersion,token:c});try{await r(l,`pro`)}catch(e){return process.stderr.write(`${e.message}\n`),2}let u,f;try{({siteId:u,site:f}=await d(l,{explicit:o.siteId,headless:!!o.json,cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let p=f?.url?f.url.replace(/^https?:\/\//,``).replace(/\/$/,``):f?.name??u;if(a(o)){let e=await l.getSessions(u);return i({type:`sessions.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=y(S.createElement(k,{api:l,siteId:u,siteLabel:p,cliVersion:o.cliVersion,onExit:n=>{t(),e(n)}}))})}const k=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{h();let{exit:a}=b(),{theme:d}=l(),[y,O]=w(null),[k,A]=w(!0),[j,M]=w(null),[N,P]=w(t),[F,I]=w(n),L=g(e,N,e=>{P(e.id),I(e.url.replace(/^https?:\/\//,``).replace(/\/$/,``)),O(null)});if(x((e,t)=>{if(L.open){(t.escape||e===`s`)&&L.close();return}if(e===`o`||e===`O`){o(m(`sessions`,{siteId:N}));return}if(e===`s`){L.toggle();return}e===`q`&&(a(),i(0))}),C(()=>{let t=!1;return(async()=>{try{let n=await e.getSessions(N);t||(O(n),A(!1))}catch(e){t||(M(e.message),A(!1))}})(),()=>{t=!0}},[e,N]),k)return S.createElement(_,{flexDirection:`column`},S.createElement(s,{version:r,subtitle:`sessions · ${F}`}),S.createElement(c,{title:`Loading`,state:`busy`},S.createElement(_,null,S.createElement(v,{color:d.accent},S.createElement(T,{type:`dots`})),S.createElement(v,null,` Fetching sessions…`))));if(j)return S.createElement(_,{flexDirection:`column`},S.createElement(s,{version:r,subtitle:`sessions · ${F}`}),S.createElement(p,{reason:`error`,headline:`Failed to load`,hint:j}),L.overlay,S.createElement(u,{items:[{key:`s`,label:`site`},{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}]}));if(!y||y.length===0)return S.createElement(_,{flexDirection:`column`},S.createElement(s,{version:r,subtitle:`sessions · ${F}`}),S.createElement(p,{reason:`no-data`,headline:`No replays yet`,hint:`Enable session replay in your site settings, press [s] to switch site, then revisit your site to capture one.`}),L.overlay,S.createElement(u,{items:[{key:`s`,label:`site`},{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}]}));let R=[{key:`id`,label:`session id`,width:24},{key:`visitor`,label:`visitor`,width:18},{key:`duration`,label:`duration`,align:`right`,width:9,format:e=>E(e)},{key:`startedAt`,label:`when`,align:`right`,width:6,format:e=>D(String(e))},{key:`pageCount`,label:`events`,align:`right`,width:7},{key:`deviceType`,label:`device`,width:8,format:e=>String(e??`—`)}],z=process.stdout.rows??40,B=Math.max(4,z-15),V=y.slice(0,B),H=y.length-V.length;return S.createElement(_,{flexDirection:`column`},S.createElement(s,{version:r,subtitle:`sessions · ${F}`}),S.createElement(c,{title:`Recent sessions (${y.length})`},S.createElement(f,{columns:R,data:V,zebra:!0}),H>0?S.createElement(v,{color:d.dim},` +${H} more · run with --json for all`):null),S.createElement(_,{marginTop:1},S.createElement(v,{color:d.dim},`Open any session for replay at https://app.zenovay.com/replay`)),L.overlay,S.createElement(u,{items:[{key:`s`,label:`site`},{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}],active:`o`}))};export{O as sessionsCommand};
|
|
@@ -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";function r(e){try{return JSON.parse(e)}catch{return e}}async function i(i){let a=await e(),o=await t({strict:!1}),s=new n({config:a,cliVersion:i.cliVersion,token:o});try{switch(i.action){case`get`:{let{settings:e}=await s.getSettings();if(i.key){let t=e[i.key];return t===void 0?(process.stderr.write(`Unknown setting: ${i.key}\n`),2):(i.json?process.stdout.write(JSON.stringify({[i.key]:t},null,2)+`
|
|
2
2
|
`):process.stdout.write(`${i.key} = ${t===null?`—`:JSON.stringify(t)}\n`),0)}if(i.json)return process.stdout.write(JSON.stringify({settings:e},null,2)+`
|
|
3
3
|
`),0;for(let[t,n]of Object.entries(e))process.stdout.write(`${t.padEnd(28)} ${n===null?`—`:JSON.stringify(n)}\n`);return 0}case`set`:{if(!i.key||i.value===void 0)return process.stderr.write("Error: usage `zenovay settings set <key> <value>`.\n"),2;let e=r(i.value),t=await s.setSetting(i.key,e);return i.json?(process.stdout.write(JSON.stringify(t,null,2)+`
|
|
4
4
|
`),0):(process.stdout.write(`✔ Set ${i.key} → ${JSON.stringify(e)}\n`),0)}}}catch(e){return process.stderr.write(`✗ ${e.message}\n`),1}}export{i as settingsCommand};
|
|
@@ -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{confirmDestructive as r}from"./confirm-DS5wux0g.js";import"./theme-Brz9wK0w.js";import"./panel-CTtQ2ue6.js";import"./prompt-BXvg2B4R.js";import{resolveSiteId as i}from"./resolve-site-BTVBMF1C.js";async function a(a){let o=await e(),s=await t({strict:!1}),c=new n({config:o,cliVersion:a.cliVersion,token:s}),l,u;try{({siteId:l,site:u}=await i(c,{explicit:a.siteId,headless:!!a.json,cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let d=u?.url?u.url.replace(/^https?:\/\//,``).replace(/\/$/,``):u?.name??l;try{switch(a.action){case`enable`:{let e=await c.enableShare(l);if(a.json)return process.stdout.write(JSON.stringify(e,null,2)+`
|
|
2
2
|
`),0;let t=`═`.repeat(72);return process.stdout.write(`\n${t}\n Public dashboard sharing enabled\n url: ${e.url}\n${t}\n\n Anyone with this link can view your dashboard. Disable with\n \`zenovay share disable\` to invalidate the link immediately.\n\n`),0}case`disable`:{let e=await r({resource:`public share link`,name:d,yes:a.yes,destructive:!0});if(!e)return process.stdout.write(`Cancelled.
|
|
3
3
|
`),1;let t=await c.disableShare(l);return a.json?(process.stdout.write(JSON.stringify(t)+`
|
|
4
4
|
`),0):(process.stdout.write(`✔ Public sharing disabled. The previous link is no longer valid.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{updateConfig as e}from"./config
|
|
1
|
+
import{updateConfig as e}from"./config-JVhBplSX.js";import{Panel as t,useTheme as n}from"./panel-CTtQ2ue6.js";import{Select as r}from"./prompt-BXvg2B4R.js";import{Box as i,Text as a}from"ink";import o,{useCallback as s,useState as c}from"react";function l(l,u,d){let{theme:f}=n(),[p,m]=c(!1),[h,g]=c([]),_=s(()=>{m(e=>{let t=!e;return t&&h.length===0&&l.getSites().then(e=>g(e)).catch(()=>{}),t})},[l,h.length]),v=s(()=>m(!1),[]),y=s(t=>{m(!1),e({defaultSiteId:t.id,defaultSiteName:t.name}),d(t)},[d]),b=p?o.createElement(i,{marginTop:1},o.createElement(t,{title:`Switch site`,state:`idle`},h.length===0?o.createElement(a,{color:f.muted},`Loading your sites…`):o.createElement(r,{items:h.map(e=>({label:`${e.name} · ${e.url.replace(/^https?:\/\//,``).replace(/\/$/,``)}${e.id===u?` (current)`:``}`,value:e})),onSelect:y}),o.createElement(i,{marginTop:1},o.createElement(a,{color:f.dim},`[↑↓ navigate] · [enter] select — becomes your default everywhere · [s/esc] close`)))):null;return{open:p,toggle:_,close:v,overlay:b}}export{l as useSiteSwitcher};
|
|
@@ -1,2 +1,2 @@
|
|
|
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"./error-codes-ByhvHx2M.js";import"./telemetry-BV-xvfdt.js";import{ApiV2Client as n}from"./api-v2-D0mvt__4.js";import{formatTabular as r,selectFormat as i}from"./formatter-C4YSOKuq.js";import{openInBrowser as a}from"./open-url-BtI5aLgL.js";import"./client-ntsEXSVC.js";import"./theme-Brz9wK0w.js";import{useTheme as o}from"./panel-CTtQ2ue6.js";import"./prompt-BXvg2B4R.js";import"./keybar-DO5OoZy9.js";import"./chat-panel-D9IjovCR.js";import{resolveSiteId as s}from"./resolve-site-BTVBMF1C.js";import{DataTable as c}from"./data-table-BhKjjiOS.js";import{EmptyState as l}from"./empty-state-D-krMX62.js";import"./grid-CMwhs-Ms.js";import{Bar as u}from"./bar-NfgovYHe.js";import{deepLinkFor as d}from"./keybar-deep-link-B4VJn2ko.js";import"./use-fullscreen-ucSyZkjO.js";import"./range-tabs-CH2cEXOf.js";import{runAnalyticalScreen as f}from"./analytical-screen-BvQa8oH6.js";import{Box as p,Text as m}from"ink";import h from"react";function g(e){return e==null?{glyph:`·`,tone:`neutral`}:e>.5?{glyph:`▲`,tone:`up`}:e<-.5?{glyph:`▼`,tone:`down`}:{glyph:`→`,tone:`neutral`}}function _({data:e}){let{theme:t}=o();return h.createElement(m,null,h.createElement(m,{bold:!0},e.totalVisitors.toLocaleString()),` `,h.createElement(m,{color:t.muted},`visitors · `,e.sources.length,` sources`))}function v({data:e}){let{theme:t}=o();if(e.sources.length===0)return h.createElement(l,{reason:`no-data`,headline:`No source data yet`,hint:`Visit your site so referrers can be attributed, or widen the window with the number keys.`});let n={up:t.success,down:t.accent2,neutral:t.muted},r=e.totalVisitors||1,i=[...e.sources].sort((e,t)=>t.visitors-e.visitors).slice(0,12);return h.createElement(p,{flexDirection:`column`},i.map((e,i)=>{let a=e.visitors/r*100,o=g(e.delta);return h.createElement(p,{key:`${e.source}-${i}`,flexDirection:`row`},h.createElement(p,{width:20,marginRight:1,flexShrink:0},h.createElement(m,{wrap:`truncate`},e.source)),h.createElement(p,{flexShrink:0},h.createElement(u,{value:e.visitors,max:r,width:30,showPercent:!1,track:!0})),h.createElement(p,{width:7,marginLeft:1,flexShrink:0,justifyContent:`flex-end`},h.createElement(m,{color:t.fg},e.visitors.toLocaleString())),h.createElement(p,{width:8,marginLeft:1,flexShrink:0,justifyContent:`flex-end`},h.createElement(m,{color:t.muted},a.toFixed(1),`%`)),h.createElement(p,{width:2,marginLeft:1,flexShrink:0},h.createElement(m,{color:n[o.tone]},o.glyph)))}))}function y({data:e,columns:t}){return e.sources.length===0?h.createElement(l,{reason:`no-data`,headline:`No source data yet`,hint:`Visit your site so referrers can be attributed, or widen the window with [1-4].`}):h.createElement(c,{data:e.sources.slice(0,20),columns:t,headerStyle:`accent`})}async function b(o){let c=await e(),l=await t({strict:!1}),u=new n({config:c,cliVersion:o.cliVersion,token:l}),p,m;try{({siteId:p,site:m}=await s(u,{explicit:o.siteId,headless:!!(o.json||o.csv||o.tsv||o.ndjson),cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let g=i(o),b=o.period??`30d`,x=[{key:`source`,label:`source`,width:22},{key:`channel`,label:`channel`,width:10,format:e=>String(e??`—`)},{key:`visitors`,label:`visitors`,width:8,align:`right`},{key:`delta`,label:`Δ`,width:6,align:`right`,format:e=>typeof e==`number`?`${e>0?`+`:``}${(e*100).toFixed(1)}%`:`—`}];return f({cliVersion:o.cliVersion,title:`sources · ${m?.url?m.url.replace(/^https?:\/\//,``).replace(/\/$/,``):m?.name??p}`,commandName:`sources`,authToken:l?.accessToken??null,refreshIntervalMs:6e4,ranges:{windows:[`7d`,`30d`,`90d`]},fetcher:(e,t)=>u.getSources(p,t&&t!==`24h`?t:b,o.compare,e),format:g,ai:{api:u,siteId:p,siteLabel:m?.url?m.url.replace(/^https?:\/\//,``).replace(/\/$/,``):m?.name??p},keybindings:{o:{label:`open in browser`,handler:()=>{a(d(`sources`,{siteId:p}))}}},headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){process.stdout.write(JSON.stringify(e,null,t===`json`?2:0)),t===`ndjson`&&process.stdout.write(`
|
|
2
2
|
`);return}process.stdout.write(r(e.sources,[`source`,`channel`,`visitors`,`conversions`,`revenue`,`delta`],t))},panels:[{id:`summary`,title:`Total`,render:e=>h.createElement(_,{data:e})},{id:`channels`,title:`By channel`,render:e=>h.createElement(v,{data:e})},{id:`table`,title:`Detail`,render:e=>h.createElement(y,{data:e,columns:x})}]})}export{b as sourcesCommand};
|
|
@@ -1,2 +1,2 @@
|
|
|
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"./error-codes-ByhvHx2M.js";import"./telemetry-BV-xvfdt.js";import{ApiV2Client as n}from"./api-v2-D0mvt__4.js";import{formatTabular as r,selectFormat as i}from"./formatter-C4YSOKuq.js";import"./client-ntsEXSVC.js";import"./theme-Brz9wK0w.js";import{useTheme as a}from"./panel-CTtQ2ue6.js";import"./prompt-BXvg2B4R.js";import"./keybar-DO5OoZy9.js";import"./chat-panel-D9IjovCR.js";import{resolveSiteId as o}from"./resolve-site-BTVBMF1C.js";import{DataTable as s}from"./data-table-BhKjjiOS.js";import{EmptyState as c}from"./empty-state-D-krMX62.js";import"./grid-CMwhs-Ms.js";import"./use-fullscreen-ucSyZkjO.js";import"./range-tabs-CH2cEXOf.js";import{runAnalyticalScreen as l}from"./analytical-screen-BvQa8oH6.js";import{Box as u,Text as d}from"ink";import f from"react";function p(e){return`${(e*100).toFixed(1)}%`}function m(e){return e<60?`${Math.round(e)}s`:e<3600?`${Math.floor(e/60)}m ${Math.round(e%60)}s`:`${Math.floor(e/3600)}h ${Math.floor(e%3600/60)}m`}const h=({data:e})=>{let{theme:t}=a();return f.createElement(u,{flexDirection:`column`},f.createElement(d,null,f.createElement(d,{bold:!0},e.visitors.toLocaleString()),f.createElement(d,{color:t.muted},` visitors `),f.createElement(d,{bold:!0},e.pageviews.toLocaleString()),f.createElement(d,{color:t.muted},` pageviews `),f.createElement(d,{bold:!0},e.sessions.toLocaleString()),f.createElement(d,{color:t.muted},` sessions`)),f.createElement(d,{color:t.muted},`bounce `,p(e.bounceRate),` · avg session `,m(e.avgSessionSec)))};async function g(a){let u=await e(),d=await t({strict:!1}),g=new n({config:u,cliVersion:a.cliVersion,token:d}),_,v;try{({siteId:_,site:v}=await o(g,{explicit:a.siteId,headless:!!(a.json||a.csv||a.tsv||a.ndjson),cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let y=i(a),b=a.range??`24h`,x=[{key:`url`,label:`page`,width:40,format:e=>String(e??`—`)},{key:`views`,label:`views`,width:8,align:`right`}],S=[{key:`country`,label:`country`,width:8},{key:`visitors`,label:`visitors`,width:8,align:`right`}];return l({cliVersion:a.cliVersion,title:`stats · ${v?.url?v.url.replace(/^https?:\/\//,``).replace(/\/$/,``):v?.name??_}`,commandName:`stats`,ranges:{windows:[`24h`,`7d`,`30d`]},ai:{api:g,siteId:_,siteLabel:v?.url?v.url.replace(/^https?:\/\//,``).replace(/\/$/,``):v?.name??_},authToken:d?.accessToken??null,refreshIntervalMs:a.watch?6e4:0,fetcher:(e,t)=>g.getStats(_,t??b,e),format:y,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){process.stdout.write(JSON.stringify(e,null,t===`json`?2:0)),t===`ndjson`&&process.stdout.write(`
|
|
2
2
|
`);return}process.stdout.write(r([{range:b,visitors:e.visitors,pageviews:e.pageviews,sessions:e.sessions,bounceRate:p(e.bounceRate),avgSession:m(e.avgSessionSec)}],[`range`,`visitors`,`pageviews`,`sessions`,`bounceRate`,`avgSession`],t))},panels:[{id:`summary`,title:`Summary`,render:e=>f.createElement(h,{data:e})},{id:`pages`,title:`Top pages`,render:e=>e.topPages.length===0?f.createElement(c,{reason:`no-data`,headline:`No pages yet`,hint:`No page views in the ${b} window.`}):f.createElement(s,{data:e.topPages.slice(0,10),columns:x,headerStyle:`accent`})},{id:`countries`,title:`Top countries`,render:e=>e.topCountries.length===0?f.createElement(c,{reason:`no-data`,headline:`No country data yet`,hint:`No located visitors in the ${b} window.`}):f.createElement(s,{data:e.topCountries.slice(0,10),columns:S,headerStyle:`accent`})}]})}export{g as statsCommand};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{configPath as e,readConfig as t,writeConfig as n}from"./config
|
|
1
|
+
import{configPath as e,readConfig as t,writeConfig as n}from"./config-JVhBplSX.js";import"./api-CdcB84ie.js";import{readToken as r}from"./token-store-BvSCse1t.js";import{emit as i}from"./telemetry-BV-xvfdt.js";import{ApiV2Client as a}from"./api-v2-D0mvt__4.js";import{spawn as o}from"node:child_process";import s from"node:path";import{existsSync as c,mkdirSync as l,readFileSync as u,renameSync as d,unlinkSync as f,writeFileSync as p}from"node:fs";import{homedir as m}from"node:os";const h=6e4;function g(){return s.join(m(),`.zenovay`)}function _(){return s.join(g(),`status-agent.pid`)}function v(){return s.join(g(),`tmux-status`)}function y(){l(g(),{recursive:!0,mode:448})}function b(e){let t=_(),n=`${t}.tmp.${process.pid}`;p(n,String(e),{mode:384}),d(n,t)}function x(e){try{return process.kill(e,0),!0}catch{return!1}}function S(e){if(!e)return[];let t=[];for(let n of e.split(`,`).map(e=>e.trim()).filter(Boolean)){let e=n.match(/^([a-z_]+)\s*(>|<)\s*(-?\d+(?:\.\d+)?)$/i);if(!e)continue;t.push({key:(e[1]??``).toLowerCase(),op:e[2]??`>`,value:Number(e[3]??0)})}return t}function C(e,t,n,r=!1){let i=(t/1e5).toFixed(1),a=[`#[fg=colour141]● ${e} live`,`#[fg=colour114]▲ MRR $${i}k`,`#[fg=colour203]✗ ${n.toFixed(0)} err/s`].join(` `);return r?`#[reverse]${a}#[noreverse]`:a}const w=3e4,T=5*60*1e3,E=new Map;function D(e,t){let n=Math.floor(t/10),r=`${e}:${n}`,i=Date.now(),a=E.get(r);return a&&i-a<T?!1:(E.set(r,i),!0)}async function O(e,t){let n=process.platform;try{if(n===`darwin`){await new Promise((n,r)=>{let i=o(`terminal-notifier`,[`-title`,e,`-message`,t,`-group`,`zenovay`],{stdio:`ignore`});i.on(`error`,r),i.on(`exit`,()=>n())});return}if(n===`linux`){await new Promise((n,r)=>{let i=o(`notify-send`,[e,t],{stdio:`ignore`});i.on(`error`,r),i.on(`exit`,()=>n())});return}}catch{}process.stdout.write(`\x1b]9;${e} — ${t}\x07`)}function k(e,t){let n=[];for(let r of e){let e=t[r.key];if(typeof e!=`number`)continue;r.op===`>`&&e>r.value&&n.push({rule:r,actual:e}),r.op===`<`&&e<r.value&&n.push({rule:r,actual:e})}return n}async function A(e){let n=await t(),o=await r({strict:!1});if(!o)return process.stderr.write(`status-agent: not logged in
|
|
2
2
|
`),2;let s=new a({config:n,cliVersion:e.cliVersion,token:o}),c=e.siteId??n.defaultSiteId??``;if(!c)return process.stderr.write("status-agent: no site selected — pass --site-id or run `zenovay use <site>`\n"),2;y();let l=n.statusAgent?.notifyOn,u=n.statusAgent?.refreshIntervalMs,d=S(e.notifyOn??l),m=e.intervalMs??u??h,g=Date.now(),b=0;i(`status_agent.start`,{properties:{rule_count:d.length,interval_ms:m}});let x=null,T=!1,E=0,A=null,j=()=>{T=!0,A&&A()};for(process.on(`SIGTERM`,j),process.on(`SIGINT`,j);!T;){try{let[e,t,n]=await Promise.all([s.getLive(c).catch(()=>({activeVisitors:0,recentEvents:[]})),s.getErrors(c,{window:`24h`}).catch(()=>({errors:[],total:0})),s.getRevenue(c,`24h`).catch(()=>null)]),r=e.activeVisitors,a=n?.mrr??n?.totalAmount??0,o=t.total/86400,l=x&&x>0?(x-a)/x*100:0,u=k(d,{error_rate:o,revenue_drop:l}),f=!1;for(let e of u){if(!D(e.rule.key,e.actual))continue;f=!0,i(`status_agent.alert_fired`,{properties:{rule_key:e.rule.key,op:e.rule.op}}),await O(`Zenovay alert`,`${e.rule.key} ${e.rule.op} ${e.rule.value} (got ${e.actual.toFixed(2)})`)}f&&(E=Date.now());let m=E>0&&Date.now()-E<w;p(v(),C(r,a,o,m),{mode:420}),b+=1,b%10==0&&i(`status_agent.tick`,{properties:{tick:b,has_revenue:a>0,has_visitors:r>0,had_errors:o>0}}),x=a}catch(e){process.stderr.write(`status-agent tick failed: ${e.message}\n`)}await new Promise(e=>{let t=setTimeout(e,m);A=()=>{clearTimeout(t),e()}}),A=null}i(`status_agent.stop`,{duration_ms:Date.now()-g,properties:{ticks:b}});try{f(_())}catch{}return 0}function j(){return[`# Add to ~/.tmux.conf:`,`set -g status-right "#(cat ~/.zenovay/tmux-status) %H:%M"`,``,`# Then reload:`,`# $ tmux source ~/.tmux.conf`].join(`
|
|
3
3
|
`)}function M(){let e=process.argv[0]??`zenovay`;return[`[Unit]`,`Description=Zenovay status agent`,`After=network.target`,``,`[Service]`,`Type=simple`,`ExecStart=${e} status-agent --child`,`Restart=on-failure`,`RestartSec=10`,``,`[Install]`,`WantedBy=default.target`,``,`# Save as ~/.config/systemd/user/zenovay-status.service`,`# systemctl --user enable --now zenovay-status`].join(`
|
|
4
4
|
`)}function N(){let e=process.argv[0]??`zenovay`;return[`<?xml version="1.0" encoding="UTF-8"?>`,`<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">`,`<plist version="1.0">`,`<dict>`,` <key>Label</key><string>com.zenovay.status-agent</string>`,` <key>ProgramArguments</key>`,` <array>`,` <string>${e}</string>`,` <string>status-agent</string>`,` <string>--child</string>`,` </array>`,` <key>RunAtLoad</key><true/>`,` <key>KeepAlive</key><true/>`,`</dict>`,`</plist>`,``,`<!-- Save as ~/Library/LaunchAgents/com.zenovay.status-agent.plist -->`,`<!-- launchctl load ~/Library/LaunchAgents/com.zenovay.status-agent.plist -->`].join(`
|
|
@@ -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";import{fmtDate as a,formatTable as o,shortId as s}from"./fmt-xxIPQJX-.js";async function c(c){let l=await e(),u=await t({strict:!1}),d=new n({config:l,cliVersion:c.cliVersion,token:u});try{await r(d,`pro`)}catch(e){return process.stderr.write(`✗ ${e.message}\n`),2}try{switch(c.action){case`list`:{let e=await d.listTeam();if(c.json)return process.stdout.write(JSON.stringify(e,null,2)+`
|
|
2
2
|
`),0;let t=[{key:`userId`,header:`user id`,width:14,format:e=>s(String(e))},{key:`email`,header:`email`,width:32,format:e=>String(e??`—`)},{key:`role`,header:`role`,width:8},{key:`joinedAt`,header:`joined`,width:10,format:e=>a(e)}],n=[{key:`id`,header:`invite id`,width:14,format:e=>s(String(e))},{key:`email`,header:`email`,width:32},{key:`role`,header:`role`,width:8},{key:`expiresAt`,header:`expires`,width:10,format:e=>a(e)}];return process.stdout.write(`\nMEMBERS (${e.members.length})\n`),e.members.length===0?process.stdout.write(` — none —
|
|
3
3
|
`):process.stdout.write(o({rows:e.members,cols:t})),process.stdout.write(`\nPENDING INVITES (${e.invites.length})\n`),e.invites.length===0?process.stdout.write(` — none —
|
|
4
4
|
`):process.stdout.write(o({rows:e.invites,cols:n})),process.stdout.write(`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{readConfig as e,updateConfig as t}from"./config
|
|
1
|
+
import{readConfig as e,updateConfig as t}from"./config-JVhBplSX.js";import"./api-CdcB84ie.js";import{readToken as n}from"./token-store-BvSCse1t.js";import{ApiV2Client as r}from"./api-v2-D0mvt__4.js";function i(e){return e.length>12?`${e.slice(0,8)}…${e.slice(-4)}`:e}async function a(a){let o=await e(),s=await n({strict:!1});if(!s)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let c=new r({config:o,cliVersion:a.cliVersion,token:s});try{switch(a.action){case`reset`:{let e=await t({currentTeamId:void 0,currentTeamName:void 0});return a.json?(process.stdout.write(JSON.stringify({reset:!0,currentTeamId:e.currentTeamId??null})+`
|
|
2
2
|
`),0):(process.stdout.write(`✔ Team override cleared. Future commands use the API key's default team.
|
|
3
3
|
`),0)}case`current`:{let e=await c.me(),t=e.teams?.find(e=>e.isCurrent)??(e.team?{id:e.team.id,name:e.team.name,plan:e.team.plan,role:`?`,siteCount:0,isCurrent:!0}:null);return a.json?(process.stdout.write(JSON.stringify({current:t,override:o.currentTeamId??null},null,2)+`
|
|
4
4
|
`),0):t?(process.stdout.write(`\n current team: ${t.name} (${i(t.id)})\n plan: ${t.plan}\n override? ${o.currentTeamId?"yes — set via `teams switch`":`no — using API key default`}\n\n`),0):(process.stdout.write(`No team currently bound.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{configDir as e,readConfig as t,writeConfig as n}from"./config
|
|
1
|
+
import{configDir as e,readConfig as t,writeConfig as n}from"./config-JVhBplSX.js";import r from"node:path";import{mkdirSync as i,promises as a,readFileSync as o,writeFileSync as s}from"node:fs";import{ulid as c}from"ulid";const l=`/cli/telemetry/events`,u=5e3,d=20,f=100,p=3e3,m=r.join(e(),`telemetry-pending.json`),h=c(),g=Date.now(),_=[];let v=null,y=null,b=`0.0.0`,x=`https://api.zenovay.com`,S,C=!1,w=null;async function T(e){if(C)return;if(C=!0,b=e.cliVersion,x=e.apiBase??`https://api.zenovay.com`,S=e.token,E()){w=!1;return}let r=await t().catch(()=>null);if(r){if(r.telemetry===void 0){process.stderr.write(`Zenovay CLI sends anonymous usage telemetry to help us improve.
|
|
2
2
|
No site data, file contents, or chat messages are included.
|
|
3
3
|
Disable: \`zenovay telemetry off\` or set ZENOVAY_TELEMETRY=0 / DO_NOT_TRACK=1
|
|
4
4
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./config-JVhBplSX.js";import{emit as e,flush as t,getProcessUptimeMs as n,getTelemetryStatus as r,initTelemetry as i,setTelemetry as a}from"./telemetry-BV-xvfdt.js";export{e as emit,t as flush,n as getProcessUptimeMs,r as getTelemetryStatus,i as initTelemetry,a as setTelemetry};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import"./config
|
|
1
|
+
import"./config-JVhBplSX.js";import{getTelemetryStatus as e,setTelemetry as t}from"./telemetry-BV-xvfdt.js";async function n(n){let r=n.action??`status`;if(r===`on`)return await t(!0),n.json?process.stdout.write(JSON.stringify({ok:!0,enabled:!0})+`
|
|
2
2
|
`):process.stdout.write(`Telemetry enabled.
|
|
3
3
|
`),0;if(r===`off`)return await t(!1),n.json?process.stdout.write(JSON.stringify({ok:!0,enabled:!1})+`
|
|
4
4
|
`):process.stdout.write(`Telemetry disabled. Existing pending events on disk will not be sent.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readConfig as e,updateConfig as t}from"./config
|
|
1
|
+
import{readConfig as e,updateConfig as t}from"./config-JVhBplSX.js";const n=5*60*1e3,r=new Set([`free`,`pro`,`scale`,`enterprise`]),i={free:0,pro:1,scale:2,enterprise:3},a=`https://app.zenovay.com/billing`;function o(e){let t=(e??`free`).trim().toLowerCase();return r.has(t)?t:`free`}async function s(r){let i=await e(),a=Date.now();if(i.cachedTier&&i.cachedTierAt&&a-i.cachedTierAt<n)return o(i.cachedTier);try{let e=await r.me(),n=o(e.team?.plan);return await t({cachedTier:n,cachedTierAt:a}),n}catch{return i.cachedTier?o(i.cachedTier):`free`}}async function c(e,t){let n=await s(e);if(i[n]>=i[t])return;let r=t.charAt(0).toUpperCase()+t.slice(1);throw Error(`This command requires the ${r} plan or higher (you're on ${n}). Upgrade at ${a}.`)}export{s as getCachedTier,c as requireTier};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{configDir as e}from"./config
|
|
1
|
+
import{configDir as e}from"./config-JVhBplSX.js";import t from"node:path";import{promises as n}from"node:fs";import{z as r}from"zod";const i=r.object({accessToken:r.string().min(1),refreshToken:r.string().min(1),expiresAt:r.number(),tokenType:r.literal(`Bearer`).default(`Bearer`),scope:r.string().optional(),userId:r.string().optional(),teamId:r.string().optional(),email:r.string().email().optional(),region:r.string().optional(),cliVersionAtIssue:r.string().optional()});function a(){return t.join(e(),`auth.json`)}async function o(e){let r=a(),o;try{o=await n.stat(r)}catch(e){if(e.code===`ENOENT`)return null;throw e}if(process.platform!==`win32`){let n=o.mode&511;if(n&63){let i=e?.strict??!0;if(i)throw Error(`Refusing to read ${r}: file has insecure permissions ${n.toString(8).padStart(3,`0`)} (expected 600). Fix: chmod 600 "${r}" && chmod 700 "${t.dirname(r)}"`)}}let s=await n.readFile(r,`utf8`),c;try{c=JSON.parse(s)}catch{throw Error(`Auth file at ${r} is not valid JSON. Run \`zenovay login\` again.`)}let l=i.safeParse(c);if(!l.success)throw Error(`Auth file at ${r} is malformed. Run \`zenovay login\` again.`);return l.data}async function s(t){let r=e();await n.mkdir(r,{recursive:!0,mode:448});let o=a(),s=i.parse(t),c=JSON.stringify(s,null,2);if(await n.writeFile(o,c,{mode:384}),process.platform!==`win32`){await n.chmod(o,384);try{await n.chmod(r,448)}catch{}}}async function c(){try{await n.unlink(a())}catch(e){if(e.code!==`ENOENT`)throw e}}function l(e,t=3e4){return Date.now()>=e.expiresAt-t}export{a as authPath,c as clearToken,l as isExpired,o as readToken,i as tokenStateSchema,s as writeToken};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./config-JVhBplSX.js";import{authPath as e,clearToken as t,isExpired as n,readToken as r,tokenStateSchema as i,writeToken as a}from"./token-store-BvSCse1t.js";export{r as readToken};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config-JVhBplSX.js";import{classifyBump as t,fetchManifest as n}from"./check-D9G0N7NB.js";import{applyUpdate as r}from"./apply-oUMOH7u2.js";import"./formatter-C4YSOKuq.js";import{emit$1 as i,isHeadless as a}from"./emit-D4YlMlzk.js";async function o(o){let s=await e(),c=await n({cliBase:s.cliBase}),l=t(o.cliVersion,c.latest);if(o.check)return a({json:o.json})?i({type:`info`,message:`latest=${c.latest} current=${o.cliVersion} bump=${l}`}):process.stdout.write(`Current: ${o.cliVersion}\nLatest: ${c.latest}\nBump: ${l}\n`),{updated:!1,from:o.cliVersion,to:c.latest};if(l===`none`)return a({json:o.json})||process.stdout.write(`Already on latest (${o.cliVersion}).\n`),{updated:!1,from:o.cliVersion,to:c.latest};if(l===`downgrade`&&!o.forceDowngrade)throw Error(`Refused to downgrade ${o.cliVersion} → ${c.latest}. Pass --force-downgrade if you really want this.`);let u=await r({currentVersion:o.cliVersion,cliBase:s.cliBase,binaryPath:o.binaryPath,forceDowngrade:o.forceDowngrade});return a({json:o.json})?u.updated&&i({type:`update.applied`,from:u.from,to:u.to}):u.updated?process.stdout.write(`Updated ${u.from} → ${u.to}\n`):process.stdout.write(`Not updated (${u.reason??`unknown`}).\n`),u}export{o as updateCommand};
|
|
@@ -1 +1 @@
|
|
|
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"./formatter-C4YSOKuq.js";import{emit$1 as i,isHeadless as a}from"./emit-D4YlMlzk.js";import{openInBrowser as o}from"./open-url-BtI5aLgL.js";import"./theme-Brz9wK0w.js";import{Banner as s,Panel as c,useTheme as l}from"./panel-CTtQ2ue6.js";import"./prompt-BXvg2B4R.js";import{Keybar as u}from"./keybar-DO5OoZy9.js";import{resolveSiteId as d}from"./resolve-site-BTVBMF1C.js";import{stripUrlPrefix as f}from"./fmt-xxIPQJX-.js";import{DataTable as p}from"./data-table-BhKjjiOS.js";import{EmptyState as m}from"./empty-state-D-krMX62.js";import{deepLinkFor as h}from"./keybar-deep-link-B4VJn2ko.js";import{useFullscreen as g}from"./use-fullscreen-ucSyZkjO.js";import{useSiteSwitcher as _}from"./site-switcher-BAoYWp18.js";import{Box as v,Text as y,render as b,useApp as x,useInput as S}from"ink";import C,{useEffect as w,useState as T}from"react";import E from"ink-spinner";function D(e){return e===`up`?`● up`:e===`down`?`● down`:`○ unknown`}function O(e){if(!e)return`—`;let t=Date.parse(e);if(Number.isNaN(t))return`—`;let n=Math.round((t-Date.now())/(1e3*60*60*24));return`${n}d`}function k(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`}async function A(o){let s=await e(),c=await t({strict:!1});if(!c)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let l=new n({config:s,cliVersion:o.cliVersion,token:c});try{await r(l,`pro`)}catch(e){return process.stderr.write(`${e.message}\n`),2}let u,f;try{({siteId:u,site:f}=await d(l,{explicit:o.siteId,headless:!!o.json,cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let p=f?.url?f.url.replace(/^https?:\/\//,``).replace(/\/$/,``):f?.name??u;if(a(o)){let e=await l.getUptime(u);return i({type:`uptime.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=b(C.createElement(j,{api:l,siteId:u,siteLabel:p,cliVersion:o.cliVersion,onExit:n=>{t(),e(n)}}))})}const j=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{g();let{exit:a}=x(),{theme:d}=l(),[b,A]=T(null),[j,M]=T(!0),[N,P]=T(null),[ee,F]=T(0),[I,L]=T(!1),[R,z]=T(null),[B,V]=T(()=>Date.now()),[H,U]=T(t),[W,G]=T(n),K=_(e,H,e=>{U(e.id),G(e.url.replace(/^https?:\/\//,``).replace(/\/$/,``)),A(null)}),q=[{key:`r`,label:`refresh`},{key:`s`,label:`site`},{key:`o`,label:`browser`},{key:`q`,label:`quit`}];if(S((e,t)=>{if(K.open){(t.escape||e===`s`)&&K.close();return}if(e===`r`||e===`R`){F(e=>e+1);return}if(e===`s`){K.toggle();return}if(e===`o`||e===`O`){o(h(`uptime`,{siteId:H}));return}e===`q`&&(a(),i(0))}),w(()=>{let e=setInterval(()=>V(Date.now()),5e3),t=setInterval(()=>F(e=>e+1),3e4);return()=>{clearInterval(e),clearInterval(t)}},[]),w(()=>{let t=!1;return b===null?M(!0):L(!0),(async()=>{try{let n=await e.getUptime(H);if(t)return;A(n.monitors),M(!1),L(!1),z(Date.now())}catch(e){t||(P(e.message),M(!1),L(!1))}})(),()=>{t=!0}},[e,H,ee]),j)return C.createElement(v,{flexDirection:`column`},C.createElement(s,{version:r,subtitle:`uptime · ${W}`,live:!1}),C.createElement(c,{title:`Loading`,state:`busy`},C.createElement(v,null,C.createElement(y,{color:d.accent},C.createElement(E,{type:`dots`})),C.createElement(y,null,` Fetching monitors…`))));if(N)return C.createElement(v,{flexDirection:`column`},C.createElement(s,{version:r,subtitle:`uptime · ${W}`,live:!1}),C.createElement(m,{reason:`error`,headline:`Couldn't load monitors`,hint:N}),C.createElement(u,{items:q,active:`r`}));if(!b||b.length===0)return C.createElement(v,{flexDirection:`column`},C.createElement(s,{version:r,subtitle:`uptime · ${W}`,live:!1}),C.createElement(m,{reason:`no-data`,headline:`No monitors configured`,hint:`Add an uptime monitor at app.zenovay.com/uptime, press [s] to switch site, then re-run.`}),K.overlay,C.createElement(u,{items:q,active:`r`}));let J=[{key:`url`,label:`monitor`,width:36,format:e=>f(String(e??``))},{key:`status`,label:`status`,width:11,format:e=>D(String(e))},{key:`p95ms`,label:`p95 ms`,align:`right`,width:8,format:e=>typeof e==`number`?String(e):`—`},{key:`sslExpiry`,label:`ssl exp`,align:`right`,width:8,format:e=>O(e)}],Y=process.stdout.rows??40,X=Math.max(4,Y-16),Z=b.slice(0,X),Q=b.length-Z.length,$=b.filter(e=>e.status===`down`).length,te=b.filter(e=>e.status===`up`).length;return C.createElement(v,{flexDirection:`column`},C.createElement(s,{version:r,subtitle:`uptime · ${W}`,live:!0}),C.createElement(v,{marginTop:1,flexDirection:`row`},C.createElement(y,{color:d.success},te,` up`),C.createElement(y,{color:d.dim},` · `),C.createElement(y,{color:$>0?d.error:d.dim},$,` down`)),C.createElement(v,{marginTop:1},C.createElement(c,{title:`Monitors (${b.length})`},C.createElement(p,{columns:J,data:Z,zebra:!0}),Q>0?C.createElement(y,{color:d.dim},` +${Q} more · run with --json for all`):null)),C.createElement(v,{marginTop:1},C.createElement(y,{color:d.dim},I?`↻ refreshing…`:R===null?``:`↻ updated ${k(R,B)} · [r] refresh`)),K.overlay,C.createElement(u,{items:q,active:`r`}))};export{A as uptimeCommand};
|
|
@@ -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{ApiV2Client as n}from"./api-v2-D0mvt__4.js";import{fmtDate as r,fmtNumber as i}from"./fmt-xxIPQJX-.js";const a=1e8,o=e=>e<=0||e>=a;function s(e,t,n=24){if(o(t))return`─`.repeat(n);let r=Math.min(1,e/t),i=Math.round(r*n);return`█`.repeat(i)+`░`.repeat(Math.max(0,n-i))}function c(e,t){if(o(t))return`—`;let n=e/t*100;return`${n.toFixed(0)}%`}function l(e,t){if(o(t))return``;let n=e/t;return n>=1?`⚠ over limit`:n>=.8?`⚠ near limit`:``}function u(e,t){return o(e)?`∞`:t(e)}async function d(a){let o=await e(),d=await t({strict:!1});if(!d)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let f=new n({config:o,cliVersion:a.cliVersion,token:d}),p;try{p=await f.getUsage()}catch(e){return process.stderr.write(`✗ ${e.message}\n`),1}if(a.json)return process.stdout.write(JSON.stringify(p,null,2)+`
|
|
2
2
|
`),0;let m=[{label:`events this month`,used:p.events.thisMonth,limit:p.events.monthlyLimit,format:i},{label:`events today`,used:p.events.today,limit:p.events.dailyLimit,format:i},{label:`websites`,used:p.websites.used,limit:p.websites.limit},{label:`team members`,used:p.teamMembers.used,limit:p.teamMembers.limit}],h=18,g=8,_=9,v=[];v.push(``),v.push(` plan: ${p.plan}`),v.push(``);for(let e of m){let t=e.format??i,n=t(e.used).padStart(g),r=u(e.limit,t).padStart(_),a=s(e.used,e.limit),o=c(e.used,e.limit).padStart(5),d=l(e.used,e.limit);v.push(` ${e.label.padEnd(h)} ${n} / ${r} ${a} ${o} ${d}`.trimEnd())}return v.push(` ${`api keys`.padEnd(h)} ${i(p.apiKeys.used).padStart(g)} / ${`—`.padStart(_)} ${`─`.repeat(24)} ${`—`.padStart(5)}`),v.push(``),v.push(` data retention: ${p.dataRetentionDays} days`),v.push(` last event: ${r(p.events.lastEventAt,`datetime`)}`),v.push(``),process.stdout.write(v.join(`
|
|
3
3
|
`)),0}export{d as usageCommand};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{readConfig as e,updateConfig as t}from"./config
|
|
1
|
+
import{readConfig as e,updateConfig as t}from"./config-JVhBplSX.js";import{ApiClient as n}from"./api-CdcB84ie.js";import{readToken as r}from"./token-store-BvSCse1t.js";import"./formatter-C4YSOKuq.js";import{emitEnvelope as i,wrapSnapshot as a}from"./emit-D4YlMlzk.js";async function o(o){if(o.reset)return await t({defaultSiteId:void 0,defaultSiteName:void 0}),o.json?(i(a({reset:!0,defaultSiteId:null},`use.reset`)),0):(process.stdout.write(`Default site cleared.
|
|
2
2
|
`),0);if(!o.match||!o.match.trim()){let t=await e();if(t.defaultSiteId){let e={siteId:t.defaultSiteId,name:t.defaultSiteName??null,domain:t.defaultSiteName??null};return o.json?(i(a(e,`use.current`,{siteId:t.defaultSiteId})),0):(process.stdout.write(`Default site: ${e.name??e.siteId} (${t.defaultSiteId})\n`),0)}return o.json?(i(a(null,`use.current`,{})),0):(process.stdout.write("No default site set. Run `zenovay use <domain>` to set one.\n"),0)}let c=await e(),l=await r({strict:!1});if(!l&&!process.env.ZENOVAY_API_TOKEN)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let u=new n({config:c,cliVersion:o.cliVersion,token:l}),d=o.match.trim().toLowerCase(),f=await u.getSites(),p=f.find(e=>e.id===o.match||e.trackingCode===o.match||e.url===o.match||s(e.url)===d||e.name.toLowerCase()===d),m=p??f.find(e=>s(e.url).includes(d)||e.name.toLowerCase().includes(d));return m?(await t({defaultSiteId:m.id,defaultSiteName:m.name}),o.json?(i(a({siteId:m.id,name:m.name,domain:s(m.url)},`use.set`,{siteId:m.id})),0):(process.stdout.write(`Default site → ${m.name} (${m.url})\n`),0)):(process.stderr.write(`No site matched "${o.match}". Your sites:\n${f.map(e=>` ${e.name} — ${e.url} — ${e.id}`).join(`
|
|
3
3
|
`)}\n`),2)}function s(e){return e.toLowerCase().replace(/^https?:\/\//,``).replace(/\/.*$/,``)}export{o as useCommand};
|
|
@@ -1,2 +1,2 @@
|
|
|
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"./error-codes-ByhvHx2M.js";import"./telemetry-BV-xvfdt.js";import{ApiV2Client as n}from"./api-v2-D0mvt__4.js";import{formatTabular as r,selectFormat as i}from"./formatter-C4YSOKuq.js";import{openInBrowser as a}from"./open-url-BtI5aLgL.js";import"./client-ntsEXSVC.js";import"./theme-Brz9wK0w.js";import{useTheme as o}from"./panel-CTtQ2ue6.js";import"./prompt-BXvg2B4R.js";import"./keybar-DO5OoZy9.js";import{brailleSpark as s,spark as c}from"./sparkline-CpoBjjlc.js";import"./chat-panel-D9IjovCR.js";import{resolveSiteId as l}from"./resolve-site-BTVBMF1C.js";import{DataTable as u}from"./data-table-BhKjjiOS.js";import{EmptyState as d}from"./empty-state-D-krMX62.js";import"./grid-CMwhs-Ms.js";import{deepLinkFor as f}from"./keybar-deep-link-B4VJn2ko.js";import"./use-fullscreen-ucSyZkjO.js";import"./range-tabs-CH2cEXOf.js";import{runAnalyticalScreen as p}from"./analytical-screen-BvQa8oH6.js";import{Box as m,Text as h}from"ink";import g from"react";function _(e){let t=Math.max(0,Math.floor((Date.now()-new Date(e).getTime())/1e3));return t<60?`${t}s`:t<3600?`${Math.floor(t/60)}m`:t<86400?`${Math.floor(t/3600)}h`:`${Math.floor(t/86400)}d`}function v(e){let t=e,n=t.events??t.timeseries;return Array.isArray(n)&&n.length>0?c(n,8):`▁▁▁▁▁▁▁▁`}function y(e){let t=e;if(typeof t.sessionDurationSec==`number`)return t.sessionDurationSec;if(typeof t.sessionDurationMs==`number`)return Math.floor(t.sessionDurationMs/1e3);if(typeof t.durationMs==`number`)return Math.floor(t.durationMs/1e3);if(typeof t.duration==`number`)return Math.floor(t.duration/1e3);let n=Date.parse(e.startedAt);return Number.isNaN(n)?0:Math.max(0,Math.floor((Date.now()-n)/1e3))}async function b(o){let s=await e(),c=await t({strict:!1}),u=new n({config:s,cliVersion:o.cliVersion,token:c}),d,m;try{({siteId:d,site:m}=await l(u,{explicit:o.siteId,headless:!!(o.json||o.csv||o.tsv||o.ndjson),cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let h=m?.url?m.url.replace(/^https?:\/\//,``).replace(/\/$/,``):m?.name??d,b=i(o),C=o.limit??50,w=typeof o.minDuration==`number`&&o.minDuration>0?o.minDuration:0,T=e=>w<=0?e:e.filter(e=>y(e)>=w),E=6e4,D=e=>{let t=Date.parse(e.startedAt);return Number.isFinite(t)&&Date.now()-t<E},O=[{key:`startedAt`,label:``,width:5,format:(e,t)=>D(t)?`● new`:``},{key:`startedAt`,label:`when`,width:6,format:e=>_(String(e))},{key:`country`,label:`country`,width:7,format:e=>String(e??`—`)},{key:`city`,label:`city`,width:14,format:e=>String(e??`—`)},{key:`device`,label:`device`,width:7,format:e=>String(e??`—`)},{key:`page`,label:`page`,width:26,format:e=>String(e??`—`)},{key:`id`,label:`24h`,width:8,format:(e,t)=>v(t)}];return p({cliVersion:o.cliVersion,title:`visitors · ${h}`,commandName:`visitors`,ai:{api:u,siteId:d,siteLabel:h},authToken:c?.accessToken??null,refreshIntervalMs:1e4,fetcher:e=>u.getVisitors(d,{limit:C},e),format:b,keybindings:{o:{label:`open in browser`,handler:()=>{a(f(`visitors`,{siteId:d}))}}},headlessEmit:(e,t)=>{let n={...e,visitors:T(e.visitors)};if(t===`json`||t===`ndjson`){process.stdout.write(JSON.stringify(n,null,t===`json`?2:0)),t===`ndjson`&&process.stdout.write(`
|
|
2
2
|
`);return}let i=[`startedAt`,`country`,`city`,`device`,`page`];process.stdout.write(r(n.visitors,i,t))},panels:[{id:`live`,title:`Now`,render:e=>g.createElement(x,{visitors:T(e.visitors)})},{id:`visitors`,title:`Active sessions`,render:e=>g.createElement(S,{visitors:T(e.visitors),limit:C,columns:O})}]})}const x=({visitors:e})=>{let{theme:t}=o(),n=[...e].sort((e,t)=>Date.parse(t.startedAt)-Date.parse(e.startedAt)),r=n[0],i=Array(24*6).fill(0),a=Date.now();for(let t of e){let e=a-new Date(t.startedAt).getTime(),n=Math.floor(e/(10*60*1e3));n>=0&&n<i.length&&(i[i.length-1-n]+=1)}return g.createElement(m,{flexDirection:`column`},g.createElement(h,{bold:!0},e.length,` live`),g.createElement(h,{color:t.muted},s(i,40)),r?g.createElement(h,{color:t.muted},`top: `,r.city??r.country??`—`,` · `,r.page??`—`):null)},S=({visitors:e,limit:t,columns:n})=>{let r=[...e].sort((e,t)=>Date.parse(t.startedAt)-Date.parse(e.startedAt)).slice(0,t);return r.length===0?g.createElement(d,{reason:`no-data`,headline:`No active sessions yet`,hint:`Visitors appear here as they browse — this view polls every 10s.`}):g.createElement(u,{columns:n,data:r,headerStyle:`accent`})};export{b as visitorsCommand};
|
|
@@ -1,2 +1,2 @@
|
|
|
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"./error-codes-ByhvHx2M.js";import"./telemetry-BV-xvfdt.js";import{ApiV2Client as n}from"./api-v2-D0mvt__4.js";import{formatTabular as r,selectFormat as i}from"./formatter-C4YSOKuq.js";import{openInBrowser as a}from"./open-url-BtI5aLgL.js";import"./client-ntsEXSVC.js";import"./theme-Brz9wK0w.js";import{useTheme as o}from"./panel-CTtQ2ue6.js";import"./prompt-BXvg2B4R.js";import"./keybar-DO5OoZy9.js";import"./chat-panel-D9IjovCR.js";import{resolveSiteId as s}from"./resolve-site-BTVBMF1C.js";import{DataTable as c}from"./data-table-BhKjjiOS.js";import{EmptyState as l}from"./empty-state-D-krMX62.js";import"./grid-CMwhs-Ms.js";import{deepLinkFor as u}from"./keybar-deep-link-B4VJn2ko.js";import"./use-fullscreen-ucSyZkjO.js";import"./range-tabs-CH2cEXOf.js";import{runAnalyticalScreen as d}from"./analytical-screen-BvQa8oH6.js";import{Box as f,Text as p}from"ink";import m from"react";const h={lcp:{good:2500,poor:4e3},inp:{good:200,poor:500},cls:{good:.1,poor:.25},ttfb:{good:800,poor:1800},fcp:{good:1800,poor:3e3}};function g(e,t){let n=h[e];return t<=n.good?{label:`good`,tone:`good`}:t<=n.poor?{label:`needs`,tone:`needs`}:{label:`poor`,tone:`poor`}}function _(e,t){return e===`cls`?t.toFixed(3):t<1e3?`${Math.round(t)}ms`:`${(t/1e3).toFixed(2)}s`}function v({data:e}){let{theme:t}=o(),n={good:t.success,needs:t.warn,poor:t.error},r=t=>{let n=0,r=0;for(let i of e.vitals){let e=i[t]?.p75;typeof e==`number`&&(n+=e*i.samples,r+=i.samples)}return r>0?n/r:0},i=[`lcp`,`inp`,`cls`,`ttfb`,`fcp`];return m.createElement(f,{flexDirection:`column`},i.map(e=>{let t=r(e),i=g(e,t);return m.createElement(p,{key:e},m.createElement(p,{color:n[i.tone]},`● `),m.createElement(p,{bold:!0},e.toUpperCase().padEnd(5)),` `,m.createElement(p,null,_(e,t).padStart(8)),` `,m.createElement(p,{color:n[i.tone]},i.label))}))}function y({data:e,columns:t}){return e.vitals.length===0?m.createElement(l,{reason:`no-data`,headline:`No vitals data yet`,hint:`Core Web Vitals appear once real visitors load instrumented pages.`}):m.createElement(c,{data:e.vitals.slice(0,15),columns:t,headerStyle:`accent`})}async function b(o){let c=await e(),l=await t({strict:!1}),f=new n({config:c,cliVersion:o.cliVersion,token:l}),p,h;try{({siteId:p,site:h}=await s(f,{explicit:o.siteId,headless:!!(o.json||o.csv||o.tsv||o.ndjson),cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let g=i(o),b=[{key:`url`,label:`url`,width:32},{key:`device`,label:`device`,width:7,format:e=>String(e??`—`)},{key:`lcp`,label:`LCP p75`,width:9,align:`right`,format:e=>e&&typeof e==`object`&&`p75`in e?_(`lcp`,e.p75):`—`},{key:`inp`,label:`INP p75`,width:9,align:`right`,format:e=>e&&typeof e==`object`&&`p75`in e?_(`inp`,e.p75):`—`},{key:`cls`,label:`CLS p75`,width:9,align:`right`,format:e=>e&&typeof e==`object`&&`p75`in e?_(`cls`,e.p75):`—`},{key:`samples`,label:`n`,width:6,align:`right`}];return d({cliVersion:o.cliVersion,title:`vitals · ${h?.url?h.url.replace(/^https?:\/\//,``).replace(/\/$/,``):h?.name??p}`,commandName:`vitals`,ai:{api:f,siteId:p,siteLabel:h?.url?h.url.replace(/^https?:\/\//,``).replace(/\/$/,``):h?.name??p},authToken:l?.accessToken??null,refreshIntervalMs:o.watch?5*6e4:0,ranges:!0,fetcher:(e,t)=>f.getVitals(p,{url:o.url,device:o.device,window:t??o.window},e),format:g,keybindings:{o:{label:`open in browser`,handler:()=>{a(u(`vitals`,{siteId:p}))}}},headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){process.stdout.write(JSON.stringify(e,null,t===`json`?2:0)),t===`ndjson`&&process.stdout.write(`
|
|
2
2
|
`);return}process.stdout.write(r(e.vitals,[`url`,`device`,`samples`],t))},panels:[{id:`summary`,title:`Site-wide p75`,render:e=>m.createElement(v,{data:e})},{id:`pages`,title:`Per-page`,render:e=>m.createElement(y,{data:e,columns:b})}]})}export{b as vitalsCommand};
|
|
@@ -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";function c(e){return e.length>12?`${e.slice(0,8)}…${e.slice(-4)}`:e}function l(e){return e?new Date(e).toISOString().slice(0,10):`—`}async function u(u){let d=await e(),f=await t({strict:!1}),p=new r({config:d,cliVersion:u.cliVersion,token:f});try{switch(u.action){case`list`:{let{webhooks:e}=await p.listWebhooks();if(u.json)return a(s(e,`webhooks.list`),{legacyKey:`webhooks`,legacyValue:e}),0;if(e.length===0)return process.stdout.write("No webhooks yet. Add one with `zenovay webhooks add <https-url> --events <e1,e2>`.\n"),0;let t=[``,`id`,`url`,`events`,`created`],n=[1,14,40,28,10],r=e=>e.map((e,t)=>(e??``).padEnd(n[t])).join(` `);process.stdout.write(r(t)+`
|
|
2
2
|
`),process.stdout.write(r(n.map(e=>`─`.repeat(e)))+`
|
|
3
3
|
`);for(let t of e){let e=t.status===`disabled`?`○`:`●`,i=t.url.length>n[2]?`${t.url.slice(0,n[2]-1)}…`:t.url,a=t.events.join(`,`),o=a.length>n[3]?`${a.slice(0,n[3]-1)}…`:a;process.stdout.write(r([e,c(t.id),i,o,l(t.createdAt)])+`
|
|
4
4
|
`)}return process.stdout.write(`
|
|
@@ -1,2 +1,2 @@
|
|
|
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"./theme-Brz9wK0w.js";import{Banner as r,Panel as i,useTheme as a}from"./panel-CTtQ2ue6.js";import"./progress-row-Afnt5Ng8.js";import"./prompt-BXvg2B4R.js";import{Keybar as o}from"./keybar-DO5OoZy9.js";import"./sparkline-CpoBjjlc.js";import{resolveSiteId as s}from"./resolve-site-BTVBMF1C.js";import"./data-table-BhKjjiOS.js";import"./bar-NfgovYHe.js";import"./ui-BTnLAro-.js";import{Box as c,Text as l,render as u,useApp as d,useInput as f}from"ink";import p,{useEffect as m,useState as h}from"react";function g(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`}async function _(e,t){let n=new TextEncoder,r=await crypto.subtle.importKey(`raw`,n.encode(e),{name:`HMAC`,hash:`SHA-256`},!1,[`sign`]),i=await crypto.subtle.sign(`HMAC`,r,n.encode(t));return Array.from(new Uint8Array(i),e=>e.toString(16).padStart(2,`0`)).join(``)}function v({label:e,value:t,valueColor:n}){let{theme:r}=a();return p.createElement(c,{flexDirection:`row`},p.createElement(c,{width:14},p.createElement(l,{color:r.dim},e.toUpperCase())),p.createElement(c,{flexGrow:1},p.createElement(l,{color:n??r.fg,wrap:`truncate`},t)))}function y({stats:e,target:t}){let{theme:n}=a();return p.createElement(i,{title:`webhooks forward`,state:e.connected?`ok`:`busy`},p.createElement(v,{label:`public url`,value:e.publicUrl,valueColor:n.accent}),p.createElement(v,{label:`forwarding to`,value:t}),p.createElement(c,{flexDirection:`row`,marginTop:1},e.connected?p.createElement(l,{color:n.success},`● connected`):p.createElement(l,{color:n.warn},`○ connecting…`),p.createElement(l,{color:n.muted},` · `,e.total,` requests · `),p.createElement(l,{color:n.success},e.ok,` ok`),p.createElement(l,{color:n.muted},` · `),p.createElement(l,{color:e.err>0?n.error:n.muted},e.err,` err`),e.lastStatus===null?null:p.createElement(l,{color:n.muted},` · last HTTP `,e.lastStatus)),e.lastError?p.createElement(c,{flexDirection:`row`},p.createElement(l,{color:n.error,wrap:`truncate`},`last error: `,e.lastError)):null)}async function b(i){let v=await e(),b=await t({strict:!1});if(!b?.accessToken)return process.stderr.write("Not authenticated. Run `zenovay login` first.\n"),2;if(!i.to)return process.stderr.write(`Missing --to <url> (e.g. --to localhost:3000/webhook).
|
|
2
2
|
`),2;let x=i.to.match(/^https?:\/\//)?i.to:`http://${i.to}`,S=new n({config:v,cliVersion:i.cliVersion,token:b}),C,w;try{({siteId:C,site:w}=await s(S,{explicit:i.siteId,headless:!1,cliVersion:i.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let T=w?.url?w.url.replace(/^https?:\/\//,``).replace(/\/$/,``):w?.name??C,E;try{E=await S.createTunnel(C,i.to)}catch(e){return process.stderr.write(`Failed to register tunnel: ${e.message}\n`),1}let D=i.sign?i.secret??E.tunnelKey:null,O=()=>{let{theme:e}=a(),{exit:t}=d(),[n,s]=h({total:0,ok:0,err:0,lastStatus:null,lastError:null,lastForwardedAt:null,publicUrl:E.publicUrl,wsUrl:E.wsUrl,connected:!1}),[u,v]=h(()=>Date.now());m(()=>{let e=setInterval(()=>v(Date.now()),5e3);return()=>clearInterval(e)},[]),f((e,n)=>{(e===`q`||n.escape)&&t()}),m(()=>{let e=new AbortController,t=async e=>{try{let t={...e.headers};delete t.host,delete t[`content-length`],D&&(t[`X-Zenovay-Signature`]=`sha256=${await _(D,e.body)}`);let n=await fetch(x,{method:e.method,headers:t,body:e.method===`GET`||e.method===`HEAD`?void 0:e.body}),r=await n.text(),i={};return n.headers.forEach((e,t)=>{i[t]=e}),s(e=>({...e,total:e.total+1,ok:e.ok+(n.ok?1:0),err:e.err+(n.ok?0:1),lastStatus:n.status,lastError:n.ok?null:`HTTP ${n.status}`,lastForwardedAt:Date.now()})),{status:n.status,headers:i,body:r}}catch(e){let t=e instanceof Error?e.message:String(e);return s(e=>({...e,total:e.total+1,err:e.err+1,lastError:t,lastForwardedAt:Date.now()})),{status:502,body:JSON.stringify({error:`cli_local_failed`,detail:t})}}};return(async()=>{let n=S.tunnelClient(E.wsUrl);s(e=>({...e,connected:!0}));try{await n.start(t,e.signal)}catch(e){s(t=>({...t,connected:!1,lastError:e.message}))}})(),()=>{e.abort()}},[]);let b=n.lastForwardedAt===null?n.connected?`↻ live · waiting for first webhook`:`↻ connecting…`:`↻ last forward ${g(n.lastForwardedAt,u)}`;return p.createElement(c,{flexDirection:`column`},p.createElement(r,{version:i.cliVersion,subtitle:`webhooks forward · ${T} · ${n.connected?`live`:`connecting`}`,live:n.connected}),p.createElement(y,{stats:n,target:`${x}${i.sign?` · HMAC-signed`:``}`}),p.createElement(c,{marginTop:1},p.createElement(l,{color:e.dim},b)),p.createElement(o,{items:[{key:`q`,label:`quit`},{key:`esc`,label:`quit`}]}))},{waitUntilExit:k}=u(p.createElement(O,null));return await k(),0}export{b as webhooksForwardCommand};
|
package/dist/wizard-bin.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import(`./init-
|
|
2
|
+
import(`./init-x1CXZTzr.js`).then(async({initCommand:e})=>{let{readFileSync:t}=await import(`node:fs`),n=await import(`node:path`),{fileURLToPath:r}=await import(`node:url`),i=n.dirname(r(import.meta.url)),a=JSON.parse(t(n.join(i,`..`,`package.json`),`utf8`)),o=process.argv.slice(2),s=o.includes(`--json`),c=o.includes(`--yes`),l=o.includes(`--skip-mcp`),u=o.includes(`--skip-verify`),d=await e({cliVersion:a.version,cwd:process.cwd(),json:s,yes:c,skipMcp:l,skipVerify:u});process.exit(d)});
|