Lines 1-22javascript
2import { createRequire as __seoCreateRequire } from 'node:module'; const require = __seoCreateRequire(import.meta.url);
3import{$ as e,$t as t,A as n,At as r,B as i,Bt as a,C as o,Ct as s,D as c,Dt as l,E as u,Et as d,F as f,Ft as p,G as m,Gt as h,H as g,Ht as _,I as ee,It as te,J as ne,Jt as re,K as ie,Kt as ae,L as oe,Lt as se,M as
4`);return}process.stdout.write(`Deleted local OAuth tokens.
MediumInstall Persistence
Source writes installer persistence such as shell profile or service configuration.
dist/cli.jsView on unpkg · L2 5Revoke at https://myaccount.google.com/permissions if you also want Google to forget the grant.
6`)}}),whoami:S({meta:{name:`whoami`,description:`Show the signed-in Google account`},run:async()=>{let e=await Ne();if(e.activeMode===`service-account`){process.stdout.write(`service account · `+(e.identity??`invalid configuration`)+` · `+Qn(e.serviceAccount.source)+`
7`);return}let t=e.tokens;if(!t){process.stdout.write(`Not logged in.
8`);return}process.stdout.write(`${t.account_email} · ${t.scope.replace(`https://www.googleapis.com/auth/`,``)} · ${Vn(t.expires_at)} · ${t.client_source===`shared`?`shared seo app`:`BYO client`}\n`)}}),status:S({meta:{name:`status`,description:`Show local Google auth status`},args:{json:{type:`boolean`,default:!1,description:`Print machine-readable JSON.`}},run:async({args:e})=>{let n=await Ne(),r=n.activeMode===`oauth`?await t():void 0;if(N(e)){F({authenticated:n.activeMode===`oauth`?!!n.tokens:n.serviceAccount.configured,mode:n.activeMode,identity:n.identity,account:n.activeMode===`oauth`?n. ...
9`);return}let e=await je();process.stdout.write(`Refreshed. New expiry ${new Date(e.expires_at).toISOString()}.\n`)}}),"setup-client":S({meta:{name:`setup-client`,description:`Save your own Google Desktop OAuth client`},args:{json:{type:`boolean`,default:!1,description:`Return a structured error instead of prompting.`}},run:async({args:e})=>{if(!P({json:N(e)}))throw new v(`INVALID_INPUT`,"`seo auth setup-client` needs an interactive terminal. Run it without --json, or set SEO_GOOGLE_CLIENT_ID and SEO_GOOGLE_CLIENT_SECRET.");bn(`seo BYO OAuth client`),C([`This is the advanced path.`,`Most users ...
10`),`Advanced`),xt({clientId:R(await Tn({message:`Google Desktop OAuth client ID`,validate:e=>e?void 0:`Client ID is required`})),clientSecret:R(await Cn({message:`Google Desktop OAuth client secret`,validate:e=>e?void 0:`Client secret is required`}))}),Sn(`Saved BYO OAuth client to ${ze().oauthClientFile}`)}})}}),tr=S({meta:{name:`cache`,description:`Cache helpers`},subCommands:{stats:S({meta:{name:`stats`,description:`Show local cache size and row counts`},run:async()=>{let e=yt();I([[`DB`,e.dbPath],[`Size`,Zn(e.sizeBytes)],[`sites`,String(e.counts.sites??0)],[`gsc_cache`,String(e.counts.gsc_ ...
11`};function _r(){return new Date().toISOString().replace(/[:.]/g,`-`)}function vr(e,t){Ht(b(e),{recursive:!0,mode:448});let n=`${e}.${process.pid}.${Date.now()}.tmp`;Yt(n,t,{encoding:`utf8`,mode:y(e)?Jt(e).mode&511:384}),Kt(n,e)}function yr(e){let t=`${e}.bak-${_r()}`,n=t,r=2;for(;y(n);)n=`${t}-${r}`,r+=1;Vt(e,n,Bt.COPYFILE_EXCL)}function br(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function xr(e){if(!y(e.path))return{source:`{}
12`,config:{}};let t=Ut(e.path,`utf8`),n=[],r=jn(t,n,{allowTrailingComma:!0});if(n.length>0){let t=n[0],r=t?`${Mn(t.error)} at offset ${t.offset}`:`unknown parse error`;throw Error(`Cannot update ${e.path}: invalid JSONC (${r}).`)}if(!br(r))throw Error(`Cannot update ${e.path}: config root must be an object.`);if(r.mcpServers!==void 0&&!br(r.mcpServers))throw Error(`Cannot update ${e.path}: mcpServers must be an object.`);return{source:t,config:r}}function Sr(e){return e.includes(`mcp`)&&e.includes(`serve`)&&e.some(e=>e===`seo`||e.startsWith(`seo@`)||e===`@seo/cli`)}function Cr(e,t){return typeo ...
13`)}function Ur(e,t,n){if(n)return;let r=Xe().filter(t=>t.siteUrl===e);return r.length===1?r[0]:r.find(e=>e.isDefault)??r.find(e=>e.name.toLocaleLowerCase()===t.toLocaleLowerCase())}async function Wr(e){let t=N(e);if(t||bn(process.argv[2]===`start`?`seo start`:`seo setup`),e[`dry-run`]){let e=[`seo auth login`,`seo start`,`seo report --project acme`,`seo refresh-priorities --project acme --verify-content`,`seo technical-watch --project acme`];t?F({dryRun:!0,next:e}):(C(e.join(`
14`),`This setup will guide you through`),Sn(`Dry run complete.`));return}rt();let n={site:E(e.site),options:{json:t,refresh:O(e.refresh)}},r=t?await z(n):void 0,i=await Lr(e),a=r??await z(n),o=sr(a);if(P({json:t})&&C(`A project profile remembers the site and report defaults so future commands stay short.`,`Project profile`),!(O(e[`skip-profile`])!==!0&&(!P({json:t})||R(await yn({message:`Save this site as a project profile?`,initialValue:!0}))))){let n=await zr(e),r=`--site ${Br(a)}`,o=[`seo report ${r}`,`seo refresh-priorities ${r} --verify-content`,`seo technical-watch ${r}`],s={site:a,auth:i ...
15`),`Try next`),Sn(`Setup complete.`);return}let s=E(e.name)??(P({json:t})?R(await Tn({message:`Project name`,placeholder:o,defaultValue:o})):o),c=E(e.id),l=c??Ur(a,s,c)?.id??cr(s),u=V(a)??``,d=E(e.url)??(P({json:t})?R(await Tn({message:`Website URL to crawl`,placeholder:u||`https://example.com`,defaultValue:u})):u||void 0),f=M(e.urls).length>0?M(e.urls):[],p=await Rr({property:E(e.ga4),site:a,interactive:P({json:t})}),m=p?.propertyId,h=he({id:l,name:s,siteUrl:a}),g=gt({id:l,name:s,siteUrl:a,startUrl:d,watchUrls:f,brandTerms:M(e.brand).length>0?M(e.brand):h,ga4PropertyId:m,reportDay:k(e[`report ...
16`),`Try next`),Sn(`Setup complete.`)}const Gr=S({meta:{name:`setup`,description:`Guided setup for auth, one project profile, MCP, and next commands`},args:{id:{type:`string`,description:`Short stable project id.`},name:{type:`string`,description:`Human project name.`},site:{type:`string`,description:`GSC property URL, for example sc-domain:example.com.`},url:{type:`string`,description:`Default technical crawl start URL.`},urls:{type:`string`,description:`Comma-separated URLs to watch with URL Inspection.`},ga4:{type:`string`,description:`Optional GA4 property ID.`},brand:{type:`string`,descrip ...
18`),K([`Heading`,`Queries`],r.brief.sections.map(e=>[G(e.heading,48),G(e.queries.join(`, `),80)]))),r.intentMix.length&&(process.stdout.write(`
20`),K([`Intent`,`Queries`,`Impressions`,`Clicks`],r.intentMix.map(e=>[e.intent,H(e.queries),H(e.impressions),H(e.clicks)]))),J(`Caveats`,r.caveats)}})}}),ai={high:3,medium:2,low:1},oi=S({meta:{name:`crawl`,description:`Crawl a site and run technical SEO checks`},args:{crawlUrl:{type:`positional`,required:!1,description:`Start URL to crawl.`},url:{type:`string`,description:`Start URL to crawl. Optional when --project has a saved crawl URL.`},site:{type:`string`,description:`GSC property URL for joining page metrics.`},client:{type:`string`,description:`Legacy alias for --project.`},project:{type ...
22`),I([[`Saved report`,m?.id??`no`],[`Fail threshold`,o??`off`]])),(_||g)&&(process.exitCode=1)}});function si(e){let t=E(e);if(t){if([`site`,`page`,`list`,`sitemap`].includes(t))return t;throw Error(`Mode must be one of: site, page, list, sitemap.`)}}function ci(e){let t=E(e);if(t){if([`low`,`medium`,`high`].includes(t))return t;throw Error(`Severity must be one of: low, medium, high.`)}}function li(e){let t=E(e.crawlUrl),n=E(e.url);if(t&&n&&t!==n)throw Error(`Use either a URL argument or --url, not both.`);return t??n}function ui(e,t){let n=E(e);if(t&&n&&n!==`json`)throw Error(`Use either --j ...
Long lines were clipped for display.