@zenovay/cli 0.1.60 → 0.1.61
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/dist/{agency-Jld-6MFj.js → agency-C69JHza5.js} +1 -1
- package/dist/{ai-C-GanomY.js → ai-CPogCNEQ.js} +1 -1
- package/dist/{alerts-CPFSBaVU.js → alerts-DWVCFKlS.js} +1 -1
- package/dist/{analytical-screen-CRn5UoFi.js → analytical-screen-BasvNR-9.js} +1 -1
- package/dist/{analytics-Dg7UtCHo.js → analytics-C7mAE3gV.js} +2 -2
- package/dist/{annotation-GkAYwvze.js → annotation-BuwTxCIH.js} +1 -1
- package/dist/{api-BD_nTdOq.js → api-FCanTxsb.js} +1 -1
- package/dist/{api-keys-DphyO-_Y.js → api-keys-CHRLCfrl.js} +1 -1
- package/dist/{api-v2-q-vnosdb.js → api-v2-CI5hxW-O.js} +1 -1
- package/dist/api-v2-CTc_U2Gw.js +1 -0
- package/dist/{audit-5ImaVfEy.js → audit-Demn5lBp.js} +1 -1
- package/dist/bin.js +5 -5
- package/dist/binaries/zenovay-darwin-arm64 +0 -0
- package/dist/binaries/zenovay-darwin-arm64.sha256 +1 -1
- package/dist/{chat-panel-C_yjPXnw.js → chat-panel-CqJaCIg3.js} +1 -1
- package/dist/{companies-COJh5d6p.js → companies-DEdYd-bV.js} +1 -1
- package/dist/{completions-C_hmoEps.js → completions-CaYLmArp.js} +1 -1
- package/dist/config--JRu_jFq.js +1 -0
- package/dist/{config-i0nb93yX.js → config-DB3jF5gG.js} +1 -1
- package/dist/{deploys-D044xeG7.js → deploys-DTIU1Kqt.js} +1 -1
- package/dist/{devices-CKVbnV06.js → devices-DK_o0JcI.js} +1 -1
- package/dist/doctor-CEtbqf4s.js +20 -0
- package/dist/{domains-2z51Uxcq.js → domains-BCDiOFYb.js} +1 -1
- package/dist/{error-codes-BohPg7wr.js → error-codes-C5caZH9p.js} +1 -1
- package/dist/error-codes-fnm-9MRL.js +1 -0
- package/dist/{errors-CX-BTLp1.js → errors-Dig3nVCV.js} +1 -1
- package/dist/{events-tail-pDYhVzFg.js → events-tail-u_lwZas2.js} +1 -1
- package/dist/{export-DCbp6_Ae.js → export-DkAIRS9F.js} +1 -1
- package/dist/{funnel-CBYMcT0x.js → funnel-Brtq8avo.js} +1 -1
- package/dist/{geo-CZGN3jMJ.js → geo-c9hA42_9.js} +1 -1
- package/dist/{globe-BesYTdf0.js → globe-C_m7zGZM.js} +1 -1
- package/dist/{goals-xzqn8Yvu.js → goals-OQ1s7Vhq.js} +1 -1
- package/dist/health-CwR_B-IA.js +1 -0
- package/dist/health-D8uQvrtL.js +2 -0
- package/dist/{heatmaps-Dbw4tjvl.js → heatmaps-BPxqgMmV.js} +1 -1
- package/dist/{home-DAjqGgZH.js → home-DGrXLbbO.js} +1 -1
- package/dist/{init-J3iobD6o.js → init-BIJkCrgc.js} +2 -2
- package/dist/init-BhfcLbDE.js +1 -0
- package/dist/{insights-mWJUgQim.js → insights-CrUKfMD5.js} +1 -1
- package/dist/{integrations-eq4v-lwT.js → integrations-S-9EITZH.js} +1 -1
- package/dist/{journeys-DYHyPzD3.js → journeys-BbySeXM2.js} +1 -1
- package/dist/{live-BV3Ke3Pe.js → live-dcM0RwGp.js} +1 -1
- package/dist/login-DgU__egg.js +1 -0
- package/dist/{login-C9V2iVUx.js → login-yhuXiFqh.js} +1 -1
- package/dist/{logout-BiMIjAoN.js → logout-eXZJMigi.js} +1 -1
- package/dist/{notes-Cbj12dSg.js → notes-DUqpXghJ.js} +1 -1
- package/dist/{pages-B3Va-Uv4.js → pages-Bk5gbJ2v.js} +1 -1
- package/dist/{plans-JCNd2VsV.js → plans-CNWFx-qt.js} +1 -1
- package/dist/{profile-BywGL64A.js → profile-CZm-_uy-.js} +1 -1
- package/dist/{projects-0DoM_DNY.js → projects-BOU9sd2x.js} +1 -1
- package/dist/{query-Cvxg7VGc.js → query-CFNNsz6m.js} +1 -1
- package/dist/{resolve-site-DSJR9vuz.js → resolve-site-mj0esTrm.js} +1 -1
- package/dist/{retention-C6UOSoTA.js → retention-CYDhYbyf.js} +1 -1
- package/dist/{revenue-BoCu83Qb.js → revenue-D8uN4mjW.js} +1 -1
- package/dist/{self-test-C2breHMW.js → self-test-Cc5PWB08.js} +2 -2
- package/dist/{sessions-bW9Zq9Ie.js → sessions-DqTjJFcP.js} +1 -1
- package/dist/{settings-goNP_z8b.js → settings-CTbX2BXa.js} +1 -1
- package/dist/{share-DGMIOBqH.js → share-BG5ipcQi.js} +1 -1
- package/dist/{sources-COk75RfB.js → sources-D0FxjzeB.js} +1 -1
- package/dist/{stats-Cljlonha.js → stats-DmkvUylD.js} +1 -1
- package/dist/status-agent-Dej6dGvX.js +10 -0
- package/dist/{team-DVMA4G7x.js → team-B1qfFxKA.js} +1 -1
- package/dist/{teams-k4OJgxiP.js → teams-BzLZoKsj.js} +1 -1
- package/dist/{telemetry-DVyGPeIl.js → telemetry--Yk0J5zc.js} +1 -1
- package/dist/telemetry-C1045t6Q.js +1 -0
- package/dist/{telemetry-urcJlNpJ.js → telemetry-DRh10SvO.js} +1 -1
- package/dist/{tier-DST3Yt2-.js → tier-BneaO4vD.js} +1 -1
- package/dist/{token-store-DWXh9r3Z.js → token-store-BQuGH0z2.js} +1 -1
- package/dist/token-store-TmBx42nv.js +1 -0
- package/dist/{update-DV3UrhdN.js → update-CyyvYJPz.js} +1 -1
- package/dist/{uptime-B50oSlpy.js → uptime-CNGVODGc.js} +1 -1
- package/dist/{usage-Ck3nnMro.js → usage-kXVWbunU.js} +1 -1
- package/dist/{use-DKqiTC6X.js → use-B8cSIrZL.js} +1 -1
- package/dist/{visitors-BhAgZwqV.js → visitors-D7Q6chjq.js} +1 -1
- package/dist/{vitals-BfCdH0Um.js → vitals-DmMAuIdP.js} +1 -1
- package/dist/{watch-C3s26qCL.js → watch-D5WeMSz2.js} +1 -1
- package/dist/{webhooks-TMX618nq.js → webhooks-BhZkT0SX.js} +1 -1
- package/dist/{webhooks-forward-Dijs9bUk.js → webhooks-forward-D9PZDQ77.js} +1 -1
- package/dist/wizard-bin.js +1 -1
- package/package.json +1 -1
- package/dist/api-v2-BlZLQy11.js +0 -1
- package/dist/config-Dn_Cl0cD.js +0 -1
- package/dist/doctor-CF3D4SXm.js +0 -16
- package/dist/error-codes-BeJw1P4i.js +0 -1
- package/dist/health-9O6q4lla.js +0 -1
- package/dist/health-lTPnKNY9.js +0 -1
- package/dist/init-DJ7cYn-0.js +0 -1
- package/dist/login-CxdKhA-o.js +0 -1
- package/dist/status-agent-C2184gQB.js +0 -10
- package/dist/telemetry-BHyqKLqh.js +0 -1
- package/dist/token-store-BliA7lF_.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{readConfig as e,updateConfig as t}from"./config-Dn_Cl0cD.js";import{ApiClient as n}from"./api-BD_nTdOq.js";import{readToken as r}from"./token-store-DWXh9r3Z.js";import{parseSseStream as i}from"./client-DTXWADkX.js";import{emit$1 as a,isHeadless as o}from"./emit-DBYk96TD.js";import{scrubSecrets as s}from"./secrets-ApB7yh2A.js";import{loginCommand as c}from"./login-C9V2iVUx.js";import{Panel as l}from"./panel-B_yDcIcn.js";import{Banner as u}from"./banner-3iSWTDFy.js";import{BrandGradient as d,ProgressRow as f}from"./progress-row-BpAXjJPL.js";import{Select as p}from"./prompt-D-Uzz_GF.js";import{Keybar as m}from"./keybar-DsYTkKZX.js";import{spark as h}from"./sparkline-BZ0eMB-w.js";import g from"node:path";import{promises as _}from"node:fs";import{z as v}from"zod";import y from"node:os";import b from"node:crypto";import{ulid as x}from"ulid";import{Box as S,Text as C,render as w,useApp as ee,useInput as T}from"ink";import E,{useEffect as D,useRef as O,useState as k}from"react";import{globby as A}from"globby";import j from"ink-spinner";import{applyPatch as M}from"diff";const N=[`@zenovay/tracker`,`@zenovay/next`,`@zenovay/nuxt`,`@zenovay/svelte`,`@zenovay/astro`,`@zenovay/remix`,`@zenovay/node`],P=[`zenovay.config.ts`,`zenovay.config.js`,`zenovay.config.mjs`,`zenovay.config.json`],F=/<script[^>]*src\s*=\s*["']https:\/\/(?:api|cdn)\.zenovay\.com\/[^"']+["'][^>]*>\s*<\/script>/gi,te=/data-id\s*=\s*["'](ZV_[A-Za-z0-9]+)["']/i,I=/data-zenovay-site\s*=\s*["']([^"']+)["']/i,ne=[{name:`PostHog`,patterns:[/posthog\.com\b/i,/posthog-js/,/window\.posthog/]},{name:`Plausible`,patterns:[/plausible\.io\/js/i,/window\.plausible/]},{name:`Google Analytics`,patterns:[/googletagmanager\.com\/gtag\/js/i,/www\.google-analytics\.com\/analytics\.js/i,/window\.gtag\b/]},{name:`Mixpanel`,patterns:[/cdn\.mxpnl\.com/i,/mixpanel-browser/]},{name:`Segment`,patterns:[/cdn\.segment\.com\/analytics\.js/i,/window\.analytics\b/]},{name:`Hotjar`,patterns:[/static\.hotjar\.com/i,/\(h,o,t,j,a,r\)/i]},{name:`Amplitude`,patterns:[/cdn\.amplitude\.com/i,/amplitude\.getInstance/]},{name:`Heap`,patterns:[/cdn\.heapanalytics\.com/i]},{name:`FullStory`,patterns:[/fullstory\.com\/s\/fs\.js/i,/window\.FS\.identify/]}];async function re(e,t){let n={zenovayInstalled:!1,correctTrackingCode:!1,foundTrackingCodes:[],zenovayFiles:[],competitors:[],summary:``,recommendation:`fresh-install`};try{let t=await _.readFile(g.join(e,`package.json`),`utf8`),r=JSON.parse(t),i={...r.dependencies,...r.devDependencies};for(let e of N)if(e in i){n.zenovayInstalled=!0,n.packageMarker=e;break}}catch{}for(let t of P)try{await _.access(g.join(e,t)),n.zenovayInstalled=!0,n.configFile=t;break}catch{}let r=await A([`**/*.{html,htm,tsx,jsx,vue,svelte,astro,ts,js,mjs}`,`!node_modules/**`,`!.git/**`,`!dist/**`,`!.next/**`,`!.nuxt/**`,`!build/**`,`!.output/**`],{cwd:e,gitignore:!0,deep:4,absolute:!0}).catch(()=>[]),i=new Map,a=new Set;for(let t of r.slice(0,300)){let r;try{r=await _.readFile(t,`utf8`)}catch{continue}let o=g.relative(e,t),s=r.match(F);if(s&&s.length>0){n.zenovayInstalled=!0;let e=s[0].slice(0,200),t=e.match(te)??e.match(I),r=t?.[1]??null;r&&a.add(r),n.zenovayFiles.push({file:o,currentTrackingCode:r,scriptTagCount:s.length,matchSample:e})}for(let e of ne)if(e.patterns.some(e=>e.test(r))){let t=i.get(e.name)??new Set;t.add(o),i.set(e.name,t)}}if(n.foundTrackingCodes=Array.from(a),n.competitors=Array.from(i.entries()).map(([e,t])=>({name:e,files:Array.from(t).slice(0,5)})),n.zenovayInstalled)if(n.foundTrackingCodes.length>0){let e=n.foundTrackingCodes.every(e=>e===t);n.correctTrackingCode=e,n.recommendation=e?`no-op`:`update-tracking-code`}else n.correctTrackingCode=!1,n.recommendation=`no-op`;else n.competitors.length>0?n.recommendation=`fresh-install-alongside-competitor`:n.recommendation=`fresh-install`;return n.summary=ie(n,t),n}function ie(e,t){let n=[];return e.zenovayInstalled?e.foundTrackingCodes.length===0?n.push(`Zenovay package or config detected but no <script> tag found.`):e.correctTrackingCode?n.push(`Zenovay tracker present in ${e.zenovayFiles.length} file(s) with correct ID ${t}.`):n.push(`Zenovay tracker present in ${e.zenovayFiles.length} file(s), but with mismatching ID(s): ${e.foundTrackingCodes.join(`, `)} (target: ${t}).`):n.push(`No Zenovay tracker found.`),e.competitors.length>0&&n.push(`Competitor tracker(s) present (DO NOT modify): ${e.competitors.map(e=>e.name).join(`, `)}.`),n.join(` `)}async function ae(e){let t=await re(e,``);return{installed:t.zenovayInstalled,reasons:t.summary?[t.summary]:[],packageMarker:t.packageMarker,configFile:t.configFile,scriptFile:t.zenovayFiles[0]?.file}}const oe=[/^package\.json$/,/^package-lock\.json$/,/^pnpm-lock\.yaml$/,/^yarn\.lock$/,/^bun\.lock$/,/^tsconfig.*\.json$/,/^(next|nuxt|vite|astro|remix|svelte|tailwind|postcss)\.config\.(ts|mts|cts|js|mjs|cjs)$/,/^app\/.*\.(tsx|ts|jsx|js|svelte|astro|vue)$/,/^pages\/.*\.(tsx|ts|jsx|js)$/,/^public\/index\.html$/,/^index\.html$/,/^src\/main\.(tsx|ts|jsx|js)$/,/^src\/App\.(tsx|ts|jsx|js|svelte|vue)$/,/^src\/routes\/\+layout\.(svelte|ts|js)$/,/^src\/routes\/root\..*$/,/^src\/layouts\/.*\.(astro|svelte|vue)$/,/^\.env\.example$/,/^README\.md$/,/^\.gitignore$/,/^nuxt\.config\.(ts|js|mjs)$/,/^plugins\/.*\.(ts|js)$/],se=[/(^|\/)\.env($|\.(?!example$)[^/]+$)/,/(^|\/)\.git(\/|$)/,/(^|\/)node_modules\//,/(^|\/)\.ssh\//,/(^|\/)\.aws\//,/\.pem$/,/\.key$/,/(^|\/)id_rsa($|\.)/,/(^|\/)\.npmrc$/,/(^|\/)credentials(\.|$)/],L=256*1024,R=50,z=20,B=40;var V=class extends Error{constructor(e,t){super(t),this.code=e,this.name=`SandboxError`}};const H=/<script[^>]*src\s*=\s*["']https:\/\/(?:api|cdn)\.zenovay\.com\/[^"']+["'][^>]*>\s*<\/script>/i,U=[{name:`PostHog`,re:/posthog\.com\b|posthog-js|window\.posthog/i},{name:`Plausible`,re:/plausible\.io\/js|window\.plausible/i},{name:`Google Analytics`,re:/googletagmanager\.com\/gtag\/js|google-analytics\.com\/analytics\.js|window\.gtag\b/i},{name:`Mixpanel`,re:/cdn\.mxpnl\.com|mixpanel-browser/i},{name:`Segment`,re:/cdn\.segment\.com\/analytics\.js|window\.analytics\b/i},{name:`Hotjar`,re:/static\.hotjar\.com|\(h,o,t,j,a,r\)/i},{name:`Amplitude`,re:/cdn\.amplitude\.com|amplitude\.getInstance/i},{name:`Heap`,re:/cdn\.heapanalytics\.com/i},{name:`FullStory`,re:/fullstory\.com\/s\/fs\.js|window\.FS\.identify/i}];var W=class{sessionId;cwd;cwdReal;undoRoot;readCount=0;writeCount=0;roundCount=0;writtenPathsSet=new Set;constructor(e){this.sessionId=e.sessionId??x(),this.cwd=e.cwd,this.cwdReal=_.realpath(e.cwd),this.undoRoot=e.undoRoot??g.join(y.homedir(),`.zenovay`,`undo`)}incrementRound(){if(this.roundCount++,this.roundCount>B)throw new V(`round-cap`,`Tool-call recursion cap (${B}) exceeded.`)}stats(){return{sessionId:this.sessionId,reads:this.readCount,writes:this.writeCount,rounds:this.roundCount,writtenPaths:[...this.writtenPathsSet]}}async resolveForRead(e){return this.resolveSafe(e,`read`)}async resolveForWrite(e){return this.resolveSafe(e,`write`)}async resolveSafe(e,t){if(typeof e!=`string`||e.length===0)throw new V(`escape`,`Path must be a non-empty string.`);if(e.includes(`\0`))throw new V(`escape`,`Null byte in path.`);if(/^\\\\[?.]\\/.test(e)||/^\\\\[A-Za-z0-9]/.test(e))throw new V(`escape`,`Windows special path prefix: ${e}`);if(/%/.test(e))try{let t=decodeURIComponent(e);if(/%[0-9A-Fa-f]{2}/.test(t))throw new V(`escape`,`Double-encoded path: ${e}`);e=t}catch(t){throw t instanceof V?t:new V(`escape`,`Malformed percent-encoding: ${e}`)}if(e.includes(`\0`))throw new V(`escape`,`Null byte in decoded path.`);if(e.includes(`\\`))throw new V(`escape`,`Backslash in path (Windows-style separator not accepted): ${e}`);let n=await this.cwdReal,r=g.isAbsolute(e)?e:g.join(n,e),i=g.normalize(r),a=i;try{a=await _.realpath(i)}catch(e){if(e.code!==`ENOENT`)throw new V(`escape`,`realpath failed: ${e.message}`);let t=g.dirname(i);try{let e=await _.realpath(t);a=g.join(e,g.basename(i))}catch{}}if(!this.isWithin(a,n))throw new V(`escape`,`Path escapes cwd: ${e}`);let o=g.relative(n,a);for(let e of se)if(e.test(o)){if(t===`read`&&/(^|\/)node_modules\//.test(o))continue;throw new V(`blocklisted`,`Path is on the hard blocklist: ${o}`)}if(t===`write`){let e=oe.some(e=>e.test(o));if(!e&&!/^\.env(\.local)?$/.test(o)&&!/^\.claude\//.test(o)&&!/^\.cursor\//.test(o))throw new V(`not-allowlisted`,`Write path not on allowlist: ${o}`)}return a}isWithin(e,t){let n=g.relative(t,e);return!n.startsWith(`..`)&&!g.isAbsolute(n)}async safeRead(e){if(this.readCount>=R)throw new V(`read-cap`,`Read cap (${R}) reached.`);let t=await this.resolveForRead(e),n=await _.stat(t);if(n.size>L)throw new V(`too-large`,`File exceeds ${L}B: ${e} (${n.size}B)`);let r=await _.readFile(t),i=r.subarray(0,Math.min(r.length,8192));if(i.includes(0))throw new V(`binary-rejected`,`Binary content in ${e}.`);return this.readCount++,r.toString(`utf8`)}async safeWrite(e,t){if(this.writeCount>=z)throw new V(`write-cap`,`Write cap (${z}) reached.`);if(t.length>L)throw new V(`too-large`,`Write exceeds ${L}B: ${e}`);let n=await this.resolveForWrite(e),r=await _.readFile(n,`utf8`).catch(e=>{if(e.code===`ENOENT`)return null;throw e});if(r!==null){if(H.test(r)&&!H.test(t))throw new V(`destructive-tracker-removal`,`Refusing to write ${e}: existing Zenovay tracker tag would be removed. If you want to change the data-id, use patch_file to swap the attribute value instead of overwriting the file.`);for(let{name:n,re:i}of U)if(i.test(r)&&!i.test(t))throw new V(`destructive-competitor-removal`,`Refusing to write ${e}: existing ${n} tracker would be removed. Zenovay installs alongside competitors — never replace them.`)}let i=await this.journalBackup(n);await _.mkdir(g.dirname(n),{recursive:!0}),await _.writeFile(n,t,`utf8`),this.writeCount++;let a=await this.cwdReal;return this.writtenPathsSet.add(g.relative(a,n)),{backupPath:i}}async journalBackup(e){let t=await _.readFile(e).catch(e=>{if(e.code===`ENOENT`)return null;throw e}),n=g.join(this.undoRoot,this.sessionId);await _.mkdir(n,{recursive:!0,mode:448});let r=b.createHash(`sha256`).update(e).digest(`hex`).slice(0,16),i=g.join(n,`${r}.bak`),a=g.join(n,`manifest.jsonl`);t&&await _.writeFile(i,t,{mode:384});let o=JSON.stringify({abs:e,backupPath:t?i:null,ts:Date.now()});return await _.appendFile(a,o+`
|
|
1
|
+
import{readConfig as e,updateConfig as t}from"./config--JRu_jFq.js";import{ApiClient as n}from"./api-FCanTxsb.js";import{readToken as r}from"./token-store-BQuGH0z2.js";import{parseSseStream as i}from"./client-DTXWADkX.js";import{emit$1 as a,isHeadless as o}from"./emit-DBYk96TD.js";import{scrubSecrets as s}from"./secrets-ApB7yh2A.js";import{loginCommand as c}from"./login-yhuXiFqh.js";import{Panel as l}from"./panel-B_yDcIcn.js";import{Banner as u}from"./banner-3iSWTDFy.js";import{BrandGradient as d,ProgressRow as f}from"./progress-row-BpAXjJPL.js";import{Select as p}from"./prompt-D-Uzz_GF.js";import{Keybar as m}from"./keybar-DsYTkKZX.js";import{spark as h}from"./sparkline-BZ0eMB-w.js";import g from"node:path";import{promises as _}from"node:fs";import{z as v}from"zod";import y from"node:os";import b from"node:crypto";import{ulid as x}from"ulid";import{Box as S,Text as C,render as w,useApp as ee,useInput as T}from"ink";import E,{useEffect as D,useRef as O,useState as k}from"react";import{globby as A}from"globby";import j from"ink-spinner";import{applyPatch as M}from"diff";const N=[`@zenovay/tracker`,`@zenovay/next`,`@zenovay/nuxt`,`@zenovay/svelte`,`@zenovay/astro`,`@zenovay/remix`,`@zenovay/node`],P=[`zenovay.config.ts`,`zenovay.config.js`,`zenovay.config.mjs`,`zenovay.config.json`],F=/<script[^>]*src\s*=\s*["']https:\/\/(?:api|cdn)\.zenovay\.com\/[^"']+["'][^>]*>\s*<\/script>/gi,te=/data-id\s*=\s*["'](ZV_[A-Za-z0-9]+)["']/i,I=/data-zenovay-site\s*=\s*["']([^"']+)["']/i,ne=[{name:`PostHog`,patterns:[/posthog\.com\b/i,/posthog-js/,/window\.posthog/]},{name:`Plausible`,patterns:[/plausible\.io\/js/i,/window\.plausible/]},{name:`Google Analytics`,patterns:[/googletagmanager\.com\/gtag\/js/i,/www\.google-analytics\.com\/analytics\.js/i,/window\.gtag\b/]},{name:`Mixpanel`,patterns:[/cdn\.mxpnl\.com/i,/mixpanel-browser/]},{name:`Segment`,patterns:[/cdn\.segment\.com\/analytics\.js/i,/window\.analytics\b/]},{name:`Hotjar`,patterns:[/static\.hotjar\.com/i,/\(h,o,t,j,a,r\)/i]},{name:`Amplitude`,patterns:[/cdn\.amplitude\.com/i,/amplitude\.getInstance/]},{name:`Heap`,patterns:[/cdn\.heapanalytics\.com/i]},{name:`FullStory`,patterns:[/fullstory\.com\/s\/fs\.js/i,/window\.FS\.identify/]}];async function re(e,t){let n={zenovayInstalled:!1,correctTrackingCode:!1,foundTrackingCodes:[],zenovayFiles:[],competitors:[],summary:``,recommendation:`fresh-install`};try{let t=await _.readFile(g.join(e,`package.json`),`utf8`),r=JSON.parse(t),i={...r.dependencies,...r.devDependencies};for(let e of N)if(e in i){n.zenovayInstalled=!0,n.packageMarker=e;break}}catch{}for(let t of P)try{await _.access(g.join(e,t)),n.zenovayInstalled=!0,n.configFile=t;break}catch{}let r=await A([`**/*.{html,htm,tsx,jsx,vue,svelte,astro,ts,js,mjs}`,`!node_modules/**`,`!.git/**`,`!dist/**`,`!.next/**`,`!.nuxt/**`,`!build/**`,`!.output/**`],{cwd:e,gitignore:!0,deep:4,absolute:!0}).catch(()=>[]),i=new Map,a=new Set;for(let t of r.slice(0,300)){let r;try{r=await _.readFile(t,`utf8`)}catch{continue}let o=g.relative(e,t),s=r.match(F);if(s&&s.length>0){n.zenovayInstalled=!0;let e=s[0].slice(0,200),t=e.match(te)??e.match(I),r=t?.[1]??null;r&&a.add(r),n.zenovayFiles.push({file:o,currentTrackingCode:r,scriptTagCount:s.length,matchSample:e})}for(let e of ne)if(e.patterns.some(e=>e.test(r))){let t=i.get(e.name)??new Set;t.add(o),i.set(e.name,t)}}if(n.foundTrackingCodes=Array.from(a),n.competitors=Array.from(i.entries()).map(([e,t])=>({name:e,files:Array.from(t).slice(0,5)})),n.zenovayInstalled)if(n.foundTrackingCodes.length>0){let e=n.foundTrackingCodes.every(e=>e===t);n.correctTrackingCode=e,n.recommendation=e?`no-op`:`update-tracking-code`}else n.correctTrackingCode=!1,n.recommendation=`no-op`;else n.competitors.length>0?n.recommendation=`fresh-install-alongside-competitor`:n.recommendation=`fresh-install`;return n.summary=ie(n,t),n}function ie(e,t){let n=[];return e.zenovayInstalled?e.foundTrackingCodes.length===0?n.push(`Zenovay package or config detected but no <script> tag found.`):e.correctTrackingCode?n.push(`Zenovay tracker present in ${e.zenovayFiles.length} file(s) with correct ID ${t}.`):n.push(`Zenovay tracker present in ${e.zenovayFiles.length} file(s), but with mismatching ID(s): ${e.foundTrackingCodes.join(`, `)} (target: ${t}).`):n.push(`No Zenovay tracker found.`),e.competitors.length>0&&n.push(`Competitor tracker(s) present (DO NOT modify): ${e.competitors.map(e=>e.name).join(`, `)}.`),n.join(` `)}async function ae(e){let t=await re(e,``);return{installed:t.zenovayInstalled,reasons:t.summary?[t.summary]:[],packageMarker:t.packageMarker,configFile:t.configFile,scriptFile:t.zenovayFiles[0]?.file}}const oe=[/^package\.json$/,/^package-lock\.json$/,/^pnpm-lock\.yaml$/,/^yarn\.lock$/,/^bun\.lock$/,/^tsconfig.*\.json$/,/^(next|nuxt|vite|astro|remix|svelte|tailwind|postcss)\.config\.(ts|mts|cts|js|mjs|cjs)$/,/^app\/.*\.(tsx|ts|jsx|js|svelte|astro|vue)$/,/^pages\/.*\.(tsx|ts|jsx|js)$/,/^public\/index\.html$/,/^index\.html$/,/^src\/main\.(tsx|ts|jsx|js)$/,/^src\/App\.(tsx|ts|jsx|js|svelte|vue)$/,/^src\/routes\/\+layout\.(svelte|ts|js)$/,/^src\/routes\/root\..*$/,/^src\/layouts\/.*\.(astro|svelte|vue)$/,/^\.env\.example$/,/^README\.md$/,/^\.gitignore$/,/^nuxt\.config\.(ts|js|mjs)$/,/^plugins\/.*\.(ts|js)$/],se=[/(^|\/)\.env($|\.(?!example$)[^/]+$)/,/(^|\/)\.git(\/|$)/,/(^|\/)node_modules\//,/(^|\/)\.ssh\//,/(^|\/)\.aws\//,/\.pem$/,/\.key$/,/(^|\/)id_rsa($|\.)/,/(^|\/)\.npmrc$/,/(^|\/)credentials(\.|$)/],L=256*1024,R=50,z=20,B=40;var V=class extends Error{constructor(e,t){super(t),this.code=e,this.name=`SandboxError`}};const H=/<script[^>]*src\s*=\s*["']https:\/\/(?:api|cdn)\.zenovay\.com\/[^"']+["'][^>]*>\s*<\/script>/i,U=[{name:`PostHog`,re:/posthog\.com\b|posthog-js|window\.posthog/i},{name:`Plausible`,re:/plausible\.io\/js|window\.plausible/i},{name:`Google Analytics`,re:/googletagmanager\.com\/gtag\/js|google-analytics\.com\/analytics\.js|window\.gtag\b/i},{name:`Mixpanel`,re:/cdn\.mxpnl\.com|mixpanel-browser/i},{name:`Segment`,re:/cdn\.segment\.com\/analytics\.js|window\.analytics\b/i},{name:`Hotjar`,re:/static\.hotjar\.com|\(h,o,t,j,a,r\)/i},{name:`Amplitude`,re:/cdn\.amplitude\.com|amplitude\.getInstance/i},{name:`Heap`,re:/cdn\.heapanalytics\.com/i},{name:`FullStory`,re:/fullstory\.com\/s\/fs\.js|window\.FS\.identify/i}];var W=class{sessionId;cwd;cwdReal;undoRoot;readCount=0;writeCount=0;roundCount=0;writtenPathsSet=new Set;constructor(e){this.sessionId=e.sessionId??x(),this.cwd=e.cwd,this.cwdReal=_.realpath(e.cwd),this.undoRoot=e.undoRoot??g.join(y.homedir(),`.zenovay`,`undo`)}incrementRound(){if(this.roundCount++,this.roundCount>B)throw new V(`round-cap`,`Tool-call recursion cap (${B}) exceeded.`)}stats(){return{sessionId:this.sessionId,reads:this.readCount,writes:this.writeCount,rounds:this.roundCount,writtenPaths:[...this.writtenPathsSet]}}async resolveForRead(e){return this.resolveSafe(e,`read`)}async resolveForWrite(e){return this.resolveSafe(e,`write`)}async resolveSafe(e,t){if(typeof e!=`string`||e.length===0)throw new V(`escape`,`Path must be a non-empty string.`);if(e.includes(`\0`))throw new V(`escape`,`Null byte in path.`);if(/^\\\\[?.]\\/.test(e)||/^\\\\[A-Za-z0-9]/.test(e))throw new V(`escape`,`Windows special path prefix: ${e}`);if(/%/.test(e))try{let t=decodeURIComponent(e);if(/%[0-9A-Fa-f]{2}/.test(t))throw new V(`escape`,`Double-encoded path: ${e}`);e=t}catch(t){throw t instanceof V?t:new V(`escape`,`Malformed percent-encoding: ${e}`)}if(e.includes(`\0`))throw new V(`escape`,`Null byte in decoded path.`);if(e.includes(`\\`))throw new V(`escape`,`Backslash in path (Windows-style separator not accepted): ${e}`);let n=await this.cwdReal,r=g.isAbsolute(e)?e:g.join(n,e),i=g.normalize(r),a=i;try{a=await _.realpath(i)}catch(e){if(e.code!==`ENOENT`)throw new V(`escape`,`realpath failed: ${e.message}`);let t=g.dirname(i);try{let e=await _.realpath(t);a=g.join(e,g.basename(i))}catch{}}if(!this.isWithin(a,n))throw new V(`escape`,`Path escapes cwd: ${e}`);let o=g.relative(n,a);for(let e of se)if(e.test(o)){if(t===`read`&&/(^|\/)node_modules\//.test(o))continue;throw new V(`blocklisted`,`Path is on the hard blocklist: ${o}`)}if(t===`write`){let e=oe.some(e=>e.test(o));if(!e&&!/^\.env(\.local)?$/.test(o)&&!/^\.claude\//.test(o)&&!/^\.cursor\//.test(o))throw new V(`not-allowlisted`,`Write path not on allowlist: ${o}`)}return a}isWithin(e,t){let n=g.relative(t,e);return!n.startsWith(`..`)&&!g.isAbsolute(n)}async safeRead(e){if(this.readCount>=R)throw new V(`read-cap`,`Read cap (${R}) reached.`);let t=await this.resolveForRead(e),n=await _.stat(t);if(n.size>L)throw new V(`too-large`,`File exceeds ${L}B: ${e} (${n.size}B)`);let r=await _.readFile(t),i=r.subarray(0,Math.min(r.length,8192));if(i.includes(0))throw new V(`binary-rejected`,`Binary content in ${e}.`);return this.readCount++,r.toString(`utf8`)}async safeWrite(e,t){if(this.writeCount>=z)throw new V(`write-cap`,`Write cap (${z}) reached.`);if(t.length>L)throw new V(`too-large`,`Write exceeds ${L}B: ${e}`);let n=await this.resolveForWrite(e),r=await _.readFile(n,`utf8`).catch(e=>{if(e.code===`ENOENT`)return null;throw e});if(r!==null){if(H.test(r)&&!H.test(t))throw new V(`destructive-tracker-removal`,`Refusing to write ${e}: existing Zenovay tracker tag would be removed. If you want to change the data-id, use patch_file to swap the attribute value instead of overwriting the file.`);for(let{name:n,re:i}of U)if(i.test(r)&&!i.test(t))throw new V(`destructive-competitor-removal`,`Refusing to write ${e}: existing ${n} tracker would be removed. Zenovay installs alongside competitors — never replace them.`)}let i=await this.journalBackup(n);await _.mkdir(g.dirname(n),{recursive:!0}),await _.writeFile(n,t,`utf8`),this.writeCount++;let a=await this.cwdReal;return this.writtenPathsSet.add(g.relative(a,n)),{backupPath:i}}async journalBackup(e){let t=await _.readFile(e).catch(e=>{if(e.code===`ENOENT`)return null;throw e}),n=g.join(this.undoRoot,this.sessionId);await _.mkdir(n,{recursive:!0,mode:448});let r=b.createHash(`sha256`).update(e).digest(`hex`).slice(0,16),i=g.join(n,`${r}.bak`),a=g.join(n,`manifest.jsonl`);t&&await _.writeFile(i,t,{mode:384});let o=JSON.stringify({abs:e,backupPath:t?i:null,ts:Date.now()});return await _.appendFile(a,o+`
|
|
2
2
|
`,{mode:384}),t?i:null}static wrapForModel(e,t){let n=b.createHash(`sha256`).update(t).digest(`hex`).slice(0,16),r=t.replaceAll(`&`,`&`).replaceAll(`<`,`<`).replaceAll(`>`,`>`);return`<FILE path="${e}" sha256="${n}">\n${r}\n</FILE>`}static scrubSecrets(e){return s(e)}};const ce=[`astro.config.ts`,`astro.config.mjs`,`astro.config.js`];async function le(e){for(let t of ce)if(await e.exists(t))return{matched:!0,confidence:.95,reason:`Detected Astro via \`${t}\`.`};let t=await e.readFile(`package.json`);if(t)try{let e=JSON.parse(t);if(e.dependencies?.astro??e.devDependencies?.astro)return{matched:!0,confidence:.8,reason:"Detected Astro via `astro` dependency."}}catch{}return{matched:!1,confidence:0,reason:"No astro.config.* or `astro` dependency found."}}function ue(e){let t=e.trackingCode??e.siteId??``,n=`<script defer data-id="${t}" data-allow-localhost="true" src="https://api.zenovay.com/z.js" is:inline></script>`;return[{targetPath:`src/layouts/Layout.astro`,anchorKind:`head-tag`,code:n,description:`Inject the Zenovay tracker inside <head> of the primary layout.`},{targetPath:`src/layouts/BaseHead.astro`,anchorKind:`head-tag`,code:n,description:"Fallback target when the project uses a dedicated `BaseHead.astro`."}]}const de={id:`astro`,displayName:`Astro`,detect:le,files:[{path:`src/layouts/Layout.astro`,kind:`mutate`,required:!1},{path:`src/layouts/BaseHead.astro`,kind:`mutate`,required:!1},{path:`.env`,kind:`create`,required:!0}],envVarName:`PUBLIC_ZENOVAY_SITE`,buildSnippets:ue},fe=[`app/layout.tsx`,`app/layout.ts`,`app/layout.jsx`,`app/layout.js`];async function pe(e){for(let t of fe)if(await e.exists(t))return t;return null}async function me(e){let t=await e.readFile(`package.json`);if(!t)return!1;try{let e=JSON.parse(t);return!!(e.dependencies?.next??e.devDependencies?.next)}catch{return!1}}async function he(e){let t=await me(e),n=await e.exists(`app`),r=await pe(e);return t?n?r?{matched:!0,confidence:.95,reason:`Detected Next.js App Router via \`next\` dep + \`${r}\`.`}:{matched:!1,confidence:.4,reason:"Found `app/` but no root layout file (layout.tsx/ts/jsx/js)."}:{matched:!1,confidence:0,reason:"No `app/` directory found — not an App Router project."}:{matched:!1,confidence:0,reason:"package.json does not list `next` as a dependency."}}function ge(e,t=`script`){let n=`app/layout.tsx`,r=e.trackingCode??e.siteId??``;return t===`npm`?ve(n,r):_e(n,r)}function _e(e,t){return[{targetPath:e,anchorKind:`after-imports`,code:`import Script from 'next/script';`,description:`Import next/script to inject the Zenovay tracker.`},{targetPath:e,anchorKind:`wrap-children`,code:`<Script
|
|
3
3
|
defer
|
|
4
4
|
data-id="${t}"
|
|
@@ -67,7 +67,7 @@ export default function App({ Component, pageProps }: AppProps) {
|
|
|
67
67
|
`)+`
|
|
68
68
|
`;if(o)await _.writeFile(i,f,`utf8`);else{let e=await _.open(i,`w`,384);try{await e.writeFile(f,`utf8`)}finally{await e.close()}}return{created:!o,existing:o,addedKeys:c,skippedKeys:l}}const Ue=`https://api.zenovay.com/mcp`,We=v.object({url:v.string().url(),headers:v.record(v.string(),v.string()).optional()}),Ge=v.object({mcpServers:v.record(v.string(),We).optional()}).passthrough();function Ke(e){return e.HOME??e.USERPROFILE??y.homedir()}function qe(e){return e.APPDATA??null}function Je(e,t){let n=Ke(t),r=qe(t),i=[];return i.push({id:`cursor`,displayName:`Cursor`,configPath:g.join(n,`.cursor`,`mcp.json`)}),e===`win32`&&r&&i.push({id:`cursor`,displayName:`Cursor (AppData)`,configPath:g.join(r,`Cursor`,`User`,`globalStorage`,`cursor.mcp`,`mcp.json`)}),e===`darwin`?i.push({id:`claude-desktop`,displayName:`Claude Desktop`,configPath:g.join(n,`Library`,`Application Support`,`Claude`,`claude_desktop_config.json`)}):e===`win32`&&r?i.push({id:`claude-desktop`,displayName:`Claude Desktop`,configPath:g.join(r,`Claude`,`claude_desktop_config.json`)}):i.push({id:`claude-desktop`,displayName:`Claude Desktop`,configPath:g.join(n,`.config`,`Claude`,`claude_desktop_config.json`)}),i.push({id:`vscode`,displayName:`VS Code`,configPath:g.join(n,`.vscode`,`mcp.json`)}),i}async function Ye(e){try{return await _.access(e),!0}catch{return!1}}async function Xe(e){try{let t=await _.readFile(e,`utf8`);if(t.trim().length===0)return{};let n=JSON.parse(t),r=Ge.safeParse(n);return r.success?r.data:n&&typeof n==`object`?n:{}}catch{return{}}}function Ze(e){return{url:Ue,headers:{Authorization:`Bearer ${e}`}}}async function Y(e){let t=e.env??process.env,n=e.platform??process.platform,r=new Set(e.skip??[]),i=[],a=[],o=[],s=new Set,c=Ze(e.accessToken);for(let e of Je(n,t)){if(r.has(e.id)){a.push(e.displayName);continue}if(s.has(e.configPath))continue;s.add(e.configPath);try{let t=await Ye(e.configPath);if(!t){a.push(e.displayName);continue}let n=await Xe(e.configPath),r=`${e.configPath}.bak`;await _.copyFile(e.configPath,r);let o={...n,mcpServers:{...n.mcpServers??{},zenovay:c}};await _.mkdir(g.dirname(e.configPath),{recursive:!0}),await _.writeFile(e.configPath,JSON.stringify(o,null,2)+`
|
|
69
69
|
`,`utf8`),i.push(e.displayName)}catch(t){o.push({client:e.displayName,message:t instanceof Error?t.message:String(t)})}}return{installed:i,skipped:a,errors:o}}async function Qe(e,t,n){let r=n.timeoutMs??18e4,i=n.pollIntervalMs??2e3,a=n.now??(()=>Date.now()),o=n.sleep??(e=>new Promise(t=>setTimeout(t,e))),s=a(),c=s+r;for(n.onTick?.(0);;){let l=await n.api.getFirstEvent({siteId:e,since:t});if(l.received)return{received:!0,event:l.event};let u=a()-s;if(u>=r)return{received:!1};let d=c-a(),f=Math.min(i,Math.max(0,d));if(f<=0)return{received:!1};await o(f),n.onTick?.(a()-s)}}const $e=v.object({path:v.string().min(1)}),et=v.object({path:v.string().min(1),content:v.string(),reason:v.string().min(1)}),tt=v.object({path:v.string().min(1),patch:v.string().min(1),reason:v.string().min(1)}),nt=v.object({}),rt=v.object({question:v.string().min(1),choices:v.array(v.string()).optional()});async function it(e,t){let n=$e.safeParse(t);if(!n.success)return{ok:!1,content:null,error:`invalid_args`};try{let t=await e.safeRead(n.data.path),r=W.scrubSecrets(t);return{ok:!0,content:W.wrapForModel(n.data.path,r)}}catch(e){return{ok:!1,content:null,error:e.message}}}async function at(e,t,n){let r=et.safeParse(t);if(!r.success)return{ok:!1,content:null,error:`invalid_args`};let{path:i,content:a,reason:o}=r.data,s=``;try{s=await e.safeRead(i)}catch{s=``}let c=await n.approve({path:i,oldContent:s,newContent:a,reason:o});if(c===`n`)return{ok:!1,content:null,error:`skipped_by_user`};if(c===`e`)return{ok:!1,content:null,error:`deferred_to_user_edit`};try{let{backupPath:t}=await e.safeWrite(i,a);return{ok:!0,content:{path:i,backupPath:t}}}catch(e){return{ok:!1,content:null,error:e.message}}}async function ot(e,t,n){let r=tt.safeParse(t);if(!r.success)return{ok:!1,content:null,error:`invalid_args`};let{path:i,patch:a,reason:o}=r.data;if(/^\*\*\*\s+Begin Patch/m.test(a)||/^\*\*\*\s+Update File:/m.test(a))return{ok:!1,content:null,error:'unsupported_patch_format: This tool only accepts STANDARD unified diff with `--- a/...`, `+++ b/...`, and `@@ -N,M +N,M @@` headers. The "*** Begin Patch / *** Update File:" V4A format is NOT supported. Please call write_file with the full new file content instead.'};let s;try{s=await e.safeRead(i)}catch(e){return{ok:!1,content:null,error:e.message}}let c;try{c=M(s,a)}catch(e){return{ok:!1,content:null,error:`patch_failed: ${e.message}. Please call write_file with the full new file content instead — write_file is more reliable than patch_file for this use case.`}}return c===!1||typeof c!=`string`?{ok:!1,content:null,error:`patch_did_not_apply_cleanly. The patch context may not match the file. Please call write_file with the full new file content instead.`}:at(e,{path:i,content:c,reason:o},n)}async function st(e){try{let t=K(e),{adapter:n,ranked:r}=await G(t);return{ok:!0,content:{matched:n!==null,adapter:n?.id,displayName:n?.displayName,ranked:r.map(e=>({id:e.adapter.id,confidence:e.result.confidence,reason:e.result.reason}))}}}catch(e){return{ok:!1,content:null,error:e.message}}}async function ct(e,t){let n=rt.safeParse(t);if(!n.success)return{ok:!1,content:null,error:`invalid_args`};try{let t=await e.ask(n.data);return{ok:!0,content:{answer:t}}}catch(e){return{ok:!1,content:null,error:e.message}}}async function lt(e){let{api:t,sandbox:n,approval:r,prompter:a,handlers:o}=e,s=[...e.initialMessages],c=``,l=0;for(;l<B;){n.incrementRound(),l++;let u=await t.openAiStream(`install`,{messages:s,cwd_fingerprint:n.sessionId,diagnosis:e.diagnosis,targetTrackingCode:e.targetTrackingCode}),d=[],f=``;for await(let e of i(u))switch(e.type){case`delta`:f+=e.content,o?.onDelta?.(e.content);break;case`tool_start`:o?.onToolStart?.({id:e.id,name:e.name});break;case`tool_call`:{let t=await ut(e.name,e.arguments,{sandbox:n,cwd:n.cwd,approval:r,prompter:a});d.push({id:e.id,name:e.name,arguments:e.arguments,result:t}),o?.onToolResult?.({id:e.id,name:e.name,result:t});break}case`usage`:o?.onUsage?.(e);break;case`error`:throw o?.onError?.(e),Error(`[${e.code}] ${e.message}`);case`done`:break}if(f&&(c+=f),d.length===0){f&&s.push({role:`assistant`,content:f});break}s.push({role:`assistant`,content:f,toolCalls:d.map(e=>({id:e.id,type:`function`,function:{name:e.name,arguments:JSON.stringify(e.arguments)}}))});for(let e of d)s.push({role:`tool`,toolCallId:e.id,toolName:e.name,content:JSON.stringify(e.result)})}return{finalText:c,rounds:l}}async function ut(e,t,n){try{switch(e){case`read_file`:return await it(n.sandbox,t);case`write_file`:return await at(n.sandbox,t,n.approval);case`patch_file`:return await ot(n.sandbox,t,n.approval);case`detect_framework`:return await st(n.cwd);case`ask_user`:return await ct(n.prompter,t);default:return{ok:!1,content:null,error:`unknown_tool:${e}`}}}catch(e){return{ok:!1,content:null,error:`tool_threw: ${e.message}`}}}const dt=e=>`<script defer\n data-id="${e}"\n data-allow-localhost="true"\n src="https://api.zenovay.com/z.js">\n</script>`;async function ft(e){let t={installed:[],skipped:[],errors:[]},n=await A([`**/*.html`,`!node_modules/**`,`!.git/**`,`!dist/**`,`!.next/**`,`!.nuxt/**`,`!build/**`,`!.output/**`],{cwd:e.cwd,gitignore:!0,absolute:!1});if(n.length===0)return t;let r=dt(e.trackingCode),i=RegExp(`data-id\\s*=\\s*["']${pt(e.trackingCode)}["']`);for(let a of n){let n=g.join(e.cwd,a),o;try{o=await _.readFile(n,`utf8`)}catch(e){t.errors.push({file:a,error:e.message});continue}if(H.test(o)&&i.test(o)){t.skipped.push({file:a,reason:`already installed with correct tracking code`});continue}let s;if(H.test(o))s=o.replace(/(<script[^>]*src\s*=\s*["']https:\/\/(?:api|cdn)\.zenovay\.com\/[^"']+["'][^>]*>)/i,t=>t.replace(/data-id\s*=\s*["']ZV_\w+["']/i,`data-id="${e.trackingCode}"`)),s===o&&(s=o.replace(/<script(\s)/i,`<script$1data-id="${e.trackingCode}"$1`));else if(e.updateOnly){t.skipped.push({file:a,reason:`updateOnly=true and no Zenovay tag present`});continue}else if(/<\/head>/i.test(o)){if(s=o.replace(/(\n[\t ]*)?<\/head>/i,(e,t)=>{let n=t??`
|
|
70
|
-
`,i=r.replace(/\n/g,`${n}`);return`${n}${i}${n}</head>`}),s===o){t.skipped.push({file:a,reason:`</head> regex did not match unexpectedly`});continue}}else{t.skipped.push({file:a,reason:`no <head>...</head> in file (fragment or non-page)`});continue}let c=null;for(let{name:e,re:t}of U)if(t.test(o)&&!t.test(s)){c=e;break}if(c){t.errors.push({file:a,error:`would remove ${c} tracker — refusing to write`});continue}try{await _.writeFile(n,s,`utf8`),t.installed.push(a)}catch(e){t.errors.push({file:a,error:e.message})}}return t}function pt(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function mt(){let e=[12,15,18,22,28,35,41,50,58,64,72,78],t=h(e,24);return[` ↑`,` ${t}`,` └────────────────────────`,` May Jun Jul Aug Sep`]}function ht(){return[` Landing page ████████████████████ 100%`,` ↓ -28%`,` Pricing ██████████████░░░░░░ 72%`,` ↓ -50%`,` Checkout ███████░░░░░░░░░░░░░ 36%`,` ↓ -64%`,` Purchased ███░░░░░░░░░░░░░░░░░ 13%`]}function gt(){return[` ▇▇▇▇▇▇▇▇▇▎ 89 Sarah K. /pricing 🇺🇸`,` ▇▇▇▇▇▇░░░░ 61 anon /docs 🇩🇪`,` ▇▇▇░░░░░░░ 34 anon /changelog 🇯🇵`]}function _t(){return[` LCP ● 2.1s good ████████████░░░░░░`,` INP ● 89ms good ██████████████████`,` CLS ⚠ 0.14 needs ████████████░░░░░░`,` TTFB ● 380ms good ███████████████░░░`]}const X=[{title:`Welcome`,body:[`The wizard is an agent — it handles the entire`,`Zenovay setup process on your behalf.`,``,`Reading your project, deciding where the tracker`,`belongs, and writing the snippet for you.`]},{title:`Events`,body:[`Events are the foundation of Zenovay analytics.`,``,`Every pageview, click, and custom action is an`,`event. Group them into Goals to track conversions.`]},{title:`Trends`,body:[`Use trends to measure growth.`,``,`See how visitors, signups, and revenue have`,`changed over the last week, month, or quarter.`],visual:mt},{title:`Funnels`,body:[`Funnels reveal where users drop off.`,``,`Define the steps you care about — landing,`,`pricing, checkout, purchase — and Zenovay shows`,`the per-step conversion rate.`],visual:ht},{title:`Live visitors`,body:[`Watch every visitor in real time, ranked by an`,`AI score that highlights high-intent traffic.`,``,"Use `zenovay visitors --live` after install."],visual:gt},{title:`Core Web Vitals`,body:[`LCP, INP, CLS — Google's page-experience metrics,`,`collected automatically once the tracker is in.`,``,"Use `zenovay vitals` to see them per page + device."],visual:_t},{title:`MCP integration`,body:[`Your CLI session can install Zenovay's MCP server`,`into Cursor / Claude Desktop / VS Code.`,``,`Then ask your AI: "what were my top pages today?"`,`and it queries Zenovay directly.`]},{title:`AI insights`,body:[`Zenovay watches your data and surfaces anomalies`,`automatically — traffic spikes, error bursts,`,`revenue drops — without you needing to ask.`,``,"Run `zenovay ai` after install to chat with them."]},{title:`Privacy-first`,body:[`No cookies required. No third-party trackers.`,`Cookieless mode is one toggle in your dashboard.`,``,`GDPR, CCPA, and PECR-compliant out of the box.`]}],vt=8e3,yt=({width:e,height:t})=>{let[n,r]=k(0);D(()=>{let e=setInterval(()=>{r(e=>(e+1)%X.length)},vt);return()=>clearInterval(e)},[]);let i=X[n],a=i.visual?i.visual():[],o=X.map((e,t)=>t===n?`●`:`·`).join(` `);return E.createElement(S,{flexDirection:`column`,width:e,height:t,paddingX:2,paddingY:1},E.createElement(S,{marginBottom:1},E.createElement(C,{color:`magentaBright`,bold:!0},`Learn`)),E.createElement(S,{marginBottom:1},E.createElement(C,{bold:!0,color:`white`},i.title)),i.body.map((e,t)=>E.createElement(C,{key:t,color:`gray`},e||` `)),a.length>0&&E.createElement(S,{flexDirection:`column`,marginTop:1},a.map((e,t)=>E.createElement(C,{key:t,color:`cyan`},e))),E.createElement(S,{flexGrow:1}),E.createElement(S,{marginTop:1},E.createElement(C,{color:`gray`,dimColor:!0},o,` · `,n+1,` / `,X.length)))},bt={pending:`·`,active:`⠋`,done:`✓`,error:`✗`},xt={pending:`gray`,active:`magenta`,done:`green`,error:`red`},St=({tasks:e,width:t,height:n,liveLine:r})=>{let i=e.filter(e=>e.status===`done`).length;return E.createElement(S,{flexDirection:`column`,width:t,height:n,paddingX:2,paddingY:1},E.createElement(S,{marginBottom:1},E.createElement(C,{color:`magentaBright`,bold:!0},`Tasks`)),e.map(e=>E.createElement(S,{key:e.id,flexDirection:`column`},E.createElement(S,null,e.status===`active`?E.createElement(C,{color:`magenta`},E.createElement(j,{type:`dots`})):E.createElement(C,{color:xt[e.status]},bt[e.status]),E.createElement(C,null,` `),E.createElement(C,{color:e.status===`pending`?`gray`:`white`},e.label)),e.detail&&E.createElement(S,{paddingLeft:2},E.createElement(C,{color:`gray`,dimColor:!0},e.detail)))),E.createElement(S,{flexGrow:1}),r&&E.createElement(S,{marginTop:1},E.createElement(C,{color:`cyan`},`◆ `),E.createElement(C,{color:`white`},r)),E.createElement(S,{marginTop:1},E.createElement(C,{color:`gray`,dimColor:!0},i,` / `,e.length)))};async function Ct(e){if(o(e))return wt(e);let t=`quit`,n=null,r=await new Promise(r=>{let{unmount:i,waitUntilExit:a}=w(E.createElement(Tt,{opts:e,onExit:(e,a,o)=>{t=a??`quit`,n=o??null,i(),r(e)}}));a().catch(()=>r(1))});if(r!==0||t===`quit`||!n)return r;let i=n.id;if(t===`watch`){let{watchCommand:t}=await import(`./watch-C3s26qCL.js`);return t({cliVersion:e.cliVersion,siteId:i})}if(t===`events`){let{eventsTailCommand:t}=await import(`./events-tail-pDYhVzFg.js`);return t({cliVersion:e.cliVersion,siteId:i})}return 0}async function wt(t){let i=await import(`./telemetry-BHyqKLqh.js`).catch(()=>null);i?.emit(`install.start`,{properties:{mode:`headless`}});try{let o=await e(),s=await q(t.cwd);if(!s)return a({type:`error`,code:`no_framework`,message:`Could not detect framework (headless mode has no picker).`}),i?.emit(`install.error`,{error_code:`no_framework`,properties:{mode:`headless`}}),2;a({type:`framework.detected`,framework:s.id,confidence:1}),i?.emit(`install.framework_detected`,{properties:{framework:s.id}});let c=await r({strict:!1});if(!c&&!process.env.ZENOVAY_API_TOKEN)return a({type:`error`,code:`not_logged_in`,message:"Run `zenovay login` first (or set ZENOVAY_API_TOKEN)."}),2;let l=new n({config:o,cliVersion:t.cliVersion,token:c}),u=await l.getSites(),d=t.siteId?u.find(e=>e.id===t.siteId):u[0];if(!d&&t.siteId)return a({type:`error`,code:`site_not_found`,message:`Site ${t.siteId} not found.`}),2;if(!d)return a({type:`error`,code:`no_site`,message:`No sites exist; create one at app.zenovay.com or re-run interactively.`}),2;a({type:`info`,message:`Using site ${d.id} (${d.name}) trackingCode=${d.trackingCode??d.id}`});let f=await J(t.cwd,{[s.envVarName]:d.trackingCode??d.id});return a({type:`info`,message:`env vars added: ${f.addedKeys.join(`,`)}`}),a({type:`done`,command:`init`,exitCode:0}),i?.emit(`install.success`,{properties:{framework:s.id,mode:`headless`,env_keys_added:f.addedKeys.length}}),0}catch(e){return a({type:`error`,code:`init_failed`,message:e.message}),i?.emit(`install.error`,{error_code:`init_failed`,properties:{mode:`headless`,error:(e.message??`unknown`).slice(0,128)}}),1}}const Tt=({opts:t,onExit:i})=>{let{exit:a}=ee(),[o,s]=k(`intro`),[d,f]=k(null),[p,h]=k([]),[g,_]=k(null),[v,y]=k(null),[b,x]=k(null),[w,T]=k([]),[A,M]=k(void 0),[N,P]=k(null),[F,te]=k(0),I=O(!1);return D(()=>(process.stdout.isTTY&&process.stdout.write(`\x1B[?1049h\x1B[H`),()=>{process.stdout.isTTY&&process.stdout.write(`\x1B[?1049l`)}),[]),D(()=>{I.current||(I.current=!0,(async()=>{try{s(`detecting`);let i=await q(t.cwd);if(!i){x(`Could not detect your framework. Supported: Next.js, Nuxt, SvelteKit, Astro, Remix, plain HTML.`),s(`error`);return}f(i);let a=await r({strict:!1});!process.env.ZENOVAY_API_TOKEN&&!a&&(s(`login`),await c({cliVersion:t.cliVersion})),s(`loading-sites`);let o=await e(),l=await r({strict:!1}),u=new n({config:o,cliVersion:t.cliVersion,token:l}),d=await u.getSites(),p=await zt(t.cwd),m=Bt(d,p);if(h(d),_(p),d.length===0){s(`create-site`);return}if(t.siteId){let e=d.find(e=>e.id===t.siteId);if(!e){x(`Site ${t.siteId} not found in your account.`),s(`error`);return}y(e),Z(e,i,t,{setPhase:s,setErrorMsg:x,setTasks:T,setLiveLine:M,setSandboxStats:P});return}if(t.yes&&m){y(m),Z(m,i,t,{setPhase:s,setErrorMsg:x,setTasks:T,setLiveLine:M,setSandboxStats:P});return}s(`site-picker`)}catch(e){x(e.message),s(`error`)}})())},[]),D(()=>{o===`error`&&setTimeout(()=>{a(),i(1)},8e3)},[o]),E.createElement(S,{flexDirection:`column`},E.createElement(u,{version:t.cliVersion,subtitle:`AI install wizard`}),o===`intro`&&E.createElement(Et,null),o===`detecting`&&E.createElement(l,{title:`Scanning`,state:`busy`},E.createElement(S,null,E.createElement(C,{color:`magenta`},E.createElement(j,{type:`dots`})),E.createElement(C,null,` Detecting framework…`))),o===`login`&&E.createElement(l,{title:`Authenticating`,state:`busy`},E.createElement(C,null,`Opening browser for login… (paste ZENOVAY_API_TOKEN env var to skip)`)),o===`loading-sites`&&E.createElement(l,{title:`Loading your sites`,state:`busy`},E.createElement(S,null,E.createElement(C,{color:`magenta`},E.createElement(j,{type:`dots`})),E.createElement(C,null,` Fetching your Zenovay sites…`))),o===`site-picker`&&d&&E.createElement(Ot,{sites:p,preselectHint:g,onPick:e=>{if(e===`create-new`){s(`create-site`);return}y(e),Z(e,d,t,{setPhase:s,setErrorMsg:x,setTasks:T,setLiveLine:M,setSandboxStats:P})}}),o===`create-site`&&E.createElement(l,{title:`Create a new site`,state:`warn`},E.createElement(C,{color:`yellow`},"No site picked (or none exist yet). Visit https://app.zenovay.com/websites to create one, then re-run `zenovay init`."),E.createElement(C,{color:`gray`},`(Inline site creation from the CLI is scheduled for V1.1 — it requires a plan-limit check.)`)),o===`agent`&&d&&v&&E.createElement(Dt,{adapter:d,site:v,tasks:w,liveLine:A}),o===`install-complete`&&d&&v&&E.createElement(jt,{adapter:d,site:v,stats:N,onCommit:()=>s(`commit-prompt`),onSkipCommit:()=>s(`deploy-prompt`)}),o===`commit-prompt`&&v&&E.createElement(Mt,{cwd:t.cwd,onDone:e=>{e.committed&&M(`Pushed ${e.shortSha} to ${e.branch}`),s(`deploy-prompt`)},onError:e=>{x(e),s(`error`)}}),o===`deploy-prompt`&&v&&E.createElement(Nt,{site:v,onDeployed:()=>s(`visit-prompt`),onSkip:()=>s(`verify`)}),o===`visit-prompt`&&v&&E.createElement(Pt,{site:v,onContinue:()=>s(`verify`)}),o===`verify`&&v&&E.createElement(It,{site:v,elapsed:F,onTick:e=>te(e),onArrived:()=>s(`success`),onTimeout:()=>s(`success`)}),o===`success`&&d&&v&&E.createElement(At,{adapter:d,site:v,stats:N,onPick:e=>{a(),i(0,e,v)}}),o===`error`&&E.createElement(l,{title:`Install failed`,state:`err`},E.createElement(C,{color:`red`},b??`Unknown error`)),E.createElement(m,{items:[{key:`q`,label:`quit`},{key:`ctrl-c`,label:`abort`}]}))};async function Z(i,a,o,s){try{s.setPhase(`agent`);let c=await e(),l=await r({strict:!1}),u=new n({config:c,cliVersion:o.cliVersion,token:l}),d=new W({cwd:o.cwd}),f=i.trackingCode??i.id;await t({defaultSiteId:i.id,defaultSiteName:i.name}).catch(()=>void 0);let p=await re(o.cwd,f);if(p.recommendation===`no-op`){s.setTasks(e=>e.map(e=>e.id===`detect`||e.id===`read`||e.id===`write`?{...e,status:`done`,detail:`already installed correctly`}:e)),s.setLiveLine(p.summary),s.setSandboxStats?.({reads:0,writes:0,rounds:0}),!o.skipMcp&&l&&await Y({accessToken:l.accessToken}).catch(()=>void 0),s.setPhase(`install-complete`);return}p.competitors.length>0&&s.setLiveLine(`Detected ${p.competitors.map(e=>e.name).join(`, `)} — will install Zenovay alongside (won't touch their tags).`);let m=a.id===`plain-html`&&(p.recommendation===`fresh-install`||p.recommendation===`fresh-install-alongside-competitor`||p.recommendation===`update-tracking-code`);if(m){s.setTasks(e=>e.map(e=>e.id===`detect`?{...e,status:`done`,detail:`Plain HTML`}:e)),s.setLiveLine(`Plain HTML — using fast install path (no AI needed)…`);let e=await ft({cwd:o.cwd,trackingCode:f,updateOnly:p.recommendation===`update-tracking-code`});if(e.installed.length===0&&e.errors.length===0)throw Error(`No HTML files were modified. Either no .html files contain a <head>...</head> block, or every file already has the correct tracker.`);if(e.installed.length===0&&e.errors.length>0)throw Error(`Programmatic install failed for all ${e.errors.length} file(s). First error: ${e.errors[0].file}: ${e.errors[0].error}`);s.setTasks(t=>t.map(t=>t.id===`read`||t.id===`write`?{...t,status:`done`,detail:`${e.installed.length} file(s)`}:t)),s.setLiveLine(`Tracker added to ${e.installed.length} file(s). Skipped ${e.skipped.length}, errored ${e.errors.length}.`);let t=await J(o.cwd,{[a.envVarName]:f});if(s.setTasks(e=>e.map(e=>e.id===`env`?{...e,status:`done`,detail:`${t.addedKeys.length} key(s) added`}:e)),!o.skipMcp&&l){let e=await Y({accessToken:l.accessToken}).catch(()=>null);s.setTasks(t=>t.map(t=>t.id===`mcp`?{...t,status:`done`,detail:e&&e.installed.length>0?e.installed.join(`, `):`none detected`}:t))}else s.setTasks(e=>e.map(e=>e.id===`mcp`?{...e,status:`done`,detail:`skipped`}:e));s.setLiveLine(void 0),s.setSandboxStats?.({reads:e.installed.length,writes:e.installed.length,rounds:0}),s.setPhase(`install-complete`);return}let h=a.buildSnippets({trackingCode:f,siteId:i.id}),g=`Install Zenovay tracking into this ${a.displayName} project.\nSite: ${i.name} (trackingCode: ${f}).\n1. Call detect_framework to confirm the framework.\n2. Read the entry file(s) for this framework:\n`+a.files.map(e=>` - ${e.path}`).join(`
|
|
70
|
+
`,i=r.replace(/\n/g,`${n}`);return`${n}${i}${n}</head>`}),s===o){t.skipped.push({file:a,reason:`</head> regex did not match unexpectedly`});continue}}else{t.skipped.push({file:a,reason:`no <head>...</head> in file (fragment or non-page)`});continue}let c=null;for(let{name:e,re:t}of U)if(t.test(o)&&!t.test(s)){c=e;break}if(c){t.errors.push({file:a,error:`would remove ${c} tracker — refusing to write`});continue}try{await _.writeFile(n,s,`utf8`),t.installed.push(a)}catch(e){t.errors.push({file:a,error:e.message})}}return t}function pt(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function mt(){let e=[12,15,18,22,28,35,41,50,58,64,72,78],t=h(e,24);return[` ↑`,` ${t}`,` └────────────────────────`,` May Jun Jul Aug Sep`]}function ht(){return[` Landing page ████████████████████ 100%`,` ↓ -28%`,` Pricing ██████████████░░░░░░ 72%`,` ↓ -50%`,` Checkout ███████░░░░░░░░░░░░░ 36%`,` ↓ -64%`,` Purchased ███░░░░░░░░░░░░░░░░░ 13%`]}function gt(){return[` ▇▇▇▇▇▇▇▇▇▎ 89 Sarah K. /pricing 🇺🇸`,` ▇▇▇▇▇▇░░░░ 61 anon /docs 🇩🇪`,` ▇▇▇░░░░░░░ 34 anon /changelog 🇯🇵`]}function _t(){return[` LCP ● 2.1s good ████████████░░░░░░`,` INP ● 89ms good ██████████████████`,` CLS ⚠ 0.14 needs ████████████░░░░░░`,` TTFB ● 380ms good ███████████████░░░`]}const X=[{title:`Welcome`,body:[`The wizard is an agent — it handles the entire`,`Zenovay setup process on your behalf.`,``,`Reading your project, deciding where the tracker`,`belongs, and writing the snippet for you.`]},{title:`Events`,body:[`Events are the foundation of Zenovay analytics.`,``,`Every pageview, click, and custom action is an`,`event. Group them into Goals to track conversions.`]},{title:`Trends`,body:[`Use trends to measure growth.`,``,`See how visitors, signups, and revenue have`,`changed over the last week, month, or quarter.`],visual:mt},{title:`Funnels`,body:[`Funnels reveal where users drop off.`,``,`Define the steps you care about — landing,`,`pricing, checkout, purchase — and Zenovay shows`,`the per-step conversion rate.`],visual:ht},{title:`Live visitors`,body:[`Watch every visitor in real time, ranked by an`,`AI score that highlights high-intent traffic.`,``,"Use `zenovay visitors --live` after install."],visual:gt},{title:`Core Web Vitals`,body:[`LCP, INP, CLS — Google's page-experience metrics,`,`collected automatically once the tracker is in.`,``,"Use `zenovay vitals` to see them per page + device."],visual:_t},{title:`MCP integration`,body:[`Your CLI session can install Zenovay's MCP server`,`into Cursor / Claude Desktop / VS Code.`,``,`Then ask your AI: "what were my top pages today?"`,`and it queries Zenovay directly.`]},{title:`AI insights`,body:[`Zenovay watches your data and surfaces anomalies`,`automatically — traffic spikes, error bursts,`,`revenue drops — without you needing to ask.`,``,"Run `zenovay ai` after install to chat with them."]},{title:`Privacy-first`,body:[`No cookies required. No third-party trackers.`,`Cookieless mode is one toggle in your dashboard.`,``,`GDPR, CCPA, and PECR-compliant out of the box.`]}],vt=8e3,yt=({width:e,height:t})=>{let[n,r]=k(0);D(()=>{let e=setInterval(()=>{r(e=>(e+1)%X.length)},vt);return()=>clearInterval(e)},[]);let i=X[n],a=i.visual?i.visual():[],o=X.map((e,t)=>t===n?`●`:`·`).join(` `);return E.createElement(S,{flexDirection:`column`,width:e,height:t,paddingX:2,paddingY:1},E.createElement(S,{marginBottom:1},E.createElement(C,{color:`magentaBright`,bold:!0},`Learn`)),E.createElement(S,{marginBottom:1},E.createElement(C,{bold:!0,color:`white`},i.title)),i.body.map((e,t)=>E.createElement(C,{key:t,color:`gray`},e||` `)),a.length>0&&E.createElement(S,{flexDirection:`column`,marginTop:1},a.map((e,t)=>E.createElement(C,{key:t,color:`cyan`},e))),E.createElement(S,{flexGrow:1}),E.createElement(S,{marginTop:1},E.createElement(C,{color:`gray`,dimColor:!0},o,` · `,n+1,` / `,X.length)))},bt={pending:`·`,active:`⠋`,done:`✓`,error:`✗`},xt={pending:`gray`,active:`magenta`,done:`green`,error:`red`},St=({tasks:e,width:t,height:n,liveLine:r})=>{let i=e.filter(e=>e.status===`done`).length;return E.createElement(S,{flexDirection:`column`,width:t,height:n,paddingX:2,paddingY:1},E.createElement(S,{marginBottom:1},E.createElement(C,{color:`magentaBright`,bold:!0},`Tasks`)),e.map(e=>E.createElement(S,{key:e.id,flexDirection:`column`},E.createElement(S,null,e.status===`active`?E.createElement(C,{color:`magenta`},E.createElement(j,{type:`dots`})):E.createElement(C,{color:xt[e.status]},bt[e.status]),E.createElement(C,null,` `),E.createElement(C,{color:e.status===`pending`?`gray`:`white`},e.label)),e.detail&&E.createElement(S,{paddingLeft:2},E.createElement(C,{color:`gray`,dimColor:!0},e.detail)))),E.createElement(S,{flexGrow:1}),r&&E.createElement(S,{marginTop:1},E.createElement(C,{color:`cyan`},`◆ `),E.createElement(C,{color:`white`},r)),E.createElement(S,{marginTop:1},E.createElement(C,{color:`gray`,dimColor:!0},i,` / `,e.length)))};async function Ct(e){if(o(e))return wt(e);let t=`quit`,n=null,r=await new Promise(r=>{let{unmount:i,waitUntilExit:a}=w(E.createElement(Tt,{opts:e,onExit:(e,a,o)=>{t=a??`quit`,n=o??null,i(),r(e)}}));a().catch(()=>r(1))});if(r!==0||t===`quit`||!n)return r;let i=n.id;if(t===`watch`){let{watchCommand:t}=await import(`./watch-D5WeMSz2.js`);return t({cliVersion:e.cliVersion,siteId:i})}if(t===`events`){let{eventsTailCommand:t}=await import(`./events-tail-u_lwZas2.js`);return t({cliVersion:e.cliVersion,siteId:i})}return 0}async function wt(t){let i=await import(`./telemetry-C1045t6Q.js`).catch(()=>null);i?.emit(`install.start`,{properties:{mode:`headless`}});try{let o=await e(),s=await q(t.cwd);if(!s)return a({type:`error`,code:`no_framework`,message:`Could not detect framework (headless mode has no picker).`}),i?.emit(`install.error`,{error_code:`no_framework`,properties:{mode:`headless`}}),2;a({type:`framework.detected`,framework:s.id,confidence:1}),i?.emit(`install.framework_detected`,{properties:{framework:s.id}});let c=await r({strict:!1});if(!c&&!process.env.ZENOVAY_API_TOKEN)return a({type:`error`,code:`not_logged_in`,message:"Run `zenovay login` first (or set ZENOVAY_API_TOKEN)."}),2;let l=new n({config:o,cliVersion:t.cliVersion,token:c}),u=await l.getSites(),d=t.siteId?u.find(e=>e.id===t.siteId):u[0];if(!d&&t.siteId)return a({type:`error`,code:`site_not_found`,message:`Site ${t.siteId} not found.`}),2;if(!d)return a({type:`error`,code:`no_site`,message:`No sites exist; create one at app.zenovay.com or re-run interactively.`}),2;a({type:`info`,message:`Using site ${d.id} (${d.name}) trackingCode=${d.trackingCode??d.id}`});let f=await J(t.cwd,{[s.envVarName]:d.trackingCode??d.id});return a({type:`info`,message:`env vars added: ${f.addedKeys.join(`,`)}`}),a({type:`done`,command:`init`,exitCode:0}),i?.emit(`install.success`,{properties:{framework:s.id,mode:`headless`,env_keys_added:f.addedKeys.length}}),0}catch(e){return a({type:`error`,code:`init_failed`,message:e.message}),i?.emit(`install.error`,{error_code:`init_failed`,properties:{mode:`headless`,error:(e.message??`unknown`).slice(0,128)}}),1}}const Tt=({opts:t,onExit:i})=>{let{exit:a}=ee(),[o,s]=k(`intro`),[d,f]=k(null),[p,h]=k([]),[g,_]=k(null),[v,y]=k(null),[b,x]=k(null),[w,T]=k([]),[A,M]=k(void 0),[N,P]=k(null),[F,te]=k(0),I=O(!1);return D(()=>(process.stdout.isTTY&&process.stdout.write(`\x1B[?1049h\x1B[H`),()=>{process.stdout.isTTY&&process.stdout.write(`\x1B[?1049l`)}),[]),D(()=>{I.current||(I.current=!0,(async()=>{try{s(`detecting`);let i=await q(t.cwd);if(!i){x(`Could not detect your framework. Supported: Next.js, Nuxt, SvelteKit, Astro, Remix, plain HTML.`),s(`error`);return}f(i);let a=await r({strict:!1});!process.env.ZENOVAY_API_TOKEN&&!a&&(s(`login`),await c({cliVersion:t.cliVersion})),s(`loading-sites`);let o=await e(),l=await r({strict:!1}),u=new n({config:o,cliVersion:t.cliVersion,token:l}),d=await u.getSites(),p=await zt(t.cwd),m=Bt(d,p);if(h(d),_(p),d.length===0){s(`create-site`);return}if(t.siteId){let e=d.find(e=>e.id===t.siteId);if(!e){x(`Site ${t.siteId} not found in your account.`),s(`error`);return}y(e),Z(e,i,t,{setPhase:s,setErrorMsg:x,setTasks:T,setLiveLine:M,setSandboxStats:P});return}if(t.yes&&m){y(m),Z(m,i,t,{setPhase:s,setErrorMsg:x,setTasks:T,setLiveLine:M,setSandboxStats:P});return}s(`site-picker`)}catch(e){x(e.message),s(`error`)}})())},[]),D(()=>{o===`error`&&setTimeout(()=>{a(),i(1)},8e3)},[o]),E.createElement(S,{flexDirection:`column`},E.createElement(u,{version:t.cliVersion,subtitle:`AI install wizard`}),o===`intro`&&E.createElement(Et,null),o===`detecting`&&E.createElement(l,{title:`Scanning`,state:`busy`},E.createElement(S,null,E.createElement(C,{color:`magenta`},E.createElement(j,{type:`dots`})),E.createElement(C,null,` Detecting framework…`))),o===`login`&&E.createElement(l,{title:`Authenticating`,state:`busy`},E.createElement(C,null,`Opening browser for login… (paste ZENOVAY_API_TOKEN env var to skip)`)),o===`loading-sites`&&E.createElement(l,{title:`Loading your sites`,state:`busy`},E.createElement(S,null,E.createElement(C,{color:`magenta`},E.createElement(j,{type:`dots`})),E.createElement(C,null,` Fetching your Zenovay sites…`))),o===`site-picker`&&d&&E.createElement(Ot,{sites:p,preselectHint:g,onPick:e=>{if(e===`create-new`){s(`create-site`);return}y(e),Z(e,d,t,{setPhase:s,setErrorMsg:x,setTasks:T,setLiveLine:M,setSandboxStats:P})}}),o===`create-site`&&E.createElement(l,{title:`Create a new site`,state:`warn`},E.createElement(C,{color:`yellow`},"No site picked (or none exist yet). Visit https://app.zenovay.com/websites to create one, then re-run `zenovay init`."),E.createElement(C,{color:`gray`},`(Inline site creation from the CLI is scheduled for V1.1 — it requires a plan-limit check.)`)),o===`agent`&&d&&v&&E.createElement(Dt,{adapter:d,site:v,tasks:w,liveLine:A}),o===`install-complete`&&d&&v&&E.createElement(jt,{adapter:d,site:v,stats:N,onCommit:()=>s(`commit-prompt`),onSkipCommit:()=>s(`deploy-prompt`)}),o===`commit-prompt`&&v&&E.createElement(Mt,{cwd:t.cwd,onDone:e=>{e.committed&&M(`Pushed ${e.shortSha} to ${e.branch}`),s(`deploy-prompt`)},onError:e=>{x(e),s(`error`)}}),o===`deploy-prompt`&&v&&E.createElement(Nt,{site:v,onDeployed:()=>s(`visit-prompt`),onSkip:()=>s(`verify`)}),o===`visit-prompt`&&v&&E.createElement(Pt,{site:v,onContinue:()=>s(`verify`)}),o===`verify`&&v&&E.createElement(It,{site:v,elapsed:F,onTick:e=>te(e),onArrived:()=>s(`success`),onTimeout:()=>s(`success`)}),o===`success`&&d&&v&&E.createElement(At,{adapter:d,site:v,stats:N,onPick:e=>{a(),i(0,e,v)}}),o===`error`&&E.createElement(l,{title:`Install failed`,state:`err`},E.createElement(C,{color:`red`},b??`Unknown error`)),E.createElement(m,{items:[{key:`q`,label:`quit`},{key:`ctrl-c`,label:`abort`}]}))};async function Z(i,a,o,s){try{s.setPhase(`agent`);let c=await e(),l=await r({strict:!1}),u=new n({config:c,cliVersion:o.cliVersion,token:l}),d=new W({cwd:o.cwd}),f=i.trackingCode??i.id;await t({defaultSiteId:i.id,defaultSiteName:i.name}).catch(()=>void 0);let p=await re(o.cwd,f);if(p.recommendation===`no-op`){s.setTasks(e=>e.map(e=>e.id===`detect`||e.id===`read`||e.id===`write`?{...e,status:`done`,detail:`already installed correctly`}:e)),s.setLiveLine(p.summary),s.setSandboxStats?.({reads:0,writes:0,rounds:0}),!o.skipMcp&&l&&await Y({accessToken:l.accessToken}).catch(()=>void 0),s.setPhase(`install-complete`);return}p.competitors.length>0&&s.setLiveLine(`Detected ${p.competitors.map(e=>e.name).join(`, `)} — will install Zenovay alongside (won't touch their tags).`);let m=a.id===`plain-html`&&(p.recommendation===`fresh-install`||p.recommendation===`fresh-install-alongside-competitor`||p.recommendation===`update-tracking-code`);if(m){s.setTasks(e=>e.map(e=>e.id===`detect`?{...e,status:`done`,detail:`Plain HTML`}:e)),s.setLiveLine(`Plain HTML — using fast install path (no AI needed)…`);let e=await ft({cwd:o.cwd,trackingCode:f,updateOnly:p.recommendation===`update-tracking-code`});if(e.installed.length===0&&e.errors.length===0)throw Error(`No HTML files were modified. Either no .html files contain a <head>...</head> block, or every file already has the correct tracker.`);if(e.installed.length===0&&e.errors.length>0)throw Error(`Programmatic install failed for all ${e.errors.length} file(s). First error: ${e.errors[0].file}: ${e.errors[0].error}`);s.setTasks(t=>t.map(t=>t.id===`read`||t.id===`write`?{...t,status:`done`,detail:`${e.installed.length} file(s)`}:t)),s.setLiveLine(`Tracker added to ${e.installed.length} file(s). Skipped ${e.skipped.length}, errored ${e.errors.length}.`);let t=await J(o.cwd,{[a.envVarName]:f});if(s.setTasks(e=>e.map(e=>e.id===`env`?{...e,status:`done`,detail:`${t.addedKeys.length} key(s) added`}:e)),!o.skipMcp&&l){let e=await Y({accessToken:l.accessToken}).catch(()=>null);s.setTasks(t=>t.map(t=>t.id===`mcp`?{...t,status:`done`,detail:e&&e.installed.length>0?e.installed.join(`, `):`none detected`}:t))}else s.setTasks(e=>e.map(e=>e.id===`mcp`?{...e,status:`done`,detail:`skipped`}:e));s.setLiveLine(void 0),s.setSandboxStats?.({reads:e.installed.length,writes:e.installed.length,rounds:0}),s.setPhase(`install-complete`);return}let h=a.buildSnippets({trackingCode:f,siteId:i.id}),g=`Install Zenovay tracking into this ${a.displayName} project.\nSite: ${i.name} (trackingCode: ${f}).\n1. Call detect_framework to confirm the framework.\n2. Read the entry file(s) for this framework:\n`+a.files.map(e=>` - ${e.path}`).join(`
|
|
71
71
|
`)+`
|
|
72
72
|
3. Insert the tracker using the snippet below.
|
|
73
73
|
4. Confirm the change with a diff before writing.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import"./token-store-BQuGH0z2.js";import{initCommand as e}from"./init-BIJkCrgc.js";import"./client-DTXWADkX.js";import"./formatter-DutfcQAc.js";import"./emit-DBYk96TD.js";import"./secrets-ApB7yh2A.js";import"./login-yhuXiFqh.js";import"./panel-B_yDcIcn.js";import"./banner-3iSWTDFy.js";import"./progress-row-BpAXjJPL.js";import"./prompt-D-Uzz_GF.js";import"./keybar-DsYTkKZX.js";import"./sparkline-BZ0eMB-w.js";export{e as initCommand};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{requireTier as r}from"./tier-BneaO4vD.js";import"./formatter-DutfcQAc.js";import{emit$1 as i,isHeadless as a}from"./emit-DBYk96TD.js";import{Panel as o}from"./panel-B_yDcIcn.js";import{Banner as s}from"./banner-3iSWTDFy.js";import"./prompt-D-Uzz_GF.js";import{Keybar as c}from"./keybar-DsYTkKZX.js";import{resolveSiteId as l}from"./resolve-site-mj0esTrm.js";import{EmptyState as u}from"./empty-state-CJxa1jUN.js";import{deepLinkFor as d,openInBrowser as f}from"./keybar-deep-link-DC31T3CP.js";import{Box as p,Text as m,render as h,useApp as g,useInput as _}from"ink";import v,{useEffect as y,useState as b}from"react";import x from"ink-spinner";function S(e){return e===`critical`?`err`:e===`warning`?`warn`:`ok`}function C(e){return e===`anomaly`?`⚡ anomaly`:e===`recommendation`?`✦ recommendation`:`↗ trend`}async function w(o){let s=await e(),c=await t({strict:!1});if(!c)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let u=new n({config:s,cliVersion:o.cliVersion,token:c});try{await r(u,`pro`)}catch(e){return process.stderr.write(`${e.message}\n`),2}let d,f;try{({siteId:d,site:f}=await l(u,{explicit:o.siteId,headless:!!o.json,cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let p=f?.url?f.url.replace(/^https?:\/\//,``).replace(/\/$/,``):f?.name??d;if(a(o)){let e=await u.getInsights(d);return i({type:`insights.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=h(v.createElement(T,{api:u,siteId:d,siteLabel:p,cliVersion:o.cliVersion,onExit:n=>{t(),e(n)}}))})}const T=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:a}=g(),[l,h]=b(null),[w,T]=b(!0),[E,D]=b(null);return _(e=>{if(e===`o`||e===`O`){f(d(`insights`,{siteId:t}));return}e===`q`&&(a(),i(0))}),y(()=>{let n=!1;return(async()=>{try{let r=await e.getInsights(t);n||(h(r),T(!1))}catch(e){n||(D(e.message),T(!1))}})(),()=>{n=!0}},[e,t]),w?v.createElement(p,{flexDirection:`column`},v.createElement(s,{version:r,subtitle:`insights · ${n}`}),v.createElement(o,{title:`Loading`,state:`busy`},v.createElement(p,null,v.createElement(m,{color:`magenta`},v.createElement(x,{type:`dots`})),v.createElement(m,null,` Fetching insights…`)))):E?v.createElement(p,{flexDirection:`column`},v.createElement(s,{version:r,subtitle:`insights · ${n}`}),v.createElement(u,{reason:`error`,headline:`Failed to load`,hint:E})):!l||l.length===0?v.createElement(p,{flexDirection:`column`},v.createElement(s,{version:r,subtitle:`insights · ${n}`}),v.createElement(u,{reason:`no-data`,headline:`No insights yet`,hint:`Insights are generated nightly — check back tomorrow`})):v.createElement(p,{flexDirection:`column`},v.createElement(s,{version:r,subtitle:`insights · ${n}`}),l.map((e,t)=>v.createElement(o,{key:t,title:`${C(e.kind)} · ${e.severity}`,state:S(e.severity)},v.createElement(m,{bold:!0},e.title),e.body?v.createElement(m,{color:`gray`},e.body):null)),v.createElement(c,{items:[{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}]}))};export{w as insightsCommand};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{confirmDestructive as r}from"./confirm-DS5wux0g.js";import i from"open";async function a(a){let o=await e(),s=await t({strict:!1}),c=new n({config:o,cliVersion:a.cliVersion,token:s});try{switch(a.action){case`list`:{let{integrations:e}=await c.listIntegrations();if(a.json)return process.stdout.write(JSON.stringify({integrations:e},null,2)+`
|
|
2
2
|
`),0;let t=[10,30,14],n=e=>e.map((e,n)=>(e??``).padEnd(t[n])).join(` `);process.stdout.write(`
|
|
3
3
|
`+n([`name`,`service`,`status`])+`
|
|
4
4
|
`),process.stdout.write(n(t.map(e=>`─`.repeat(e)))+`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{requireTier as r}from"./tier-BneaO4vD.js";import"./formatter-DutfcQAc.js";import{emit$1 as i,isHeadless as a}from"./emit-DBYk96TD.js";import{Panel as o}from"./panel-B_yDcIcn.js";import{Banner as s}from"./banner-3iSWTDFy.js";import"./prompt-D-Uzz_GF.js";import{Keybar as c}from"./keybar-DsYTkKZX.js";import{resolveSiteId as l}from"./resolve-site-mj0esTrm.js";import{EmptyState as u}from"./empty-state-CJxa1jUN.js";import{deepLinkFor as d,openInBrowser as f}from"./keybar-deep-link-DC31T3CP.js";import{Box as p,Text as m,render as h,useApp as g,useInput as _}from"ink";import v,{useEffect as y,useState as b}from"react";import x from"ink-spinner";async function S(o){let s=await e(),c=await t({strict:!1});if(!c)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let u=new n({config:s,cliVersion:o.cliVersion,token:c});try{await r(u,`pro`)}catch(e){return process.stderr.write(`${e.message}\n`),2}let d,f;try{({siteId:d,site:f}=await l(u,{explicit:o.siteId,headless:!!o.json,cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let p=f?.url?f.url.replace(/^https?:\/\//,``).replace(/\/$/,``):f?.name??d;if(a(o)){let e=await u.getJourneys(d);return i({type:`journeys.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=h(v.createElement(C,{api:u,siteId:d,siteLabel:p,cliVersion:o.cliVersion,onExit:n=>{t(),e(n)}}))})}const C=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:a}=g(),[l,h]=b(null),[S,C]=b(!0),[w,T]=b(null);if(_(e=>{if(e===`o`||e===`O`){f(d(`journeys`,{siteId:t}));return}e===`q`&&(a(),i(0))}),y(()=>{let n=!1;return(async()=>{try{let r=await e.getJourneys(t);n||(h(r.flows),C(!1))}catch(e){n||(T(e.message),C(!1))}})(),()=>{n=!0}},[e,t]),S)return v.createElement(p,{flexDirection:`column`},v.createElement(s,{version:r,subtitle:`journeys · ${n}`}),v.createElement(o,{title:`Loading`,state:`busy`},v.createElement(p,null,v.createElement(m,{color:`magenta`},v.createElement(x,{type:`dots`})),v.createElement(m,null,` Computing flows…`))));if(w)return v.createElement(p,{flexDirection:`column`},v.createElement(s,{version:r,subtitle:`journeys · ${n}`}),v.createElement(u,{reason:`error`,headline:`Failed to load`,hint:w}));if(!l||l.length===0)return v.createElement(p,{flexDirection:`column`},v.createElement(s,{version:r,subtitle:`journeys · ${n}`}),v.createElement(u,{reason:`no-data`,headline:`No journeys yet`,hint:`Need at least 2 page-views per session to compute flows`}));let E=Math.max(...l.map(e=>e.count),1),D=12;return v.createElement(p,{flexDirection:`column`},v.createElement(s,{version:r,subtitle:`journeys · ${n}`}),v.createElement(o,{title:`Top page transitions (${l.length})`},l.map((e,t)=>{let n=Math.max(1,Math.round(e.count/E*D));return v.createElement(p,{key:t,flexDirection:`row`},v.createElement(m,null,e.from.padEnd(22).slice(0,22)),v.createElement(m,{color:`cyan`},` → `),v.createElement(m,null,e.to.padEnd(22).slice(0,22)),v.createElement(m,{color:`magenta`},` `,`█`.repeat(n),`░`.repeat(D-n)),v.createElement(m,{color:`gray`},` ${e.count}`))})),v.createElement(c,{items:[{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}]}))};export{S as journeysCommand};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import"./telemetry-DRh10SvO.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import"./client-DTXWADkX.js";import"./formatter-DutfcQAc.js";import{emit$1 as r,isHeadless as i}from"./emit-DBYk96TD.js";import{Panel as a}from"./panel-B_yDcIcn.js";import{Banner as o}from"./banner-3iSWTDFy.js";import"./prompt-D-Uzz_GF.js";import{Keybar as s}from"./keybar-DsYTkKZX.js";import"./sparkline-BZ0eMB-w.js";import{ChatPanel as c}from"./chat-panel-CqJaCIg3.js";import{resolveSiteId as l}from"./resolve-site-mj0esTrm.js";import{EmptyState as u}from"./empty-state-CJxa1jUN.js";import{MetricCard as d}from"./metric-card-COEIZmbN.js";import{deepLinkFor as f,openInBrowser as p}from"./keybar-deep-link-DC31T3CP.js";import{Box as m,Text as h,render as g,useApp as _,useInput as v}from"ink";import y,{useEffect as b,useState as x}from"react";import S from"ink-spinner";async function C(a){let o=await e(),s=await t({strict:!1});if(!s)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let c=new n({config:o,cliVersion:a.cliVersion,token:s}),u,d;try{({siteId:u,site:d}=await l(c,{explicit:a.siteId,headless:!!a.json,cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let f=d?.url?d.url.replace(/^https?:\/\//,``).replace(/\/$/,``):d?.name??u;if(i(a)){let e=await c.getLive(u);return r({type:`live.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=g(y.createElement(w,{api:c,siteId:u,siteLabel:f,cliVersion:a.cliVersion,onExit:n=>{t(),e(n)}}))})}const w=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:l}=_(),[g,C]=x(null),[w,T]=x(!0),[E,D]=x(null),[O,k]=x(!1);if(v(e=>{if(!O){if(e===`/`){k(!0);return}if(e===`o`||e===`O`){p(f(`live`,{siteId:t}));return}e===`q`&&(l(),i(0))}}),b(()=>{if(O)return;let n=!1,r=async()=>{try{let r=await e.getLive(t);n||(C(r),T(!1),D(null))}catch(e){n||(D(e.message),T(!1))}};r();let i=setInterval(r,2e3);return()=>{n=!0,clearInterval(i)}},[e,t,O]),O)return y.createElement(c,{cliVersion:r,api:e,dashboardContext:{commandName:`live`,siteId:t,siteLabel:n,metricsSnapshot:g},onClose:()=>k(!1)});if(w)return y.createElement(m,{flexDirection:`column`},y.createElement(o,{version:r,subtitle:`live · ${n}`}),y.createElement(a,{title:`Loading`,state:`busy`},y.createElement(m,null,y.createElement(h,{color:`magenta`},y.createElement(S,{type:`dots`})),y.createElement(h,null,` Connecting…`))));if(E&&!g)return y.createElement(m,{flexDirection:`column`},y.createElement(o,{version:r,subtitle:`live · ${n}`}),y.createElement(u,{reason:`error`,headline:`Failed to load`,hint:E}));let A=process.stdout.columns??80,j=Math.max(20,Math.min(40,Math.floor(A/3)));return y.createElement(m,{flexDirection:`column`},y.createElement(o,{version:r,subtitle:`live · ${n}`}),y.createElement(d,{title:`Active now`,value:g?.activeVisitors??0,format:`number`,width:j}),y.createElement(a,{title:`Recent events`},!g||g.recentEvents.length===0?y.createElement(h,{color:`gray`},`— waiting for events —`):g.recentEvents.slice(0,15).map((e,t)=>y.createElement(m,{key:t},y.createElement(h,{color:`cyan`},(e.type??`pageview`).padEnd(10)),y.createElement(h,null,e.path.padEnd(36).slice(0,36)),y.createElement(h,{color:`gray`},e.country??`—`)))),y.createElement(s,{items:[{key:`/`,label:`ask AI`},{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}]}))};export{C as liveCommand};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import"./token-store-BQuGH0z2.js";import"./formatter-DutfcQAc.js";import"./emit-DBYk96TD.js";import{loginCommand as e}from"./login-yhuXiFqh.js";export{e as loginCommand};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config--JRu_jFq.js";import{ApiClient as t,pollDeviceToken as n,startDeviceAuthorization as r}from"./api-FCanTxsb.js";import{writeToken as i}from"./token-store-BQuGH0z2.js";import{emit$1 as a,isHeadless as o}from"./emit-DBYk96TD.js";import s from"node:path";import{promises as c}from"node:fs";import l from"node:os";import u from"open";async function d(s){let c=await e(),l=o({json:s.json}),d=await r({apiBase:c.apiBase}),f=d.verification_uri_complete??d.verification_uri;l?a({type:`info`,message:`Open ${f} and enter code ${d.user_code}`}):s.onCode?s.onCode({userCode:d.user_code,verificationUri:d.verification_uri,verificationUriComplete:d.verification_uri_complete}):process.stdout.write(`\n Open this URL to authorize the CLI:\n ${f}\n Or enter code: ${d.user_code}\n\n`);let p=s.openBrowser??!l;if(p)try{await u(f)}catch{}let m=await n({apiBase:c.apiBase,deviceCode:d.device_code,interval:d.interval,expiresIn:d.expires_in});await i(m);let h=new t({config:c,cliVersion:s.cliVersion,token:m}),_=await h.me().catch(()=>null);if(_){let e={...m,userId:_.user.id,teamId:_.team?.id,email:_.user.email};await i(e)}return l?a({type:`done`,command:`login`,exitCode:0}):await g().catch(()=>void 0),{email:_?.user.email}}function f(){let e=process.env.SHELL??``,t=l.homedir();if(e.endsWith(`/zsh`)||e.endsWith(`zsh`))return{shell:`zsh`,rcPath:s.join(t,`.zshrc`)};if(e.endsWith(`/bash`)||e.endsWith(`bash`)){let e=process.platform===`darwin`?s.join(t,`.bash_profile`):s.join(t,`.bashrc`);return{shell:`bash`,rcPath:e}}return e.endsWith(`/fish`)||e.endsWith(`fish`)?{shell:`fish`,rcPath:s.join(t,`.config`,`fish`,`config.fish`)}:null}const p=/zenovay\s+completions/;async function m(e,t){try{let n=await c.readFile(e,`utf8`);return t.test(n)}catch{return!1}}function h(e){return process.stdin.isTTY?new Promise(t=>{process.stdout.write(e),process.stdin.setEncoding(`utf8`);let n=e=>{process.stdin.removeListener(`data`,n);try{process.stdin.pause()}catch{}let r=e.trim().toLowerCase();return t(r===``||r===`y`||r===`yes`)};process.stdin.resume(),process.stdin.on(`data`,n)}):Promise.resolve(!1)}async function g(){let e=f();if(!e||await m(e.rcPath,p))return;let t=await h(`Install shell completions for ${e.shell}? [Y/n] `);if(!t){process.stdout.write(`Skipped. You can install later with: zenovay completions ${e.shell} >> ${e.rcPath}\n`);return}let n=e.shell===`fish`?`zenovay completions fish | source
|
|
2
2
|
`:`eval "$(zenovay completions ${e.shell})"\n`;try{await c.mkdir(s.dirname(e.rcPath),{recursive:!0}),await c.appendFile(e.rcPath,`\n# Added by zenovay login\n${n}`,`utf8`),process.stdout.write(`✓ Completions installed. Restart your shell or source ${e.rcPath}.\n`)}catch(t){process.stdout.write(`Could not write ${e.rcPath} (${t.message}). Run manually: zenovay completions ${e.shell} >> ${e.rcPath}\n`)}}export{d as loginCommand};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config--JRu_jFq.js";import{ApiClient as t}from"./api-FCanTxsb.js";import{clearToken as n,readToken as r}from"./token-store-BQuGH0z2.js";import"./formatter-DutfcQAc.js";import{emit$1 as i,isHeadless as a}from"./emit-DBYk96TD.js";async function o(o){let s=await e(),c=await r({strict:!1}).catch(()=>null);if(c)try{let e=new t({config:s,cliVersion:o.cliVersion,token:c});await e.revokeCurrentToken()}catch{}await n(),a({json:o.json})?i({type:`done`,command:`logout`,exitCode:0}):process.stdout.write(`Logged out.
|
|
2
2
|
`)}export{o as logoutCommand};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config--JRu_jFq.js";import{ApiError as t}from"./api-FCanTxsb.js";import{readToken as n}from"./token-store-BQuGH0z2.js";import{ApiV2Client as r}from"./api-v2-CI5hxW-O.js";import{confirmDestructive as i}from"./confirm-DS5wux0g.js";function a(e){return e.length>12?`${e.slice(0,8)}…${e.slice(-4)}`:e}function o(e){return e?new Date(e).toISOString().slice(0,10):`—`}async function s(s){let c=await e(),l=await n({strict:!1}),u=new r({config:c,cliVersion:s.cliVersion,token:l});try{switch(s.action){case`list`:{let{notes:e}=await u.listNotes();if(s.json)return process.stdout.write(JSON.stringify({notes:e},null,2)+`
|
|
2
2
|
`),0;if(e.length===0)return process.stdout.write('No notes yet. Create one with `zenovay notes create --content "<text>"`.\n'),0;let t=[14,12,50],n=e=>e.map((e,n)=>(e??``).padEnd(t[n])).join(` `);process.stdout.write(`
|
|
3
3
|
`+n([`id`,`created`,`content`])+`
|
|
4
4
|
`),process.stdout.write(n(t.map(e=>`─`.repeat(e)))+`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import"./formatter-DutfcQAc.js";import{emit$1 as r,isHeadless as i}from"./emit-DBYk96TD.js";import{Panel as a}from"./panel-B_yDcIcn.js";import{Banner as o}from"./banner-3iSWTDFy.js";import"./prompt-D-Uzz_GF.js";import{Keybar as s}from"./keybar-DsYTkKZX.js";import{resolveSiteId as c}from"./resolve-site-mj0esTrm.js";import{DataTable as l}from"./data-table-BpbyyNSA.js";import{EmptyState as u}from"./empty-state-CJxa1jUN.js";import{deepLinkFor as d,openInBrowser as f}from"./keybar-deep-link-DC31T3CP.js";import{Box as p,Text as m,render as h,useApp as g,useInput as _}from"ink";import v,{useEffect as y,useState as b}from"react";import x from"ink-spinner";async function S(a){let o=await e(),s=await t({strict:!1});if(!s)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let l=new n({config:o,cliVersion:a.cliVersion,token:s}),u,d;try{({siteId:u,site:d}=await c(l,{explicit:a.siteId,headless:!!a.json,cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let f=d?.url?d.url.replace(/^https?:\/\//,``).replace(/\/$/,``):d?.name??u;if(i(a)){let e=await l.getPages(u);return r({type:`pages.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=h(v.createElement(C,{api:l,siteId:u,siteLabel:f,cliVersion:a.cliVersion,onExit:n=>{t(),e(n)}}))})}const C=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:c}=g(),[h,S]=b(null),[C,w]=b(!0),[T,E]=b(null);if(_(e=>{if(e===`o`||e===`O`){f(d(`pages`,{siteId:t}));return}e===`q`&&(c(),i(0))}),y(()=>{let n=!1;return(async()=>{try{let r=await e.getPages(t);n||(S(r),w(!1))}catch(e){n||(E(e.message),w(!1))}})(),()=>{n=!0}},[e,t]),C)return v.createElement(p,{flexDirection:`column`},v.createElement(o,{version:r,subtitle:`pages · ${n}`}),v.createElement(a,{title:`Loading`,state:`busy`},v.createElement(p,null,v.createElement(m,{color:`magenta`},v.createElement(x,{type:`dots`})),v.createElement(m,null,` Fetching pages…`))));if(T)return v.createElement(p,{flexDirection:`column`},v.createElement(o,{version:r,subtitle:`pages · ${n}`}),v.createElement(u,{reason:`error`,headline:`Failed to load`,hint:T}));if(!h||h.length===0)return v.createElement(p,{flexDirection:`column`},v.createElement(o,{version:r,subtitle:`pages · ${n}`}),v.createElement(u,{reason:`no-data`,headline:`No pages yet`,hint:`Visit your site to send the first event`}));let D=[{key:`path`,label:`path`,width:36},{key:`views`,label:`views`,align:`right`,width:8},{key:`uniqueVisitors`,label:`unique`,align:`right`,width:8},{key:`avgTime`,label:`avg time`,align:`right`,width:9,format:e=>typeof e==`number`?`${Math.round(e/1e3)}s`:`—`},{key:`bounceRate`,label:`bounce`,align:`right`,width:7,format:e=>typeof e==`number`?`${(e*100).toFixed(0)}%`:`—`}];return v.createElement(p,{flexDirection:`column`},v.createElement(o,{version:r,subtitle:`pages · ${n}`}),v.createElement(a,{title:`Top pages (${h.length})`},v.createElement(l,{columns:D,data:h,zebra:!0})),v.createElement(s,{items:[{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}]}))};export{S as pagesCommand};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config--JRu_jFq.js";import{ApiError as t}from"./api-FCanTxsb.js";import{readToken as n}from"./token-store-BQuGH0z2.js";import{ApiV2Client as r}from"./api-v2-CI5hxW-O.js";import{fmtCurrency as i,formatTable as a}from"./fmt-gMsty5jy.js";import o from"open";async function s(s){let c=await e(),l=await n({strict:!1}),u=new r({config:c,cliVersion:s.cliVersion,token:l});try{switch(s.action){case`info`:{let e=await u.getPlanInfo();if(s.json)return process.stdout.write(JSON.stringify(e,null,2)+`
|
|
2
2
|
`),0;let t=[{key:`plan`,value:e.plan},{key:`status`,value:`${e.status}${e.cancelAtPeriodEnd?` (cancels at period end)`:``}`},{key:`current period`,value:`${e.currentPeriodStart??`—`} → ${e.currentPeriodEnd??`—`}`},{key:`websites in use`,value:String(e.usage.websites)}];e.nextInvoice&&t.push({key:`next invoice`,value:`${i(e.nextInvoice.amountDue,e.nextInvoice.currency)} on ${e.nextInvoice.periodEnd??`—`}`});let n=[{key:`key`,header:`field`,width:18},{key:`value`,header:`value`,width:48}];return process.stdout.write(`
|
|
3
3
|
`),process.stdout.write(a({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--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";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--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import"./telemetry-DRh10SvO.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import"./client-DTXWADkX.js";import{formatTabular as r,selectFormat as i}from"./formatter-DutfcQAc.js";import"./panel-B_yDcIcn.js";import"./banner-3iSWTDFy.js";import"./prompt-D-Uzz_GF.js";import"./keybar-DsYTkKZX.js";import"./chat-panel-CqJaCIg3.js";import{resolveSiteId as a}from"./resolve-site-mj0esTrm.js";import{DataTable as o}from"./data-table-BpbyyNSA.js";import{runAnalyticalScreen as s}from"./analytical-screen-BasvNR-9.js";import{Text as c}from"ink";import l from"react";function u(){let e=process.stdout.columns??80,t=Math.max(40,e-4-18),n=1,r=t-n,i=Math.max(8,Math.floor(r*.3)),a=Math.max(8,Math.floor(r*.32)),o=Math.max(4,Math.floor(r*.1)),s=Math.max(6,Math.floor(r*.12)),c=Math.max(4,r-i-a-o-s);return{current:n,name:i,domain:a,tier:o,pageviews24h:s,id:c}}async function d(d){let f=await e(),p=await t({strict:!1}),m=new n({config:f,cliVersion:d.cliVersion,token:p}),h,g;try{({siteId:h,site:g}=await a(m,{explicit:d.siteId,headless:!!(d.json||d.csv||d.tsv||d.ndjson),cliVersion:d.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let _=i(d),v=u(),y=[{key:`isCurrent`,label:``,width:v.current,format:e=>e?`*`:` `},{key:`name`,label:`project`,width:v.name},{key:`domain`,label:`domain`,width:v.domain,format:e=>String(e??`—`)},{key:`tier`,label:`tier`,width:v.tier},{key:`pageviews24h`,label:`24h pv`,width:v.pageviews24h,align:`right`},{key:`id`,label:`id`,width:v.id}];return s({cliVersion:d.cliVersion,title:`projects · ${p?.teamId??`—`}`,commandName:`projects`,authToken:p?.accessToken??null,refreshIntervalMs:0,fetcher:e=>m.getProjects(h,e),format:_,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){if(t===`ndjson`)for(let t of e.projects)process.stdout.write(JSON.stringify(t)+`
|
|
2
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(c,{color:`gray`},`— no projects yet —`):l.createElement(o,{data:e.projects,columns:y,headerStyle:`accent`})}]})}export{d as projectsCommand};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{requireTier as r}from"./tier-BneaO4vD.js";import{formatTabular as i,selectFormat as a}from"./formatter-DutfcQAc.js";import{Panel as o}from"./panel-B_yDcIcn.js";import{Banner as s}from"./banner-3iSWTDFy.js";import"./progress-row-BpAXjJPL.js";import"./prompt-D-Uzz_GF.js";import"./keybar-DsYTkKZX.js";import"./sparkline-BZ0eMB-w.js";import{resolveSiteId as c}from"./resolve-site-mj0esTrm.js";import{DataTable as l}from"./data-table-BpbyyNSA.js";import"./bar-DWT-1xOE.js";import"./ui-Cey-h6wI.js";import{Box as u,Text as d,useApp as f,useInput as p}from"ink";import m,{useMemo as h,useState as g}from"react";import _ from"ink-text-input";function v({api:e,siteId:t,maxRows:n}){let{exit:r}=f(),[i,a]=g(``),[c,v]=g(null),[y,b]=g(null),[x,S]=g(!1),[C,w]=g([]);p((e,t)=>{t.escape&&r()});let T=async i=>{if(i.trim()){if(i.trim()===`\\q`||i.trim()===`exit`||i.trim()===`quit`){r();return}w(e=>[...e,i]),S(!0),b(null);try{let r=await e.runSqlQuery(t,i,{maxRows:n});v(r)}catch(e){b(e.message),v(null)}finally{S(!1),a(``)}}},E=h(()=>c?c.columns.map(e=>({key:e,label:e,width:18,format:e=>e==null?`∅`:String(e).slice(0,18)})):[],[c]);return m.createElement(u,{flexDirection:`column`},m.createElement(s,{version:`query`}),m.createElement(o,{title:`History`,state:`idle`},C.length===0?m.createElement(d,{color:`gray`},`— no queries yet — Esc or \\q to exit —`):C.slice(-5).map((e,t)=>m.createElement(d,{key:t,color:`gray`},`> ${e.slice(0,80)}${e.length>80?`…`:``}`))),m.createElement(u,null,m.createElement(d,{color:`magenta`},`sql`,`>`,` `),m.createElement(_,{value:i,onChange:a,onSubmit:T})),x?m.createElement(d,{color:`gray`},`running…`):null,y?m.createElement(o,{title:`Error`,state:`err`},m.createElement(d,{color:`red`},y)):null,c?m.createElement(o,{title:`${c.row_count} rows · ${c.duration_ms}ms${c.truncated?` · truncated`:``}`,state:`ok`},c.row_count===0?m.createElement(d,{color:`gray`},`— empty —`):m.createElement(l,{data:c.rows.slice(0,50),columns:E,headerStyle:`accent`})):null)}async function y(o){let s=await e(),l=await t({strict:!1}),u=new n({config:s,cliVersion:o.cliVersion,token:l});try{await r(u,`scale`)}catch(e){return process.stderr.write(`${e.message}\n`),2}let d;try{({siteId:d}=await c(u,{explicit:o.siteId,headless:!!(o.json||o.csv||o.tsv||o.ndjson),cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let f=o.maxRows??1e3,p=a(o);if(o.sql)try{let e=await u.runSqlQuery(d,o.sql,{maxRows:f});if(p===`json`)process.stdout.write(JSON.stringify(e,null,2)),process.stdout.write(`
|
|
2
2
|
`);else if(p===`ndjson`)for(let t of e.rows)process.stdout.write(JSON.stringify(t)+`
|
|
3
3
|
`);else if(p===`csv`||p===`tsv`)process.stdout.write(i(e.rows,e.columns,p));else{let t=e.columns.map(t=>Math.max(t.length,...e.rows.map(e=>String(e[t]??``).length))),n=`+`+t.map(e=>`-`.repeat(e+2)).join(`+`)+`+`;process.stdout.write(n+`
|
|
4
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--JRu_jFq.js";import{Panel as n}from"./panel-B_yDcIcn.js";import{Banner as r}from"./banner-3iSWTDFy.js";import{Select as i}from"./prompt-D-Uzz_GF.js";import{Box as a,Text as o,render as s}from"ink";import c from"react";async function l(n,r){if(r.explicit&&r.explicit.trim())return{siteId:r.explicit.trim(),saved:!1};let i=await e(),a;try{a=await n.getSites()}catch(e){if(i.defaultSiteId)return{siteId:i.defaultSiteId,saved:!1};throw Error(`Could not fetch your sites (${e.message}). Pass --site-id <ID> to bypass.`)}if(i.defaultSiteId){let e=a.find(e=>e.id===i.defaultSiteId);if(e)return{siteId:e.id,site:e,saved:!1};await t({defaultSiteId:void 0,defaultSiteName:void 0})}if(a.length===0)throw Error("No sites in your account. Run `zenovay init` to add one, or create one at app.zenovay.com.");if(a.length===1){let e=a[0];return await t({defaultSiteId:e.id,defaultSiteName:e.name}),{siteId:e.id,site:e,saved:!0}}if(r.headless||!process.stdout.isTTY){let e=a.map(e=>` ${e.name.padEnd(24)} ${e.url.padEnd(36)} ${e.id}`).join(`
|
|
2
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 u(a,r.cliVersion);return await t({defaultSiteId:o.id,defaultSiteName:o.name}),{siteId:o.id,site:o,saved:!0}}function u(e,t=`0`){return new Promise((n,r)=>{let i,a=e=>{i?.(),n(e)},o=()=>{i?.(),r(Error(`Site selection cancelled`))},l=s(c.createElement(d,{sites:e,cliVersion:t,onPick:a,onCancel:o}));i=l.unmount})}const d=({sites:e,cliVersion:t,onPick:s})=>{let l=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 c.createElement(a,{flexDirection:`column`},c.createElement(r,{version:t,subtitle:`pick a site`}),c.createElement(n,{title:`Which site?`,state:`idle`},c.createElement(a,{marginBottom:1},c.createElement(o,{color:`gray`},"We'll save your pick as the default — re-run with `zenovay use --reset` to change it.")),c.createElement(i,{items:l,onSelect:s})))};export{l as resolveSiteId};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{requireTier as r}from"./tier-BneaO4vD.js";import"./formatter-DutfcQAc.js";import{emit$1 as i,isHeadless as a}from"./emit-DBYk96TD.js";import{Panel as o}from"./panel-B_yDcIcn.js";import{Banner as s}from"./banner-3iSWTDFy.js";import"./prompt-D-Uzz_GF.js";import{Keybar as c}from"./keybar-DsYTkKZX.js";import{resolveSiteId as l}from"./resolve-site-mj0esTrm.js";import{EmptyState as u}from"./empty-state-CJxa1jUN.js";import{deepLinkFor as d,openInBrowser as f}from"./keybar-deep-link-DC31T3CP.js";import{Box as p,Text as m,render as h,useApp as g,useInput as _}from"ink";import v,{useEffect as y,useState as b}from"react";import x from"ink-spinner";function S(e){return e>=.6?`magenta`:e>=.4?`cyan`:e>=.2?`blue`:`gray`}function C(e){return!Number.isFinite(e)||e===0?` — `:` ${(e*100).toFixed(0).padStart(3)}% `}async function w(o){let s=await e(),c=await t({strict:!1});if(!c)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let u=new n({config:s,cliVersion:o.cliVersion,token:c});try{await r(u,`pro`)}catch(e){return process.stderr.write(`${e.message}\n`),2}let d,f;try{({siteId:d,site:f}=await l(u,{explicit:o.siteId,headless:!!o.json,cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let p=f?.url?f.url.replace(/^https?:\/\//,``).replace(/\/$/,``):f?.name??d;if(a(o)){let e=await u.getRetention(d);return i({type:`retention.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=h(v.createElement(T,{api:u,siteId:d,siteLabel:p,cliVersion:o.cliVersion,onExit:n=>{t(),e(n)}}))})}const T=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:a}=g(),[l,h]=b(null),[w,T]=b(!0),[E,D]=b(null);return _(e=>{if(e===`o`||e===`O`){f(d(`retention`,{siteId:t}));return}e===`q`&&(a(),i(0))}),y(()=>{let n=!1;return(async()=>{try{let r=await e.getRetention(t);n||(h(r.cohorts),T(!1))}catch(e){n||(D(e.message),T(!1))}})(),()=>{n=!0}},[e,t]),w?v.createElement(p,{flexDirection:`column`},v.createElement(s,{version:r,subtitle:`retention · ${n}`}),v.createElement(o,{title:`Loading`,state:`busy`},v.createElement(p,null,v.createElement(m,{color:`magenta`},v.createElement(x,{type:`dots`})),v.createElement(m,null,` Crunching cohorts…`)))):E?v.createElement(p,{flexDirection:`column`},v.createElement(s,{version:r,subtitle:`retention · ${n}`}),v.createElement(u,{reason:`error`,headline:`Failed to load`,hint:E})):!l||l.length===0?v.createElement(p,{flexDirection:`column`},v.createElement(s,{version:r,subtitle:`retention · ${n}`}),v.createElement(u,{reason:`no-data`,headline:`No retention data yet`,hint:`Retention needs at least 30 days of traffic`})):v.createElement(p,{flexDirection:`column`},v.createElement(s,{version:r,subtitle:`retention · ${n}`}),v.createElement(o,{title:`Cohort retention (D1 / D7 / D30)`},v.createElement(p,{flexDirection:`row`},v.createElement(m,{bold:!0},`cohort`.padEnd(12)),v.createElement(m,{bold:!0},` D1 `),v.createElement(m,{bold:!0},` D7 `),v.createElement(m,{bold:!0},` D30 `)),l.map(e=>v.createElement(p,{key:e.date,flexDirection:`row`},v.createElement(m,null,e.date.padEnd(12).slice(0,12)),v.createElement(m,{color:S(e.day1)},C(e.day1)),v.createElement(m,{color:S(e.day7)},C(e.day7)),v.createElement(m,{color:S(e.day30)},C(e.day30))))),v.createElement(c,{items:[{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}]}))};export{w as retentionCommand};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import"./telemetry-DRh10SvO.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import"./client-DTXWADkX.js";import{formatTabular as r,selectFormat as i}from"./formatter-DutfcQAc.js";import"./panel-B_yDcIcn.js";import"./banner-3iSWTDFy.js";import"./progress-row-BpAXjJPL.js";import"./prompt-D-Uzz_GF.js";import"./keybar-DsYTkKZX.js";import{spark as a}from"./sparkline-BZ0eMB-w.js";import"./chat-panel-CqJaCIg3.js";import{resolveSiteId as o}from"./resolve-site-mj0esTrm.js";import"./data-table-BpbyyNSA.js";import"./bar-DWT-1xOE.js";import{deepLinkFor as s,openInBrowser as c}from"./keybar-deep-link-DC31T3CP.js";import{runAnalyticalScreen as l}from"./analytical-screen-BasvNR-9.js";import"./ui-Cey-h6wI.js";import{Box as u,Text as d}from"ink";import f from"react";function p(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}`}async function m(m){let h=await e(),g=await t({strict:!1}),_=new n({config:h,cliVersion:m.cliVersion,token:g}),v,y;try{({siteId:v,site:y}=await o(_,{explicit:m.siteId,headless:!!(m.json||m.csv||m.tsv||m.ndjson),cliVersion:m.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let b=i(m),x=m.range??`30d`;return l({cliVersion:m.cliVersion,title:`revenue · ${v} · ${x}`,commandName:`revenue`,ai:{api:_,siteId:v,siteLabel:y?.url?y.url.replace(/^https?:\/\//,``).replace(/\/$/,``):y?.name??v},authToken:g?.accessToken??null,refreshIntervalMs:m.watch?5*6e4:0,fetcher:e=>_.getRevenue(v,x,e),format:b,keybindings:{o:{label:`open in browser`,handler:()=>{c(s(`revenue`,{siteId:v}))}}},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=>f.createElement(u,{flexDirection:`column`},f.createElement(d,null,f.createElement(d,{color:`green`,bold:!0},p(e.totalAmount,e.currency)),` `,f.createElement(d,{color:`gray`},`total · `,e.totalTransactions,` transactions`)),typeof e.mrr==`number`?f.createElement(d,null,f.createElement(d,{bold:!0},`MRR `),f.createElement(d,{color:`magenta`},p(e.mrr,e.currency)),typeof e.arpu==`number`?f.createElement(d,{color:`gray`},` · ARPU `,p(e.arpu,e.currency)):null):null)},{id:`series`,title:`Daily (${x})`,render:e=>{let t=e.series.map(e=>e.amount);if(t.length===0)return f.createElement(d,{color:`gray`},`— no transactions —`);let n=Math.max(...t,1);return f.createElement(u,{flexDirection:`column`},f.createElement(d,{color:`magenta`},a(t,Math.min(60,t.length*2))),f.createElement(d,{color:`gray`},`peak: `,p(n,e.currency),` ·`,` `,`avg: `,p(e.totalAmount/Math.max(1,t.length),e.currency)))}},{id:`window`,title:`Window`,render:e=>f.createElement(d,{color:`gray`},new Date(e.windowStart).toISOString().slice(0,10),` →`,` `,new Date(e.windowEnd).toISOString().slice(0,10))}]})}export{m as revenueCommand};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{spawn as e}from"node:child_process";import t from"chalk";const n=3e4,r=4,i=1e3;function a(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 o(t,n,r,i){return new Promise(a=>{let o=
|
|
1
|
+
import{spawn as e}from"node:child_process";import t from"chalk";const n=3e4,r=4,i=1e3;function a(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 o(t,n,r,i){return new Promise(a=>{let o=/\.[mc]?js$/.test(t),s=o?`node`:t,c=o?[t,...n]:n,l=e(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 s(e,t){let r=Date.now(),s=a(e,t.env);if(s)return{name:e.name,category:e.category,status:`skip`,durationMs:0,reason:s};if(e.inProcess)try{let t=await e.inProcess(),n=Date.now()-r;return t.ok?{name:e.name,category:e.category,status:`pass`,durationMs:n,...t.detail?{detail:t.detail}:{}}:{name:e.name,category:e.category,status:`fail`,durationMs:n,reason:t.reason}}catch(t){return{name:e.name,category:e.category,status:`fail`,durationMs:Date.now()-r,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??n,u=await o(t.binPath,e.command,l,c),d=Date.now()-r;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,i),rawStderr:u.stderr.slice(0,i)}:{}};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,i),rawStderr:u.stderr.slice(0,i)}:{}}}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,i),rawStderr:u.stderr.slice(0,i)}:{}}:{name:e.name,category:e.category,status:`fail`,durationMs:d,reason:f.reason,...t.verbose?{rawStdout:u.stdout.slice(0,i),rawStderr:u.stderr.slice(0,i)}:{}}}async function c(e,t){let n=Date.now(),i=Math.max(1,t.parallel??r),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 c=0,l=[],u=async()=>{for(;;){let n=c;if(c+=1,n>=o.length)return;let r=o[n];if(r===void 0)return;let i=e[r];if(!i)continue;let l=await s(i,t);a[r]=l,t.onResult?.(l)}};for(let e=0;e<i;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 l(e){let t={currentTier:null,hasMultipleTeams:!1,hasFreeTeam:!1,authenticated:!1};try{let{readToken:n}=await import(`./token-store-TmBx42nv.js`),{readConfig:r}=await import(`./config-DB3jF5gG.js`),{ApiV2Client:i}=await import(`./api-v2-CTc_U2Gw.js`),a=await n({strict:!1}).catch(()=>null);if(!a)return t;t.authenticated=!0;let o=await r(),s=new i({config:o,cliVersion:e,token:a}),c=await s.me();if(c.team?.plan){let e=c.team.plan.toLowerCase();(e===`free`||e===`pro`||e===`scale`||e===`enterprise`)&&(t.currentTier=e)}c.teams&&c.teams.length>=2&&(t.hasMultipleTeams=!0),(c.teams&&c.teams.some(e=>e.plan?.toLowerCase()===`free`)||t.currentTier===`free`)&&(t.hasFreeTeam=!0)}catch{}return t}function u(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 d(e,t,n){if(n!==0)return{ok:!1,reason:`exit ${n}`};let r=u(e);return r.ok?{ok:!0}:{ok:!1,reason:r.reason}}function f(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=u(e);return r.ok?{ok:!0}:{ok:!1,reason:r.reason}}function p(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 m=[{name:`analytics`,category:`ANALYTICS`,command:[`analytics`,`--json`],assert:(e,t,n)=>{let r=d(e,t,n);if(!r.ok)return r;let i=u(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:d},{name:`pages`,category:`ANALYTICS`,command:[`pages`,`--json`],assert:(e,t,n)=>{let r=d(e,t,n);if(!r.ok)return r;let i=u(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:d,quick:!0},{name:`devices`,category:`ANALYTICS`,command:[`devices`,`--json`],assert:d},{name:`geo`,category:`ANALYTICS`,command:[`geo`,`--json`],assert:d},{name:`live`,category:`ANALYTICS`,command:[`live`,`--json`],assert:(e,t,n)=>{let r=d(e,t,n);if(!r.ok)return r;let i=u(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:d},{name:`funnels`,category:`ANALYTICS`,command:[`funnels`,`--json`],assert:f,requires:{tier:`pro`}},{name:`home`,category:`ANALYTICS`,command:[`home`,`--json`],assert:d},{name:`usage`,category:`ANALYTICS`,command:[`usage`,`--json`],assert:d,quick:!0},{name:`stats`,category:`ANALYTICS`,command:[`stats`,`--json`],assert:d},{name:`retention`,category:`BEHAVIOR`,command:[`retention`,`--json`],assert:f,requires:{tier:`pro`}},{name:`uptime`,category:`BEHAVIOR`,command:[`uptime`,`--json`],assert:f,requires:{tier:`pro`}},{name:`sessions`,category:`BEHAVIOR`,command:[`sessions`,`--json`],assert:f,requires:{tier:`pro`}},{name:`heatmaps`,category:`BEHAVIOR`,command:[`heatmaps`,`--json`],assert:f,requires:{tier:`pro`}},{name:`journeys`,category:`BEHAVIOR`,command:[`journeys`,`--json`],assert:f,requires:{tier:`pro`}},{name:`insights`,category:`INTELLIGENCE`,command:[`insights`,`--json`],assert:f,requires:{tier:`pro`}},{name:`domains list`,category:`MANAGE`,command:[`domains`,`list`,`--json`],assert:(e,t,n)=>{let r=d(e,t,n);if(!r.ok)return r;let i=u(e);return!i.ok||!p(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=d(e,t,n);if(!r.ok)return r;let i=u(e);return!i.ok||!p(i.value)?{ok:!1,reason:`expected list shape`}:{ok:!0}}},{name:`team list`,category:`MANAGE`,command:[`team`,`list`,`--json`],assert:f,requires:{tier:`pro`}},{name:`webhooks list`,category:`MANAGE`,command:[`webhooks`,`list`,`--json`],assert:d},{name:`profile show`,category:`ACCOUNT`,command:[`profile`,`show`,`--json`],assert:d,quick:!0},{name:`plans info`,category:`ACCOUNT`,command:[`plans`,`info`,`--json`],assert:d},{name:`settings get`,category:`ACCOUNT`,command:[`settings`,`get`,`--json`],assert:d},{name:`integrations list`,category:`ACCOUNT`,command:[`integrations`,`list`,`--json`],assert:d},{name:`goals list`,category:`ACCOUNT`,command:[`goals`,`list`,`--json`],assert:f,requires:{tier:`pro`}},{name:`notes list`,category:`ACCOUNT`,command:[`notes`,`list`,`--json`],assert:d},{name:`audit list`,category:`ACCOUNT`,command:[`audit`,`list`,`--json`],assert:f,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:d},{name:`health`,category:`OPERATIONS`,command:[`health`,`--json`],assert:(e,t,n)=>{let r=u(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=d(e,t,n);if(!r.ok)return r;let i=u(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:d},{name:`projects`,category:`OPERATIONS`,command:[`projects`,`--json`],assert:d},{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-BtWVpY-G.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=u(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}],h=m.length;async function g(e){let t=process.argv[1]??process.execPath,
|
|
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-BtWVpY-G.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=u(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}],h=m.length;async function g(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=m.filter(e=>i||!e.dev);e.quick&&(a=a.filter(e=>e.quick));let o=await l(e.cliVersion);return e.json?_({...e,binPath:r,env:o,catalog:a}):b({...e,binPath:r,env:o,catalog:a})}async function _(e){let t=await c(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 v=26,y=8;async function b(e){S(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 c(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&&(C(a.category,i.get(a.category)??0),r=a.category),w(a,o),t.delete(a.name),n+=1}}});return T(a),a.fail>0?1:0}function x(){return Math.max(60,process.stdout.columns??80)}function S(e,n,r){let i=Math.min(120,x()),a=i-2,o=`ZENOVAY · v${e}`,s=`self-test · ${n?`quick`:`full`} · ${r} test${r===1?``:`s`}`,c=`╭─ `+o+` `+`─`.repeat(Math.max(0,a-o.length-4))+`╮`,l=`│ `+s+` `.repeat(Math.max(0,a-s.length-2))+`│`,u=`╰`+`─`.repeat(a)+`╯`;process.stdout.write(t.cyan(c)+`
|
|
5
5
|
`),process.stdout.write(t.cyan(l)+`
|
|
6
6
|
`),process.stdout.write(t.cyan(u)+`
|
|
7
7
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{requireTier as r}from"./tier-BneaO4vD.js";import"./formatter-DutfcQAc.js";import{emit$1 as i,isHeadless as a}from"./emit-DBYk96TD.js";import{Panel as o}from"./panel-B_yDcIcn.js";import{Banner as s}from"./banner-3iSWTDFy.js";import"./prompt-D-Uzz_GF.js";import{Keybar as c}from"./keybar-DsYTkKZX.js";import{resolveSiteId as l}from"./resolve-site-mj0esTrm.js";import{DataTable as u}from"./data-table-BpbyyNSA.js";import{EmptyState as d}from"./empty-state-CJxa1jUN.js";import{deepLinkFor as f,openInBrowser as p}from"./keybar-deep-link-DC31T3CP.js";import{Box as m,Text as h,render as g,useApp as _,useInput as v}from"ink";import y,{useEffect as b,useState as x}from"react";import S from"ink-spinner";function C(e){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 w(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 T(o){let s=await e(),c=await t({strict:!1});if(!c)return process.stderr.write("Not logged in — run `zenovay login` first.\n"),2;let u=new n({config:s,cliVersion:o.cliVersion,token:c});try{await r(u,`pro`)}catch(e){return process.stderr.write(`${e.message}\n`),2}let d,f;try{({siteId:d,site:f}=await l(u,{explicit:o.siteId,headless:!!o.json,cliVersion:o.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let p=f?.url?f.url.replace(/^https?:\/\//,``).replace(/\/$/,``):f?.name??d;if(a(o)){let e=await u.getSessions(d);return i({type:`sessions.snapshot`,data:e}),0}return new Promise(e=>{let{unmount:t}=g(y.createElement(E,{api:u,siteId:d,siteLabel:p,cliVersion:o.cliVersion,onExit:n=>{t(),e(n)}}))})}const E=({api:e,siteId:t,siteLabel:n,cliVersion:r,onExit:i})=>{let{exit:a}=_(),[l,g]=x(null),[T,E]=x(!0),[D,O]=x(null);if(v(e=>{if(e===`o`||e===`O`){p(f(`sessions`,{siteId:t}));return}e===`q`&&(a(),i(0))}),b(()=>{let n=!1;return(async()=>{try{let r=await e.getSessions(t);n||(g(r),E(!1))}catch(e){n||(O(e.message),E(!1))}})(),()=>{n=!0}},[e,t]),T)return y.createElement(m,{flexDirection:`column`},y.createElement(s,{version:r,subtitle:`sessions · ${n}`}),y.createElement(o,{title:`Loading`,state:`busy`},y.createElement(m,null,y.createElement(h,{color:`magenta`},y.createElement(S,{type:`dots`})),y.createElement(h,null,` Fetching sessions…`))));if(D)return y.createElement(m,{flexDirection:`column`},y.createElement(s,{version:r,subtitle:`sessions · ${n}`}),y.createElement(d,{reason:`error`,headline:`Failed to load`,hint:D}));if(!l||l.length===0)return y.createElement(m,{flexDirection:`column`},y.createElement(s,{version:r,subtitle:`sessions · ${n}`}),y.createElement(d,{reason:`no-data`,headline:`No replays yet`,hint:`Enable session replay in your site settings`}));let k=[{key:`id`,label:`session id`,width:24},{key:`visitor`,label:`visitor`,width:18},{key:`duration`,label:`duration`,align:`right`,width:9,format:e=>C(e)},{key:`startedAt`,label:`when`,align:`right`,width:6,format:e=>w(String(e))},{key:`pageCount`,label:`events`,align:`right`,width:7},{key:`deviceType`,label:`device`,width:8,format:e=>String(e??`—`)}];return y.createElement(m,{flexDirection:`column`},y.createElement(s,{version:r,subtitle:`sessions · ${n}`}),y.createElement(o,{title:`Recent sessions (${l.length})`},y.createElement(u,{columns:k,data:l,zebra:!0})),y.createElement(m,{marginTop:1},y.createElement(h,{color:`gray`},`Open any session for replay at https://app.zenovay.com/replay`)),y.createElement(c,{items:[{key:`o`,label:`open in browser`},{key:`q`,label:`quit`}]}))};export{T as sessionsCommand};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";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--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import{confirmDestructive as r}from"./confirm-DS5wux0g.js";import"./panel-B_yDcIcn.js";import"./banner-3iSWTDFy.js";import"./prompt-D-Uzz_GF.js";import{resolveSiteId as i}from"./resolve-site-mj0esTrm.js";async function a(a){let o=await e(),s=await t({strict:!1}),c=new n({config:o,cliVersion:a.cliVersion,token:s}),l;try{({siteId:l}=await i(c,{explicit:a.siteId,headless:!!a.json,cliVersion:a.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}try{switch(a.action){case`enable`:{let e=await c.enableShare(l);if(a.json)return process.stdout.write(JSON.stringify(e,null,2)+`
|
|
2
2
|
`),0;let t=`═`.repeat(72);return process.stdout.write(`\n${t}\n Public dashboard sharing enabled\n url: ${e.url}\n${t}\n\n Anyone with this link can view your dashboard. Disable with\n \`zenovay share disable\` to invalidate the link immediately.\n\n`),0}case`disable`:{let e=await r({resource:`public share link`,name:l.length>12?`${l.slice(0,8)}…${l.slice(-4)}`:l,yes:a.yes,destructive:!0});if(!e)return process.stdout.write(`Cancelled.
|
|
3
3
|
`),1;let t=await c.disableShare(l);return a.json?(process.stdout.write(JSON.stringify(t)+`
|
|
4
4
|
`),0):(process.stdout.write(`✔ Public sharing disabled. The previous link is no longer valid.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import"./telemetry-DRh10SvO.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import"./client-DTXWADkX.js";import{formatTabular as r,selectFormat as i}from"./formatter-DutfcQAc.js";import"./panel-B_yDcIcn.js";import"./banner-3iSWTDFy.js";import"./prompt-D-Uzz_GF.js";import"./keybar-DsYTkKZX.js";import"./chat-panel-CqJaCIg3.js";import{resolveSiteId as a}from"./resolve-site-mj0esTrm.js";import{DataTable as o}from"./data-table-BpbyyNSA.js";import{deepLinkFor as s,openInBrowser as c}from"./keybar-deep-link-DC31T3CP.js";import{runAnalyticalScreen as l}from"./analytical-screen-BasvNR-9.js";import{Box as u,Text as d}from"ink";import f from"react";function p(e,t){let n=Math.round(e/100*t);return`█`.repeat(n)+`░`.repeat(Math.max(0,t-n))}function m(e){return e==null?{glyph:`·`,color:`gray`}:e>.5?{glyph:`▲`,color:`green`}:e<-.5?{glyph:`▼`,color:`red`}:{glyph:`→`,color:`gray`}}async function h(h){let g=await e(),_=await t({strict:!1}),v=new n({config:g,cliVersion:h.cliVersion,token:_}),y,b;try{({siteId:y,site:b}=await a(v,{explicit:h.siteId,headless:!!(h.json||h.csv||h.tsv||h.ndjson),cliVersion:h.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let x=i(h),S=h.period??`30d`,C=[{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 l({cliVersion:h.cliVersion,title:`sources · ${y} · ${S}`,commandName:`sources`,authToken:_?.accessToken??null,refreshIntervalMs:6e4,fetcher:e=>v.getSources(y,S,h.compare,e),format:x,ai:{api:v,siteId:y,siteLabel:b?.url?b.url.replace(/^https?:\/\//,``).replace(/\/$/,``):b?.name??y},keybindings:{o:{label:`open in browser`,handler:()=>{c(s(`sources`,{siteId:y}))}}},headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){process.stdout.write(JSON.stringify(e,null,t===`json`?2:0)),t===`ndjson`&&process.stdout.write(`
|
|
2
2
|
`);return}process.stdout.write(r(e.sources,[`source`,`channel`,`visitors`,`conversions`,`revenue`,`delta`],t))},panels:[{id:`summary`,title:`Total`,render:e=>f.createElement(d,null,f.createElement(d,{bold:!0},e.totalVisitors.toLocaleString()),` `,f.createElement(d,{color:`gray`},`visitors · `,e.sources.length,` sources`))},{id:`channels`,title:`By channel`,render:e=>{if(e.sources.length===0)return f.createElement(d,{color:`gray`},`— no source data —`);let t=e.totalVisitors||1,n=[...e.sources].sort((e,t)=>t.visitors-e.visitors).slice(0,12);return f.createElement(u,{flexDirection:`column`},n.map((e,n)=>{let r=e.visitors/t*100,i=m(e.delta);return f.createElement(u,{key:`${e.source}-${n}`},f.createElement(d,null,f.createElement(d,{color:`cyan`},e.source.padEnd(20).slice(0,20)),` `,f.createElement(d,{color:`magenta`},p(r,30)),` `,f.createElement(d,null,e.visitors.toString().padStart(6),` `),f.createElement(d,{color:`gray`},`(`,r.toFixed(1),`%)`),` `,f.createElement(d,{color:i.color},i.glyph)))}))}},{id:`table`,title:`Detail`,render:e=>e.sources.length===0?f.createElement(d,{color:`gray`},`— —`):f.createElement(o,{data:e.sources.slice(0,20),columns:C,headerStyle:`accent`})}]})}export{h as sourcesCommand};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{readConfig as e}from"./config
|
|
1
|
+
import{readConfig as e}from"./config--JRu_jFq.js";import"./api-FCanTxsb.js";import{readToken as t}from"./token-store-BQuGH0z2.js";import"./telemetry-DRh10SvO.js";import{ApiV2Client as n}from"./api-v2-CI5hxW-O.js";import"./client-DTXWADkX.js";import{formatTabular as r,selectFormat as i}from"./formatter-DutfcQAc.js";import"./panel-B_yDcIcn.js";import"./banner-3iSWTDFy.js";import"./prompt-D-Uzz_GF.js";import"./keybar-DsYTkKZX.js";import"./chat-panel-CqJaCIg3.js";import{resolveSiteId as a}from"./resolve-site-mj0esTrm.js";import{DataTable as o}from"./data-table-BpbyyNSA.js";import{runAnalyticalScreen as s}from"./analytical-screen-BasvNR-9.js";import{Box as c,Text as l}from"ink";import u from"react";function d(e){return`${(e*100).toFixed(1)}%`}function f(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`}async function p(p){let m=await e(),h=await t({strict:!1}),g=new n({config:m,cliVersion:p.cliVersion,token:h}),_,v;try{({siteId:_,site:v}=await a(g,{explicit:p.siteId,headless:!!(p.json||p.csv||p.tsv||p.ndjson),cliVersion:p.cliVersion}))}catch(e){return process.stderr.write(`${e.message}\n`),2}let y=i(p),b=p.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 s({cliVersion:p.cliVersion,title:`stats · ${_} · ${b}`,commandName:`stats`,ai:{api:g,siteId:_,siteLabel:v?.url?v.url.replace(/^https?:\/\//,``).replace(/\/$/,``):v?.name??_},authToken:h?.accessToken??null,refreshIntervalMs:p.watch?6e4:0,fetcher:e=>g.getStats(_,b,e),format:y,headlessEmit:(e,t)=>{if(t===`json`||t===`ndjson`){process.stdout.write(JSON.stringify(e,null,t===`json`?2:0)),t===`ndjson`&&process.stdout.write(`
|
|
2
2
|
`);return}process.stdout.write(r([{range:b,visitors:e.visitors,pageviews:e.pageviews,sessions:e.sessions,bounceRate:d(e.bounceRate),avgSession:f(e.avgSessionSec)}],[`range`,`visitors`,`pageviews`,`sessions`,`bounceRate`,`avgSession`],t))},panels:[{id:`summary`,title:`Summary`,render:e=>u.createElement(c,{flexDirection:`column`},u.createElement(l,null,u.createElement(l,{bold:!0},e.visitors.toLocaleString()),u.createElement(l,{color:`gray`},` visitors `),u.createElement(l,{bold:!0},e.pageviews.toLocaleString()),u.createElement(l,{color:`gray`},` pageviews `),u.createElement(l,{bold:!0},e.sessions.toLocaleString()),u.createElement(l,{color:`gray`},` sessions`)),u.createElement(l,{color:`gray`},`bounce `,d(e.bounceRate),` · avg session `,f(e.avgSessionSec)))},{id:`pages`,title:`Top pages`,render:e=>e.topPages.length===0?u.createElement(l,{color:`gray`},`— no pages —`):u.createElement(o,{data:e.topPages.slice(0,10),columns:x,headerStyle:`accent`})},{id:`countries`,title:`Top countries`,render:e=>e.topCountries.length===0?u.createElement(l,{color:`gray`},`— no country data —`):u.createElement(o,{data:e.topCountries.slice(0,10),columns:S,headerStyle:`accent`})}]})}export{p as statsCommand};
|