@sleekcms/sync 2.11.0 → 2.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -135,6 +135,8 @@ The CLI runs a local watcher after the initial fetch. Every time you save a file
135
135
 
136
136
  On first run, the CLI pulls the full site state from the server. After that, a local `.cache/` folder tracks server-known state so only real diffs are pushed — no redundant API calls.
137
137
 
138
+ Renames sync too. Rename or move a page's, entry's, or block's model, view, or content file (in your editor, with `mv`, or `git mv`) and SleekCMS renames it: its other files are moved to match and a page's URL follows (`models/pages/about.model` → `about-us.model` moves `/about` to `/about-us`). Rename a collection by its model file (`models/pages/blog+.model` → `news+.model`) and its records folder follows; renaming a record's content file changes its URL. Links typed into templates or copy keep the old URL, and the sync log lists them.
139
+
138
140
  ```
139
141
  Your editor → file save → watcher → SleekCMS API → rebuild → live site
140
142
  ```
package/dist/AGENT.md CHANGED
@@ -72,6 +72,8 @@ Never guess at why something isn't rendering — read `sync-errors.log` first, t
72
72
 
73
73
  For collection pages, the `<slug>` is the content file's name: `content/pages/blog+/my-post.json` → `/blog/my-post`. Renaming the file renames the URL.
74
74
 
75
+ **Renaming.** Rename a page, entry, or block by `mv`-ing only its model file — a collection too (`blog+.model`, not its folder). The sync renames it on the server and moves its view, content, and records to match: `models/pages/about.model` → `about-us.model` moves `/about` to `/about-us`. A collection record is the exception: its content file name is its slug, so to change one record's URL, rename that file within its folder — `content/pages/blog+/old-post.json` → `new-post.json` moves just that record from `/blog/old-post` to `/blog/new-post`. Keep slugs lowercase and dash-separated, and keep the file in its collection's folder. The kind and `+` can't change. Update hard-coded links and `getEntry()` calls that use the old name.
76
+
75
77
  ## 4. Folder Structure (under `src/`)
76
78
 
77
79
  ```
@@ -436,7 +438,7 @@ Callable from **any** view (page, block, entry, layout); duplicates are removed
436
438
  | `style(css, order?)` | Add `<style>` |
437
439
  | `script(value, order?)` | Add `<script>` — `.js` URL → external, otherwise inline |
438
440
 
439
- `script()`/`link()` also accept a predefined library name — `gsap` (includes ScrollTrigger, pre-registered), `aos` (auto-`AOS.init()`, JS+CSS), `alpinejs`, `swiper`, `animejs`, `chartjs`, `threejs` (import map — pair with a `type: 'module'` script), `lottie`, `typedjs`, `splide`, `htmx`, `vanilla-tilt` — either call injects all of the library's CDN assets, deduped. Prefer these names over hand-picked CDN URLs, and only add a library the site actually uses.
441
+ `script()`/`link()` also accept a predefined library name — `gsap` (includes ScrollTrigger, pre-registered), `aos` (auto-`AOS.init()`, JS+CSS), `swiper`, `animejs`, `chartjs`, `threejs` (import map — pair with a `type: 'module'` script), `lottie`, `typedjs`, `splide`, `htmx`, `vanilla-tilt` — either call injects all of the library's CDN assets, deduped. Prefer these names over hand-picked CDN URLs, and only add a library the site actually uses.
440
442
 
441
443
  `script()` also takes an attributes object — `script({ src: '/js/app.js', defer: '' })`, `script({ content: '...', type: 'module' })` — so a tag that needs attributes still never needs a raw `<script>`. That is how a third-party script is put behind cookie consent: `script({ src: 'https://…', 'data-sleekcms-consent': 'marketing' })` (§14).
442
444
 
package/dist/index.js CHANGED
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import{readFileSync as Le}from"node:fs";import{fileURLToPath as zn}from"node:url";import{createRequire as Yn}from"node:module";import It from"node:path";import{render as Vn}from"ink";import{execSync as Zt,spawn as P}from"child_process";import{program as Yt,Option as kt}from"commander";function te(){return Yt.name("cms-sync").description("SleekCMS CLI tool to sync and edit CMS templates locally. Log in once, then add the sites you want to sync \u2014 changes are watched and pushed automatically.").addOption(new kt("-v, --version","output the version number").hideHelp()).addOption(new kt("-e, --env <env>","Environment (localhost, development, production)").default("production").hideHelp()).addOption(new kt("-d, --dev <secret>","Dev secret for non-production envs (sent as the _dev cookie; enables OTP-in-response). Falls back to SLEEKCMS_DEV_SECRET.").hideHelp()).option("-p, --path <path>","Directory path for files (default: ~/SleekCMS)").addHelpText("after",`
2
+ import{readFileSync as Ne}from"node:fs";import{fileURLToPath as ar}from"node:url";import{createRequire as cr}from"node:module";import Ut from"node:path";import{render as lr}from"ink";import{execSync as ne,spawn as M}from"child_process";import{program as Zt,Option as Ct}from"commander";function re(){return Zt.name("cms-sync").description("SleekCMS CLI tool to sync and edit CMS templates locally. Log in once, then add the sites you want to sync \u2014 changes are watched and pushed automatically.").addOption(new Ct("-v, --version","output the version number").hideHelp()).addOption(new Ct("-e, --env <env>","Environment (localhost, development, production)").default("production").hideHelp()).addOption(new Ct("-d, --dev <secret>","Dev secret for non-production envs (sent as the _dev cookie; enables OTP-in-response). Falls back to SLEEKCMS_DEV_SECRET.").hideHelp()).option("-p, --path <path>","Directory path for files (default: ~/SleekCMS)").addHelpText("after",`
3
3
  Examples:
4
4
  $ sleekcms # log in and pick sites to sync
5
5
  $ sleekcms -e development # use a non-production backend
6
- `).parse(process.argv),Yt.opts()}function D(t){let e=process.platform==="win32"?`where ${t}`:`which ${t}`;try{return Zt(e,{stdio:"ignore"}),!0}catch{return!1}}function ee(t){if(process.platform!=="darwin")return!1;try{return Zt(`osascript -e 'id of application "${t}"'`,{stdio:"ignore"}),!0}catch{return!1}}function Qe(t,e){let n={detached:!0,stdio:"ignore",windowsHide:!0};process.platform==="win32"?P("cmd.exe",["/c",t,...e],n).unref():P(t,e,n).unref()}var Vt=[{name:"VS Code",cmd:"code",args:t=>["-n",t]},{name:"Cursor",cmd:"cursor",args:t=>["-n",t]}];function Qt(t,e){let r=(e?Vt.filter(s=>s.cmd===e):Vt).find(s=>D(s.cmd));return r?(Qe(r.cmd,r.args(t)),r.name):null}function Ze(t){if(process.platform==="darwin")return P("open",["-a","Terminal",t],{detached:!0,stdio:"ignore"}).unref(),!0;if(process.platform==="win32"){if(D("wt"))P("wt.exe",["-d",t],{detached:!0,stdio:"ignore"}).unref();else{let e=D("powershell")?"powershell.exe":"cmd.exe";P("cmd.exe",["/c","start","",e],{cwd:t,detached:!0,stdio:"ignore"}).unref()}return!0}return!1}function tn(t){return ee("iTerm")?(P("open",["-a","iTerm",t],{detached:!0,stdio:"ignore"}).unref(),!0):!1}function en(t){return`'${t.replace(/'/g,"'\\''")}'`}var nn=[{cmd:"x-terminal-emulator",args:t=>["-e","bash","-c",t]},{cmd:"gnome-terminal",args:t=>["--","bash","-c",t]},{cmd:"konsole",args:t=>["-e","bash","-c",t]},{cmd:"xfce4-terminal",args:t=>["-x","bash","-c",t]},{cmd:"kitty",args:t=>["bash","-c",t]},{cmd:"alacritty",args:t=>["-e","bash","-c",t]},{cmd:"xterm",args:t=>["-e","bash","-c",t]}];function ne(t,e){if(!D(e))return!1;if(process.platform==="darwin"){let r=`tell application "Terminal" to do script ("cd " & quoted form of "${t}" & " && ${e}")`;return P("osascript",["-e",r,"-e",'tell application "Terminal" to activate'],{detached:!0,stdio:"ignore"}).unref(),!0}if(process.platform==="win32")return D("wt")?P("wt.exe",["-d",t,"cmd","/k",e],{detached:!0,stdio:"ignore"}).unref():P("cmd.exe",["/c","start","","cmd","/k",e],{cwd:t,detached:!0,stdio:"ignore"}).unref(),!0;let n=`cd ${en(t)} && ${e}; exec bash`;for(let r of nn)if(D(r.cmd))try{return P(r.cmd,r.args(n),{cwd:t,detached:!0,stdio:"ignore"}).unref(),!0}catch{}return!1}function rn(t){return ne(t,"claude")}function sn(t){return ne(t,"pi")}function re(t){if(!t)return!1;try{return process.platform==="darwin"?P("open",[t],{detached:!0,stdio:"ignore"}).unref():process.platform==="win32"?P("cmd.exe",["/c","start","",t],{detached:!0,stdio:"ignore",windowsHide:!0}).unref():P("xdg-open",[t],{detached:!0,stdio:"ignore"}).unref(),!0}catch{return!1}}function se(){let t=process.platform==="darwin",e=process.platform==="win32",n=[];return(t||e)&&n.push({key:"terminal",label:"terminal",run:Ze}),ee("iTerm")&&n.push({key:"iterm",label:"iterm",run:tn}),D("code")&&n.push({key:"code",label:"vscode",run:r=>Qt(r,"code")!==null}),D("cursor")&&n.push({key:"cursor",label:"cursor",run:r=>Qt(r,"cursor")!==null}),D("claude")&&n.push({key:"claude",label:"claude",run:rn}),D("pi")&&n.push({key:"pi",label:"pi",run:sn}),n}import{EventEmitter as Mn}from"node:events";import{spawn as On}from"node:child_process";import Q from"fs-extra";import At from"path";import Dn from"chokidar";import m from"fs-extra";import an from"os";import S from"path";var ie={localhost:"http://app.sleekcms.test/api/mcp",development:"https://app.sleekcms.dev/api/mcp",production:"https://app.sleekcms.com/api/mcp"},cn=["src/views/blocks","src/views/entries","src/views/pages","src/views/layouts","src/models/blocks","src/models/entries","src/models/pages","src/content/pages","src/content/entries","src/public/js","src/public/css"],Bt=class extends Error{status;body;constructor(e,n,r){super(e),this.status=n,this.body=r}};async function Ct(t,e,n,r,s){let o=await fetch(t+r,{method:n,headers:{Authorization:`Bearer ${e}`,...s!==void 0?{"Content-Type":"application/json"}:{}},body:s!==void 0?JSON.stringify(s):void 0});if(!o.ok){let c=await o.text();throw new Bt(`${n} ${r} \u2192 ${o.status}: ${c}`,o.status,c)}return o.json()}async function ln(t,e){e&&(await m.outputFile(S.join(t,"AGENT.md"),e),await m.outputFile(S.join(t,"CLAUDE.md"),e),await m.outputFile(S.join(t,".vscode","copilot-instructions.md"),e)),await m.outputFile(S.join(t,".vscode","settings.json"),JSON.stringify({"files.associations":{"*.model":"javascript"},"[javascript]":{"editor.defaultFormatter":"esbenp.prettier-vscode"},"js/ts.validate.enabled":!1},null,2))}async function un(t,e){if(!e)return;let n=S.join(t,"build.mjs"),r=e.match(/build\.mjs v\d+/)?.[0];if(await m.pathExists(n)){let s=(await m.readFile(n,"utf-8")).match(/build\.mjs v\d+/)?.[0];if(s&&s===r)return}await m.outputFile(n,e)}async function dn(t,e,n){let r=S.join(t,".cache","token");if(await m.pathExists(r)){if((await m.readFile(r,"utf-8")).trim()===e)return;n?.("\u267B\uFE0F Workspace was tied to a different site \u2014 recreating it."),await m.emptyDir(t)}await m.outputFile(r,e)}function gn(t,e){let n=`${e.name.substr(0,20)} ${e.id}`.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,""),r=t||S.join(an.homedir(),"SleekCMS");return S.resolve(r,n)}async function Pt(t){let e=(t.token||"").trim();if(!e)throw new Error("syncSite: token is required");let n=t.log??(v=>console.log(v)),r=t.onProgress,s=(t.env||e.split("-")[2]||"production").toLowerCase(),o=ie[s]||ie.production,c=await Ct(o,e,"GET","/get_site"),h=t.viewsDir?S.resolve(t.viewsDir):gn(t.path,c);await m.ensureDir(h),await dn(h,e,n),await Promise.all(cn.map(v=>m.ensureDir(S.join(h,v)))),await un(h,t.buildScript);let p=S.join(h,".cache","state.json");t.flush&&await m.remove(p);let x=!await m.pathExists(p),w=x?{}:(await m.readJson(p)).fileMap||{},f=0,b=0;return x?({fileMap:w,pulled:b}=await Sn(h,o,e,n,r),await ln(h,t.agentMd)):f=await fn(h,w,o,e,n,r),await m.outputJson(p,{fileMap:w},{spaces:2}),{viewsDir:h,site:c,isFirstRun:x,pushed:f,pulled:b}}var hn=new Set([".DS_Store","Thumbs.db","desktop.ini"]);async function pn(t){let e=S.join(t,"src");if(!await m.pathExists(e))return[];let n=[];async function r(s){let o=await m.readdir(s,{withFileTypes:!0});for(let c of o){if(hn.has(c.name))continue;let h=S.join(s,c.name);c.isDirectory()?await r(h):c.isFile()&&n.push(S.relative(t,h).replace(/\\/g,"/"))}}return await r(e),n}async function fn(t,e,n,r,s,o){let c=[];for(let f of await pn(t)){let b=S.join(t,f),v=e[f],O=await m.stat(b);if(v&&v.mtimeMs===O.mtimeMs)continue;let R=await m.readFile(b,"utf-8");R.trim()&&c.push({rel:f,full:b,stat:O,content:R,prior:v})}if(c.length===0)return 0;let h;try{h=await Ct(n,r,"POST","/save_files",c.map(f=>({path:f.rel,content:f.content})))}catch(f){let b=f;return s(`\u274C Error saving files: ${b.body||b.message}`),0}let p=await wn(t),x=0,w=mn(h);for(let f=0;f<c.length;f++){let b=c[f],v=yn(b,f,h,w);if(o?.(f+1,c.length),!v){let O="No save response returned";p[b.rel]=O,s(`\u274C Error saving ${b.rel}: ${O}`);continue}if(v.error){p[b.rel]=v.error,s(`\u274C Error saving ${b.rel}: ${v.error}`);continue}delete p[b.rel],e[b.rel]={mtimeMs:b.stat.mtimeMs},s(`\u2705 ${b.prior?"Updated":"Created"} ${b.rel}`),x++}return await xn(t,p),x}function mn(t){let e=new Map;for(let n of t)n.path&&e.set(n.path,n);return e}function yn(t,e,n,r){let s=r.get(t.rel);if(s)return s;let o=n[e];if(!o?.path||o.path===t.rel)return o}var $t="sync-errors.log",Et=new Map;async function wn(t){let e=S.resolve(t),n=Et.get(e);if(n)return n;let r=await bn(e);return Et.set(e,r),r}async function bn(t){let e=S.join(t,$t);if(!await m.pathExists(e))return{};let n=await m.readFile(e,"utf-8"),r={};for(let s of n.split(`
7
- `)){let o=s.indexOf(": ");o>0&&(r[s.slice(0,o)]=s.slice(o+2))}return r}async function xn(t,e){let n=S.join(t,$t),r=Object.entries(e);if(r.length===0){await m.remove(n);return}await m.outputFile(n,r.map(([s,o])=>`${s}: ${o}`).join(`
6
+ `).parse(process.argv),Zt.opts()}function j(t){let e=process.platform==="win32"?`where ${t}`:`which ${t}`;try{return ne(e,{stdio:"ignore"}),!0}catch{return!1}}function se(t){if(process.platform!=="darwin")return!1;try{return ne(`osascript -e 'id of application "${t}"'`,{stdio:"ignore"}),!0}catch{return!1}}function sn(t,e){let n={detached:!0,stdio:"ignore",windowsHide:!0};process.platform==="win32"?M("cmd.exe",["/c",t,...e],n).unref():M(t,e,n).unref()}var te=[{name:"VS Code",cmd:"code",args:t=>["-n",t]},{name:"Cursor",cmd:"cursor",args:t=>["-n",t]}];function ee(t,e){let r=(e?te.filter(s=>s.cmd===e):te).find(s=>j(s.cmd));return r?(sn(r.cmd,r.args(t)),r.name):null}function on(t){if(process.platform==="darwin")return M("open",["-a","Terminal",t],{detached:!0,stdio:"ignore"}).unref(),!0;if(process.platform==="win32"){if(j("wt"))M("wt.exe",["-d",t],{detached:!0,stdio:"ignore"}).unref();else{let e=j("powershell")?"powershell.exe":"cmd.exe";M("cmd.exe",["/c","start","",e],{cwd:t,detached:!0,stdio:"ignore"}).unref()}return!0}return!1}function an(t){return se("iTerm")?(M("open",["-a","iTerm",t],{detached:!0,stdio:"ignore"}).unref(),!0):!1}function cn(t){return`'${t.replace(/'/g,"'\\''")}'`}var ln=[{cmd:"x-terminal-emulator",args:t=>["-e","bash","-c",t]},{cmd:"gnome-terminal",args:t=>["--","bash","-c",t]},{cmd:"konsole",args:t=>["-e","bash","-c",t]},{cmd:"xfce4-terminal",args:t=>["-x","bash","-c",t]},{cmd:"kitty",args:t=>["bash","-c",t]},{cmd:"alacritty",args:t=>["-e","bash","-c",t]},{cmd:"xterm",args:t=>["-e","bash","-c",t]}];function ie(t,e){if(!j(e))return!1;if(process.platform==="darwin"){let r=`tell application "Terminal" to do script ("cd " & quoted form of "${t}" & " && ${e}")`;return M("osascript",["-e",r,"-e",'tell application "Terminal" to activate'],{detached:!0,stdio:"ignore"}).unref(),!0}if(process.platform==="win32")return j("wt")?M("wt.exe",["-d",t,"cmd","/k",e],{detached:!0,stdio:"ignore"}).unref():M("cmd.exe",["/c","start","","cmd","/k",e],{cwd:t,detached:!0,stdio:"ignore"}).unref(),!0;let n=`cd ${cn(t)} && ${e}; exec bash`;for(let r of ln)if(j(r.cmd))try{return M(r.cmd,r.args(n),{cwd:t,detached:!0,stdio:"ignore"}).unref(),!0}catch{}return!1}function un(t){return ie(t,"claude")}function dn(t){return ie(t,"pi")}function oe(t){if(!t)return!1;try{return process.platform==="darwin"?M("open",[t],{detached:!0,stdio:"ignore"}).unref():process.platform==="win32"?M("cmd.exe",["/c","start","",t],{detached:!0,stdio:"ignore",windowsHide:!0}).unref():M("xdg-open",[t],{detached:!0,stdio:"ignore"}).unref(),!0}catch{return!1}}function ae(){let t=process.platform==="darwin",e=process.platform==="win32",n=[];return(t||e)&&n.push({key:"terminal",label:"terminal",run:on}),se("iTerm")&&n.push({key:"iterm",label:"iterm",run:an}),j("code")&&n.push({key:"code",label:"vscode",run:r=>ee(r,"code")!==null}),j("cursor")&&n.push({key:"cursor",label:"cursor",run:r=>ee(r,"cursor")!==null}),j("claude")&&n.push({key:"claude",label:"claude",run:un}),j("pi")&&n.push({key:"pi",label:"pi",run:dn}),n}import{EventEmitter as Gn}from"node:events";import{spawn as Un}from"node:child_process";import nt from"fs-extra";import It from"path";import qn from"chokidar";import{createHash as mn}from"crypto";import y from"fs-extra";import hn from"os";import v from"path";var ce={localhost:"http://app.sleekcms.test/api/mcp",development:"https://app.sleekcms.dev/api/mcp",production:"https://app.sleekcms.com/api/mcp"},fn=["src/views/blocks","src/views/entries","src/views/pages","src/views/layouts","src/models/blocks","src/models/entries","src/models/pages","src/content/pages","src/content/entries","src/public/js","src/public/css"],Pt=class extends Error{status;body;constructor(e,n,r){super(e),this.status=n,this.body=r}};async function ft(t,e,n,r,s){let i=await fetch(t+r,{method:n,headers:{Authorization:`Bearer ${e}`,...s!==void 0?{"Content-Type":"application/json"}:{}},body:s!==void 0?JSON.stringify(s):void 0});if(!i.ok){let a=await i.text();throw new Pt(`${n} ${r} \u2192 ${i.status}: ${a}`,i.status,a)}return i.json()}async function pn(t,e){e&&(await y.outputFile(v.join(t,"AGENT.md"),e),await y.outputFile(v.join(t,"CLAUDE.md"),e),await y.outputFile(v.join(t,".vscode","copilot-instructions.md"),e)),await y.outputFile(v.join(t,".vscode","settings.json"),JSON.stringify({"files.associations":{"*.model":"javascript"},"[javascript]":{"editor.defaultFormatter":"esbenp.prettier-vscode"},"js/ts.validate.enabled":!1},null,2))}async function yn(t,e){if(!e)return;let n=v.join(t,"build.mjs"),r=e.match(/build\.mjs v\d+/)?.[0];if(await y.pathExists(n)){let s=(await y.readFile(n,"utf-8")).match(/build\.mjs v\d+/)?.[0];if(s&&s===r)return}await y.outputFile(n,e)}async function wn(t,e,n){let r=v.join(t,".cache","token");if(await y.pathExists(r)){if((await y.readFile(r,"utf-8")).trim()===e)return;n?.("\u267B\uFE0F Workspace was tied to a different site \u2014 recreating it."),await y.emptyDir(t)}await y.outputFile(r,e)}function bn(t,e){let n=`${e.name.substr(0,20)} ${e.id}`.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,""),r=t||v.join(hn.homedir(),"SleekCMS");return v.resolve(r,n)}async function Mt(t){let e=(t.token||"").trim();if(!e)throw new Error("syncSite: token is required");let n=t.log??(x=>console.log(x)),r=t.onProgress,s=(t.env||e.split("-")[2]||"production").toLowerCase(),i=ce[s]||ce.production,a=await ft(i,e,"GET","/get_site"),u=t.viewsDir?v.resolve(t.viewsDir):bn(t.path,a);await y.ensureDir(u),await wn(u,e,n),await Promise.all(fn.map(x=>y.ensureDir(v.join(u,x)))),await yn(u,t.buildScript);let h=v.join(u,".cache","state.json");t.flush&&await y.remove(h);let w=!await y.pathExists(h),l=w?{}:(await y.readJson(h)).fileMap||{},b=0,S=0,g=0;if(w)({fileMap:l,pulled:S}=await Dn(u,i,e,n,r)),await pn(u,t.agentMd);else{let x=await Mn(u,l,i,e,n);g=x.renamed,b=await xn(u,l,i,e,n,r,x.held)}return await y.outputJson(h,{fileMap:l},{spaces:2}),{viewsDir:u,site:a,isFirstRun:w,pushed:b,pulled:S,renamed:g}}var tt=t=>mn("sha1").update(t).digest("hex"),Sn=new Set([".DS_Store","Thumbs.db","desktop.ini"]);async function Rt(t){let e=v.join(t,"src");if(!await y.pathExists(e))return[];let n=[];async function r(s){let i=await y.readdir(s,{withFileTypes:!0});for(let a of i){if(Sn.has(a.name))continue;let u=v.join(s,a.name);a.isDirectory()?await r(u):a.isFile()&&n.push(v.relative(t,u).replace(/\\/g,"/"))}}return await r(e),n}async function xn(t,e,n,r,s,i,a=new Set){let u=[];for(let S of await Rt(t)){if(a.has(S))continue;let g=v.join(t,S),x=e[S],C=await y.stat(g);if(x&&x.mtimeMs===C.mtimeMs){x.hash||(x.hash=tt(await y.readFile(g,"utf-8")));continue}let k=await y.readFile(g,"utf-8");k.trim()&&u.push({rel:S,full:g,stat:C,content:k,prior:x})}if(u.length===0)return 0;let h;try{h=await ft(n,r,"POST","/save_files",u.map(S=>({path:S.rel,content:S.content})))}catch(S){let g=S;return s(`\u274C Error saving files: ${g.body||g.message}`),0}let w=await de(t),l=0,b=vn(h);for(let S=0;S<u.length;S++){let g=u[S],x=Tn(g,S,h,b);if(i?.(S+1,u.length),!x){let C="No save response returned";w[g.rel]=C,s(`\u274C Error saving ${g.rel}: ${C}`);continue}if(x.error){w[g.rel]=x.error,s(`\u274C Error saving ${g.rel}: ${x.error}`);continue}delete w[g.rel],e[g.rel]={mtimeMs:g.stat.mtimeMs,hash:tt(g.content)},s(`\u2705 ${g.prior?"Updated":"Created"} ${g.rel}`),l++}return await ge(t,w),l}function vn(t){let e=new Map;for(let n of t)n.path&&e.set(n.path,n);return e}function Tn(t,e,n,r){let s=r.get(t.rel);if(s)return s;let i=n[e];if(!i?.path||i.path===t.rel)return i}var le=/^src\/(?:(?:models|views)\/(?:pages|entries|blocks)|content\/(?:pages|entries))\//,kn={PAGE:"pages",ENTRY:"entries",BLOCK:"blocks"},$n=t=>t.split("/").slice(0,3).join("/");function En(t,e,n){let r=new Map,s=(i,a)=>{let u=`${$n(i)}|${a}`;return r.has(u)||r.set(u,{from:[],to:[],hash:a}),r.get(u)};for(let i of t)s(i,n[i].hash).from.push(i);for(let[i,a]of e)s(i,a).to.push(i);return[...r.values()].filter(i=>i.from.length===1&&i.to.length===1).map(i=>({from:i.from[0],to:i.to[0],hash:i.hash}))}function Bn(t,e){let n=new Map,r=(s,i,a,u,h)=>{let w=n.get(s);w?(w.pairs.push(h),i<w.rank&&Object.assign(w,{from:a,to:u,rank:i})):n.set(s,{from:a,to:u,rank:i,pairs:[h]})};for(let s of t){let[,i,a,...u]=s.from.split("/"),h=s.to.split("/").slice(3);if(i==="content"&&a==="pages"&&u.length>1){let[l,...b]=u,[S,...g]=h;if(g.length===0)continue;S===l?r(`record:${s.from}`,0,s.from,s.to,s):b.join("/")===g.join("/")&&![...e].some(x=>x.startsWith(`src/content/pages/${l}/`))&&r(`pages:${l}`,3,`src/content/pages/${l}`,`src/content/pages/${S}`,s);continue}let w=u.join("/").replace(/\.[^./]+$/,"");r(`${a}:${w}`,i==="models"?0:i==="views"?1:2,s.from,s.to,s)}return[...n.values()].map(({from:s,to:i,pairs:a})=>({from:s,to:i,pairs:a}))}function ue(t,e){if(t.slug!==void 0&&t.new_slug!==void 0){let a=`src/content/pages/${t.key}/`,u=e.startsWith(a)?e.slice(a.length).match(/^(.+)\.(json|md)$/):null;return u&&u[1].toLowerCase()===t.slug.toLowerCase()?`${a}${t.new_slug}.${u[2]}`:null}let n=kn[t.type],{key:r,new_key:s}=t;if(!n||!s)return null;if(e===`src/models/${n}/${r}.model`)return`src/models/${n}/${s}.model`;if(e===`src/views/${n}/${r}.ejs`)return`src/views/${n}/${s}.ejs`;if(n!=="blocks"&&(e===`src/content/${n}/${r}.json`||e===`src/content/${n}/${r}.md`))return`src/content/${n}/${s}${v.extname(e)}`;let i=`src/content/pages/${r}/`;return n==="pages"&&r.endsWith("+")&&e.startsWith(i)?`src/content/pages/${s}/${e.slice(i.length)}`:null}async function Cn(t,e){let n=t;for(;n.startsWith(e+v.sep);){let r=await y.readdir(n).catch(()=>null);if(!r||r.length>0)return;await y.remove(n),n=v.dirname(n)}}async function Pn(t,e,n,r){let s=l=>v.join(t,l),i=v.join(t,"src"),a=l=>v.resolve(t,l).startsWith(i+v.sep),u=async(l,b)=>{e[l]={mtimeMs:(await y.stat(s(l))).mtimeMs,hash:b}},h=l=>Cn(v.dirname(s(l)),v.join(t,...l.split("/").slice(0,3))),w=[];for(let l of r){let b=ue(n.rename,l.from)??l.to;a(b)&&(b!==l.to&&(await y.move(s(l.to),s(b),{overwrite:!0}),await h(l.to),w.push(l.to)),delete e[l.from],w.push(l.from),await u(b,l.hash))}for(let l of new Set([...await Rt(t),...Object.keys(e)])){let b=ue(n.rename,l);if(!b||!a(b))continue;let S=await y.pathExists(s(l));if(S&&await y.pathExists(s(b)))continue;let g=e[l];if(delete e[l],w.push(l),!S)continue;let x=!!g?.hash&&g.mtimeMs===(await y.stat(s(l))).mtimeMs;await y.move(s(l),s(b)),x&&await u(b,g.hash),await h(l)}for(let l of n.files||[]){let b=e[l.path];if(!b||!a(l.path))continue;let S=await y.stat(s(l.path)).catch(()=>null);!S||S.mtimeMs!==b.mtimeMs||await y.readFile(s(l.path),"utf-8")!==l.content&&(await y.outputFile(s(l.path),l.content),await u(l.path,tt(l.content)))}return w}function On(t){try{let e=JSON.parse(t.body).message;if(e)return e}catch{}return(t.body||t.message||String(t)).slice(0,300)}async function Mn(t,e,n,r,s){let i=new Set,a=await Rt(t),u=new Set(a),h=Object.keys(e).filter(g=>!u.has(g)&&e[g].hash&&le.test(g));if(h.length===0)return{renamed:0,held:i};let w=new Map;for(let g of a){if(e[g]||!le.test(g))continue;let x=await y.readFile(v.join(t,g),"utf-8");x.trim()&&w.set(g,tt(x))}let l=Bn(En(h,w,e),u);if(l.length===0)return{renamed:0,held:i};let b=await de(t),S=0;for(let g of l){let x;try{x=await ft(n,r,"POST","/rename",{from:g.from,to:g.to})}catch(D){let L=D,q=On(L);if(L.status>=400&&L.status<500)s(`\u26A0\uFE0F Couldn't rename ${g.from} \u2192 ${g.to}: ${q} Saving it as a new file.`);else{for(let z of g.pairs)i.add(z.to),b[z.to]=`rename from ${z.from} failed: ${q}`;s(`\u274C Error renaming ${g.from} \u2192 ${g.to}: ${q}`)}continue}let C=await Pn(t,e,x,g.pairs);for(let D of[...C,...g.pairs.map(L=>L.to)])delete b[D];let[k,...P]=x.message.split(`
7
+ `);s(`\u{1F500} ${k}`);for(let D of P)s(` ${D}`);S++}return await ge(t,b),{renamed:S,held:i}}var Dt="sync-errors.log",Ot=new Map;async function de(t){let e=v.resolve(t),n=Ot.get(e);if(n)return n;let r=await Rn(e);return Ot.set(e,r),r}async function Rn(t){let e=v.join(t,Dt);if(!await y.pathExists(e))return{};let n=await y.readFile(e,"utf-8"),r={};for(let s of n.split(`
8
+ `)){let i=s.indexOf(": ");i>0&&(r[s.slice(0,i)]=s.slice(i+2))}return r}async function ge(t,e){let n=v.join(t,Dt),r=Object.entries(e);if(r.length===0){await y.remove(n);return}await y.outputFile(n,r.map(([s,i])=>`${s}: ${i}`).join(`
8
9
  `)+`
9
- `)}async function Sn(t,e,n,r,s){Et.delete(S.resolve(t)),await m.remove(S.join(t,$t)),r("\u{1F4E5} Fetching files...");let o=await Ct(e,n,"GET","/get_files"),c={},h=0;for(let p of o){let x=S.join(t,p.path);await m.outputFile(x,p.content);let w=(await m.stat(x)).mtimeMs;h++,s?.(h,o.length),c[p.path]={mtimeMs:w}}return r(`\u2714\uFE0F Synced ${o.length} file(s).`),{fileMap:c,pulled:h}}import vn from"path";import Tn from"chokidar";var kn=5e3,Bn=/(^|[/\\])(\.DS_Store|Thumbs\.db|desktop\.ini)$/,V=class{viewsDir;onSync;debounceMs;watcher=null;debounceTimer=null;isShuttingDown=!1;dirty=!1;syncInFlight=!1;constructor(e){this.viewsDir=e.viewsDir,this.onSync=e.onSync,this.debounceMs=e.debounceMs??kn}start(){if(this.watcher)return;let e=vn.join(this.viewsDir,"src");this.watcher=Tn.watch([e],{persistent:!0,ignoreInitial:!0,ignored:Bn}).on("change",()=>this.scheduleSync()).on("add",()=>this.scheduleSync()).on("unlink",()=>this.scheduleSync())}setShuttingDown(e){this.isShuttingDown=e}async stop(){this.debounceTimer&&(clearTimeout(this.debounceTimer),this.debounceTimer=null),this.watcher&&(await this.watcher.close(),this.watcher=null)}scheduleSync(){this.isShuttingDown||(this.dirty=!0,this.debounceTimer&&clearTimeout(this.debounceTimer),this.debounceTimer=setTimeout(()=>this.flush(),this.debounceMs))}async flush(){if(this.debounceTimer=null,!(!this.dirty||this.isShuttingDown)){if(this.syncInFlight){this.debounceTimer=setTimeout(()=>this.flush(),this.debounceMs);return}this.dirty=!1,this.syncInFlight=!0;try{await this.onSync()}catch(e){let n=e;console.error("\u274C Sync failed:",n.body||n.message)}finally{this.syncInFlight=!1}}}};import gt from"fs-extra";import En from"os";import ae from"path";var oe={localhost:"http://app.sleekcms.test/api",development:"https://app.sleekcms.dev/api",production:"https://app.sleekcms.com/api"};function Ot(t){return oe[t]||oe.production}var Cn=ae.join(En.homedir(),"SleekCMS"),ht=ae.join(Cn,"auth.json"),Mt;function ce(t){Mt=t||void 0}function Dt(t){let e=[];return t&&e.push(`_auth=${t}`),Mt&&e.push(`_dev=${Mt}`),e.length?e.join("; "):void 0}var L=class extends Error{status;body;constructor(e,n,r=""){super(e),this.name="UserAuthError",this.status=n,this.body=r}};async function le(){try{let t=await gt.readJson(ht);return t&&t.userToken?t:null}catch{return null}}async function ue(t){await gt.outputJson(ht,t,{spaces:2});try{await gt.chmod(ht,384)}catch{}}async function de(){await gt.remove(ht)}async function q(t){let e={},n=Dt(t.userToken);n&&(e.Cookie=n),t.subdomain&&(e["x-subdomain"]=t.subdomain),t.slug&&(e.site=t.slug),t.body!==void 0&&(e["Content-Type"]="application/json");let r=await fetch(Ot(t.env)+t.path,{method:t.method,headers:e,body:t.body!==void 0?JSON.stringify(t.body):void 0});if(!r.ok){let s=await r.text().catch(()=>"");throw new L(`${t.method} ${t.path} \u2192 ${r.status}: ${s}`,r.status,s)}return r.json()}async function ge(t,e){let n={"Content-Type":"application/json"},r=Dt();r&&(n.Cookie=r);let s=await fetch(Ot(t)+"/auth/otp",{method:"PUT",headers:n,body:JSON.stringify({email:e})});if(!s.ok){let c=await s.text().catch(()=>"");throw new L(`Failed to send OTP \u2192 ${s.status}: ${c}`,s.status,c)}return{otp:(await s.json().catch(()=>({}))).do_not_use_in_code}}async function Lt(t,e,n){let r={"Content-Type":"application/json"},s=Dt();s&&(r.Cookie=s);let o=await fetch(Ot(t)+"/auth/login",{method:"POST",headers:r,body:JSON.stringify({email:e,otp:n})});if(!o.ok){let p=await o.text().catch(()=>"");throw new L(`Login failed \u2192 ${o.status}: ${p}`,o.status,p)}let c=o.headers.getSetCookie?.()??[],h=Pn(c);if(!h)throw new L("Login succeeded but no _auth cookie was returned.",500);return h}function Pn(t){for(let e of t){let n=e.match(/(?:^|;\s*)_auth=([^;]+)/);if(n&&n[1])return decodeURIComponent(n[1])}return null}async function Rt(t,e){return q({env:t,userToken:e,method:"GET",path:"/org"})}async function he(t,e,n){return q({env:t,userToken:e,method:"GET",path:"/site",subdomain:n})}function $n(t){if(t==null)return"(unknown error)";if(typeof t=="string")return t;if(typeof t!="object")return String(t);let e=t,n=typeof e.file_path=="string"?e.file_path:"",r=typeof e.path=="string"?e.path:typeof e.filename=="string"?e.filename:"",s=n||r,o=e.line!=null?`:${e.line}`:"",c=e.column!=null?`:${e.column}`:"",h=typeof e.message=="string"&&e.message?e.message:typeof e.name=="string"&&e.name?e.name:"",p=n&&r&&r!==n?` (on page ${r})`:"";if(s)return`${s}${o}${c}${p}: ${h||"(no message)"}`;if(h)return h;try{return JSON.stringify(t)}catch{return"(unknown error)"}}async function pe(t,e,n,r){let s;try{s=await q({env:t,userToken:e,method:"GET",path:"/site_build",subdomain:n,slug:r})}catch{return null}if(!Array.isArray(s)||s.length===0)return null;let o=s[0],c=s.find(p=>typeof p.url=="string"&&p.url.length>0),h=Array.isArray(o.errors)?o.errors.map($n):[];return h.length>0?{status:"error",mode:"preview",errors:h,url:c?.url||void 0,at:o.updated_at?Date.parse(o.updated_at):void 0}:c?{status:"success",mode:"preview",url:c.url||void 0,at:c.updated_at?Date.parse(c.updated_at):void 0}:null}async function fe(t,e,n,r){let{token:s}=await q({env:t,userToken:e,method:"POST",path:"/site_user/api_token",subdomain:n,slug:r,body:{refresh:!1}});return s}async function me(t,e,n){let r=await q({env:t,userToken:e,method:"POST",path:"/org",body:n?{name:n}:{}});return{id:r.id,name:r.name,subdomain:r.subdomain}}async function ye(t,e,n,r){let s=await q({env:t,userToken:e,method:"POST",path:"/site",subdomain:n,body:{name:r}});return{id:s.id,name:s.name,slug:s.slug}}var we=500;function Ln(){return new Date().toTimeString().slice(0,8)}function pt(t){let e=t;if(e.body){try{let n=JSON.parse(e.body);if(n&&typeof n.message=="string")return n.message;if(n&&typeof n.error=="string")return n.error}catch{}return e.body}return e.message}async function be(t){t&&(await Q.remove(At.join(t,"src")),await Q.remove(At.join(t,".cache","state.json")))}var ft=class extends Mn{env="production";userToken="";email;catalog=[];synced=new Map;message;messageIsError=!1;agentMd;buildScript;isShuttingDown=!1;constructor(e,n){super(),this.agentMd=e,this.buildScript=n}changed(){this.emit("change")}flash(e,n=!1){this.message=e,this.messageIsError=n,this.changed()}appendLog(e,n){let r=this.synced.get(e);r&&(r.logs.push({time:Ln(),text:n}),r.logs.length>we&&r.logs.splice(0,r.logs.length-we),this.changed())}siteCount(){return this.synced.size}syncingCount(){let e=0;for(let n of this.synced.values())n.status==="syncing"&&e++;return e}watchingCount(){let e=0;for(let n of this.synced.values())(n.status==="watching"||n.status==="syncing")&&e++;return e}async init(e,n,r){this.env=e,this.userToken=n,r&&(this.email=r);let s=await Rt(e,n);await this.buildCatalog(s)}async buildCatalog(e){let n=[];for(let r of e)try{n.push({org:r,sites:await he(this.env,this.userToken,r.subdomain)})}catch(s){if(s instanceof L&&s.status===401)throw s;n.push({org:r,sites:[]})}this.catalog=n,this.changed()}isSynced(e){return this.synced.has(e)}availableSites(){let e=[];for(let n of this.catalog)for(let r of n.sites)this.synced.has(r.id)||e.push({org:n.org,site:r});return e}async addSite(e,n){if(this.synced.has(n.id))return;let r;try{r=await fe(this.env,this.userToken,e.subdomain,n.slug)}catch(o){this.flash(`Failed to authorize "${n.name}": ${pt(o)}`,!0);return}let s={org:e,site:n,siteToken:r,viewsDir:"",status:"syncing",logs:[]};this.synced.set(n.id,s),this.appendLog(n.id,"\u2795 added \u2014 pulling files"),this.changed();try{let o=await Pt({token:r,env:this.env,agentMd:this.agentMd,buildScript:this.buildScript,log:c=>this.appendLog(n.id,c),onProgress:(c,h)=>{s.progress={done:c,total:h},this.changed()}});s.viewsDir=o.viewsDir,s.progress=void 0,s.status="watching",s.lastSyncedAt=Date.now(),s.lastMsg=`pulled ${o.pulled} file(s)`,s.watcher=new V({viewsDir:o.viewsDir,onSync:()=>this.runSync(n.id)}),s.watcher.start(),this.watchBuildStatus(n.id),this.seedLastBuild(n.id),this.appendLog(n.id,"\u{1F440} watching for changes")}catch(o){let c=o;s.status="error",s.progress=void 0,s.lastMsg=c.body||c.message,this.appendLog(n.id,`\u274C ${c.body||c.message}`)}this.changed()}async removeSite(e){let n=this.synced.get(e);n&&(n.watcher?.setShuttingDown(!0),await n.watcher?.stop(),await n.buildWatcher?.close(),await be(n.viewsDir),this.synced.delete(e),this.changed())}buildSite(e,n=!1){let r=this.synced.get(e);if(!r||!r.viewsDir)return;let s=n?"live":"preview";this.writeBuildFile(r.viewsDir,{status:"building",mode:s,stage:"queued",url:r.lastBuild?.url,at:Date.now()}),On("node",n?["build.mjs","--publish"]:["build.mjs"],{cwd:r.viewsDir,stdio:"ignore"}).on("error",h=>{this.writeBuildFile(r.viewsDir,{status:"error",mode:s,errors:[h.message],url:r.lastBuild?.url,at:Date.now()}),this.appendLog(e,`\u274C build: ${h.message}`)}),this.appendLog(e,n?"\u{1F680} publishing\u2026":"\u{1F528} building\u2026")}buildFile(e){return At.join(e,".cache","build.json")}async readBuildFile(e){try{let n=await Q.readJson(this.buildFile(e));return n&&n.status?n:null}catch{return null}}async writeBuildFile(e,n){let r=this.buildFile(e),s=`${r}.tmp`;try{await Q.outputJson(s,n),await Q.rename(s,r)}catch{}}watchBuildStatus(e){let n=this.synced.get(e);!n||!n.viewsDir||(n.buildWatcher=Dn.watch(this.buildFile(n.viewsDir),{ignoreInitial:!1}).on("add",()=>{this.readBuildStatus(e)}).on("change",()=>{this.readBuildStatus(e)}))}async readBuildStatus(e){let n=this.synced.get(e);if(!n)return;let r=await this.readBuildFile(n.viewsDir);if(!r)return;let s=n.lastBuild?.url;n.lastBuild={status:r.status,mode:r.mode??"preview",url:r.url??(r.status==="success"?void 0:s),errors:r.errors,stage:r.stage,at:r.at},this.changed()}async seedLastBuild(e){let n=this.synced.get(e);if(!n)return;let r=await pe(this.env,this.userToken,n.org.subdomain,n.site.slug);if(!r)return;let s=this.synced.get(e);if(!s)return;let o=await this.readBuildFile(s.viewsDir);o?.at!=null&&(r.at==null||o.at>=r.at)||await this.writeBuildFile(s.viewsDir,r)}async ensureOrg(e){if(e)return e;if(this.catalog[0])return this.catalog[0].org;let n;try{n=await Rt(this.env,this.userToken)}catch(r){return this.flash(`Couldn't check your organizations: ${pt(r)}`,!0),null}if(n.length>0){try{await this.buildCatalog(n)}catch{}return n[0]}try{let r=this.email?`${this.email.split("@")[0]}'s Sites`:"My Sites";this.flash("No organization yet \u2014 creating one\u2026");let s=await me(this.env,this.userToken,r);return this.catalog=[...this.catalog,{org:s,sites:[]}],this.changed(),s}catch(r){return this.flash(`Could not create an organization: ${pt(r)}`,!0),null}}async createNewSite(e,n){let r=await this.ensureOrg(n);if(!r)return;let s;try{s=await ye(this.env,this.userToken,r.subdomain,e)}catch(c){this.flash(`Could not create "${e}": ${pt(c)}`,!0);return}let o=this.catalog.find(c=>c.org.id===r.id);o&&!o.sites.some(c=>c.id===s.id)&&(o.sites=[...o.sites,s]),this.flash(`Created "${s.name}".`),await this.addSite(r,s)}async refetch(e){await this.runSync(e,{flush:!0})}async runSync(e,n={}){let r=this.synced.get(e);if(!(!r||!r.viewsDir||r.status==="paused")){r.status="syncing",this.changed();try{let s=await Pt({token:r.siteToken,env:this.env,viewsDir:r.viewsDir,agentMd:this.agentMd,buildScript:this.buildScript,flush:n.flush,log:o=>this.appendLog(e,o),onProgress:(o,c)=>{r.progress={done:o,total:c},this.changed()}});r.progress=void 0,r.status="watching",r.lastSyncedAt=Date.now(),n.flush?r.lastMsg=`re-fetched ${s.pulled} file(s)`:r.lastMsg=s.pushed>0?`pushed ${s.pushed} file(s)`:"up to date"}catch(s){let o=s;r.status="error",r.progress=void 0,r.lastMsg=o.body||o.message,this.appendLog(e,`\u274C ${o.body||o.message}`)}this.changed()}}async togglePause(e){let n=this.synced.get(e);!n||!n.viewsDir||(n.status==="paused"?(n.watcher=new V({viewsDir:n.viewsDir,onSync:()=>this.runSync(e)}),n.watcher.start(),n.status="watching",this.appendLog(e,"\u25B6 resumed \u2014 watching for changes")):(n.watcher?.setShuttingDown(!0),await n.watcher?.stop(),n.watcher=void 0,n.progress=void 0,n.status="paused",this.appendLog(e,"\u23F8 paused")),this.changed())}async cleanupAll(){for(let e of this.synced.values())e.watcher?.setShuttingDown(!0),await e.watcher?.stop(),await e.buildWatcher?.close(),await be(e.viewsDir)}async exit(){this.isShuttingDown||(this.isShuttingDown=!0,await this.cleanupAll(),this.emit("exit"))}async logout(){this.isShuttingDown||(this.isShuttingDown=!0,await de(),await this.cleanupAll(),this.emit("logout"))}};import{useEffect as Hn,useState as Me}from"react";import{Box as Jn,Text as Xn,useInput as Kn}from"ink";import{useState as Z}from"react";import{Box as tt,Text as H}from"ink";import xe from"ink-text-input";import{jsx as N,jsxs as J}from"react/jsx-runtime";function Se(t){let e=t;return e?.body||e?.message||String(t)}function ve({env:t,initialError:e,onAuthed:n}){let[r,s]=Z("email"),[o,c]=Z(""),[h,p]=Z(""),[x,w]=Z(e),[f,b]=Z(),v=async R=>{let E=R.trim();if(E){w(void 0),s("busy");try{let{otp:$}=await ge(t,E);if(c(E),$){let X=await Lt(t,E,$);await n(X,E);return}b(`OTP sent to ${E}`),s("otp")}catch($){w(Se($)),s("email")}}},O=async R=>{let E=R.trim();if(E){w(void 0),s("busy");try{let $=await Lt(t,o,E);await n($,o)}catch($){w(Se($)),p(""),s("otp")}}};return J(tt,{flexDirection:"column",children:[J(H,{bold:!0,children:["\u25C6 SleekCMS \u2014 sign in",t!=="production"?` (${t})`:""]}),x?J(H,{color:"red",children:["\u2717 ",x]}):null,r==="email"&&J(tt,{marginTop:1,children:[N(H,{children:"Email: "}),N(xe,{value:o,onChange:c,onSubmit:v,placeholder:"you@example.com"})]}),r==="otp"&&J(tt,{flexDirection:"column",marginTop:1,children:[f?N(H,{color:"green",children:f}):null,J(tt,{children:[N(H,{children:"Enter OTP: "}),N(xe,{value:h,onChange:p,onSubmit:O})]})]}),r==="busy"&&N(tt,{marginTop:1,children:N(H,{children:"Working\u2026"})})]})}import{Fragment as An,useEffect as et,useMemo as Fn,useState as C}from"react";import{Box as g,Text as l,useInput as jn,useStdout as _n}from"ink";import Be from"ink-text-input";import Rn from"node:os";function Ft(t){if(!t)return"\u2014";let e=Rn.homedir();return t.startsWith(e)?"~"+t.slice(e.length):t}function jt(t){if(!t)return"\u2014";let e=Math.floor((Date.now()-t)/1e3);if(e<5)return"just now";if(e<60)return`${e}s ago`;let n=Math.floor(e/60);if(n<60)return`${n}m ago`;let r=Math.floor(n/60);return r<24?`${r}h ago`:`${Math.floor(r/24)}d ago`}function yt(t){return!t||t.total<=0?null:Math.round(t.done/t.total*100)}var mt=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"];function Te(t){return mt[(t%mt.length+mt.length)%mt.length]}function wt(t){switch(t){case"syncing":return{dot:"\u25CF",color:"green",label:"syncing"};case"watching":return{dot:"\u25CB",color:"gray",label:"watching"};case"paused":return{dot:"\u2016",color:"yellow",label:"paused"};case"error":return{dot:"\u2717",color:"red",label:"error"}}}function ke(t){if(!t)return{dot:"\xB7",color:"gray",label:"\u2014"};switch(t.status){case"building":return{dot:"\u2234",color:"yellow",label:"building"};case"error":return{dot:"\u2717",color:"red",label:"failed"};case"success":return{dot:"\u2713",color:"green",label:t.mode==="live"?"live":"preview"}}}import{Fragment as nt,jsx as i,jsxs as u}from"react/jsx-runtime";var U=(t,e)=>e<=0?0:Math.max(0,Math.min(t,e-1)),In=16,Nn=5,Un="greenBright",Ee="blueBright",Ce="magentaBright";function Pe({k:t,bg:e=Un}){return i(l,{color:"black",backgroundColor:e,children:` ${t} `})}function j({k:t,label:e,width:n=16,bg:r}){return u(g,{width:n,children:[i(Pe,{k:t,bg:r}),i(l,{color:"gray",children:` ${e}`})]})}function B({k:t,label:e,bg:n}){return u(g,{marginBottom:1,children:[i(g,{width:9,children:i(Pe,{k:t,bg:n})}),i(l,{color:"gray",children:e})]})}function Wn({launchers:t}){return u(g,{flexDirection:"column",borderStyle:"round",borderColor:"green",paddingX:2,paddingY:1,width:66,children:[u(g,{justifyContent:"space-between",children:[i(l,{color:"green",bold:!0,children:"KEYBOARD SHORTCUTS"}),i(l,{color:"gray",children:"? or esc to close"})]}),u(g,{marginTop:1,children:[u(g,{flexDirection:"column",width:34,children:[i(l,{color:"cyan",bold:!0,children:"Navigate"}),i(B,{k:"\u2191\u2193",label:"move selection"}),i(B,{k:"tab",label:"focus logs \xB7 \u2191\u2193 scroll"}),i(B,{k:"esc",label:"clear filter / back"}),i(g,{marginTop:1,children:i(l,{color:"cyan",bold:!0,children:"Global"})}),i(B,{k:"/",label:"search sites"}),i(B,{k:"n",label:"new site"}),i(B,{k:"?",label:"toggle this help",bg:Ee}),i(B,{k:"q",label:"logout"}),i(B,{k:"ctrl+c",label:"quit"})]}),u(g,{flexDirection:"column",flexGrow:1,children:[i(l,{color:"cyan",bold:!0,children:"Site actions"}),i(B,{k:"s",label:"start sync"}),i(B,{k:"d",label:"disconnect"}),i(B,{k:"p",label:"pause / resume sync"}),i(B,{k:"b",label:"build preview"}),i(B,{k:"B",label:"publish live"}),i(B,{k:"o",label:"open preview url"}),t.map((e,n)=>i(B,{k:String(n+1),label:`open in ${e.label}`,bg:Ce},e.key))]})]})]})}function Gn({percent:t,width:e=28}){let n=Math.round(Math.max(0,Math.min(100,t))/100*e);return u(l,{children:[i(l,{color:"green",children:"\u2588".repeat(n)}),i(l,{color:"gray",children:"\u2591".repeat(Math.max(0,e-n))})]})}function qn({frame:t,width:e=24,seg:n=6}){let r=e+n,s=t%r-n,o="";for(let c=0;c<e;c++)o+=c>=s&&c<s+n?"\u25AE":"\u25AF";return i(l,{color:"yellow",children:o})}function $e({controller:t}){let{stdout:e}=_n(),n=Fn(()=>se(),[]),[,r]=C(0),[s,o]=C(()=>new Date),[c,h]=C(null),[p,x]=C(()=>t.synced.size>0||t.catalog.some(d=>d.sites.length>0)?"dashboard":t.catalog.length<=1?"newName":"newOrg"),[w,f]=C(0),[b,v]=C(""),[O,R]=C(!1),[E,$]=C(""),[X,rt]=C(!1),[Nt,Ae]=C(0),[Ut,Wt]=C(!1),[Fe,je]=C(!1),[st,it]=C("list"),[_e,K]=C(0),Gt=()=>r(a=>a+1);et(()=>(t.on("change",Gt),()=>{t.off("change",Gt)}),[t]),et(()=>{let a,d=()=>{o(new Date),a=setTimeout(d,6e4-Date.now()%6e4)};return a=setTimeout(d,6e4-Date.now()%6e4),()=>clearTimeout(a)},[]);let F=t.catalog.flatMap(a=>a.sites.map(d=>({org:a.org,site:d,entry:t.synced.get(d.id)}))).sort((a,d)=>(a.entry?0:1)-(d.entry?0:1)),_=E.trim().toLowerCase(),M=_?F.filter(a=>a.site.name.toLowerCase().includes(_)||(a.org.name||a.org.subdomain||"").toLowerCase().includes(_)):F,W=M.findIndex(a=>a.site.id===c);W<0&&(W=0);let T=M[W],y=T?.entry,ot=Math.max(3,(e?.rows??30)-26),I=y?.logs??[],xt=Math.max(0,I.length-ot),Ie=Math.min(_e,xt),at=I.length-Ie,qt=I.slice(Math.max(0,at-ot),at),Ne=T?.site.id;et(()=>K(0),[Ne]);let A=y?.lastBuild,St=A?.status==="building",vt=ke(A),ct=St;if(!ct){for(let a of t.synced.values())if(a.status==="syncing"){ct=!0;break}}et(()=>{if(!ct)return;let a=setInterval(()=>Ae(d=>d+1),120);return()=>clearInterval(a)},[ct]);let Ht=M.findIndex(a=>!a.entry),G=Math.max(Nn,(e?.rows??30)-In),z=M.length,lt=z>G,Ue=Math.floor(G/2),Y=lt?Math.max(0,Math.min(W-Ue,z-G)):0,Tt=Math.min(z,Y+G),We=M.slice(Y,Tt);et(()=>{p!=="dashboard"||O||F.length>0||(v(""),t.catalog.length<=1?x("newName"):(f(0),x("newOrg")))},[F.length,p,O,t.catalog.length]);let ut=a=>{if(M.length===0)return;let d=U(W+a,M.length);h(M[d].site.id)},Ge=()=>{if(T){if(T.entry){t.flash("Already syncing \u2014 press d to disconnect.");return}t.addSite(T.org,T.site)}},qe=()=>{T?.entry&&t.removeSite(T.site.id)},He=()=>{v(""),t.catalog.length<=1?x("newName"):(f(0),x("newOrg"))},Je=a=>{if(!y){t.flash("Press s to start syncing this site first.",!0);return}je(!0);let d=a.run(y.viewsDir);t.flash(d?`Opened ${a.label} at ${Ft(y.viewsDir)}`:`Couldn't open ${a.label}.`,!d)},Xe=()=>{if(!y){t.flash("Press s to start syncing this site first.",!0);return}t.togglePause(y.site.id)},Jt=a=>{if(!y){t.flash("Press s to start syncing this site first.",!0);return}t.buildSite(y.site.id,a),t.flash(a?"Publishing \u2014 making this live\u2026":"Building preview\u2026")},Ke=()=>{let a=y?.lastBuild?.url;if(!a){t.flash("No build URL yet \u2014 press b to build.",!0);return}t.flash(re(a)?`Opening ${a}`:"Couldn't open the browser.",!1)};jn((a,d)=>{if(Ut){(a==="?"||d.escape)&&Wt(!1);return}if(p==="newOrg"){d.escape?x("dashboard"):d.upArrow?f(k=>U(k-1,t.catalog.length)):d.downArrow?f(k=>U(k+1,t.catalog.length)):d.return&&x("newName");return}if(X){d.escape?(rt(!1),$(""),h(null)):d.return?rt(!1):d.upArrow?ut(-1):d.downArrow&&ut(1);return}if(d.tab){st==="logs"?it("list"):y&&it("logs"),K(0);return}if(st==="logs"){if(d.escape){it("list"),K(0);return}if(d.upArrow)return void K(k=>Math.min(k+1,xt));if(d.downArrow)return void K(k=>Math.max(0,k-1))}if(d.escape){$(""),h(null);return}if(a==="?")return void Wt(!0);if(a==="/")return it("list"),void rt(!0);if(a==="n")return void He();if(a==="q")return void t.logout();if(d.upArrow)return ut(-1);if(d.downArrow)return ut(1);if(a==="s")return Ge();if(a==="d")return qe();if(a==="p")return Xe();if(a==="b")return Jt(!1);if(a==="B")return Jt(!0);if(a==="o")return Ke();if(a>="1"&&a<="9"){let k=n[parseInt(a,10)-1];if(k)return Je(k)}},{isActive:p!=="newName"});let ze=async a=>{let d=a.trim();if(!d){x("dashboard");return}let k=t.catalog[U(w,t.catalog.length)]?.org??t.catalog[0]?.org;R(!0),x("dashboard"),await t.createNewSite(d,k),R(!1)},Xt=u(g,{justifyContent:"space-between",paddingX:1,children:[u(g,{children:[i(l,{color:"green",bold:!0,children:"\u25C6 SleekCMS"}),i(l,{color:"gray",children:" \u2502 "}),i(l,{children:t.email??"signed in"})]}),u(g,{children:[u(l,{color:"gray",children:[_?`${M.length}/${F.length}`:F.length," sites \xB7 "]}),u(l,{color:"green",children:[t.watchingCount()," watching"]}),i(l,{color:"gray",children:` \xB7 ${s.toTimeString().slice(0,5)}`})]})]});return Ut?u(g,{flexDirection:"column",children:[Xt,i(g,{marginTop:1,justifyContent:"center",children:i(Wn,{launchers:n})})]}):u(g,{flexDirection:"column",children:[Xt,u(g,{children:[u(g,{flexDirection:"column",borderStyle:"round",borderColor:"green",width:38,paddingX:1,children:[u(g,{justifyContent:"space-between",children:[i(l,{color:"green",bold:!0,children:"SITE WORKSPACES"}),F.length>G&&!X&&!_?i(l,{color:"gray",children:"/ filter"}):null]}),X?u(g,{children:[i(l,{color:"cyan",children:"/ "}),i(Be,{value:E,onChange:$,onSubmit:()=>rt(!1),placeholder:"type to filter\u2026"})]}):_?i(l,{color:"gray",children:`/ ${E} \xB7 ${M.length} match${M.length===1?"":"es"}`}):null,i(g,{flexDirection:"column",marginTop:1,minHeight:lt?G+3:void 0,children:M.length===0?i(l,{color:"gray",children:_?`no matches for \u201C${E}\u201D`:"no sites \u2014 press n to create one"}):u(nt,{children:[lt?i(l,{color:"gray",children:Y>0?` \u2191 ${Y} more`:" "}):null,We.map((a,d)=>{let k=Y+d,Kt=a.entry?wt(a.entry.status):{dot:"\xB7",color:"gray",label:"idle"},zt=yt(a.entry?.progress),Ye=a.entry?a.entry.status==="syncing"&&zt!=null?`${zt}%`:a.entry.status==="paused"?"paused":"--":"",dt=k===W,Ve=k===Ht&&Ht>0;return u(An,{children:[Ve?i(l,{color:"gray",children:"\u2500".repeat(34)}):null,u(g,{justifyContent:"space-between",children:[u(g,{children:[i(l,{color:dt?"green":"gray",children:dt?"\u276F ":" "}),u(l,{color:a.entry?.status==="watching"||a.entry?.status==="syncing"?"green":Kt.color,children:[a.entry?.status==="syncing"?Te(Nt):a.entry?.status==="watching"?"\u25CF":Kt.dot," "]}),i(l,{color:dt?"white":a.entry?void 0:"gray",bold:dt,children:a.site.name})]}),i(l,{color:a.entry?.status==="syncing"?"green":"gray",children:Ye})]})]},a.site.id)}),lt?i(l,{color:"gray",children:Tt<z?` \u2193 ${z-Tt} more`:" "}):null]})}),i(g,{marginTop:1,children:i(l,{color:"gray",children:"+ new site \xB7 n"})})]}),u(g,{flexDirection:"column",flexGrow:1,marginLeft:1,children:[i(g,{flexDirection:"column",borderStyle:"round",borderColor:"gray",paddingX:1,children:T?u(nt,{children:[u(l,{children:[T.org.name||T.org.subdomain?u(l,{color:"gray",children:[T.org.name||T.org.subdomain," / "]}):null,i(l,{color:"cyan",bold:!0,children:T.site.name})]}),u(g,{marginTop:1,children:[i(l,{color:"gray",children:"status "}),y?i(l,{color:wt(y.status).color,children:`: ${wt(y.status).label}`}):i(l,{color:"gray",children:": idle \u2014 not syncing (press s to start)"})]}),u(g,{children:[i(l,{color:"gray",children:"path "}),i(l,{wrap:"truncate-end",children:y?.viewsDir?Ft(y.viewsDir):"\u2014"})]}),u(g,{children:[i(l,{color:"gray",children:"synced "}),i(l,{children:jt(y?.lastSyncedAt)}),i(l,{color:"gray",children:" progress "}),i(l,{color:y?.status==="syncing"?"green":"gray",children:y?.status==="syncing"?`${yt(y.progress)??0}%`:"\u2014"})]}),i(g,{marginTop:1,children:i(Gn,{percent:y?y.status==="syncing"?yt(y.progress)??0:y.status==="watching"?100:0:0})}),y?u(nt,{children:[u(g,{marginTop:1,children:[i(l,{color:"gray",children:"build "}),i(l,{color:vt.color,children:`${vt.dot} ${vt.label}`}),i(l,{color:"gray",children:" last "}),i(l,{children:St?"in progress":jt(A?.at)})]}),u(g,{children:[i(l,{color:"gray",children:"url "}),A?.url?i(l,{color:"cyan",wrap:"truncate-end",children:A.url}):i(l,{color:"gray",children:"\u2014"})]}),A?.status==="error"&&A.errors?.length?u(g,{children:[i(l,{color:"red",children:"\u258C "}),i(l,{color:"red",wrap:"truncate-end",children:`\u2717 ${A.errors[0]}`})]}):null,St?u(g,{children:[i(qn,{frame:Nt}),i(l,{color:"gray",children:` ${A?.stage??"building"}`})]}):null]}):null]}):i(l,{color:"gray",children:"No site selected."})}),p==="dashboard"?u(g,{flexDirection:"column",borderStyle:"round",borderColor:st==="logs"?"green":"gray",paddingX:1,marginTop:1,height:ot+4,flexShrink:0,overflowY:"hidden",children:[u(g,{justifyContent:"space-between",children:[u(l,{children:[i(l,{color:"cyan",bold:!0,children:"LOGS \xB7 "}),i(l,{color:"white",children:T?.site.name??"\u2014"})]}),y&&I.length>0?st==="logs"?i(l,{color:"green",children:`\u2191\u2193 scroll \xB7 esc back${xt>0?` \xB7 ${at}/${I.length}`:""}`}):I.length>ot?i(l,{color:"gray",children:"tab to scroll"}):null:null]}),i(g,{flexDirection:"column",marginTop:1,children:!y||I.length===0?i(l,{color:"gray",children:"no activity yet"}):qt.map((a,d)=>u(l,{wrap:"truncate-end",children:[u(l,{color:"gray",children:[a.time," "]}),a.text]},at-qt.length+d))})]}):u(g,{flexDirection:"column",borderStyle:"round",borderColor:"blue",paddingX:1,marginTop:1,flexGrow:1,children:[p==="newOrg"&&u(nt,{children:[i(l,{color:"cyan",bold:!0,children:"CREATE SITE \u2014 PICK ORG"}),i(l,{color:"gray",children:"\u2191/\u2193 select \xB7 \u23CE next \xB7 esc cancel"}),i(g,{flexDirection:"column",marginTop:1,children:t.catalog.map((a,d)=>u(l,{color:d===U(w,t.catalog.length)?"blue":void 0,bold:d===U(w,t.catalog.length),children:[d===U(w,t.catalog.length)?"\u276F ":" ",a.org.name||a.org.subdomain]},a.org.id))})]}),p==="newName"&&u(nt,{children:[i(l,{color:"cyan",bold:!0,children:"CREATE SITE"}),u(g,{marginTop:1,children:[i(l,{children:"New site name: "}),i(Be,{value:b,onChange:v,onSubmit:ze})]}),i(l,{color:"gray",children:"\u23CE create \xB7 empty + \u23CE to cancel"})]})]})]})]}),t.message?i(g,{paddingX:1,children:u(l,{color:t.messageIsError?"red":"gray",wrap:"truncate-end",children:[t.messageIsError?"\u2717 ":"",t.message]})}):null,u(g,{flexDirection:"column",marginTop:1,children:[u(g,{paddingX:1,justifyContent:"space-between",children:[u(g,{flexWrap:"wrap",children:[i(j,{k:"\u2191\u2193",label:"select"}),i(j,{k:"/",label:"search"}),i(j,{k:"s",label:"start sync"}),i(j,{k:"d",label:"disconnect"}),F.length===0?i(j,{k:"n",label:"new site"}):null,i(j,{k:"ctrl+c",label:"quit",width:14})]}),i(j,{k:"?",label:"all keys",width:12,bg:Ee})]}),!Fe&&n.length>0?i(g,{paddingX:1,marginTop:1,flexWrap:"wrap",children:n.map((a,d)=>i(j,{k:String(d+1),label:a.label,bg:Ce},a.key))}):null]})]})}import{jsx as bt}from"react/jsx-runtime";function Oe(t){let e=t;return e?.body||e?.message||String(t)}function De({controller:t,env:e,devSecret:n,savedToken:r,savedEmail:s}){let[o,c]=Me(r?"loading":"auth"),[h,p]=Me();Kn((w,f)=>{f.ctrl&&w==="c"&&t.exit()}),Hn(()=>{r&&t.init(e,r,s).then(()=>c("manage")).catch(w=>{w instanceof L&&w.status===401?p("Saved session expired \u2014 please sign in again."):p(Oe(w)),c("auth")})},[]);let x=async(w,f)=>{p(void 0),await ue({env:e,userToken:w,devSecret:n,email:f}),c("loading");try{await t.init(e,w,f),c("manage")}catch(b){p(Oe(b)),c("auth")}};return o==="auth"?bt(ve,{env:e,initialError:h,onAuthed:x}):o==="loading"?bt(Jn,{children:bt(Xn,{children:"Loading your sites\u2026 "})}):bt($e,{controller:t})}import{jsx as nr}from"react/jsx-runtime";var Qn=Yn(import.meta.url),_t=te();if(_t.version){let t=Qn("../package.json");console.log(t.version),process.exit(0)}var Re=It.dirname(zn(import.meta.url)),Zn=Le(It.join(Re,"AGENT.md"),"utf-8"),tr=Le(It.join(Re,"build.mjs"),"utf-8");async function er(){let t=new ft(Zn,tr),e=await le(),n=(_t.env??e?.env??"production").toLowerCase(),r=_t.dev??process.env.SLEEKCMS_DEV_SECRET??e?.devSecret;ce(r),process.stdout.isTTY&&process.stdout.write("\x1B[2J\x1B[3J\x1B[H");let s=Vn(nr(De,{controller:t,env:n,devSecret:r,savedToken:e?.userToken,savedEmail:e?.email}),{exitOnCtrlC:!1}),o=c=>{s.unmount(),console.log(c),process.exit(0)};t.once("exit",()=>o("\u2713 Stopped. Local site files were cleaned up.")),t.once("logout",()=>o("\u{1F44B} Logged out. Run `sleekcms` to sign in again.")),process.on("SIGINT",()=>{t.exit()}),process.on("SIGTERM",()=>{t.exit()}),await s.waitUntilExit()}er().catch(t=>{let e=t;console.error("\u274C",e.body||e.message),process.exit(1)});
10
+ `)}async function Dn(t,e,n,r,s){Ot.delete(v.resolve(t)),await y.remove(v.join(t,Dt)),r("\u{1F4E5} Fetching files...");let i=await ft(e,n,"GET","/get_files"),a={},u=0;for(let h of i){let w=v.join(t,h.path);await y.outputFile(w,h.content);let l=(await y.stat(w)).mtimeMs;u++,s?.(u,i.length),a[h.path]={mtimeMs:l,hash:tt(h.content)}}return r(`\u2714\uFE0F Synced ${i.length} file(s).`),{fileMap:a,pulled:u}}import Ln from"path";import jn from"chokidar";var Fn=5e3,An=/(^|[/\\])(\.DS_Store|Thumbs\.db|desktop\.ini)$/,et=class{viewsDir;onSync;debounceMs;watcher=null;debounceTimer=null;isShuttingDown=!1;dirty=!1;syncInFlight=!1;constructor(e){this.viewsDir=e.viewsDir,this.onSync=e.onSync,this.debounceMs=e.debounceMs??Fn}start(){if(this.watcher)return;let e=Ln.join(this.viewsDir,"src");this.watcher=jn.watch([e],{persistent:!0,ignoreInitial:!0,ignored:An}).on("change",()=>this.scheduleSync()).on("add",()=>this.scheduleSync()).on("unlink",()=>this.scheduleSync()).on("addDir",()=>this.scheduleSync()).on("unlinkDir",()=>this.scheduleSync())}setShuttingDown(e){this.isShuttingDown=e}async stop(){this.debounceTimer&&(clearTimeout(this.debounceTimer),this.debounceTimer=null),this.watcher&&(await this.watcher.close(),this.watcher=null)}scheduleSync(){this.isShuttingDown||(this.dirty=!0,this.debounceTimer&&clearTimeout(this.debounceTimer),this.debounceTimer=setTimeout(()=>this.flush(),this.debounceMs))}async flush(){if(this.debounceTimer=null,!(!this.dirty||this.isShuttingDown)){if(this.syncInFlight){this.debounceTimer=setTimeout(()=>this.flush(),this.debounceMs);return}this.dirty=!1,this.syncInFlight=!0;try{await this.onSync()}catch(e){let n=e;console.error("\u274C Sync failed:",n.body||n.message)}finally{this.syncInFlight=!1}}}};import pt from"fs-extra";import _n from"os";import he from"path";var me={localhost:"http://app.sleekcms.test/api",development:"https://app.sleekcms.dev/api",production:"https://app.sleekcms.com/api"};function jt(t){return me[t]||me.production}var In=he.join(_n.homedir(),"SleekCMS"),yt=he.join(In,"auth.json"),Lt;function fe(t){Lt=t||void 0}function Ft(t){let e=[];return t&&e.push(`_auth=${t}`),Lt&&e.push(`_dev=${Lt}`),e.length?e.join("; "):void 0}var F=class extends Error{status;body;constructor(e,n,r=""){super(e),this.name="UserAuthError",this.status=n,this.body=r}};async function pe(){try{let t=await pt.readJson(yt);return t&&t.userToken?t:null}catch{return null}}async function ye(t){await pt.outputJson(yt,t,{spaces:2});try{await pt.chmod(yt,384)}catch{}}async function we(){await pt.remove(yt)}async function K(t){let e={},n=Ft(t.userToken);n&&(e.Cookie=n),t.subdomain&&(e["x-subdomain"]=t.subdomain),t.slug&&(e.site=t.slug),t.body!==void 0&&(e["Content-Type"]="application/json");let r=await fetch(jt(t.env)+t.path,{method:t.method,headers:e,body:t.body!==void 0?JSON.stringify(t.body):void 0});if(!r.ok){let s=await r.text().catch(()=>"");throw new F(`${t.method} ${t.path} \u2192 ${r.status}: ${s}`,r.status,s)}return r.json()}async function be(t,e){let n={"Content-Type":"application/json"},r=Ft();r&&(n.Cookie=r);let s=await fetch(jt(t)+"/auth/otp",{method:"PUT",headers:n,body:JSON.stringify({email:e})});if(!s.ok){let a=await s.text().catch(()=>"");throw new F(`Failed to send OTP \u2192 ${s.status}: ${a}`,s.status,a)}return{otp:(await s.json().catch(()=>({}))).do_not_use_in_code}}async function At(t,e,n){let r={"Content-Type":"application/json"},s=Ft();s&&(r.Cookie=s);let i=await fetch(jt(t)+"/auth/login",{method:"POST",headers:r,body:JSON.stringify({email:e,otp:n})});if(!i.ok){let h=await i.text().catch(()=>"");throw new F(`Login failed \u2192 ${i.status}: ${h}`,i.status,h)}let a=i.headers.getSetCookie?.()??[],u=Nn(a);if(!u)throw new F("Login succeeded but no _auth cookie was returned.",500);return u}function Nn(t){for(let e of t){let n=e.match(/(?:^|;\s*)_auth=([^;]+)/);if(n&&n[1])return decodeURIComponent(n[1])}return null}async function _t(t,e){return K({env:t,userToken:e,method:"GET",path:"/org"})}async function Se(t,e,n){return K({env:t,userToken:e,method:"GET",path:"/site",subdomain:n})}function Wn(t){if(t==null)return"(unknown error)";if(typeof t=="string")return t;if(typeof t!="object")return String(t);let e=t,n=typeof e.file_path=="string"?e.file_path:"",r=typeof e.path=="string"?e.path:typeof e.filename=="string"?e.filename:"",s=n||r,i=e.line!=null?`:${e.line}`:"",a=e.column!=null?`:${e.column}`:"",u=typeof e.message=="string"&&e.message?e.message:typeof e.name=="string"&&e.name?e.name:"",h=n&&r&&r!==n?` (on page ${r})`:"";if(s)return`${s}${i}${a}${h}: ${u||"(no message)"}`;if(u)return u;try{return JSON.stringify(t)}catch{return"(unknown error)"}}async function xe(t,e,n,r){let s;try{s=await K({env:t,userToken:e,method:"GET",path:"/site_build",subdomain:n,slug:r})}catch{return null}if(!Array.isArray(s)||s.length===0)return null;let i=s[0],a=s.find(h=>typeof h.url=="string"&&h.url.length>0),u=Array.isArray(i.errors)?i.errors.map(Wn):[];return u.length>0?{status:"error",mode:"preview",errors:u,url:a?.url||void 0,at:i.updated_at?Date.parse(i.updated_at):void 0}:a?{status:"success",mode:"preview",url:a.url||void 0,at:a.updated_at?Date.parse(a.updated_at):void 0}:null}async function ve(t,e,n,r){let{token:s}=await K({env:t,userToken:e,method:"POST",path:"/site_user/api_token",subdomain:n,slug:r,body:{refresh:!1}});return s}async function Te(t,e,n){let r=await K({env:t,userToken:e,method:"POST",path:"/org",body:n?{name:n}:{}});return{id:r.id,name:r.name,subdomain:r.subdomain}}async function ke(t,e,n,r){let s=await K({env:t,userToken:e,method:"POST",path:"/site",subdomain:n,body:{name:r}});return{id:s.id,name:s.name,slug:s.slug}}var $e=500;function Hn(){return new Date().toTimeString().slice(0,8)}function wt(t){let e=t;if(e.body){try{let n=JSON.parse(e.body);if(n&&typeof n.message=="string")return n.message;if(n&&typeof n.error=="string")return n.error}catch{}return e.body}return e.message}async function Ee(t){t&&(await nt.remove(It.join(t,"src")),await nt.remove(It.join(t,".cache","state.json")))}var bt=class extends Gn{env="production";userToken="";email;catalog=[];synced=new Map;message;messageIsError=!1;agentMd;buildScript;isShuttingDown=!1;constructor(e,n){super(),this.agentMd=e,this.buildScript=n}changed(){this.emit("change")}flash(e,n=!1){this.message=e,this.messageIsError=n,this.changed()}appendLog(e,n){let r=this.synced.get(e);r&&(r.logs.push({time:Hn(),text:n}),r.logs.length>$e&&r.logs.splice(0,r.logs.length-$e),this.changed())}siteCount(){return this.synced.size}syncingCount(){let e=0;for(let n of this.synced.values())n.status==="syncing"&&e++;return e}watchingCount(){let e=0;for(let n of this.synced.values())(n.status==="watching"||n.status==="syncing")&&e++;return e}async init(e,n,r){this.env=e,this.userToken=n,r&&(this.email=r);let s=await _t(e,n);await this.buildCatalog(s)}async buildCatalog(e){let n=[];for(let r of e)try{n.push({org:r,sites:await Se(this.env,this.userToken,r.subdomain)})}catch(s){if(s instanceof F&&s.status===401)throw s;n.push({org:r,sites:[]})}this.catalog=n,this.changed()}isSynced(e){return this.synced.has(e)}availableSites(){let e=[];for(let n of this.catalog)for(let r of n.sites)this.synced.has(r.id)||e.push({org:n.org,site:r});return e}async addSite(e,n){if(this.synced.has(n.id))return;let r;try{r=await ve(this.env,this.userToken,e.subdomain,n.slug)}catch(i){this.flash(`Failed to authorize "${n.name}": ${wt(i)}`,!0);return}let s={org:e,site:n,siteToken:r,viewsDir:"",status:"syncing",logs:[]};this.synced.set(n.id,s),this.appendLog(n.id,"\u2795 added \u2014 pulling files"),this.changed();try{let i=await Mt({token:r,env:this.env,agentMd:this.agentMd,buildScript:this.buildScript,log:a=>this.appendLog(n.id,a),onProgress:(a,u)=>{s.progress={done:a,total:u},this.changed()}});s.viewsDir=i.viewsDir,s.progress=void 0,s.status="watching",s.lastSyncedAt=Date.now(),s.lastMsg=`pulled ${i.pulled} file(s)`,s.watcher=new et({viewsDir:i.viewsDir,onSync:()=>this.runSync(n.id)}),s.watcher.start(),this.watchBuildStatus(n.id),this.seedLastBuild(n.id),this.appendLog(n.id,"\u{1F440} watching for changes")}catch(i){let a=i;s.status="error",s.progress=void 0,s.lastMsg=a.body||a.message,this.appendLog(n.id,`\u274C ${a.body||a.message}`)}this.changed()}async removeSite(e){let n=this.synced.get(e);n&&(n.watcher?.setShuttingDown(!0),await n.watcher?.stop(),await n.buildWatcher?.close(),await Ee(n.viewsDir),this.synced.delete(e),this.changed())}buildSite(e,n=!1){let r=this.synced.get(e);if(!r||!r.viewsDir)return;let s=n?"live":"preview";this.writeBuildFile(r.viewsDir,{status:"building",mode:s,stage:"queued",url:r.lastBuild?.url,at:Date.now()}),Un("node",n?["build.mjs","--publish"]:["build.mjs"],{cwd:r.viewsDir,stdio:"ignore"}).on("error",u=>{this.writeBuildFile(r.viewsDir,{status:"error",mode:s,errors:[u.message],url:r.lastBuild?.url,at:Date.now()}),this.appendLog(e,`\u274C build: ${u.message}`)}),this.appendLog(e,n?"\u{1F680} publishing\u2026":"\u{1F528} building\u2026")}buildFile(e){return It.join(e,".cache","build.json")}async readBuildFile(e){try{let n=await nt.readJson(this.buildFile(e));return n&&n.status?n:null}catch{return null}}async writeBuildFile(e,n){let r=this.buildFile(e),s=`${r}.tmp`;try{await nt.outputJson(s,n),await nt.rename(s,r)}catch{}}watchBuildStatus(e){let n=this.synced.get(e);!n||!n.viewsDir||(n.buildWatcher=qn.watch(this.buildFile(n.viewsDir),{ignoreInitial:!1}).on("add",()=>{this.readBuildStatus(e)}).on("change",()=>{this.readBuildStatus(e)}))}async readBuildStatus(e){let n=this.synced.get(e);if(!n)return;let r=await this.readBuildFile(n.viewsDir);if(!r)return;let s=n.lastBuild?.url;n.lastBuild={status:r.status,mode:r.mode??"preview",url:r.url??(r.status==="success"?void 0:s),errors:r.errors,stage:r.stage,at:r.at},this.changed()}async seedLastBuild(e){let n=this.synced.get(e);if(!n)return;let r=await xe(this.env,this.userToken,n.org.subdomain,n.site.slug);if(!r)return;let s=this.synced.get(e);if(!s)return;let i=await this.readBuildFile(s.viewsDir);i?.at!=null&&(r.at==null||i.at>=r.at)||await this.writeBuildFile(s.viewsDir,r)}async ensureOrg(e){if(e)return e;if(this.catalog[0])return this.catalog[0].org;let n;try{n=await _t(this.env,this.userToken)}catch(r){return this.flash(`Couldn't check your organizations: ${wt(r)}`,!0),null}if(n.length>0){try{await this.buildCatalog(n)}catch{}return n[0]}try{let r=this.email?`${this.email.split("@")[0]}'s Sites`:"My Sites";this.flash("No organization yet \u2014 creating one\u2026");let s=await Te(this.env,this.userToken,r);return this.catalog=[...this.catalog,{org:s,sites:[]}],this.changed(),s}catch(r){return this.flash(`Could not create an organization: ${wt(r)}`,!0),null}}async createNewSite(e,n){let r=await this.ensureOrg(n);if(!r)return;let s;try{s=await ke(this.env,this.userToken,r.subdomain,e)}catch(a){this.flash(`Could not create "${e}": ${wt(a)}`,!0);return}let i=this.catalog.find(a=>a.org.id===r.id);i&&!i.sites.some(a=>a.id===s.id)&&(i.sites=[...i.sites,s]),this.flash(`Created "${s.name}".`),await this.addSite(r,s)}async refetch(e){await this.runSync(e,{flush:!0})}async runSync(e,n={}){let r=this.synced.get(e);if(!(!r||!r.viewsDir||r.status==="paused")){r.status="syncing",this.changed();try{let s=await Mt({token:r.siteToken,env:this.env,viewsDir:r.viewsDir,agentMd:this.agentMd,buildScript:this.buildScript,flush:n.flush,log:i=>this.appendLog(e,i),onProgress:(i,a)=>{r.progress={done:i,total:a},this.changed()}});if(r.progress=void 0,r.status="watching",r.lastSyncedAt=Date.now(),n.flush)r.lastMsg=`re-fetched ${s.pulled} file(s)`;else{let i=[s.renamed>0?`renamed ${s.renamed}`:"",s.pushed>0?`pushed ${s.pushed} file(s)`:""].filter(Boolean);r.lastMsg=i.length>0?i.join(", "):"up to date"}}catch(s){let i=s;r.status="error",r.progress=void 0,r.lastMsg=i.body||i.message,this.appendLog(e,`\u274C ${i.body||i.message}`)}this.changed()}}async togglePause(e){let n=this.synced.get(e);!n||!n.viewsDir||(n.status==="paused"?(n.watcher=new et({viewsDir:n.viewsDir,onSync:()=>this.runSync(e)}),n.watcher.start(),n.status="watching",this.appendLog(e,"\u25B6 resumed \u2014 watching for changes")):(n.watcher?.setShuttingDown(!0),await n.watcher?.stop(),n.watcher=void 0,n.progress=void 0,n.status="paused",this.appendLog(e,"\u23F8 paused")),this.changed())}async cleanupAll(){for(let e of this.synced.values())e.watcher?.setShuttingDown(!0),await e.watcher?.stop(),await e.buildWatcher?.close(),await Ee(e.viewsDir)}async exit(){this.isShuttingDown||(this.isShuttingDown=!0,await this.cleanupAll(),this.emit("exit"))}async logout(){this.isShuttingDown||(this.isShuttingDown=!0,await we(),await this.cleanupAll(),this.emit("logout"))}};import{useEffect as rr,useState as Ae}from"react";import{Box as sr,Text as ir,useInput as or}from"ink";import{useState as rt}from"react";import{Box as st,Text as Y}from"ink";import Be from"ink-text-input";import{jsx as G,jsxs as X}from"react/jsx-runtime";function Ce(t){let e=t;return e?.body||e?.message||String(t)}function Pe({env:t,initialError:e,onAuthed:n}){let[r,s]=rt("email"),[i,a]=rt(""),[u,h]=rt(""),[w,l]=rt(e),[b,S]=rt(),g=async C=>{let k=C.trim();if(k){l(void 0),s("busy");try{let{otp:P}=await be(t,k);if(a(k),P){let D=await At(t,k,P);await n(D,k);return}S(`OTP sent to ${k}`),s("otp")}catch(P){l(Ce(P)),s("email")}}},x=async C=>{let k=C.trim();if(k){l(void 0),s("busy");try{let P=await At(t,i,k);await n(P,i)}catch(P){l(Ce(P)),h(""),s("otp")}}};return X(st,{flexDirection:"column",children:[X(Y,{bold:!0,children:["\u25C6 SleekCMS \u2014 sign in",t!=="production"?` (${t})`:""]}),w?X(Y,{color:"red",children:["\u2717 ",w]}):null,r==="email"&&X(st,{marginTop:1,children:[G(Y,{children:"Email: "}),G(Be,{value:i,onChange:a,onSubmit:g,placeholder:"you@example.com"})]}),r==="otp"&&X(st,{flexDirection:"column",marginTop:1,children:[b?G(Y,{color:"green",children:b}):null,X(st,{children:[G(Y,{children:"Enter OTP: "}),G(Be,{value:u,onChange:h,onSubmit:x})]})]}),r==="busy"&&G(st,{marginTop:1,children:G(Y,{children:"Working\u2026"})})]})}import{Fragment as Kn,useEffect as it,useMemo as Yn,useState as O}from"react";import{Box as p,Text as d,useInput as Xn,useStdout as zn}from"ink";import Re from"ink-text-input";import Jn from"node:os";function Nt(t){if(!t)return"\u2014";let e=Jn.homedir();return t.startsWith(e)?"~"+t.slice(e.length):t}function Wt(t){if(!t)return"\u2014";let e=Math.floor((Date.now()-t)/1e3);if(e<5)return"just now";if(e<60)return`${e}s ago`;let n=Math.floor(e/60);if(n<60)return`${n}m ago`;let r=Math.floor(n/60);return r<24?`${r}h ago`:`${Math.floor(r/24)}d ago`}function xt(t){return!t||t.total<=0?null:Math.round(t.done/t.total*100)}var St=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"];function Oe(t){return St[(t%St.length+St.length)%St.length]}function vt(t){switch(t){case"syncing":return{dot:"\u25CF",color:"green",label:"syncing"};case"watching":return{dot:"\u25CB",color:"gray",label:"watching"};case"paused":return{dot:"\u2016",color:"yellow",label:"paused"};case"error":return{dot:"\u2717",color:"red",label:"error"}}}function Me(t){if(!t)return{dot:"\xB7",color:"gray",label:"\u2014"};switch(t.status){case"building":return{dot:"\u2234",color:"yellow",label:"building"};case"error":return{dot:"\u2717",color:"red",label:"failed"};case"success":return{dot:"\u2713",color:"green",label:t.mode==="live"?"live":"preview"}}}import{Fragment as ot,jsx as o,jsxs as m}from"react/jsx-runtime";var U=(t,e)=>e<=0?0:Math.max(0,Math.min(t,e-1)),Vn=16,Qn=5,Zn="greenBright",De="blueBright",Le="magentaBright";function je({k:t,bg:e=Zn}){return o(d,{color:"black",backgroundColor:e,children:` ${t} `})}function I({k:t,label:e,width:n=16,bg:r}){return m(p,{width:n,children:[o(je,{k:t,bg:r}),o(d,{color:"gray",children:` ${e}`})]})}function B({k:t,label:e,bg:n}){return m(p,{marginBottom:1,children:[o(p,{width:9,children:o(je,{k:t,bg:n})}),o(d,{color:"gray",children:e})]})}function tr({launchers:t}){return m(p,{flexDirection:"column",borderStyle:"round",borderColor:"green",paddingX:2,paddingY:1,width:66,children:[m(p,{justifyContent:"space-between",children:[o(d,{color:"green",bold:!0,children:"KEYBOARD SHORTCUTS"}),o(d,{color:"gray",children:"? or esc to close"})]}),m(p,{marginTop:1,children:[m(p,{flexDirection:"column",width:34,children:[o(d,{color:"cyan",bold:!0,children:"Navigate"}),o(B,{k:"\u2191\u2193",label:"move selection"}),o(B,{k:"tab",label:"focus logs \xB7 \u2191\u2193 scroll"}),o(B,{k:"esc",label:"clear filter / back"}),o(p,{marginTop:1,children:o(d,{color:"cyan",bold:!0,children:"Global"})}),o(B,{k:"/",label:"search sites"}),o(B,{k:"n",label:"new site"}),o(B,{k:"?",label:"toggle this help",bg:De}),o(B,{k:"q",label:"logout"}),o(B,{k:"ctrl+c",label:"quit"})]}),m(p,{flexDirection:"column",flexGrow:1,children:[o(d,{color:"cyan",bold:!0,children:"Site actions"}),o(B,{k:"s",label:"start sync"}),o(B,{k:"d",label:"disconnect"}),o(B,{k:"p",label:"pause / resume sync"}),o(B,{k:"b",label:"build preview"}),o(B,{k:"B",label:"publish live"}),o(B,{k:"o",label:"open preview url"}),t.map((e,n)=>o(B,{k:String(n+1),label:`open in ${e.label}`,bg:Le},e.key))]})]})]})}function er({percent:t,width:e=28}){let n=Math.round(Math.max(0,Math.min(100,t))/100*e);return m(d,{children:[o(d,{color:"green",children:"\u2588".repeat(n)}),o(d,{color:"gray",children:"\u2591".repeat(Math.max(0,e-n))})]})}function nr({frame:t,width:e=24,seg:n=6}){let r=e+n,s=t%r-n,i="";for(let a=0;a<e;a++)i+=a>=s&&a<s+n?"\u25AE":"\u25AF";return o(d,{color:"yellow",children:i})}function Fe({controller:t}){let{stdout:e}=zn(),n=Yn(()=>ae(),[]),[,r]=O(0),[s,i]=O(()=>new Date),[a,u]=O(null),[h,w]=O(()=>t.synced.size>0||t.catalog.some(f=>f.sites.length>0)?"dashboard":t.catalog.length<=1?"newName":"newOrg"),[l,b]=O(0),[S,g]=O(""),[x,C]=O(!1),[k,P]=O(""),[D,L]=O(!1),[q,z]=O(0),[qt,Ht]=O(!1),[Ge,Ue]=O(!1),[at,ct]=O("list"),[qe,V]=O(0),Jt=()=>r(c=>c+1);it(()=>(t.on("change",Jt),()=>{t.off("change",Jt)}),[t]),it(()=>{let c,f=()=>{i(new Date),c=setTimeout(f,6e4-Date.now()%6e4)};return c=setTimeout(f,6e4-Date.now()%6e4),()=>clearTimeout(c)},[]);let _=t.catalog.flatMap(c=>c.sites.map(f=>({org:c.org,site:f,entry:t.synced.get(f.id)}))).sort((c,f)=>(c.entry?0:1)-(f.entry?0:1)),N=k.trim().toLowerCase(),R=N?_.filter(c=>c.site.name.toLowerCase().includes(N)||(c.org.name||c.org.subdomain||"").toLowerCase().includes(N)):_,H=R.findIndex(c=>c.site.id===a);H<0&&(H=0);let $=R[H],T=$?.entry,lt=Math.max(3,(e?.rows??30)-26),W=T?.logs??[],kt=Math.max(0,W.length-lt),He=Math.min(qe,kt),ut=W.length-He,Kt=W.slice(Math.max(0,ut-lt),ut),Je=$?.site.id;it(()=>V(0),[Je]);let A=T?.lastBuild,$t=A?.status==="building",Et=Me(A),dt=$t;if(!dt){for(let c of t.synced.values())if(c.status==="syncing"){dt=!0;break}}it(()=>{if(!dt)return;let c=setInterval(()=>z(f=>f+1),120);return()=>clearInterval(c)},[dt]);let Yt=R.findIndex(c=>!c.entry),J=Math.max(Qn,(e?.rows??30)-Vn),Q=R.length,gt=Q>J,Ke=Math.floor(J/2),Z=gt?Math.max(0,Math.min(H-Ke,Q-J)):0,Bt=Math.min(Q,Z+J),Ye=R.slice(Z,Bt);it(()=>{h!=="dashboard"||x||_.length>0||(g(""),t.catalog.length<=1?w("newName"):(b(0),w("newOrg")))},[_.length,h,x,t.catalog.length]);let mt=c=>{if(R.length===0)return;let f=U(H+c,R.length);u(R[f].site.id)},Xe=()=>{if($){if($.entry){t.flash("Already syncing \u2014 press d to disconnect.");return}t.addSite($.org,$.site)}},ze=()=>{$?.entry&&t.removeSite($.site.id)},Ve=()=>{g(""),t.catalog.length<=1?w("newName"):(b(0),w("newOrg"))},Qe=c=>{if(!T){t.flash("Press s to start syncing this site first.",!0);return}Ue(!0);let f=c.run(T.viewsDir);t.flash(f?`Opened ${c.label} at ${Nt(T.viewsDir)}`:`Couldn't open ${c.label}.`,!f)},Ze=()=>{if(!T){t.flash("Press s to start syncing this site first.",!0);return}t.togglePause(T.site.id)},Xt=c=>{if(!T){t.flash("Press s to start syncing this site first.",!0);return}t.buildSite(T.site.id,c),t.flash(c?"Publishing \u2014 making this live\u2026":"Building preview\u2026")},tn=()=>{let c=T?.lastBuild?.url;if(!c){t.flash("No build URL yet \u2014 press b to build.",!0);return}t.flash(oe(c)?`Opening ${c}`:"Couldn't open the browser.",!1)};Xn((c,f)=>{if(qt){(c==="?"||f.escape)&&Ht(!1);return}if(h==="newOrg"){f.escape?w("dashboard"):f.upArrow?b(E=>U(E-1,t.catalog.length)):f.downArrow?b(E=>U(E+1,t.catalog.length)):f.return&&w("newName");return}if(D){f.escape?(L(!1),P(""),u(null)):f.return?L(!1):f.upArrow?mt(-1):f.downArrow&&mt(1);return}if(f.tab){at==="logs"?ct("list"):T&&ct("logs"),V(0);return}if(at==="logs"){if(f.escape){ct("list"),V(0);return}if(f.upArrow)return void V(E=>Math.min(E+1,kt));if(f.downArrow)return void V(E=>Math.max(0,E-1))}if(f.escape){P(""),u(null);return}if(c==="?")return void Ht(!0);if(c==="/")return ct("list"),void L(!0);if(c==="n")return void Ve();if(c==="q")return void t.logout();if(f.upArrow)return mt(-1);if(f.downArrow)return mt(1);if(c==="s")return Xe();if(c==="d")return ze();if(c==="p")return Ze();if(c==="b")return Xt(!1);if(c==="B")return Xt(!0);if(c==="o")return tn();if(c>="1"&&c<="9"){let E=n[parseInt(c,10)-1];if(E)return Qe(E)}},{isActive:h!=="newName"});let en=async c=>{let f=c.trim();if(!f){w("dashboard");return}let E=t.catalog[U(l,t.catalog.length)]?.org??t.catalog[0]?.org;C(!0),w("dashboard"),await t.createNewSite(f,E),C(!1)},zt=m(p,{justifyContent:"space-between",paddingX:1,children:[m(p,{children:[o(d,{color:"green",bold:!0,children:"\u25C6 SleekCMS"}),o(d,{color:"gray",children:" \u2502 "}),o(d,{children:t.email??"signed in"})]}),m(p,{children:[m(d,{color:"gray",children:[N?`${R.length}/${_.length}`:_.length," sites \xB7 "]}),m(d,{color:"green",children:[t.watchingCount()," watching"]}),o(d,{color:"gray",children:` \xB7 ${s.toTimeString().slice(0,5)}`})]})]});return qt?m(p,{flexDirection:"column",children:[zt,o(p,{marginTop:1,justifyContent:"center",children:o(tr,{launchers:n})})]}):m(p,{flexDirection:"column",children:[zt,m(p,{children:[m(p,{flexDirection:"column",borderStyle:"round",borderColor:"green",width:38,paddingX:1,children:[m(p,{justifyContent:"space-between",children:[o(d,{color:"green",bold:!0,children:"SITE WORKSPACES"}),_.length>J&&!D&&!N?o(d,{color:"gray",children:"/ filter"}):null]}),D?m(p,{children:[o(d,{color:"cyan",children:"/ "}),o(Re,{value:k,onChange:P,onSubmit:()=>L(!1),placeholder:"type to filter\u2026"})]}):N?o(d,{color:"gray",children:`/ ${k} \xB7 ${R.length} match${R.length===1?"":"es"}`}):null,o(p,{flexDirection:"column",marginTop:1,minHeight:gt?J+3:void 0,children:R.length===0?o(d,{color:"gray",children:N?`no matches for \u201C${k}\u201D`:"no sites \u2014 press n to create one"}):m(ot,{children:[gt?o(d,{color:"gray",children:Z>0?` \u2191 ${Z} more`:" "}):null,Ye.map((c,f)=>{let E=Z+f,Vt=c.entry?vt(c.entry.status):{dot:"\xB7",color:"gray",label:"idle"},Qt=xt(c.entry?.progress),nn=c.entry?c.entry.status==="syncing"&&Qt!=null?`${Qt}%`:c.entry.status==="paused"?"paused":"--":"",ht=E===H,rn=E===Yt&&Yt>0;return m(Kn,{children:[rn?o(d,{color:"gray",children:"\u2500".repeat(34)}):null,m(p,{justifyContent:"space-between",children:[m(p,{children:[o(d,{color:ht?"green":"gray",children:ht?"\u276F ":" "}),m(d,{color:c.entry?.status==="watching"||c.entry?.status==="syncing"?"green":Vt.color,children:[c.entry?.status==="syncing"?Oe(q):c.entry?.status==="watching"?"\u25CF":Vt.dot," "]}),o(d,{color:ht?"white":c.entry?void 0:"gray",bold:ht,children:c.site.name})]}),o(d,{color:c.entry?.status==="syncing"?"green":"gray",children:nn})]})]},c.site.id)}),gt?o(d,{color:"gray",children:Bt<Q?` \u2193 ${Q-Bt} more`:" "}):null]})}),o(p,{marginTop:1,children:o(d,{color:"gray",children:"+ new site \xB7 n"})})]}),m(p,{flexDirection:"column",flexGrow:1,marginLeft:1,children:[o(p,{flexDirection:"column",borderStyle:"round",borderColor:"gray",paddingX:1,children:$?m(ot,{children:[m(d,{children:[$.org.name||$.org.subdomain?m(d,{color:"gray",children:[$.org.name||$.org.subdomain," / "]}):null,o(d,{color:"cyan",bold:!0,children:$.site.name})]}),m(p,{marginTop:1,children:[o(d,{color:"gray",children:"status "}),T?o(d,{color:vt(T.status).color,children:`: ${vt(T.status).label}`}):o(d,{color:"gray",children:": idle \u2014 not syncing (press s to start)"})]}),m(p,{children:[o(d,{color:"gray",children:"path "}),o(d,{wrap:"truncate-end",children:T?.viewsDir?Nt(T.viewsDir):"\u2014"})]}),m(p,{children:[o(d,{color:"gray",children:"synced "}),o(d,{children:Wt(T?.lastSyncedAt)}),o(d,{color:"gray",children:" progress "}),o(d,{color:T?.status==="syncing"?"green":"gray",children:T?.status==="syncing"?`${xt(T.progress)??0}%`:"\u2014"})]}),o(p,{marginTop:1,children:o(er,{percent:T?T.status==="syncing"?xt(T.progress)??0:T.status==="watching"?100:0:0})}),T?m(ot,{children:[m(p,{marginTop:1,children:[o(d,{color:"gray",children:"build "}),o(d,{color:Et.color,children:`${Et.dot} ${Et.label}`}),o(d,{color:"gray",children:" last "}),o(d,{children:$t?"in progress":Wt(A?.at)})]}),m(p,{children:[o(d,{color:"gray",children:"url "}),A?.url?o(d,{color:"cyan",wrap:"truncate-end",children:A.url}):o(d,{color:"gray",children:"\u2014"})]}),A?.status==="error"&&A.errors?.length?m(p,{children:[o(d,{color:"red",children:"\u258C "}),o(d,{color:"red",wrap:"truncate-end",children:`\u2717 ${A.errors[0]}`})]}):null,$t?m(p,{children:[o(nr,{frame:q}),o(d,{color:"gray",children:` ${A?.stage??"building"}`})]}):null]}):null]}):o(d,{color:"gray",children:"No site selected."})}),h==="dashboard"?m(p,{flexDirection:"column",borderStyle:"round",borderColor:at==="logs"?"green":"gray",paddingX:1,marginTop:1,height:lt+4,flexShrink:0,overflowY:"hidden",children:[m(p,{justifyContent:"space-between",children:[m(d,{children:[o(d,{color:"cyan",bold:!0,children:"LOGS \xB7 "}),o(d,{color:"white",children:$?.site.name??"\u2014"})]}),T&&W.length>0?at==="logs"?o(d,{color:"green",children:`\u2191\u2193 scroll \xB7 esc back${kt>0?` \xB7 ${ut}/${W.length}`:""}`}):W.length>lt?o(d,{color:"gray",children:"tab to scroll"}):null:null]}),o(p,{flexDirection:"column",marginTop:1,children:!T||W.length===0?o(d,{color:"gray",children:"no activity yet"}):Kt.map((c,f)=>m(d,{wrap:"truncate-end",children:[m(d,{color:"gray",children:[c.time," "]}),c.text]},ut-Kt.length+f))})]}):m(p,{flexDirection:"column",borderStyle:"round",borderColor:"blue",paddingX:1,marginTop:1,flexGrow:1,children:[h==="newOrg"&&m(ot,{children:[o(d,{color:"cyan",bold:!0,children:"CREATE SITE \u2014 PICK ORG"}),o(d,{color:"gray",children:"\u2191/\u2193 select \xB7 \u23CE next \xB7 esc cancel"}),o(p,{flexDirection:"column",marginTop:1,children:t.catalog.map((c,f)=>m(d,{color:f===U(l,t.catalog.length)?"blue":void 0,bold:f===U(l,t.catalog.length),children:[f===U(l,t.catalog.length)?"\u276F ":" ",c.org.name||c.org.subdomain]},c.org.id))})]}),h==="newName"&&m(ot,{children:[o(d,{color:"cyan",bold:!0,children:"CREATE SITE"}),m(p,{marginTop:1,children:[o(d,{children:"New site name: "}),o(Re,{value:S,onChange:g,onSubmit:en})]}),o(d,{color:"gray",children:"\u23CE create \xB7 empty + \u23CE to cancel"})]})]})]})]}),t.message?o(p,{paddingX:1,children:m(d,{color:t.messageIsError?"red":"gray",wrap:"truncate-end",children:[t.messageIsError?"\u2717 ":"",t.message]})}):null,m(p,{flexDirection:"column",marginTop:1,children:[m(p,{paddingX:1,justifyContent:"space-between",children:[m(p,{flexWrap:"wrap",children:[o(I,{k:"\u2191\u2193",label:"select"}),o(I,{k:"/",label:"search"}),o(I,{k:"s",label:"start sync"}),o(I,{k:"d",label:"disconnect"}),_.length===0?o(I,{k:"n",label:"new site"}):null,o(I,{k:"ctrl+c",label:"quit",width:14})]}),o(I,{k:"?",label:"all keys",width:12,bg:De})]}),!Ge&&n.length>0?o(p,{paddingX:1,marginTop:1,flexWrap:"wrap",children:n.map((c,f)=>o(I,{k:String(f+1),label:c.label,bg:Le},c.key))}):null]})]})}import{jsx as Tt}from"react/jsx-runtime";function _e(t){let e=t;return e?.body||e?.message||String(t)}function Ie({controller:t,env:e,devSecret:n,savedToken:r,savedEmail:s}){let[i,a]=Ae(r?"loading":"auth"),[u,h]=Ae();or((l,b)=>{b.ctrl&&l==="c"&&t.exit()}),rr(()=>{r&&t.init(e,r,s).then(()=>a("manage")).catch(l=>{l instanceof F&&l.status===401?h("Saved session expired \u2014 please sign in again."):h(_e(l)),a("auth")})},[]);let w=async(l,b)=>{h(void 0),await ye({env:e,userToken:l,devSecret:n,email:b}),a("loading");try{await t.init(e,l,b),a("manage")}catch(S){h(_e(S)),a("auth")}};return i==="auth"?Tt(Pe,{env:e,initialError:u,onAuthed:w}):i==="loading"?Tt(sr,{children:Tt(ir,{children:"Loading your sites\u2026 "})}):Tt(Fe,{controller:t})}import{jsx as hr}from"react/jsx-runtime";var ur=cr(import.meta.url),Gt=re();if(Gt.version){let t=ur("../package.json");console.log(t.version),process.exit(0)}var We=Ut.dirname(ar(import.meta.url)),dr=Ne(Ut.join(We,"AGENT.md"),"utf-8"),gr=Ne(Ut.join(We,"build.mjs"),"utf-8");async function mr(){let t=new bt(dr,gr),e=await pe(),n=(Gt.env??e?.env??"production").toLowerCase(),r=Gt.dev??process.env.SLEEKCMS_DEV_SECRET??e?.devSecret;fe(r),process.stdout.isTTY&&process.stdout.write("\x1B[2J\x1B[3J\x1B[H");let s=lr(hr(Ie,{controller:t,env:n,devSecret:r,savedToken:e?.userToken,savedEmail:e?.email}),{exitOnCtrlC:!1}),i=a=>{s.unmount(),console.log(a),process.exit(0)};t.once("exit",()=>i("\u2713 Stopped. Local site files were cleaned up.")),t.once("logout",()=>i("\u{1F44B} Logged out. Run `sleekcms` to sign in again.")),process.on("SIGINT",()=>{t.exit()}),process.on("SIGTERM",()=>{t.exit()}),await s.waitUntilExit()}mr().catch(t=>{let e=t;console.error("\u274C",e.body||e.message),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sleekcms/sync",
3
- "version": "2.11.0",
3
+ "version": "2.12.0",
4
4
  "description": "Edit SleekCMS sites locally — models, content, templates, images — with live two-way sync and AI agent support.",
5
5
  "keywords": [
6
6
  "sleekcms",