@sleekcms/sync 2.9.0 → 2.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{readFileSync as Le}from"node:fs";import{fileURLToPath as
|
|
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",`
|
|
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
|
|
7
|
-
`)){let o=
|
|
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(`
|
|
8
8
|
`)+`
|
|
9
|
-
`)}async function xr(t,e,r,n,i){Et.delete(S.resolve(t)),await f.remove(S.join(t,Mt)),n("\u{1F4E5} Fetching files...");let o=await Ct(e,r,"GET","/get_files"),l={},h=0;for(let p of o){let x=S.join(t,p.path);await f.outputFile(x,p.content);let w=(await f.stat(x)).mtimeMs;h++,i?.(h,o.length),l[p.path]={mtimeMs:w}}return n(`\u2714\uFE0F Synced ${o.length} file(s).`),{fileMap:l,pulled:h}}import Sr from"path";import vr from"chokidar";var Tr=5e3,kr=/(^|[/\\])(\.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??Tr}start(){if(this.watcher)return;let e=Sr.join(this.viewsDir,"src");this.watcher=vr.watch([e],{persistent:!0,ignoreInitial:!0,ignored:kr}).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 r=e;console.error("\u274C Sync failed:",r.body||r.message)}finally{this.syncInFlight=!1}}}};import gt from"fs-extra";import Br 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 Er=ae.join(Br.homedir(),"SleekCMS"),ht=ae.join(Er,"auth.json"),Dt;function ce(t){Dt=t||void 0}function $t(t){let e=[];return t&&e.push(`_auth=${t}`),Dt&&e.push(`_dev=${Dt}`),e.length?e.join("; "):void 0}var L=class extends Error{status;body;constructor(e,r,n=""){super(e),this.name="UserAuthError",this.status=r,this.body=n}};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={},r=$t(t.userToken);r&&(e.Cookie=r),t.subdomain&&(e["x-subdomain"]=t.subdomain),t.slug&&(e.site=t.slug),t.body!==void 0&&(e["Content-Type"]="application/json");let n=await fetch(Ot(t.env)+t.path,{method:t.method,headers:e,body:t.body!==void 0?JSON.stringify(t.body):void 0});if(!n.ok){let i=await n.text().catch(()=>"");throw new L(`${t.method} ${t.path} \u2192 ${n.status}: ${i}`,n.status,i)}return n.json()}async function ge(t,e){let r={"Content-Type":"application/json"},n=$t();n&&(r.Cookie=n);let i=await fetch(Ot(t)+"/auth/otp",{method:"PUT",headers:r,body:JSON.stringify({email:e})});if(!i.ok){let l=await i.text().catch(()=>"");throw new L(`Failed to send OTP \u2192 ${i.status}: ${l}`,i.status,l)}return{otp:(await i.json().catch(()=>({}))).do_not_use_in_code}}async function Lt(t,e,r){let n={"Content-Type":"application/json"},i=$t();i&&(n.Cookie=i);let o=await fetch(Ot(t)+"/auth/login",{method:"POST",headers:n,body:JSON.stringify({email:e,otp:r})});if(!o.ok){let p=await o.text().catch(()=>"");throw new L(`Login failed \u2192 ${o.status}: ${p}`,o.status,p)}let l=o.headers.getSetCookie?.()??[],h=Cr(l);if(!h)throw new L("Login succeeded but no _auth cookie was returned.",500);return h}function Cr(t){for(let e of t){let r=e.match(/(?:^|;\s*)_auth=([^;]+)/);if(r&&r[1])return decodeURIComponent(r[1])}return null}async function Rt(t,e){return q({env:t,userToken:e,method:"GET",path:"/org"})}async function he(t,e,r){return q({env:t,userToken:e,method:"GET",path:"/site",subdomain:r})}async function pe(t,e,r,n){let i;try{i=await q({env:t,userToken:e,method:"GET",path:"/site_build",subdomain:r,slug:n})}catch{return null}if(!Array.isArray(i)||i.length===0)return null;let o=i[0],l=i.find(p=>typeof p.url=="string"&&p.url.length>0),h=Array.isArray(o.errors)?o.errors.map(p=>String(p)):[];return h.length>0?{status:"error",mode:"preview",errors:h,url:l?.url||void 0,at:o.updated_at?Date.parse(o.updated_at):void 0}:l?{status:"success",mode:"preview",url:l.url||void 0,at:l.updated_at?Date.parse(l.updated_at):void 0}:null}async function me(t,e,r,n){let{token:i}=await q({env:t,userToken:e,method:"POST",path:"/site_user/api_token",subdomain:r,slug:n,body:{refresh:!1}});return i}async function fe(t,e,r){let n=await q({env:t,userToken:e,method:"POST",path:"/org",body:r?{name:r}:{}});return{id:n.id,name:n.name,subdomain:n.subdomain}}async function ye(t,e,r,n){let i=await q({env:t,userToken:e,method:"POST",path:"/site",subdomain:r,body:{name:n}});return{id:i.id,name:i.name,slug:i.slug}}var we=500;function Or(){return new Date().toTimeString().slice(0,8)}function pt(t){let e=t;if(e.body){try{let r=JSON.parse(e.body);if(r&&typeof r.message=="string")return r.message;if(r&&typeof r.error=="string")return r.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 mt=class extends Pr{env="production";userToken="";email;catalog=[];synced=new Map;message;messageIsError=!1;agentMd;buildScript;isShuttingDown=!1;constructor(e,r){super(),this.agentMd=e,this.buildScript=r}changed(){this.emit("change")}flash(e,r=!1){this.message=e,this.messageIsError=r,this.changed()}appendLog(e,r){let n=this.synced.get(e);n&&(n.logs.push({time:Or(),text:r}),n.logs.length>we&&n.logs.splice(0,n.logs.length-we),this.changed())}siteCount(){return this.synced.size}syncingCount(){let e=0;for(let r of this.synced.values())r.status==="syncing"&&e++;return e}watchingCount(){let e=0;for(let r of this.synced.values())(r.status==="watching"||r.status==="syncing")&&e++;return e}async init(e,r,n){this.env=e,this.userToken=r,n&&(this.email=n);let i=await Rt(e,r);await this.buildCatalog(i)}async buildCatalog(e){let r=[];for(let n of e)try{r.push({org:n,sites:await he(this.env,this.userToken,n.subdomain)})}catch(i){if(i instanceof L&&i.status===401)throw i;r.push({org:n,sites:[]})}this.catalog=r,this.changed()}isSynced(e){return this.synced.has(e)}availableSites(){let e=[];for(let r of this.catalog)for(let n of r.sites)this.synced.has(n.id)||e.push({org:r.org,site:n});return e}async addSite(e,r){if(this.synced.has(r.id))return;let n;try{n=await me(this.env,this.userToken,e.subdomain,r.slug)}catch(o){this.flash(`Failed to authorize "${r.name}": ${pt(o)}`,!0);return}let i={org:e,site:r,siteToken:n,viewsDir:"",status:"syncing",logs:[]};this.synced.set(r.id,i),this.appendLog(r.id,"\u2795 added \u2014 pulling files"),this.changed();try{let o=await Pt({token:n,env:this.env,agentMd:this.agentMd,buildScript:this.buildScript,log:l=>this.appendLog(r.id,l),onProgress:(l,h)=>{i.progress={done:l,total:h},this.changed()}});i.viewsDir=o.viewsDir,i.progress=void 0,i.status="watching",i.lastSyncedAt=Date.now(),i.lastMsg=`pulled ${o.pulled} file(s)`,i.watcher=new V({viewsDir:o.viewsDir,onSync:()=>this.runSync(r.id)}),i.watcher.start(),this.watchBuildStatus(r.id),this.seedLastBuild(r.id),this.appendLog(r.id,"\u{1F440} watching for changes")}catch(o){let l=o;i.status="error",i.progress=void 0,i.lastMsg=l.body||l.message,this.appendLog(r.id,`\u274C ${l.body||l.message}`)}this.changed()}async removeSite(e){let r=this.synced.get(e);r&&(r.watcher?.setShuttingDown(!0),await r.watcher?.stop(),await r.buildWatcher?.close(),await be(r.viewsDir),this.synced.delete(e),this.changed())}buildSite(e,r=!1){let n=this.synced.get(e);if(!n||!n.viewsDir)return;let i=r?"live":"preview";this.writeBuildFile(n.viewsDir,{status:"building",mode:i,stage:"queued",url:n.lastBuild?.url,at:Date.now()}),Mr("node",r?["build.mjs","--deploy"]:["build.mjs"],{cwd:n.viewsDir,stdio:"ignore"}).on("error",h=>{this.writeBuildFile(n.viewsDir,{status:"error",mode:i,errors:[h.message],url:n.lastBuild?.url,at:Date.now()}),this.appendLog(e,`\u274C build: ${h.message}`)}),this.appendLog(e,r?"\u{1F680} deploying\u2026":"\u{1F528} building\u2026")}buildFile(e){return At.join(e,".cache","build.json")}async readBuildFile(e){try{let r=await Q.readJson(this.buildFile(e));return r&&r.status?r:null}catch{return null}}async writeBuildFile(e,r){let n=this.buildFile(e),i=`${n}.tmp`;try{await Q.outputJson(i,r),await Q.rename(i,n)}catch{}}watchBuildStatus(e){let r=this.synced.get(e);!r||!r.viewsDir||(r.buildWatcher=Dr.watch(this.buildFile(r.viewsDir),{ignoreInitial:!1}).on("add",()=>{this.readBuildStatus(e)}).on("change",()=>{this.readBuildStatus(e)}))}async readBuildStatus(e){let r=this.synced.get(e);if(!r)return;let n=await this.readBuildFile(r.viewsDir);if(!n)return;let i=r.lastBuild?.url;r.lastBuild={status:n.status,mode:n.mode??"preview",url:n.url??(n.status==="success"?void 0:i),errors:n.errors,stage:n.stage,at:n.at},this.changed()}async seedLastBuild(e){let r=this.synced.get(e);if(!r)return;let n=await pe(this.env,this.userToken,r.org.subdomain,r.site.slug);if(!n)return;let i=this.synced.get(e);if(!i)return;let o=await this.readBuildFile(i.viewsDir);o?.at!=null&&(n.at==null||o.at>=n.at)||await this.writeBuildFile(i.viewsDir,n)}async ensureOrg(e){if(e)return e;if(this.catalog[0])return this.catalog[0].org;let r;try{r=await Rt(this.env,this.userToken)}catch(n){return this.flash(`Couldn't check your organizations: ${pt(n)}`,!0),null}if(r.length>0){try{await this.buildCatalog(r)}catch{}return r[0]}try{let n=this.email?`${this.email.split("@")[0]}'s Sites`:"My Sites";this.flash("No organization yet \u2014 creating one\u2026");let i=await fe(this.env,this.userToken,n);return this.catalog=[...this.catalog,{org:i,sites:[]}],this.changed(),i}catch(n){return this.flash(`Could not create an organization: ${pt(n)}`,!0),null}}async createNewSite(e,r){let n=await this.ensureOrg(r);if(!n)return;let i;try{i=await ye(this.env,this.userToken,n.subdomain,e)}catch(l){this.flash(`Could not create "${e}": ${pt(l)}`,!0);return}let o=this.catalog.find(l=>l.org.id===n.id);o&&!o.sites.some(l=>l.id===i.id)&&(o.sites=[...o.sites,i]),this.flash(`Created "${i.name}".`),await this.addSite(n,i)}async refetch(e){await this.runSync(e,{flush:!0})}async runSync(e,r={}){let n=this.synced.get(e);if(!(!n||!n.viewsDir||n.status==="paused")){n.status="syncing",this.changed();try{let i=await Pt({token:n.siteToken,env:this.env,viewsDir:n.viewsDir,agentMd:this.agentMd,buildScript:this.buildScript,flush:r.flush,log:o=>this.appendLog(e,o),onProgress:(o,l)=>{n.progress={done:o,total:l},this.changed()}});n.progress=void 0,n.status="watching",n.lastSyncedAt=Date.now(),r.flush?n.lastMsg=`re-fetched ${i.pulled} file(s)`:n.lastMsg=i.pushed>0?`pushed ${i.pushed} file(s)`:"up to date"}catch(i){let o=i;n.status="error",n.progress=void 0,n.lastMsg=o.body||o.message,this.appendLog(e,`\u274C ${o.body||o.message}`)}this.changed()}}async togglePause(e){let r=this.synced.get(e);!r||!r.viewsDir||(r.status==="paused"?(r.watcher=new V({viewsDir:r.viewsDir,onSync:()=>this.runSync(e)}),r.watcher.start(),r.status="watching",this.appendLog(e,"\u25B6 resumed \u2014 watching for changes")):(r.watcher?.setShuttingDown(!0),await r.watcher?.stop(),r.watcher=void 0,r.progress=void 0,r.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 Gr,useState as De}from"react";import{Box as qr,Text as Hr,useInput as Jr}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:r}){let[n,i]=Z("email"),[o,l]=Z(""),[h,p]=Z(""),[x,w]=Z(e),[m,b]=Z(),v=async R=>{let E=R.trim();if(E){w(void 0),i("busy");try{let{otp:M}=await ge(t,E);if(l(E),M){let X=await Lt(t,E,M);await r(X,E);return}b(`OTP sent to ${E}`),i("otp")}catch(M){w(Se(M)),i("email")}}},O=async R=>{let E=R.trim();if(E){w(void 0),i("busy");try{let M=await Lt(t,o,E);await r(M,o)}catch(M){w(Se(M)),p(""),i("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,n==="email"&&J(tt,{marginTop:1,children:[N(H,{children:"Email: "}),N(xe,{value:o,onChange:l,onSubmit:v,placeholder:"you@example.com"})]}),n==="otp"&&J(tt,{flexDirection:"column",marginTop:1,children:[m?N(H,{color:"green",children:m}):null,J(tt,{children:[N(H,{children:"Enter OTP: "}),N(xe,{value:h,onChange:p,onSubmit:O})]})]}),n==="busy"&&N(tt,{marginTop:1,children:N(H,{children:"Working\u2026"})})]})}import{Fragment as Lr,useEffect as et,useMemo as Rr,useState as C}from"react";import{Box as g,Text as c,useInput as Ar,useStdout as Fr}from"ink";import Be from"ink-text-input";import $r from"node:os";function Ft(t){if(!t)return"\u2014";let e=$r.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 r=Math.floor(e/60);if(r<60)return`${r}m ago`;let n=Math.floor(r/60);return n<24?`${n}h ago`:`${Math.floor(n/24)}d ago`}function yt(t){return!t||t.total<=0?null:Math.round(t.done/t.total*100)}var ft=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"];function Te(t){return ft[(t%ft.length+ft.length)%ft.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 rt,jsx as s,jsxs as u}from"react/jsx-runtime";var U=(t,e)=>e<=0?0:Math.max(0,Math.min(t,e-1)),jr=16,_r=5,Ir="greenBright",Ee="blueBright",Ce="magentaBright";function Pe({k:t,bg:e=Ir}){return s(c,{color:"black",backgroundColor:e,children:` ${t} `})}function j({k:t,label:e,width:r=16,bg:n}){return u(g,{width:r,children:[s(Pe,{k:t,bg:n}),s(c,{color:"gray",children:` ${e}`})]})}function B({k:t,label:e,bg:r}){return u(g,{marginBottom:1,children:[s(g,{width:9,children:s(Pe,{k:t,bg:r})}),s(c,{color:"gray",children:e})]})}function Nr({launchers:t}){return u(g,{flexDirection:"column",borderStyle:"round",borderColor:"green",paddingX:2,paddingY:1,width:66,children:[u(g,{justifyContent:"space-between",children:[s(c,{color:"green",bold:!0,children:"KEYBOARD SHORTCUTS"}),s(c,{color:"gray",children:"? or esc to close"})]}),u(g,{marginTop:1,children:[u(g,{flexDirection:"column",width:34,children:[s(c,{color:"cyan",bold:!0,children:"Navigate"}),s(B,{k:"\u2191\u2193",label:"move selection"}),s(B,{k:"tab",label:"focus logs \xB7 \u2191\u2193 scroll"}),s(B,{k:"esc",label:"clear filter / back"}),s(g,{marginTop:1,children:s(c,{color:"cyan",bold:!0,children:"Global"})}),s(B,{k:"/",label:"search sites"}),s(B,{k:"n",label:"new site"}),s(B,{k:"?",label:"toggle this help",bg:Ee}),s(B,{k:"q",label:"logout"}),s(B,{k:"ctrl+c",label:"quit"})]}),u(g,{flexDirection:"column",flexGrow:1,children:[s(c,{color:"cyan",bold:!0,children:"Site actions"}),s(B,{k:"s",label:"start sync"}),s(B,{k:"d",label:"disconnect"}),s(B,{k:"p",label:"pause / resume sync"}),s(B,{k:"b",label:"build preview"}),s(B,{k:"B",label:"deploy live"}),s(B,{k:"o",label:"open preview url"}),t.map((e,r)=>s(B,{k:String(r+1),label:`open in ${e.label}`,bg:Ce},e.key))]})]})]})}function Ur({percent:t,width:e=28}){let r=Math.round(Math.max(0,Math.min(100,t))/100*e);return u(c,{children:[s(c,{color:"green",children:"\u2588".repeat(r)}),s(c,{color:"gray",children:"\u2591".repeat(Math.max(0,e-r))})]})}function Wr({frame:t,width:e=24,seg:r=6}){let n=e+r,i=t%n-r,o="";for(let l=0;l<e;l++)o+=l>=i&&l<i+r?"\u25AE":"\u25AF";return s(c,{color:"yellow",children:o})}function Me({controller:t}){let{stdout:e}=Fr(),r=Rr(()=>ie(),[]),[,n]=C(0),[i,o]=C(()=>new Date),[l,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,m]=C(0),[b,v]=C(""),[O,R]=C(!1),[E,M]=C(""),[X,nt]=C(!1),[Nt,Ae]=C(0),[Ut,Wt]=C(!1),[Fe,je]=C(!1),[it,st]=C("list"),[_e,K]=C(0),Gt=()=>n(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(),D=_?F.filter(a=>a.site.name.toLowerCase().includes(_)||(a.org.name||a.org.subdomain||"").toLowerCase().includes(_)):F,W=D.findIndex(a=>a.site.id===l);W<0&&(W=0);let T=D[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=D.findIndex(a=>!a.entry),G=Math.max(_r,(e?.rows??30)-jr),z=D.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=D.slice(Y,Tt);et(()=>{p!=="dashboard"||O||F.length>0||(v(""),t.catalog.length<=1?x("newName"):(m(0),x("newOrg")))},[F.length,p,O,t.catalog.length]);let ut=a=>{if(D.length===0)return;let d=U(W+a,D.length);h(D[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"):(m(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?"Deploying \u2014 building 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(ne(a)?`Opening ${a}`:"Couldn't open the browser.",!1)};Ar((a,d)=>{if(Ut){(a==="?"||d.escape)&&Wt(!1);return}if(p==="newOrg"){d.escape?x("dashboard"):d.upArrow?m(k=>U(k-1,t.catalog.length)):d.downArrow?m(k=>U(k+1,t.catalog.length)):d.return&&x("newName");return}if(X){d.escape?(nt(!1),M(""),h(null)):d.return?nt(!1):d.upArrow?ut(-1):d.downArrow&&ut(1);return}if(d.tab){it==="logs"?st("list"):y&&st("logs"),K(0);return}if(it==="logs"){if(d.escape){st("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){M(""),h(null);return}if(a==="?")return void Wt(!0);if(a==="/")return st("list"),void nt(!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=r[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:[s(c,{color:"green",bold:!0,children:"\u25C6 SleekCMS"}),s(c,{color:"gray",children:" \u2502 "}),s(c,{children:t.email??"signed in"})]}),u(g,{children:[u(c,{color:"gray",children:[_?`${D.length}/${F.length}`:F.length," sites \xB7 "]}),u(c,{color:"green",children:[t.watchingCount()," watching"]}),s(c,{color:"gray",children:` \xB7 ${i.toTimeString().slice(0,5)}`})]})]});return Ut?u(g,{flexDirection:"column",children:[Xt,s(g,{marginTop:1,justifyContent:"center",children:s(Nr,{launchers:r})})]}):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:[s(c,{color:"green",bold:!0,children:"SITE WORKSPACES"}),F.length>G&&!X&&!_?s(c,{color:"gray",children:"/ filter"}):null]}),X?u(g,{children:[s(c,{color:"cyan",children:"/ "}),s(Be,{value:E,onChange:M,onSubmit:()=>nt(!1),placeholder:"type to filter\u2026"})]}):_?s(c,{color:"gray",children:`/ ${E} \xB7 ${D.length} match${D.length===1?"":"es"}`}):null,s(g,{flexDirection:"column",marginTop:1,minHeight:lt?G+3:void 0,children:D.length===0?s(c,{color:"gray",children:_?`no matches for \u201C${E}\u201D`:"no sites \u2014 press n to create one"}):u(rt,{children:[lt?s(c,{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(Lr,{children:[Ve?s(c,{color:"gray",children:"\u2500".repeat(34)}):null,u(g,{justifyContent:"space-between",children:[u(g,{children:[s(c,{color:dt?"green":"gray",children:dt?"\u276F ":" "}),u(c,{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," "]}),s(c,{color:dt?"white":a.entry?void 0:"gray",bold:dt,children:a.site.name})]}),s(c,{color:a.entry?.status==="syncing"?"green":"gray",children:Ye})]})]},a.site.id)}),lt?s(c,{color:"gray",children:Tt<z?` \u2193 ${z-Tt} more`:" "}):null]})}),s(g,{marginTop:1,children:s(c,{color:"gray",children:"+ new site \xB7 n"})})]}),u(g,{flexDirection:"column",flexGrow:1,marginLeft:1,children:[s(g,{flexDirection:"column",borderStyle:"round",borderColor:"gray",paddingX:1,children:T?u(rt,{children:[u(c,{children:[T.org.name||T.org.subdomain?u(c,{color:"gray",children:[T.org.name||T.org.subdomain," / "]}):null,s(c,{color:"cyan",bold:!0,children:T.site.name})]}),u(g,{marginTop:1,children:[s(c,{color:"gray",children:"status "}),y?s(c,{color:wt(y.status).color,children:`: ${wt(y.status).label}`}):s(c,{color:"gray",children:": idle \u2014 not syncing (press s to start)"})]}),u(g,{children:[s(c,{color:"gray",children:"path "}),s(c,{wrap:"truncate-end",children:y?.viewsDir?Ft(y.viewsDir):"\u2014"})]}),u(g,{children:[s(c,{color:"gray",children:"synced "}),s(c,{children:jt(y?.lastSyncedAt)}),s(c,{color:"gray",children:" progress "}),s(c,{color:y?.status==="syncing"?"green":"gray",children:y?.status==="syncing"?`${yt(y.progress)??0}%`:"\u2014"})]}),s(g,{marginTop:1,children:s(Ur,{percent:y?y.status==="syncing"?yt(y.progress)??0:y.status==="watching"?100:0:0})}),y?u(rt,{children:[u(g,{marginTop:1,children:[s(c,{color:"gray",children:"build "}),s(c,{color:vt.color,children:`${vt.dot} ${vt.label}`}),s(c,{color:"gray",children:" last "}),s(c,{children:St?"in progress":jt(A?.at)})]}),u(g,{children:[s(c,{color:"gray",children:"url "}),A?.url?s(c,{color:"cyan",wrap:"truncate-end",children:A.url}):s(c,{color:"gray",children:"\u2014"})]}),A?.status==="error"&&A.errors?.length?u(g,{children:[s(c,{color:"red",children:"\u258C "}),s(c,{color:"red",wrap:"truncate-end",children:`\u2717 ${A.errors[0]}`})]}):null,St?u(g,{children:[s(Wr,{frame:Nt}),s(c,{color:"gray",children:` ${A?.stage??"building"}`})]}):null]}):null]}):s(c,{color:"gray",children:"No site selected."})}),p==="dashboard"?u(g,{flexDirection:"column",borderStyle:"round",borderColor:it==="logs"?"green":"gray",paddingX:1,marginTop:1,height:ot+4,flexShrink:0,overflowY:"hidden",children:[u(g,{justifyContent:"space-between",children:[u(c,{children:[s(c,{color:"cyan",bold:!0,children:"LOGS \xB7 "}),s(c,{color:"white",children:T?.site.name??"\u2014"})]}),y&&I.length>0?it==="logs"?s(c,{color:"green",children:`\u2191\u2193 scroll \xB7 esc back${xt>0?` \xB7 ${at}/${I.length}`:""}`}):I.length>ot?s(c,{color:"gray",children:"tab to scroll"}):null:null]}),s(g,{flexDirection:"column",marginTop:1,children:!y||I.length===0?s(c,{color:"gray",children:"no activity yet"}):qt.map((a,d)=>u(c,{wrap:"truncate-end",children:[u(c,{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(rt,{children:[s(c,{color:"cyan",bold:!0,children:"CREATE SITE \u2014 PICK ORG"}),s(c,{color:"gray",children:"\u2191/\u2193 select \xB7 \u23CE next \xB7 esc cancel"}),s(g,{flexDirection:"column",marginTop:1,children:t.catalog.map((a,d)=>u(c,{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(rt,{children:[s(c,{color:"cyan",bold:!0,children:"CREATE SITE"}),u(g,{marginTop:1,children:[s(c,{children:"New site name: "}),s(Be,{value:b,onChange:v,onSubmit:ze})]}),s(c,{color:"gray",children:"\u23CE create \xB7 empty + \u23CE to cancel"})]})]})]})]}),t.message?s(g,{paddingX:1,children:u(c,{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:[s(j,{k:"\u2191\u2193",label:"select"}),s(j,{k:"/",label:"search"}),s(j,{k:"s",label:"start sync"}),s(j,{k:"d",label:"disconnect"}),F.length===0?s(j,{k:"n",label:"new site"}):null,s(j,{k:"ctrl+c",label:"quit",width:14})]}),s(j,{k:"?",label:"all keys",width:12,bg:Ee})]}),!Fe&&r.length>0?s(g,{paddingX:1,marginTop:1,flexWrap:"wrap",children:r.map((a,d)=>s(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 $e({controller:t,env:e,devSecret:r,savedToken:n,savedEmail:i}){let[o,l]=De(n?"loading":"auth"),[h,p]=De();Jr((w,m)=>{m.ctrl&&w==="c"&&t.exit()}),Gr(()=>{n&&t.init(e,n,i).then(()=>l("manage")).catch(w=>{w instanceof L&&w.status===401?p("Saved session expired \u2014 please sign in again."):p(Oe(w)),l("auth")})},[]);let x=async(w,m)=>{p(void 0),await ue({env:e,userToken:w,devSecret:r,email:m}),l("loading");try{await t.init(e,w,m),l("manage")}catch(b){p(Oe(b)),l("auth")}};return o==="auth"?bt(ve,{env:e,initialError:h,onAuthed:x}):o==="loading"?bt(qr,{children:bt(Hr,{children:"Loading your sites\u2026 "})}):bt(Me,{controller:t})}import{jsx as tn}from"react/jsx-runtime";var Yr=Kr(import.meta.url),_t=te();if(_t.version){let t=Yr("../package.json");console.log(t.version),process.exit(0)}var Re=It.dirname(Xr(import.meta.url)),Vr=Le(It.join(Re,"AGENT.md"),"utf-8"),Qr=Le(It.join(Re,"build.mjs"),"utf-8");async function Zr(){let t=new mt(Vr,Qr),e=await le(),r=(_t.env??e?.env??"production").toLowerCase(),n=_t.dev??process.env.SLEEKCMS_DEV_SECRET??e?.devSecret;ce(n),process.stdout.isTTY&&process.stdout.write("\x1B[2J\x1B[3J\x1B[H");let i=zr(tn($e,{controller:t,env:r,devSecret:n,savedToken:e?.userToken,savedEmail:e?.email}),{exitOnCtrlC:!1}),o=l=>{i.unmount(),console.log(l),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 i.waitUntilExit()}Zr().catch(t=>{let e=t;console.error("\u274C",e.body||e.message),process.exit(1)});
|
|
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","--deploy"]:["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} deploying\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:"deploy 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?"Deploying \u2014 building 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)});
|