@ainyc/canonry 4.180.5 → 4.180.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/assets/assets/{AuditHistoryPanel-CdM_9qX1.js → AuditHistoryPanel-B1lmI7wm.js} +1 -1
  2. package/assets/assets/{BacklinksPage-DWWMPSPn.js → BacklinksPage-Bw61uQu8.js} +1 -1
  3. package/assets/assets/{HistoryPage-m7TtGFBQ.js → HistoryPage-D8z9-NkT.js} +1 -1
  4. package/assets/assets/{MeasurementPropertyPage-CYBfBtEz.js → MeasurementPropertyPage-CXX9GFj8.js} +1 -1
  5. package/assets/assets/{ProjectPage-CNPcNrIR.js → ProjectPage-BaN_rvoV.js} +6 -6
  6. package/assets/assets/{RunRow-O4u505Fc.js → RunRow-DXHy16T3.js} +1 -1
  7. package/assets/assets/{RunsPage-CCzFT4X0.js → RunsPage-D2aE620i.js} +1 -1
  8. package/assets/assets/{SettingsPage-DOmE3JbU.js → SettingsPage-BiiFqarS.js} +1 -1
  9. package/assets/assets/{SiteHealthSection-BZFVE2h9.js → SiteHealthSection-DCH2Ejtc.js} +3 -3
  10. package/assets/assets/TrafficPage-DFHWgvkU.js +1 -0
  11. package/assets/assets/{TrafficSourceDetailPage-Qd5Zpx_8.js → TrafficSourceDetailPage-DxjyRL8Y.js} +1 -1
  12. package/assets/assets/{extract-error-message-B0bdIDVc.js → extract-error-message-BdXUZQW9.js} +1 -1
  13. package/assets/assets/{index-BD8hYPvq.css → index-BuEq5Rhg.css} +1 -1
  14. package/assets/assets/{index-HmdbSL4h.js → index-CSictO9U.js} +10 -10
  15. package/assets/assets/{react-sigma_core.esm.min-DXCrX1Ie.js → react-sigma_core.esm.min-DAcOZae7.js} +1 -1
  16. package/assets/index.html +2 -2
  17. package/dist/{chunk-JJIESVNL.js → chunk-CWXPBQR5.js} +1 -1
  18. package/dist/{chunk-UESVOQRS.js → chunk-RXXZ5BU5.js} +23 -2
  19. package/dist/{chunk-6LSP7ODK.js → chunk-VZO6CLHY.js} +4 -4
  20. package/dist/{chunk-EC2O3LHD.js → chunk-WJFBNCVD.js} +115 -41
  21. package/dist/{chunk-DK23XZ6C.js → chunk-XYTSKRO3.js} +2 -2
  22. package/dist/cli.js +14 -20
  23. package/dist/index.js +4 -4
  24. package/dist/{intelligence-service-NJUFIWAO.js → intelligence-service-MEPYXRBS.js} +2 -2
  25. package/dist/mcp.js +3 -3
  26. package/package.json +8 -8
  27. package/assets/assets/TrafficPage-DYxOEVbW.js +0 -1
package/dist/cli.js CHANGED
@@ -26,11 +26,11 @@ import {
26
26
  showFirstRunNotice,
27
27
  trackCliCommandFinished,
28
28
  trackEvent
29
- } from "./chunk-6LSP7ODK.js";
29
+ } from "./chunk-VZO6CLHY.js";
30
30
  import {
31
31
  autoSyncSkills,
32
32
  formatAutoSyncNotice
33
- } from "./chunk-DK23XZ6C.js";
33
+ } from "./chunk-XYTSKRO3.js";
34
34
  import {
35
35
  CliError,
36
36
  EXIT_SYSTEM_ERROR,
@@ -55,7 +55,7 @@ import {
55
55
  saveConfigPatch,
56
56
  systemError,
57
57
  usageError
58
- } from "./chunk-JJIESVNL.js";
58
+ } from "./chunk-CWXPBQR5.js";
59
59
  import {
60
60
  CLOUDFLARE_WORKER_BINDINGS,
61
61
  CLOUDFLARE_WORKER_GENERATED_MARKER,
@@ -69,7 +69,7 @@ import {
69
69
  projects,
70
70
  queries,
71
71
  renderReportHtml
72
- } from "./chunk-EC2O3LHD.js";
72
+ } from "./chunk-WJFBNCVD.js";
73
73
  import {
74
74
  AdsDeliverySnapshotStatuses,
75
75
  AdsHistoricalCampaignRollupStatuses,
@@ -138,7 +138,7 @@ import {
138
138
  providerQuotaPolicySchema,
139
139
  resolveProviderInput,
140
140
  winnabilityClassSchema
141
- } from "./chunk-UESVOQRS.js";
141
+ } from "./chunk-RXXZ5BU5.js";
142
142
 
143
143
  // src/cli.ts
144
144
  import { pathToFileURL } from "url";
@@ -4066,12 +4066,12 @@ async function gaTraffic(project, opts) {
4066
4066
  console.log(` Social Sessions: ${result.socialSessions} (${share}% of total)`);
4067
4067
  }
4068
4068
  console.log(" SOCIAL REFERRAL SOURCES");
4069
- console.log(` ${"SOURCE".padEnd(25)} ${"MEDIUM".padEnd(15)} ${"CHANNEL".padEnd(chanWidth)} ${"SESSIONS".padEnd(10)}${"USERS".padEnd(8)}`);
4070
- console.log(` ${"\u2500".repeat(25)} ${"\u2500".repeat(15)} ${"\u2500".repeat(chanWidth)} ${"\u2500".repeat(10)}${"\u2500".repeat(8)}`);
4069
+ console.log(` ${"SOURCE".padEnd(25)} ${"MEDIUM".padEnd(15)} ${"CHANNEL".padEnd(chanWidth)} ${"SESSIONS".padEnd(10)}`);
4070
+ console.log(` ${"\u2500".repeat(25)} ${"\u2500".repeat(15)} ${"\u2500".repeat(chanWidth)} ${"\u2500".repeat(10)}`);
4071
4071
  for (const ref of result.socialReferrals) {
4072
4072
  const chanLabel = ref.channelGroup === "Paid Social" ? "paid" : "organic";
4073
4073
  console.log(
4074
- ` ${ref.source.padEnd(25)} ${ref.medium.padEnd(15)} ${chanLabel.padEnd(chanWidth)} ${String(ref.sessions).padEnd(10)}${String(ref.users).padEnd(8)}`
4074
+ ` ${ref.source.padEnd(25)} ${ref.medium.padEnd(15)} ${chanLabel.padEnd(chanWidth)} ${String(ref.sessions).padEnd(10)}`
4075
4075
  );
4076
4076
  }
4077
4077
  console.log();
@@ -4079,12 +4079,12 @@ async function gaTraffic(project, opts) {
4079
4079
  if (result.topPages.length > 0) {
4080
4080
  const pageWidth = Math.min(60, Math.max(15, ...result.topPages.map((r) => r.landingPage.length)));
4081
4081
  console.log(` TOP LANDING PAGES`);
4082
- console.log(` ${"PAGE".padEnd(pageWidth)} ${"SESSIONS".padEnd(10)}${"ORGANIC".padEnd(10)}${"USERS".padEnd(8)}`);
4083
- console.log(` ${"\u2500".repeat(pageWidth)} ${"\u2500".repeat(10)}${"\u2500".repeat(10)}${"\u2500".repeat(8)}`);
4082
+ console.log(` ${"PAGE".padEnd(pageWidth)} ${"SESSIONS".padEnd(10)}${"ORGANIC".padEnd(10)}`);
4083
+ console.log(` ${"\u2500".repeat(pageWidth)} ${"\u2500".repeat(10)}${"\u2500".repeat(10)}`);
4084
4084
  for (const row of result.topPages) {
4085
4085
  const page = row.landingPage.length > pageWidth ? row.landingPage.slice(0, pageWidth - 3) + "..." : row.landingPage;
4086
4086
  console.log(
4087
- ` ${page.padEnd(pageWidth)} ${String(row.sessions).padEnd(10)}${String(row.organicSessions).padEnd(10)}${String(row.users).padEnd(8)}`
4087
+ ` ${page.padEnd(pageWidth)} ${String(row.sessions).padEnd(10)}${String(row.organicSessions).padEnd(10)}`
4088
4088
  );
4089
4089
  }
4090
4090
  }
@@ -4153,12 +4153,12 @@ async function gaAiReferralHistory(project, opts) {
4153
4153
  const attrWidth = 12;
4154
4154
  console.log(`GA4 AI Referral History for "${project}":
4155
4155
  `);
4156
- console.log(` ${"DATE".padEnd(dateWidth)} ${"SOURCE".padEnd(sourceWidth)} ${"ATTRIBUTION".padEnd(attrWidth)} ${"SESSIONS".padEnd(10)}${"USERS".padEnd(8)}`);
4157
- console.log(` ${"\u2500".repeat(dateWidth)} ${"\u2500".repeat(sourceWidth)} ${"\u2500".repeat(attrWidth)} ${"\u2500".repeat(10)}${"\u2500".repeat(8)}`);
4156
+ console.log(` ${"DATE".padEnd(dateWidth)} ${"SOURCE".padEnd(sourceWidth)} ${"ATTRIBUTION".padEnd(attrWidth)} ${"SESSIONS".padEnd(10)}`);
4157
+ console.log(` ${"\u2500".repeat(dateWidth)} ${"\u2500".repeat(sourceWidth)} ${"\u2500".repeat(attrWidth)} ${"\u2500".repeat(10)}`);
4158
4158
  for (const row of result) {
4159
4159
  const dimLabel = row.sourceDimension === "first_user" ? "first-visit" : row.sourceDimension === "manual_utm" ? "utm" : "session";
4160
4160
  console.log(
4161
- ` ${row.date.padEnd(dateWidth)} ${row.source.padEnd(sourceWidth)} ${dimLabel.padEnd(attrWidth)} ${String(row.sessions).padEnd(10)}${String(row.users).padEnd(8)}`
4161
+ ` ${row.date.padEnd(dateWidth)} ${row.source.padEnd(sourceWidth)} ${dimLabel.padEnd(attrWidth)} ${String(row.sessions).padEnd(10)}`
4162
4162
  );
4163
4163
  }
4164
4164
  }
@@ -4290,7 +4290,6 @@ async function gaSocialReferralSummary(project, opts) {
4290
4290
  if (isMachineFormat(opts.format)) {
4291
4291
  console.log(JSON.stringify({
4292
4292
  socialSessions: traffic.socialSessions,
4293
- socialUsers: traffic.socialUsers,
4294
4293
  totalSessions: traffic.totalSessions,
4295
4294
  socialSharePct: traffic.socialSharePct,
4296
4295
  windowStart: traffic.windowStart,
@@ -4307,7 +4306,6 @@ async function gaSocialReferralSummary(project, opts) {
4307
4306
  if (trendWindow) console.log(`${trendWindow}
4308
4307
  `);
4309
4308
  console.log(` Sessions: ${traffic.socialSessions} (${traffic.socialSharePct}% of ${traffic.totalSessions} total)`);
4310
- console.log(` Users: ${traffic.socialUsers}`);
4311
4309
  console.log();
4312
4310
  const fmtTrend = (pct4) => pct4 === null ? "n/a" : `${pct4 >= 0 ? "+" : ""}${pct4}%`;
4313
4311
  console.log(` 7d trend: ${fmtTrend(trend.trend7dPct)} (${trend.socialSessions7d} vs ${trend.socialSessionsPrev7d})`);
@@ -4329,7 +4327,6 @@ async function gaSocialReferralSummary(project, opts) {
4329
4327
  if (isMachineFormat(opts?.format)) {
4330
4328
  console.log(JSON.stringify({
4331
4329
  socialSessions: traffic.socialSessions,
4332
- socialUsers: traffic.socialUsers,
4333
4330
  totalSessions: traffic.totalSessions,
4334
4331
  socialSharePct: traffic.socialSharePct,
4335
4332
  windowStart: traffic.windowStart,
@@ -4345,7 +4342,6 @@ async function gaSocialReferralSummary(project, opts) {
4345
4342
  if (socialWindow) console.log(`${socialWindow}
4346
4343
  `);
4347
4344
  console.log(` Sessions: ${traffic.socialSessions} (${traffic.socialSharePct}% of ${traffic.totalSessions} total)`);
4348
- console.log(` Users: ${traffic.socialUsers}`);
4349
4345
  if (traffic.socialReferrals.length > 0) {
4350
4346
  console.log();
4351
4347
  console.log(" TOP SOURCES");
@@ -4373,7 +4369,6 @@ async function gaAttribution(project, opts) {
4373
4369
  paidAiSessionsBySession: traffic.paidAiSessionsBySession,
4374
4370
  organicAiSessionsBySession: traffic.organicAiSessionsBySession,
4375
4371
  socialSessions: traffic.socialSessions,
4376
- socialUsers: traffic.socialUsers,
4377
4372
  directSessions: traffic.totalDirectSessions,
4378
4373
  aiSharePct: traffic.aiSharePct,
4379
4374
  aiSharePctBySession: traffic.aiSharePctBySession,
@@ -4457,7 +4452,6 @@ async function gaAttribution(project, opts) {
4457
4452
  paidAiSessionsBySession: traffic.paidAiSessionsBySession,
4458
4453
  organicAiSessionsBySession: traffic.organicAiSessionsBySession,
4459
4454
  socialSessions: traffic.socialSessions,
4460
- socialUsers: traffic.socialUsers,
4461
4455
  directSessions: traffic.totalDirectSessions,
4462
4456
  aiSharePct: traffic.aiSharePct,
4463
4457
  aiSharePctBySession: traffic.aiSharePctBySession,
package/dist/index.js CHANGED
@@ -3,12 +3,12 @@ import {
3
3
  createGoogleMarketingCredentialStore,
4
4
  createGoogleMarketingRuntime,
5
5
  createServer
6
- } from "./chunk-6LSP7ODK.js";
6
+ } from "./chunk-VZO6CLHY.js";
7
7
  import {
8
8
  loadConfig
9
- } from "./chunk-JJIESVNL.js";
10
- import "./chunk-EC2O3LHD.js";
11
- import "./chunk-UESVOQRS.js";
9
+ } from "./chunk-CWXPBQR5.js";
10
+ import "./chunk-WJFBNCVD.js";
11
+ import "./chunk-RXXZ5BU5.js";
12
12
  export {
13
13
  GoogleMarketingRuntimeError,
14
14
  createGoogleMarketingCredentialStore,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-EC2O3LHD.js";
4
- import "./chunk-UESVOQRS.js";
3
+ } from "./chunk-WJFBNCVD.js";
4
+ import "./chunk-RXXZ5BU5.js";
5
5
  export {
6
6
  IntelligenceService
7
7
  };
package/dist/mcp.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  autoSyncSkills
3
- } from "./chunk-DK23XZ6C.js";
3
+ } from "./chunk-XYTSKRO3.js";
4
4
  import {
5
5
  createApiClient,
6
6
  createCanonryMcpServer
7
- } from "./chunk-JJIESVNL.js";
7
+ } from "./chunk-CWXPBQR5.js";
8
8
  import {
9
9
  isReadOnlyKey
10
- } from "./chunk-UESVOQRS.js";
10
+ } from "./chunk-RXXZ5BU5.js";
11
11
 
12
12
  // src/mcp/cli.ts
13
13
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ainyc/canonry",
3
- "version": "4.180.5",
3
+ "version": "4.180.7",
4
4
  "type": "module",
5
5
  "description": "Self-hosted AI visibility (AEO) platform: track how ChatGPT, Claude, Gemini, and Perplexity cite your domain, join it with Search Console, GA4, server-side traffic, and paid media, and fix what you find through agent tools (CLI, REST, MCP). Local SQLite.",
6
6
  "license": "FSL-1.1-ALv2",
@@ -71,27 +71,27 @@
71
71
  "tsup": "^8.5.1",
72
72
  "tsx": "^4.19.0",
73
73
  "@ainyc/canonry-api-client": "0.0.0",
74
- "@ainyc/canonry-api-routes": "0.0.0",
75
74
  "@ainyc/canonry-config": "0.0.0",
76
- "@ainyc/canonry-db": "0.0.0",
75
+ "@ainyc/canonry-api-routes": "0.0.0",
77
76
  "@ainyc/canonry-contracts": "0.0.0",
77
+ "@ainyc/canonry-db": "0.0.0",
78
78
  "@ainyc/canonry-integration-bing": "0.0.0",
79
79
  "@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
80
80
  "@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
81
81
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
82
82
  "@ainyc/canonry-integration-google": "0.0.0",
83
- "@ainyc/canonry-integration-google-ads": "0.0.0",
83
+ "@ainyc/canonry-integration-cloud-run": "0.0.0",
84
84
  "@ainyc/canonry-integration-google-business-profile": "0.0.0",
85
85
  "@ainyc/canonry-integration-google-places": "0.0.0",
86
- "@ainyc/canonry-integration-cloud-run": "0.0.0",
87
86
  "@ainyc/canonry-integration-google-tag-manager": "0.0.0",
87
+ "@ainyc/canonry-integration-google-ads": "0.0.0",
88
88
  "@ainyc/canonry-integration-openai-ads": "0.0.0",
89
- "@ainyc/canonry-integration-wordpress": "0.0.0",
90
89
  "@ainyc/canonry-integration-traffic": "0.0.0",
91
- "@ainyc/canonry-provider-cdp": "0.0.0",
92
- "@ainyc/canonry-provider-claude": "0.0.0",
93
90
  "@ainyc/canonry-intelligence": "0.0.0",
91
+ "@ainyc/canonry-provider-cdp": "0.0.0",
92
+ "@ainyc/canonry-integration-wordpress": "0.0.0",
94
93
  "@ainyc/canonry-provider-gemini": "0.0.0",
94
+ "@ainyc/canonry-provider-claude": "0.0.0",
95
95
  "@ainyc/canonry-provider-local": "0.0.0",
96
96
  "@ainyc/canonry-provider-openai": "0.0.0",
97
97
  "@ainyc/canonry-provider-perplexity": "0.0.0"
@@ -1 +0,0 @@
1
- import{r as c,j as e,h as V,u as B,f as L,L as E}from"./vendor-tanstack-Dock0eH1.js";import{cV as U,cW as O,cX as I,cY as F,cZ as A,B as C,l as W,c_ as $,bW as z,i as D,j as w,f as S,c$ as H,T as G}from"./index-HmdbSL4h.js";import{d as J,f as M,g as _,c as T,a as Q,t as K}from"./extract-error-message-B0bdIDVc.js";import{G as Y,w as X,x as Z,y as ee,p as q,A as te}from"./vendor-lucide-nYKv-BB7.js";import"./vendor-radix-4UOaVWza.js";import"./vendor-recharts-D8rt5lKn.js";import"./vendor-markdown-Bn7fRwrx.js";import"./vendor-yaml-GWJz5H2G.js";function re({open:t,onOpenChange:a,projectName:n}){const[r,s]=c.useState("pick");c.useEffect(()=>{t&&s("pick")},[t]);const o=()=>{a(!1),s("pick")};return e.jsx(U,{open:t,onOpenChange:i=>{i?a(!0):o()},children:e.jsx(O,{children:r==="pick"?e.jsx(ne,{onPick:s}):r==="wordpress"?e.jsx(ie,{projectName:n,onBack:()=>s("pick"),onClose:o}):r==="vercel"?e.jsx(ce,{projectName:n,onBack:()=>s("pick"),onClose:o}):e.jsx(le,{projectName:n,onBack:()=>s("pick"),onClose:o})})})}const se=[{type:"wordpress",name:"WordPress",action:"Install the traffic plugin",icon:Y},{type:"cloud-run",name:"Google Cloud Run",action:"Read request logs",icon:X},{type:"vercel",name:"Vercel",action:"Read request logs",icon:Z}];function ne({onPick:t}){return e.jsxs(e.Fragment,{children:[e.jsxs(I,{children:[e.jsx(F,{children:"Connect a traffic source"}),e.jsx(A,{children:"Choose where Canonry should read traffic logs."})]}),e.jsx("div",{className:"mt-6 flex flex-col gap-3",children:se.map(({type:a,name:n,action:r,icon:s})=>e.jsxs("button",{type:"button",onClick:()=>t(a),className:"group flex items-center gap-3 rounded-md border border-base bg-bg-elevated/30 px-3 py-3 text-left transition-colors hover:border-mono-600 hover:bg-bg-elevated/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-mono-400",children:[e.jsx("span",{className:"mt-0.5 inline-flex size-9 shrink-0 items-center justify-center rounded-md border border-base bg-bg text-neutral group-hover:text-heading",children:e.jsx(s,{className:"size-4"})}),e.jsxs("span",{className:"flex min-w-0 flex-1 items-baseline justify-between gap-3",children:[e.jsx("span",{className:"text-sm font-medium text-heading",children:n}),e.jsx("span",{className:"text-sm text-secondary",children:r})]})]},a))})]})}function oe({title:t,description:a,onBack:n}){return e.jsxs(I,{children:[e.jsxs("button",{type:"button",onClick:n,className:"mb-1 inline-flex w-fit items-center gap-1 rounded text-sm text-secondary transition-colors hover:text-strong focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-mono-400",children:[e.jsx(ee,{className:"size-3"}),"Choose a different source"]}),e.jsx(F,{children:t}),e.jsx(A,{children:a})]})}function ae(t,a){const n=V();return async(r,s)=>{s.startInitialBackfill&&await $(t,r),s.afterConnected?.(),a(),n({to:"/traffic/$projectName/$sourceId",params:{projectName:t,sourceId:r}})}}function k(t,a){const[n,r]=c.useState(null),s=ae(t,a);return{error:n,runConnect:async i=>{r(null);const d=i.validate();if(d){r(d);return}let u;try{u=await i.mutate()}catch(l){r(T(l));return}try{await s(u.id,{startInitialBackfill:i.startInitialBackfill??!0,afterConnected:i.onConnected})}catch(l){r(`Source connected, but starting the initial backfill failed: ${T(l)}`)}}}}function P({title:t,description:a,projectName:n,onBack:r,onClose:s,onSubmit:o,isPending:i,error:d,children:u}){return e.jsxs(e.Fragment,{children:[e.jsx(oe,{title:t,description:a,onBack:r}),e.jsxs("form",{onSubmit:W(async l=>{l.preventDefault(),await o()}),className:"mt-6 flex flex-col gap-5 overflow-y-auto pr-1",children:[e.jsx(p,{label:"Project",description:"Canonry project this source attaches to.",children:e.jsx("input",{type:"text",value:n,disabled:!0,className:"w-full rounded border border-strong bg-bg-elevated/50 px-2 py-1.5 text-sm text-neutral"})}),u,d?e.jsx("p",{className:"rounded-md border border-negative-800/50 bg-negative-950/30 px-3 py-2 text-xs text-negative-200",children:d}):null,e.jsxs("div",{className:"mt-2 flex items-center justify-end gap-2 border-t border-default pt-4",children:[e.jsx(C,{type:"button",variant:"ghost",size:"sm",onClick:s,children:"Close"}),e.jsx(C,{type:"submit",disabled:i,size:"sm",children:i?"Connecting…":"Connect"})]})]})]})}function ie({projectName:t,onBack:a,onClose:n}){const[r,s]=c.useState(""),[o,i]=c.useState(""),[d,u]=c.useState(""),[l,j]=c.useState(""),f=J(t||null),{error:g,runConnect:b}=k(t,n),y=()=>b({validate:()=>r.trim()?o.trim()?d.trim()?null:"Application Password is required.":"Username is required.":"WordPress site URL is required.",mutate:()=>f.mutateAsync({baseUrl:r.trim(),username:o.trim(),applicationPassword:d.trim(),displayName:l.trim()||void 0}),onConnected:()=>u("")});return e.jsxs(P,{title:"Connect a WordPress site",description:e.jsxs(e.Fragment,{children:["Pulls request events from the Canonry Traffic Logger plugin. The Application Password is stored in ",e.jsx("code",{children:"~/.canonry/config.yaml"})," on the server and never echoed back to the dashboard."]}),projectName:t,onBack:a,onClose:n,onSubmit:y,isPending:f.isPending,error:g,children:[e.jsx(p,{label:"WordPress site URL",description:"Base URL of the site running the Canonry Traffic Logger plugin.",required:!0,children:e.jsx("input",{type:"url",value:r,onChange:x=>s(x.target.value),required:!0,autoComplete:"url",placeholder:"https://example.com",className:"w-full rounded border border-strong bg-transparent px-2 py-1.5 text-sm text-strong placeholder-mono-600 focus:border-mono-500 focus:outline-none"})}),e.jsx(p,{label:"Username",description:"WordPress user that owns the Application Password.",required:!0,children:e.jsx("input",{type:"text",value:o,onChange:x=>i(x.target.value),required:!0,autoComplete:"username",className:"w-full rounded border border-strong bg-transparent px-2 py-1.5 text-sm text-strong placeholder-mono-600 focus:border-mono-500 focus:outline-none"})}),e.jsx(p,{label:"Application Password",description:"Create one in wp-admin under Users -> Profile -> Application Passwords.",required:!0,children:e.jsx("input",{type:"password",value:d,onChange:x=>u(x.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded border border-strong bg-transparent px-2 py-1.5 text-sm text-strong placeholder-mono-600 focus:border-mono-500 focus:outline-none"})}),e.jsx(p,{label:"Display name (optional)",description:"Friendly label shown in the dashboard. Defaults to the WordPress host.",children:e.jsx("input",{type:"text",value:l,onChange:x=>j(x.target.value),autoComplete:"off",className:"w-full rounded border border-strong bg-transparent px-2 py-1.5 text-sm text-strong placeholder-mono-600 focus:border-mono-500 focus:outline-none"})})]})}function le({projectName:t,onBack:a,onClose:n}){const[r,s]=c.useState(""),[o,i]=c.useState(""),[d,u]=c.useState(""),[l,j]=c.useState(""),[f,g]=c.useState(""),b=_(t||null),{error:y,runConnect:x}=k(t,n),N=()=>x({validate:()=>r.trim()?f.trim()?null:"Service-account JSON content is required.":"GCP project ID is required.",mutate:()=>b.mutateAsync({gcpProjectId:r.trim(),serviceName:o.trim()||void 0,location:d.trim()||void 0,displayName:l.trim()||void 0,keyJson:f.trim()}),onConnected:()=>g("")}),h=async m=>{if(!m)return;const R=await m.text();g(R)};return e.jsxs(P,{title:"Connect a Cloud Run service",description:e.jsxs(e.Fragment,{children:["v1 supports service-account JSON only. The private key is stored in"," ",e.jsx("code",{children:"~/.canonry/config.yaml"})," on the server and never echoed back to the dashboard."]}),projectName:t,onBack:a,onClose:n,onSubmit:N,isPending:b.isPending,error:y,children:[e.jsx(p,{label:"GCP project ID",description:"The Google Cloud project hosting the Cloud Run service (e.g. my-prod-foo).",required:!0,children:e.jsx("input",{type:"text",value:r,onChange:m=>s(m.target.value),required:!0,autoComplete:"off",className:"w-full rounded border border-strong bg-transparent px-2 py-1.5 text-sm text-strong placeholder-mono-600 focus:border-mono-500 focus:outline-none"})}),e.jsx(p,{label:"Service name (optional)",description:"Restrict log pulls to a specific Cloud Run service. Omit to pull all services in the project.",children:e.jsx("input",{type:"text",value:o,onChange:m=>i(m.target.value),autoComplete:"off",className:"w-full rounded border border-strong bg-transparent px-2 py-1.5 text-sm text-strong placeholder-mono-600 focus:border-mono-500 focus:outline-none"})}),e.jsx(p,{label:"Location (optional)",description:"Region of the Cloud Run service (e.g. us-central1). Helpful when multiple regions emit logs.",children:e.jsx("input",{type:"text",value:d,onChange:m=>u(m.target.value),autoComplete:"off",className:"w-full rounded border border-strong bg-transparent px-2 py-1.5 text-sm text-strong placeholder-mono-600 focus:border-mono-500 focus:outline-none"})}),e.jsx(p,{label:"Display name (optional)",description:"Friendly label shown in the dashboard. Defaults to the project + service combo.",children:e.jsx("input",{type:"text",value:l,onChange:m=>j(m.target.value),autoComplete:"off",className:"w-full rounded border border-strong bg-transparent px-2 py-1.5 text-sm text-strong placeholder-mono-600 focus:border-mono-500 focus:outline-none"})}),e.jsxs(p,{label:"Service-account JSON",description:"Paste the contents of the SA key (JSON). The SA needs roles/logging.viewer (or any role granting logging.logEntries.list).",required:!0,children:[e.jsx("textarea",{value:f,onChange:m=>g(m.target.value),rows:6,spellCheck:!1,autoComplete:"off",className:"w-full rounded border border-strong bg-transparent px-2 py-1.5 font-mono text-sm text-strong placeholder-mono-600 focus:border-mono-500 focus:outline-none",placeholder:'{"type":"service_account","project_id":"…","private_key":"…"}',required:!0}),e.jsxs("label",{className:"mt-2 inline-flex cursor-pointer items-center gap-2 text-sm text-secondary hover:text-strong",children:[e.jsx("input",{type:"file",accept:"application/json,.json",className:"hidden",onChange:m=>{h(m.target.files?.[0]??null)}}),e.jsx("span",{className:"rounded-md border border-base px-2 py-1",children:"Or upload a key file"})]})]})]})}function ce({projectName:t,onBack:a,onClose:n}){const[r,s]=c.useState(""),[o,i]=c.useState(""),[d,u]=c.useState(""),[l,j]=c.useState("production"),[f,g]=c.useState(""),b=M(t||null),{error:y,runConnect:x}=k(t,n),N=()=>x({validate:()=>r.trim()?o.trim()?d.trim()?null:"Vercel personal access token is required.":"Vercel team / account ID is required.":"Vercel project ID is required.",mutate:()=>b.mutateAsync({projectId:r.trim(),teamId:o.trim(),token:d.trim(),environment:l,displayName:f.trim()||void 0}),startInitialBackfill:!1,onConnected:()=>u("")});return e.jsxs(P,{title:"Connect a Vercel project",description:e.jsxs(e.Fragment,{children:["Pulls request logs straight from Vercel, no in-app instrumentation needed. The personal access token is stored in ",e.jsx("code",{children:"~/.canonry/config.yaml"})," on the server and never echoed back to the dashboard."]}),projectName:t,onBack:a,onClose:n,onSubmit:N,isPending:b.isPending,error:y,children:[e.jsx(p,{label:"Vercel project ID",description:"The prj_… id from the Vercel dashboard or .vercel/project.json.",required:!0,children:e.jsx("input",{type:"text",value:r,onChange:h=>s(h.target.value),required:!0,autoComplete:"off",placeholder:"prj_…",className:"w-full rounded border border-strong bg-transparent px-2 py-1.5 text-sm text-strong placeholder-mono-600 focus:border-mono-500 focus:outline-none"})}),e.jsx(p,{label:"Vercel team / account ID",description:"The Vercel team or personal account that owns the project. Find it as orgId in your .vercel/project.json.",required:!0,children:e.jsx("input",{type:"text",value:o,onChange:h=>i(h.target.value),required:!0,autoComplete:"off",className:"w-full rounded border border-strong bg-transparent px-2 py-1.5 text-sm text-strong placeholder-mono-600 focus:border-mono-500 focus:outline-none"})}),e.jsx(p,{label:"Personal access token",description:"Create a Vercel personal access token under Account Settings → Tokens. Tokens can expire, so use a long-lived one.",required:!0,children:e.jsx("input",{type:"password",value:d,onChange:h=>u(h.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded border border-strong bg-transparent px-2 py-1.5 text-sm text-strong placeholder-mono-600 focus:border-mono-500 focus:outline-none"})}),e.jsx(p,{label:"Environment",description:"Which deployment environment's request logs to pull.",children:e.jsxs("select",{value:l,onChange:h=>j(h.target.value),className:"w-full rounded border border-strong bg-transparent px-2 py-1.5 text-sm text-strong focus:border-mono-500 focus:outline-none",children:[e.jsx("option",{value:"production",children:"production"}),e.jsx("option",{value:"preview",children:"preview"})]})}),e.jsx(p,{label:"Display name (optional)",description:"Friendly label shown in the dashboard. Defaults to the Vercel project ID.",children:e.jsx("input",{type:"text",value:f,onChange:h=>g(h.target.value),autoComplete:"off",className:"w-full rounded border border-strong bg-transparent px-2 py-1.5 text-sm text-strong placeholder-mono-600 focus:border-mono-500 focus:outline-none"})})]})}function p({label:t,description:a,required:n,children:r}){return e.jsxs("label",{className:"flex flex-col gap-1",children:[e.jsxs("span",{className:"text-sm font-medium text-strong",children:[t,n?e.jsx("span",{className:"ml-1 text-negative-400",children:"*"}):null]}),r,e.jsx("span",{className:"text-[13px] leading-5 text-secondary",children:a})]})}function de(t){if(!t)return"never";const a=Date.now()-new Date(t).getTime(),n=Math.floor(a/6e4);if(n<1)return"just now";if(n<60)return`${n}m ago`;const r=Math.floor(n/60);return r<24?`${r}h ago`:`${Math.floor(r/24)}d ago`}function v(t){return t>=1e6?`${(t/1e6).toFixed(1)}M`:t>=1e3?`${(t/1e3).toFixed(1)}K`:t.toLocaleString()}function ye(){const[t,a]=c.useState(""),[n,r]=c.useState(!1),o=B(z({client:D})).data??[],i=c.useMemo(()=>t||(o[0]?.name??""),[t,o]),d=Q(i||null),u=d.data?.sources??[];return e.jsxs("div",{className:"page-container",children:[e.jsxs("div",{className:"page-header",children:[e.jsxs("div",{className:"page-header-left",children:[e.jsx("h1",{className:"page-title",children:"Traffic sources"}),e.jsx("p",{className:"page-subtitle",children:"AI crawler hits and referral sessions from your server logs."})]}),!w()&&e.jsx("div",{className:"flex flex-wrap items-center justify-end gap-2",children:e.jsxs(C,{type:"button",variant:"outline",size:"sm",onClick:()=>r(!0),disabled:!i,children:[e.jsx(q,{className:"size-3.5"}),"Connect a source"]})})]}),e.jsxs("section",{children:[o.length>1&&e.jsxs("label",{className:"mb-4 flex w-fit items-center gap-2 text-sm font-medium text-secondary",htmlFor:"traffic-project",children:["Project",e.jsx("select",{id:"traffic-project",className:"h-8 min-w-44 rounded-md border border-base bg-bg px-2 text-sm text-heading outline-none transition focus:border-mono-500 focus:ring-1 focus:ring-mono-500",value:i,onChange:l=>a(l.target.value),children:o.map(l=>e.jsx("option",{value:l.name,children:l.displayName??l.name},l.id))})]}),i?d.isLoading?e.jsx(S,{className:"p-6 text-center text-sm text-muted",children:"Loading sources…"}):u.length===0?e.jsxs(S,{className:"p-8 text-center",children:[e.jsxs("p",{className:"text-sm text-neutral",children:["No traffic sources connected for ",i,"."]}),!w()&&e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"mt-1 text-sm text-secondary",children:"Connect a source to start collecting traffic."}),e.jsx("div",{className:"mt-4 flex flex-wrap items-center justify-center gap-2",children:e.jsxs(C,{type:"button",variant:"outline",size:"sm",onClick:()=>r(!0),children:[e.jsx(q,{className:"size-3.5"}),"Connect a source"]})})]})]}):e.jsx(ue,{projectName:i,sources:u}):e.jsx(S,{className:"p-6 text-center text-sm text-muted",children:"No projects yet."})]}),!w()&&e.jsx(re,{open:n,onOpenChange:r,projectName:i})]})}function ue({projectName:t,sources:a}){const n=L({queries:a.map(s=>({...H({client:D,path:{name:t,id:s.id}}),staleTime:3e4}))}),r=a.map((s,o)=>({source:s,detail:n[o]?.data,isLoading:n[o]?.isLoading??!1}));return e.jsx("div",{className:"rounded-xl border border-default bg-surface overflow-hidden",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{className:"bg-bg-elevated/50 text-[10px] font-semibold uppercase tracking-wider text-muted",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-4 py-2 text-left",children:"Source"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"Status"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"Last sync"}),e.jsx("th",{className:"px-4 py-2 text-right",children:"Content crawls"}),e.jsx("th",{className:"px-4 py-2 text-right",children:"Infra crawls"}),e.jsx("th",{className:"px-4 py-2 text-right",children:"AI fetches"}),e.jsx("th",{className:"px-4 py-2 text-right",children:"AI referrals"}),e.jsx("th",{className:"px-4 py-2 text-right"})]})}),e.jsx("tbody",{className:"divide-y divide-mono-800/60",children:r.map(({source:s,detail:o,isLoading:i})=>e.jsxs("tr",{className:"hover:bg-bg-elevated/40 transition-colors",children:[e.jsx("td",{className:"px-4 py-3",children:e.jsx("div",{className:"font-medium text-heading",children:s.displayName})}),e.jsxs("td",{className:"px-4 py-3",children:[e.jsx(G,{tone:K(s.status),children:s.status}),s.lastError?e.jsx("p",{className:"mt-1 max-w-[18rem] truncate text-sm text-negative-400",title:s.lastError,children:s.lastError}):null]}),e.jsx("td",{className:"px-4 py-3 text-neutral",children:de(s.lastSyncedAt)}),e.jsx("td",{className:"px-4 py-3 text-right tabular-nums text-heading",title:o?`${o.totals24h.crawlerHits.toLocaleString("en-US")} total crawler hits`:void 0,children:i?"—":v(o?.totals24h.crawlerContentHits??0)}),e.jsx("td",{className:"px-4 py-3 text-right tabular-nums text-muted",children:i?"—":v(o?.totals24h.crawlerInfraHits??0)}),e.jsx("td",{className:"px-4 py-3 text-right tabular-nums text-heading",children:i?"—":v(o?.totals24h.aiUserFetchHits??0)}),e.jsx("td",{className:"px-4 py-3 text-right tabular-nums text-heading",children:i?"—":v(o?.totals24h.aiReferralLandedHits??0)}),e.jsx("td",{className:"px-4 py-3 text-right",children:e.jsxs(E,{to:"/traffic/$projectName/$sourceId",params:{projectName:t,sourceId:s.id},className:"inline-flex items-center gap-1 text-sm text-secondary hover:text-heading",children:["View",e.jsx(te,{className:"size-3.5"})]})})]},s.id))})]})})}export{ye as TrafficPage};