@stacksjs/ts-cloud 0.16.19 → 0.16.20
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/aws/index.js +1 -1
- package/dist/bin/{chunk-ehb9mpt8.js → chunk-7zfydgfz.js} +3 -3
- package/dist/bin/chunk-840arz58.js +34 -0
- package/dist/bin/{chunk-4sa22raw.js → chunk-gfr2215x.js} +1 -1
- package/dist/bin/{chunk-7thhxyzy.js → chunk-gt7g41js.js} +1 -1
- package/dist/bin/{chunk-3ay4kfaw.js → chunk-ysv52qcc.js} +1 -1
- package/dist/bin/cli.js +5 -5
- package/dist/bin/dashboard-server.js +1 -1
- package/dist/{chunk-bcy9z4ks.js → chunk-0j2tpr8d.js} +3 -3
- package/dist/{chunk-4j8ef0pe.js → chunk-49vvjfrd.js} +1 -1
- package/dist/{chunk-5255nr93.js → chunk-aw1tp3p3.js} +1 -1
- package/dist/chunk-d46p0h6t.js +34 -0
- package/dist/{chunk-2m262b2n.js → chunk-wgf1ndgq.js} +1 -1
- package/dist/deploy/index.js +1 -1
- package/dist/drivers/index.js +1 -1
- package/dist/index.js +1 -1
- package/dist/ui/404.html +1 -1
- package/dist/ui/accept-invitation.html +1 -1
- package/dist/ui/access-denied.html +1 -1
- package/dist/ui/account/automation.html +6 -6
- package/dist/ui/account/security.html +1 -1
- package/dist/ui/applications/compose.html +6 -6
- package/dist/ui/applications/new.html +2 -2
- package/dist/ui/data/backups.html +6 -6
- package/dist/ui/data/services.html +6 -6
- package/dist/ui/data/volumes.html +6 -6
- package/dist/ui/index.html +6 -6
- package/dist/ui/infrastructure/topology.html +6 -6
- package/dist/ui/integrations.html +2 -2
- package/dist/ui/operations/alerts.html +6 -6
- package/dist/ui/operations/configuration.html +6 -6
- package/dist/ui/operations/jobs.html +5 -5
- package/dist/ui/operations/maintenance.html +6 -6
- package/dist/ui/operations/observability.html +6 -6
- package/dist/ui/operations/previews.html +6 -6
- package/dist/ui/operations/queue.html +6 -6
- package/dist/ui/operations/regions.html +6 -6
- package/dist/ui/operations/releases.html +5 -5
- package/dist/ui/operations/spend.html +5 -5
- package/dist/ui/operations/workloads.html +6 -6
- package/dist/ui/security.html +2 -2
- package/dist/ui/server/actions.html +6 -6
- package/dist/ui/server/activity.html +1 -1
- package/dist/ui/server/capacity.html +6 -6
- package/dist/ui/server/database.html +6 -6
- package/dist/ui/server/deployments.html +6 -6
- package/dist/ui/server/diagnostics.html +2 -2
- package/dist/ui/server/firewall.html +6 -6
- package/dist/ui/server/fleet.html +6 -6
- package/dist/ui/server/logs.html +6 -6
- package/dist/ui/server/metrics.html +6 -6
- package/dist/ui/server/security.html +2 -2
- package/dist/ui/server/services.html +2 -2
- package/dist/ui/server/sites.html +6 -6
- package/dist/ui/server/ssh-keys.html +6 -6
- package/dist/ui/server/team.html +6 -6
- package/dist/ui/server/terminal.html +1 -1
- package/dist/ui/serverless/alarms.html +6 -6
- package/dist/ui/serverless/assets.html +2 -2
- package/dist/ui/serverless/cost.html +2 -2
- package/dist/ui/serverless/data.html +6 -6
- package/dist/ui/serverless/deployments.html +2 -2
- package/dist/ui/serverless/firewall.html +1 -1
- package/dist/ui/serverless/functions.html +6 -6
- package/dist/ui/serverless/logs.html +6 -6
- package/dist/ui/serverless/metrics.html +2 -2
- package/dist/ui/serverless/queues.html +6 -6
- package/dist/ui/serverless/secrets.html +6 -6
- package/dist/ui/serverless/traces.html +6 -6
- package/dist/ui/serverless.html +5 -5
- package/package.json +3 -3
- package/dist/bin/chunk-6d8chxyr.js +0 -34
- package/dist/chunk-r1wpwfff.js +0 -34
package/dist/bin/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import{T,Lt,n,r,a,fr,e,p,i,o,I,d,lo,c,Xr,he,Es,ws,Cs,As,f}from"./chunk-2mv692y4.js";import{zs,V,Cr,C,U,To,l,s,E,Ws,Gs,Ks,Pe,Le,Ut,wo,gi,Co,fi,Ao,Ys,Zs,ea,ta,na,B,S,x,Ze,D,pe,Ro,Ue,Ft,hi,ve,Po,yi,jt,Et,ia,oa}from"./chunk-mxvekmdx.js";import{ke,k,dn,y,un,Ai,pn,Bo,Rr,tt,Ie,mn,gn,fn,hn,yn,Sn,bn,vn,te,Wt,Gt,Tn,Pr,En,wn,Cn,An,In,Rn,Pn,Nn,rt,Kt,Jt,Ct,Nr,Xt,Qt,Ii,At,Dn,se,kn,_n,xn,Dr,kr,$n,_r,Yt,Zt,nt,It,Rt,xr,ae,On,Ta,Ea,er,wa,z,Ri,Be,it,ot,Ln,$r,Or,Mn,Un,Bn,Lr,Fo,ce,me,_e,ge,jn,tr}from"./chunk-
|
|
2
|
+
import{T,Lt,n,r,a,fr,e,p,i,o,I,d,lo,c,Xr,he,Es,ws,Cs,As,f}from"./chunk-2mv692y4.js";import{zs,V,Cr,C,U,To,l,s,E,Ws,Gs,Ks,Pe,Le,Ut,wo,gi,Co,fi,Ao,Ys,Zs,ea,ta,na,B,S,x,Ze,D,pe,Ro,Ue,Ft,hi,ve,Po,yi,jt,Et,ia,oa}from"./chunk-mxvekmdx.js";import{ke,k,dn,y,un,Ai,pn,Bo,Rr,tt,Ie,mn,gn,fn,hn,yn,Sn,bn,vn,te,Wt,Gt,Tn,Pr,En,wn,Cn,An,In,Rn,Pn,Nn,rt,Kt,Jt,Ct,Nr,Xt,Qt,Ii,At,Dn,se,kn,_n,xn,Dr,kr,$n,_r,Yt,Zt,nt,It,Rt,xr,ae,On,Ta,Ea,er,wa,z,Ri,Be,it,ot,Ln,$r,Or,Mn,Un,Bn,Lr,Fo,ce,me,_e,ge,jn,tr}from"./chunk-7zfydgfz.js";import{u,Us}from"./chunk-mx9ppkmn.js";import{ie,h,wr}from"./chunk-0trtkv9g.js";import{Sr,bt,br,vr,Tr,Er,en}from"./chunk-z1dtdw3j.js";import{b,Nt,Gn,Yo,lr,Da,ka,_a,Kn,Jn,dt,Hr,Dt,qr,ut,He,$e,qe,pt,dr,Oe,We,Xn,Qn,Ge,Wr,Gr,ji,zi,mr,kt,mt,_t,Q,Gi,ei,ti,ds}from"./chunk-e24bscb0.js";import{Je,xt,fs,hs,Xe,Qi,Yi,Zi,eo,to,ro,H,$t,O,ni}from"./chunk-148x1zq8.js";import{W,P,uo,Ns,Ds,rc,nc,si,yt,ai}from"./chunk-t10e32an.js";import{v}from"./chunk-vjkyj3xy.js";import{K}from"./chunk-90102shh.js";import{St,g}from"./chunk-e55fdn0r.js";import{je,jo,le,Pi,zn,Ni,Di,Mr,ki,_i,fe,X,Ve,Re,Ur,rr,ze,nr,Br,at,de,ct,or,sr,ar,Fr,cr,_,$i,Oi,Hn,Vo,jr,zo,Ho,Ia,Li,qo,Wo,Go,Ko,lt,Jo,Mi,Ui}from"./chunk-gfr2215x.js";import"./chunk-ys5n5c84.js";import{R}from"./chunk-6kx50dyc.js";import{ue}from"./chunk-k7wh1wr5.js";import{q,ft,ao}from"./chunk-ndddd2ft.js";import{re,J,Ca,Aa,Fe}from"./chunk-48x0wc2g.js";import{Ht,cn,qt,wi,ln,Uo}from"./chunk-x63yz8xg.js";import"./chunk-rbtt23vx.js";import{w}from"./chunk-dyh0vndw.js";import{st}from"./chunk-5a7sxtwn.js";import{Y,ye}from"./chunk-840arz58.js";import{F}from"./chunk-egn33pr9.js";import"./chunk-h1rb8qvt.js";import{Ci}from"./chunk-0f1qpmd6.js";import"./chunk-apnhhfkj.js";import"./chunk-djjj62c0.js";import{ri}from"./chunk-ngyqqy6d.js";import{gr}from"./chunk-8jbkphmg.js";import{gt}from"./chunk-1j8b1d58.js";import{M}from"./chunk-9vmtm7nq.js";import{existsSync as Hd}from"node:fs";import ua from"node:fs/promises";import pl from"node:os";import pa from"node:path";import po from"node:process";import{EventEmitter as Kd}from"node:events";import Ji from"node:process";import ml from"node:process";import ga from"node:process";import $s from"node:process";import Zo from"node:process";import yl from"node:tty";import ju,{stdin as jg,stdout as Fg}from"node:process";class vl{configPath;config=null;events=[];retryCount=0;maxRetries=3;retryDelayMs=1000;constructor(){let N=pl.homedir(),t=pa.join(N,".config","clapp");this.configPath=pa.join(t,"telemetry.json")}async isEnabled(){if(po.env.DO_NOT_TRACK==="1"||po.env.DO_NOT_TRACK==="true")return!1;if(po.env.NO_TELEMETRY==="1"||po.env.NO_TELEMETRY==="true")return!1;return(await this.loadConfig()).enabled}async enable(){let N=await this.loadConfig();if(N.enabled=!0,!N.userId)N.userId=this.generateUserId();await this.saveConfig(N)}async disable(){let N=await this.loadConfig();N.enabled=!1,await this.saveConfig(N)}async track(N,t){if(!await this.isEnabled())return;let A={event:N,...t,timestamp:Date.now(),platform:pl.platform(),nodeVersion:po.version};if(this.events.push(A),this.events.length>=10)await this.send()}async trackCommand(N,t){await this.track("command",{command:N,duration:t})}async trackError(N,t){await this.track("error",{error:N,command:t})}async send(){if(!await this.isEnabled()||this.events.length===0)return!0;try{this.events=[],this.retryCount=0;let t=await this.loadConfig();return t.lastSent=Date.now(),await this.saveConfig(t),!0}catch{if(this.retryCount<this.maxRetries){this.retryCount++;let t=this.retryDelayMs*2**(this.retryCount-1);return await this.sleep(t),this.send()}return this.events=[],this.retryCount=0,!1}}async flush(){if(this.events.length===0)return!0;return this.send()}sleep(N){return new Promise((t)=>setTimeout(t,N))}async status(){let N=await this.loadConfig();return{enabled:N.enabled,doNotTrack:po.env.DO_NOT_TRACK==="1"||po.env.DO_NOT_TRACK==="true",eventsQueued:this.events.length,lastSent:N.lastSent}}async loadConfig(){if(this.config)return this.config;try{if(Hd(this.configPath)){let N=await ua.readFile(this.configPath,"utf-8");return this.config=JSON.parse(N),this.config}}catch{}return this.config={enabled:!1},this.config}async saveConfig(N){this.config=N;try{let t=pa.dirname(this.configPath);await ua.mkdir(t,{recursive:!0}),await ua.writeFile(this.configPath,JSON.stringify(N,null,2),"utf-8")}catch{}}generateUserId(){let N=Math.random().toString(36).substring(2,15),t=Date.now().toString(36);return`${N}-${t}`}}var Cg=new vl;function fa(N){return N.replace(/[<[].+/,"").trim()}function Jd(N){let t=/<([^>]+)>/g,m=/\[([^\]]+)\]/g,A=[],L=(Z)=>{let ee=!1,ne=Z[1];if(ne.startsWith("..."))ne=ne.slice(3),ee=!0;return{required:Z[0].startsWith("<"),value:ne,variadic:ee}},j;while(j=t.exec(N))A.push(L(j));let G;while(G=m.exec(N))A.push(L(G));return A}function Yd(N){let t={alias:{},boolean:[]};for(let[m,A]of N.entries()){if(A.names.length>1)t.alias[A.names[0]]=A.names.slice(1);if(A.isBoolean)if(A.negated){if(!N.some((j,G)=>G!==m&&j.names.some((Z)=>A.names.includes(Z))&&typeof j.required==="boolean"))t.boolean.push(A.names[0])}else t.boolean.push(A.names[0])}return t}function fl(N){return N.reduce((t,m)=>t.length>=m.length?t:m,"")}function ma(N,t){return N.length>=t?N:`${N}${" ".repeat(t-N.length)}`}function Ss(N){return N.replace(/([a-z])-([a-z])/g,(t,m,A)=>m+A.toUpperCase())}function Zd(N,t,m){let A=0,L=t.length,j=N,G;for(;A<L;++A)G=j[t[A]],j=j[t[A]]=A===L-1?m:G!=null?G:!!~t[A+1].indexOf(".")||!(+t[A+1]>-1)?{}:[]}function Qd(N,t){for(let m of Object.keys(t)){let A=t[m];if(A.shouldTransform){if(N[m]=Array.prototype.concat.call([],N[m]),typeof A.transformFunction==="function")N[m]=N[m].map(A.transformFunction)}}}function Xd(N){let t=/([^\\/]+)$/.exec(N);return t?t[1]:""}function Qo(N){return N.split(".").map((t,m)=>m===0?Ss(t):t).join(".")}class Xo extends Error{exitCode=2;isUsageError=!0;usage;constructor(N,t){super(N);if(this.name=this.constructor.name,t!==void 0)this.usage=t;if(typeof Error.captureStackTrace==="function")Error.captureStackTrace(this,this.constructor);else this.stack=Error(N).stack}format(N=!1){if(N&&this.stack)return`${this.message}
|
|
3
3
|
|
|
4
4
|
Stack trace:
|
|
5
5
|
${this.stack}`;return this.message}}function eu(N){if(N instanceof Xo)return!0;return!!N&&typeof N==="object"&&N.name==="ClappError"&&typeof N.message==="string"}function tu(){let{env:N}=ml,{TERM:t,TERM_PROGRAM:m}=N;if(ml.platform!=="win32")return t!=="linux";return Boolean(N.WT_SESSION)||Boolean(N.TERMINUS_SUBLIME)||N.ConEmuTask==="{cmd::Cmder}"||m==="Terminus-Sublime"||m==="vscode"||t==="xterm-256color"||t==="alacritty"||t==="rxvt-unicode"||t==="rxvt-unicode-256color"||N.TERMINAL_EMULATOR==="JetBrains-JediTerm"}var ks="\x1B",Wn=`${ks}[`;var gl={to(N,t){if(!t)return`${Wn}${N+1}G`;return`${Wn}${t+1};${N+1}H`},move(N,t){let m="";if(N<0)m+=`${Wn}${-N}D`;else if(N>0)m+=`${Wn}${N}C`;if(t<0)m+=`${Wn}${-t}A`;else if(t>0)m+=`${Wn}${t}B`;return m},up:(N=1)=>`${Wn}${N}A`,down:(N=1)=>`${Wn}${N}B`,forward:(N=1)=>`${Wn}${N}C`,backward:(N=1)=>`${Wn}${N}D`,nextLine:(N=1)=>`${Wn}E`.repeat(N),prevLine:(N=1)=>`${Wn}F`.repeat(N),left:`${Wn}G`,hide:`${Wn}?25l`,show:`${Wn}?25h`,save:`${ks}7`,restore:`${ks}8`};var Ig={screen:`${Wn}2J`,up:(N=1)=>`${Wn}1J`.repeat(N),down:(N=1)=>`${Wn}J`.repeat(N),line:`${Wn}2K`,lineEnd:`${Wn}K`,lineStart:`${Wn}1K`,lines(N){let t="";for(let m=0;m<N;m++)t+=this.line+(m<N-1?gl.up():"");if(N)t+=gl.left;return t}},Pg={screen:`${ks}c`};function nu(N,t){let m=[];for(let A=0;A<=t.length;A++)m[A]=[A];for(let A=0;A<=N.length;A++)m[0][A]=A;for(let A=1;A<=t.length;A++)for(let L=1;L<=N.length;L++)if(t.charAt(A-1)===N.charAt(L-1))m[A][L]=m[A-1][L-1];else m[A][L]=Math.min(m[A-1][L-1]+1,m[A][L-1]+1,m[A-1][L]+1);return m[t.length][N.length]}function bl(N,t,m=2,A=3){return t.map((L)=>({cmd:L,distance:nu(N,L)})).filter(({distance:L})=>L<=m).sort((L,j)=>L.distance-j.distance).slice(0,A).map(({cmd:L})=>L)}function ru(N,t={}){let m={_:[]},A=t.alias||{},L=new Set(t.boolean||[]),j={};for(let ee of Object.keys(A))for(let ne of A[ee])j[ne]=ee;for(let ee of L)if(A[ee])for(let ne of A[ee])L.add(ne);function G(ee,ne){if(ee===void 0)return ne;if(typeof ne==="boolean")return ne;return Array.isArray(ee)?[...ee,ne]:[ee,ne]}function Z(ee,ne){let oe=j[ee]||ee,be=G(m[oe],ne);if(m[oe]=be,A[oe])for(let we of A[oe])m[we]=be;if(j[ee]&&A[j[ee]])for(let we of A[j[ee]])m[we]=be;m[ee]=be}for(let ee=0;ee<N.length;ee++){let ne=N[ee];if(ne==="--"){m._.push(...N.slice(ee+1));break}if(ne.startsWith("--")){let oe=ne.indexOf("=");if(oe!==-1){let be=Ss(ne.slice(2,oe)),we=ne.slice(oe+1);Z(be,we)}else{let be=ne.slice(2);if(be.startsWith("no-")){let De=Ss(be.slice(3));Z(De,!1);continue}let we=Ss(be),Ce=j[we]||we;if(L.has(Ce)||L.has(we))Z(we,!0);else{let De=N[ee+1];if(De!==void 0&&!De.startsWith("-"))Z(we,De),ee++;else Z(we,!0)}}}else if(ne.startsWith("-")&&ne.length>1){let oe=ne.slice(1);for(let be=0;be<oe.length;be++){let we=oe[be],Ce=j[we]||we;if(be===oe.length-1&&!L.has(Ce)&&!L.has(we)){let De=N[ee+1];if(De!==void 0&&!De.startsWith("-"))Z(we,De),ee++;else Z(we,!0)}else Z(we,!0)}}else m._.push(ne)}return m}class wl{rawName;description;name;names;isBoolean;required;config;negated;constructor(N,t,m){if(this.rawName=N,this.description=t,this.config=Object.assign({},m),N=N.replace(/\.\*/g,""),this.negated=!1,this.names=fa(N).split(",").map((A)=>{let L=A.trim().replace(/^-{1,2}/,"");if(L.startsWith("no-"))this.negated=!0,L=L.replace(/^no-/,"");return Qo(L)}).sort((A,L)=>A.length>L.length?1:-1),this.name=this.names[this.names.length-1],this.negated&&this.config.default==null)this.config.default=!0;if(N.includes("<"))this.required=!0;else if(N.includes("["))this.required=!1;else this.isBoolean=!0}}var Dg=ga.argv,iu=`${ga.platform}-${ga.arch} bun-v${typeof Bun<"u"?Bun.version:"unknown"}`,hl=$s.argv,ou=`${$s.platform}-${$s.arch} node-${$s.version}`;class ha{rawName;description;config;cli;options;aliasNames;name;namespace;args;commandAction;usageText;versionNumber;examples;helpCallback;globalCommand;beforeHooks;afterHooks;middleware;constructor(N,t,m,A){this.rawName=N,this.description=t,this.config=m,this.cli=A,this.options=[],this.aliasNames=[],this.name=fa(N);let L=fa(N),j=L.indexOf(":");if(j>0)this.namespace=L.substring(0,j),this.name=L.substring(j+1);if(this.args=Jd(N),this.examples=[],this.beforeHooks=[],this.afterHooks=[],this.middleware=[],!m)this.config={}}usage(N){return this.usageText=N,this}allowUnknownOptions(){return this.config.allowUnknownOptions=!0,this}ignoreOptionDefaultValue(){return this.config.ignoreOptionDefaultValue=!0,this}version(N,t="-v, --version"){return this.versionNumber=N,this.option(t,"Display version number"),this}example(N){return this.examples.push(N),this}option(N,t,m){let A=new wl(N,t,m);return this.options.push(A),this}alias(N){return this.aliasNames.push(N),this}action(N){return this.commandAction=N,this}before(N){return this.beforeHooks.push(N),this}after(N){return this.afterHooks.push(N),this}use(N){return this.middleware.push(N),this}isMatched(N){if(this.aliasNames.includes(N))return!0;if(this.namespace)return`${this.namespace}:${this.name}`===N;return this.name===N}get isDefaultCommand(){return this.name===""||this.aliasNames.includes("!")}get isGlobalCommand(){return this instanceof ya}get displayName(){return this.namespace?`${this.namespace}:${this.name}`:this.name}hasOption(N){let t=Qo(N.split(".")[0]);return!!this.options.find((m)=>m.names.some((A)=>Qo(A)===t))}outputHelp(){let{name:N,commands:t}=this.cli,{versionNumber:m,options:A,helpCallback:L}=this.cli.globalCommand,j=[{body:`${N}${m?`/${m}`:""}`}];if(j.push({title:"Usage",body:` $ ${N} ${this.usageText||this.rawName}`}),(this.isGlobalCommand||this.isDefaultCommand)&&t.length>0){let ne=fl(t.map((De)=>De.rawName)),oe=new Map,be=[];for(let De of t)if(De.namespace){if(!oe.has(De.namespace))oe.set(De.namespace,[]);oe.get(De.namespace).push(De)}else be.push(De);let we="";if(be.sort((De,Se)=>De.rawName<Se.rawName?-1:De.rawName>Se.rawName?1:0),be.length>0)we+=be.map((De)=>` ${ma(De.rawName,ne.length)} ${De.description}`).join(`
|
|
@@ -28,7 +28,7 @@ Received ${m}, cleaning up...`),N)try{await N()}catch(A){console.error("Error du
|
|
|
28
28
|
`)),this.enableDidYouMean){let t=[];for(let A of this.commands){if(A.displayName)t.push(A.displayName);if(A.aliasNames)t.push(...A.aliasNames)}let m=bl(N,t);if(m.length>0)console.log(_o.yellow("Did you mean one of these?")),m.forEach((A)=>console.log(` ${_o.dim("•")} ${this.name} ${A}`)),console.log("")}console.log(_o.dim("Run"),`${this.name} --help`,_o.dim("to see all available commands")),Ji.exit(1)}async parse(N=hl,t={}){let{run:m=!0,exitOnError:A=!1}=t;if(A)try{return await this.parse(N,{run:m})}catch(ee){throw this.handleUsageError(ee),ee}if(this.rawArgs=N,!this.name)this.name=N[1]?Xd(N[1]):"cli";let L=!0,j=N.slice(2),G=j[0];if(G&&!G.startsWith("-")){for(let ee of this.commands)if(ee.isMatched(G)){let ne=this.mri(j,ee);L=!1;let oe={...ne,args:ne.args.slice(1)};this.setParsedInfo(oe,ee,G),this.emit(`command:${G}`,ee);break}if(L){let ee=j[1];if(ee&&!ee.startsWith("-")){let ne=`${G}:${ee}`;for(let oe of this.commands)if(oe.isMatched(ne)){let be=this.mri(j,oe);L=!1;let we={...be,args:be.args.slice(2)};this.setParsedInfo(we,oe,ne),this.emit(`command:${ne}`,oe);break}}}}if(L){for(let ee of this.commands)if(ee.name===""){L=!1;let ne=this.mri(j,ee);this.setParsedInfo(ne,ee),this.emit("command:!",ee);break}}if(L){let ee=this.mri(N.slice(2));this.setParsedInfo(ee)}if(this.options.verbose)this.isVerbose=!0;if(this.options.quiet)this.isQuiet=!0;if(this.options.debug)this.isDebug=!0;if(this.options.noInteraction||this.options.interaction===!1)this.isNoInteraction=!0;if(this.options.env)this.environment=String(this.options.env);if(this.options.dryRun)this.isDryRun=!0;if(this.options.force)this.isForce=!0;if(this.options.noEmoji||this.options.emoji===!1)this.useEmoji=!1;if(this.options.theme)this.theme=String(this.options.theme);if(this.options.noCache||this.options.cache===!1)this.isNoCache=!0;if(this.options.help&&this.showHelpOnExit)this.outputHelp(),m=!1,this.unsetMatchedCommand();if(this.options.version&&this.showVersionOnExit&&this.matchedCommandName==null)this.outputVersion(),m=!1,this.unsetMatchedCommand();let Z={args:this.args,options:this.options};if(m)await this.runMatchedCommand();if(!this.matchedCommand&&this.args[0]){if(this.emit("command:*"),!(this.listenerCount("command:*")>0))this.showCommandNotFound(this.args[0])}return Z}mri(N,t){let m=[...this.globalCommand.options,...t?t.options:[]],A=Yd(m),L=[],j=N.indexOf("--");if(j>-1)L=N.slice(j+1),N=N.slice(0,j);let G=ru(N,A),Z={_:G._};for(let we of Object.keys(G))if(we!=="_")Z[Qo(we)]=G[we];let ee=Z._,ne={"--":L},oe=t&&t.config.ignoreOptionDefaultValue?t.config.ignoreOptionDefaultValue:this.globalCommand.config.ignoreOptionDefaultValue,be=Object.create(null);for(let we of m){if(!oe&&we.config.default!==void 0)for(let Ce of we.names)ne[Ce]=we.config.default;if(Array.isArray(we.config.type)){if(be[we.name]===void 0)be[we.name]={shouldTransform:!0,transformFunction:we.config.type[0]}}}for(let we of Object.keys(Z))if(we!=="_"){let Ce=we.split(".");Zd(ne,Ce,Z[we]),Qd(ne,be)}return{args:ee,options:ne}}async run(N=hl){return this.parse(N,{run:!0,exitOnError:!0})}handleUsageError(N){if(!eu(N)||N.isUsageError===!1)return;let t=N.message||"command-line error",m=this.name?`${this.name}: `:"",A=/--help/.test(t)?"":N.usage?`
|
|
29
29
|
Usage: ${N.usage}`:`
|
|
30
30
|
Run \`${this.name??"cli"} --help\` for usage.`;Ji.stderr.write(`${m}${t}${A}
|
|
31
|
-
`),Ji.exit(N.exitCode??2)}async runMatchedCommand(){let{args:N,options:t,matchedCommand:m}=this;if(!m||!m.commandAction)return;m.checkUnknownOptions(),m.checkOptionValue(),m.checkRequiredArgs();let A=[];m.args.forEach((Z,ee)=>{if(Z.variadic)A.push(N.slice(ee));else A.push(N[ee])}),A.push(t);let L={command:m,args:A,options:t};for(let Z of m.beforeHooks)await Z(L);let j,G=async()=>{let Z=m.commandAction.apply(this,A);if(Z instanceof Promise)j=await Z;else j=Z;return j};if(m.middleware.length>0){let Z=0,ee=async()=>{if(Z<m.middleware.length){let ne=m.middleware[Z++];await ne({...L,next:ee})}else await G()};await ee()}else await G();for(let Z of m.afterHooks)await Z(L);return j}removeSignalHandlers(){if(!this.signalHandlersSet)return this;return Ji.removeAllListeners("SIGINT"),Ji.removeAllListeners("SIGTERM"),this.signalHandlersSet=!1,this}destroy(){this.removeSignalHandlers(),this.commands=[],this.rawArgs=[],this.args=[],this.options={},this.matchedCommand=void 0,this.matchedCommandName=void 0,this.removeAllListeners()}}class Sl{cache;enabled;cleanupInterval=null;hits=0;misses=0;constructor(){this.cache=new Map,this.enabled=!0,this.startCleanupInterval()}startCleanupInterval(){if(this.cleanupInterval)return;this.cleanupInterval=setInterval(()=>{this.cleanup()},30000),this.cleanupInterval.unref()}stopCleanup(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null}isEnabled(){return this.enabled}get(N){if(!this.enabled){this.misses++;return}let t=this.cache.get(N);if(!t){this.misses++;return}if(Date.now()-t.timestamp>t.ttl){this.cache.delete(N),this.misses++;return}return this.hits++,t.value}set(N,t,m=5000){if(!this.enabled)return;this.cache.set(N,{value:t,timestamp:Date.now(),ttl:m})}has(N){if(!this.enabled)return!1;let t=this.cache.get(N);if(!t)return!1;if(Date.now()-t.timestamp>t.ttl)return this.cache.delete(N),!1;return!0}delete(N){this.cache.delete(N)}clear(){this.cache.clear()}disable(){this.enabled=!1,this.clear()}enable(){this.enabled=!0}stats(){return{size:this.cache.size,enabled:this.enabled,hits:this.hits,misses:this.misses}}resetStats(){this.hits=0,this.misses=0}keys(){return Array.from(this.cache.keys())}cleanup(){let N=Date.now();for(let[t,m]of this.cache.entries())if(N-m.timestamp>m.ttl)this.cache.delete(t)}destroy(){this.stopCleanup(),this.clear(),this.resetStats()}}var Tg=new Sl;function lu(){if("FORCE_COLOR"in Zo.env)return Zo.env.FORCE_COLOR!=="0";if("NO_COLOR"in Zo.env||Zo.env.TERM==="dumb")return!1;if(Zo.platform==="win32")return!0;return yl.isatty(1)&&yl.isatty(2)}var $l=lu();function Vn(N,t){if(!$l)return(m)=>m;return(m)=>N+m+t}var du=Vn("\x1B[0m","\x1B[0m"),uu=Vn("\x1B[31m","\x1B[39m"),pu=Vn("\x1B[32m","\x1B[39m"),mu=Vn("\x1B[33m","\x1B[39m"),fu=Vn("\x1B[34m","\x1B[39m"),gu=Vn("\x1B[35m","\x1B[39m"),hu=Vn("\x1B[36m","\x1B[39m"),yu=Vn("\x1B[37m","\x1B[39m"),vu=Vn("\x1B[90m","\x1B[39m"),bu=Vn("\x1B[1m","\x1B[22m"),wu=Vn("\x1B[3m","\x1B[23m"),Su=Vn("\x1B[4m","\x1B[24m"),$u=Vn("\x1B[2m","\x1B[22m"),Cu=Vn("\x1B[7m","\x1B[27m"),Au=Vn("\x1B[8m","\x1B[28m"),ku=Vn("\x1B[9m","\x1B[29m"),Ru=Vn("\x1B[41m","\x1B[49m"),Iu=Vn("\x1B[42m","\x1B[49m"),Pu=Vn("\x1B[43m","\x1B[49m"),xu=Vn("\x1B[44m","\x1B[49m"),Du=Vn("\x1B[45m","\x1B[49m"),Eu=Vn("\x1B[46m","\x1B[49m"),Tu=Vn("\x1B[47m","\x1B[49m"),Nu=$l,Ou={reset:du,red:uu,green:pu,yellow:mu,blue:fu,magenta:gu,cyan:hu,white:yu,gray:vu,bold:bu,italic:wu,underline:Su,dim:$u,inverse:Cu,hidden:Au,strikethrough:ku,bgRed:Ru,bgGreen:Iu,bgYellow:Pu,bgBlue:xu,bgMagenta:Du,bgCyan:Eu,bgWhite:Tu,isColorSupported:Nu},Lu=Ou,Fu=["up","down","left","right","space","enter","cancel"],Bg={actions:new Set(Fu),aliases:new Map([["k","up"],["j","down"],["h","left"],["l","right"],["\x03","cancel"],["escape","cancel"]]),messages:{cancel:"Canceled",error:"Something went wrong"}};var Mg=ju.platform.startsWith("win"),_g=Symbol("clapp:cancel");var Bu=tu();var Fn=(N,t)=>Bu?N:t,zg=Fn("◆","*"),Ug=Fn("■","x"),Vg=Fn("▲","x"),Wg=Fn("◇","o"),qg=Fn("┌","T"),Mu=Fn("│","|"),Gg=Fn("└","—"),Hg=Fn("●",">"),Kg=Fn("○"," "),Jg=Fn("◻","[•]"),Yg=Fn("◼","[+]"),Zg=Fn("◻","[ ]"),Qg=Fn("▪","•"),Xg=Fn("─","-"),eh=Fn("╮","+"),th=Fn("├","+"),nh=Fn("╯","+"),rh=Fn("●","•"),ih=Fn("◆","*"),oh=Fn("▲","!"),sh=Fn("■","x");var ah={light:Fn("─","-"),heavy:Fn("━","="),block:Fn("█","#")};function _u(){return`${Lu.gray(Mu)} `}var ch=_u();var ba="0.16.
|
|
31
|
+
`),Ji.exit(N.exitCode??2)}async runMatchedCommand(){let{args:N,options:t,matchedCommand:m}=this;if(!m||!m.commandAction)return;m.checkUnknownOptions(),m.checkOptionValue(),m.checkRequiredArgs();let A=[];m.args.forEach((Z,ee)=>{if(Z.variadic)A.push(N.slice(ee));else A.push(N[ee])}),A.push(t);let L={command:m,args:A,options:t};for(let Z of m.beforeHooks)await Z(L);let j,G=async()=>{let Z=m.commandAction.apply(this,A);if(Z instanceof Promise)j=await Z;else j=Z;return j};if(m.middleware.length>0){let Z=0,ee=async()=>{if(Z<m.middleware.length){let ne=m.middleware[Z++];await ne({...L,next:ee})}else await G()};await ee()}else await G();for(let Z of m.afterHooks)await Z(L);return j}removeSignalHandlers(){if(!this.signalHandlersSet)return this;return Ji.removeAllListeners("SIGINT"),Ji.removeAllListeners("SIGTERM"),this.signalHandlersSet=!1,this}destroy(){this.removeSignalHandlers(),this.commands=[],this.rawArgs=[],this.args=[],this.options={},this.matchedCommand=void 0,this.matchedCommandName=void 0,this.removeAllListeners()}}class Sl{cache;enabled;cleanupInterval=null;hits=0;misses=0;constructor(){this.cache=new Map,this.enabled=!0,this.startCleanupInterval()}startCleanupInterval(){if(this.cleanupInterval)return;this.cleanupInterval=setInterval(()=>{this.cleanup()},30000),this.cleanupInterval.unref()}stopCleanup(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null}isEnabled(){return this.enabled}get(N){if(!this.enabled){this.misses++;return}let t=this.cache.get(N);if(!t){this.misses++;return}if(Date.now()-t.timestamp>t.ttl){this.cache.delete(N),this.misses++;return}return this.hits++,t.value}set(N,t,m=5000){if(!this.enabled)return;this.cache.set(N,{value:t,timestamp:Date.now(),ttl:m})}has(N){if(!this.enabled)return!1;let t=this.cache.get(N);if(!t)return!1;if(Date.now()-t.timestamp>t.ttl)return this.cache.delete(N),!1;return!0}delete(N){this.cache.delete(N)}clear(){this.cache.clear()}disable(){this.enabled=!1,this.clear()}enable(){this.enabled=!0}stats(){return{size:this.cache.size,enabled:this.enabled,hits:this.hits,misses:this.misses}}resetStats(){this.hits=0,this.misses=0}keys(){return Array.from(this.cache.keys())}cleanup(){let N=Date.now();for(let[t,m]of this.cache.entries())if(N-m.timestamp>m.ttl)this.cache.delete(t)}destroy(){this.stopCleanup(),this.clear(),this.resetStats()}}var Tg=new Sl;function lu(){if("FORCE_COLOR"in Zo.env)return Zo.env.FORCE_COLOR!=="0";if("NO_COLOR"in Zo.env||Zo.env.TERM==="dumb")return!1;if(Zo.platform==="win32")return!0;return yl.isatty(1)&&yl.isatty(2)}var $l=lu();function Vn(N,t){if(!$l)return(m)=>m;return(m)=>N+m+t}var du=Vn("\x1B[0m","\x1B[0m"),uu=Vn("\x1B[31m","\x1B[39m"),pu=Vn("\x1B[32m","\x1B[39m"),mu=Vn("\x1B[33m","\x1B[39m"),fu=Vn("\x1B[34m","\x1B[39m"),gu=Vn("\x1B[35m","\x1B[39m"),hu=Vn("\x1B[36m","\x1B[39m"),yu=Vn("\x1B[37m","\x1B[39m"),vu=Vn("\x1B[90m","\x1B[39m"),bu=Vn("\x1B[1m","\x1B[22m"),wu=Vn("\x1B[3m","\x1B[23m"),Su=Vn("\x1B[4m","\x1B[24m"),$u=Vn("\x1B[2m","\x1B[22m"),Cu=Vn("\x1B[7m","\x1B[27m"),Au=Vn("\x1B[8m","\x1B[28m"),ku=Vn("\x1B[9m","\x1B[29m"),Ru=Vn("\x1B[41m","\x1B[49m"),Iu=Vn("\x1B[42m","\x1B[49m"),Pu=Vn("\x1B[43m","\x1B[49m"),xu=Vn("\x1B[44m","\x1B[49m"),Du=Vn("\x1B[45m","\x1B[49m"),Eu=Vn("\x1B[46m","\x1B[49m"),Tu=Vn("\x1B[47m","\x1B[49m"),Nu=$l,Ou={reset:du,red:uu,green:pu,yellow:mu,blue:fu,magenta:gu,cyan:hu,white:yu,gray:vu,bold:bu,italic:wu,underline:Su,dim:$u,inverse:Cu,hidden:Au,strikethrough:ku,bgRed:Ru,bgGreen:Iu,bgYellow:Pu,bgBlue:xu,bgMagenta:Du,bgCyan:Eu,bgWhite:Tu,isColorSupported:Nu},Lu=Ou,Fu=["up","down","left","right","space","enter","cancel"],Bg={actions:new Set(Fu),aliases:new Map([["k","up"],["j","down"],["h","left"],["l","right"],["\x03","cancel"],["escape","cancel"]]),messages:{cancel:"Canceled",error:"Something went wrong"}};var Mg=ju.platform.startsWith("win"),_g=Symbol("clapp:cancel");var Bu=tu();var Fn=(N,t)=>Bu?N:t,zg=Fn("◆","*"),Ug=Fn("■","x"),Vg=Fn("▲","x"),Wg=Fn("◇","o"),qg=Fn("┌","T"),Mu=Fn("│","|"),Gg=Fn("└","—"),Hg=Fn("●",">"),Kg=Fn("○"," "),Jg=Fn("◻","[•]"),Yg=Fn("◼","[+]"),Zg=Fn("◻","[ ]"),Qg=Fn("▪","•"),Xg=Fn("─","-"),eh=Fn("╮","+"),th=Fn("├","+"),nh=Fn("╯","+"),rh=Fn("●","•"),ih=Fn("◆","*"),oh=Fn("▲","!"),sh=Fn("■","x");var ah={light:Fn("─","-"),heavy:Fn("━","="),block:Fn("█","#")};function _u(){return`${Lu.gray(Mu)} `}var ch=_u();var ba="0.16.20";import{existsSync as Sa}from"node:fs";import{mkdir as Uu,writeFile as Cl}from"node:fs/promises";function $a(N){N.command("init","Initialize a new ts-cloud project").option("--mode <mode>","Deployment mode: server or serverless").option("--name <name>","Project name").option("--region <region>","AWS Region").action(async(t)=>{if(i("Initializing ts-cloud Project"),Sa("cloud.config.ts")){if(!await d("cloud.config.ts already exists. Overwrite?",!1)){e("Initialization cancelled");return}}let m=t?.name||await I("Project name","my-app"),A=t?.mode||await lo("Select deployment mode",["serverless","server"]),L=t?.region||await lo("Select AWS region",["us-east-1","us-west-2","eu-west-1","eu-central-1","ap-southeast-1"]),j=new o("Creating configuration file...");j.start();let G=`import { defineConfig } from '@ts-cloud/core'
|
|
32
32
|
|
|
33
33
|
export default defineConfig({
|
|
34
34
|
project: {
|
|
@@ -315,7 +315,7 @@ Resources to create: ${Te}`);let Qe={};for(let Ke of Object.values(ne.Resources|
|
|
|
315
315
|
No changes detected - infrastructure is up to date`);return}if(e(`
|
|
316
316
|
Changes detected:
|
|
317
317
|
`),xe.length>0){n(`Resources to add (${xe.length}):`);for(let Ee of xe){let Te=Ce[Ee].Type;e(` + ${Ee} (${Te})`)}console.log()}if(Me.length>0){r(`Resources to remove (${Me.length}):`);for(let Ee of Me){let Te=we[Ee].Type;e(` - ${Ee} (${Te})`)}console.log()}if(Ae.length>0){a(`Resources to modify (${Ae.length}):`);for(let Ee of Ae){let Te=Ce[Ee].Type;e(` ~ ${Ee} (${Te})`)}console.log()}e("Summary:"),e(` - Add: ${xe.length}`),e(` - Remove: ${Me.length}`),e(` - Modify: ${Ae.length}`),e("\nRun `cloud deploy` to apply these changes")}catch(m){r(`Diff failed: ${m.message}`)}})}function no(N,t=0){let m=Number(N);return Number.isFinite(m)?m:t}function ja(N){return no(N)*1024}function wp(N){let t=N?.date?.trim(),m=N?.time?.trim();if(!t||!m)return null;let A=new Date(`${t}T${m}Z`);return Number.isFinite(A.getTime())?A.toISOString():null}function Sp(N,t,m){let A;try{A=JSON.parse(N)}catch{return[]}let L=(A?.sysstat?.hosts??[]).flatMap((G)=>G.statistics??[]),j=[];for(let G of L){let Z=wp(G.timestamp);if(!Z)continue;let ee=new Date(Z).getTime();if(ee<t.getTime()||ee>m.getTime())continue;let ne=G["cpu-load"]?.find((be)=>be.cpu==="all")??G["cpu-load"]?.[0],oe=no(ne?.idle,100);j.push({timestamp:Z,cpuUsedPercent:Math.max(0,Math.min(100,100-oe)),cpuUserPercent:no(ne?.user),cpuSystemPercent:no(ne?.system),cpuIowaitPercent:no(ne?.iowait),memoryUsedPercent:no(G.memory?.["memused-percent"]),memoryUsedBytes:ja(G.memory?.memused),memoryAvailableBytes:ja(G.memory?.avail),swapUsedPercent:no(G.memory?.["swpused-percent"]),swapUsedBytes:ja(G.memory?.swpused)})}return j.sort((G,Z)=>G.timestamp.localeCompare(Z.timestamp))}function $p(N){return Object.fromEntries(Object.entries(N.time_series??{}).map(([t,m])=>[t,(m.values??[]).map(([A,L])=>({timestamp:new Date(Number(A)*1000).toISOString(),value:no(L,Number.NaN)})).filter((A)=>Number.isFinite(A.value))]))}function Fl(N){return N.length?N.reduce((t,m)=>t+m,0)/N.length:null}function Fa(N){return N.length?Math.max(...N):null}function Cp(N){return N.length?Math.min(...N):null}async function Bl(N){let[t,m]=await Promise.all([N.client.getServerMetrics(N.serverId,{types:["cpu","disk","network"],start:N.from,end:N.to,step:N.step}),Re(N.remote.host,"LC_ALL=C sadf -j -- -u -r -S",N.remote).catch(()=>"")]),A=Sp(m,N.from,N.to),L=$p(t),G=(L.cpu??[]).map((be)=>Math.max(0,Math.min(100,be.value/Math.max(1,N.cores)))),Z=A.map((be)=>be.cpuUsedPercent),ee=G.length?G:Z,ne=A.map((be)=>be.memoryUsedPercent),oe=A.map((be)=>be.swapUsedPercent);return{from:N.from.toISOString(),to:N.to.toISOString(),cores:N.cores,host:A,provider:L,summary:{cpuAveragePercent:Fl(ee),cpuPeakPercent:Fa(ee),memoryAveragePercent:Fl(ne),memoryPeakPercent:Fa(ne),memoryMinimumAvailableBytes:Cp(A.map((be)=>be.memoryAvailableBytes)),swapPeakPercent:Fa(oe)}}}function Ap(N){if(N.length===0)throw Error("A server name cannot be empty.");if(N.length>253)throw Error(`'${N}' is longer than the 253 characters a hostname allows.`);for(let t of N.split(".")){if(t.length===0)throw Error(`'${N}' has an empty label — a hostname cannot contain '..'.`);if(t.length>63)throw Error(`'${t}' is longer than the 63 characters a hostname label allows.`);if(!/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i.test(t))throw Error(`'${t}' is not a valid hostname label. Use letters, digits and hyphens, not starting or ending with a hyphen.`)}}async function Ml(N,t,m){if(Ap(t),N===t)throw Error(`'${N}' is already named that.`);if((await m.takenNames()).some((j)=>j===t&&j!==N))throw Error(`'${t}' is already taken. Server names have to be unique within a provider project.`);let L=[];if(m.providerName&&m.renameProvider){let{providerName:j,renameProvider:G}=m;L.push({id:"provider",title:"Rename the server at the provider",change:{from:N,to:t},satisfied:async()=>await j()===t,apply:()=>G(t)})}if(m.stateName&&m.writeStateName){let{stateName:j,writeStateName:G}=m;L.push({id:"state-pin",title:"Update the recorded name in the local driver state",change:{from:N,to:t},satisfied:async()=>{let Z=await j();return Z===void 0||Z===t},apply:()=>G(t)})}if(m.remoteHostname&&m.setRemoteHostname){let{remoteHostname:j,setRemoteHostname:G}=m;L.push({id:"hostname",title:"Set the hostname on the box",change:{from:N,to:t},satisfied:async()=>await j()===t,apply:()=>G(t)})}return L.push({id:"inventory",title:"Rename the fleet inventory record",change:{from:N,to:t},satisfied:async()=>m.inventoryName()===t,apply:async()=>{await m.renameInventory(t)}}),{operation:"server:rename",target:N,steps:L}}function _l(N){let t=`'${N.replace(/'/g,`'"'"'`)}'`;return["set -eu",'TS_CLOUD_OLD="$(hostname)"',`hostnamectl set-hostname ${t} 2>/dev/null || { echo ${t} > /etc/hostname && hostname ${t}; }`,'if grep -q "^127.0.1.1" /etc/hosts; then',` TS_CLOUD_HOSTS="$(sed -E "s/^127\\.0\\.1\\.1.*/127.0.1.1\\t${N}/" /etc/hosts)"`,` printf '%s\\n' "$TS_CLOUD_HOSTS" > /etc/hosts`,"else",` printf '127.0.1.1\\t%s\\n' ${t} >> /etc/hosts`,"fi",'printf "%s -> %s\\n" "$TS_CLOUD_OLD" "$(hostname)"'].join(`
|
|
318
|
-
`)}async function kp(){let N=await Ne(),t=y(process.cwd(),N),m=new Ie(t.store),A=new mn(m,[new tt("aws"),new tt("hetzner"),new tt("ssh")]);return{controlPlane:t,store:m,service:A}}async function xi(N){let t=await kp();try{return await N(t)}finally{t.controlPlane.store.close()}}var io=(N,t)=>{let m=N.store.list(N.controlPlane.project.id).find((A)=>A.id===t||A.name===t);if(!m)throw Error(`Server ${t} was not found.`);return m},hr=(N)=>{r(N instanceof Error?N.message:String(N)),process.exitCode=1};function Ba(N,t){let m=Number.parseInt(N??"",10);return Number.isFinite(m)&&m>=0?m:t}function Rp(N="3h"){let t=N.match(/^(\d+)(m|h)$/);if(!t)throw Error("--range must use minutes or hours, for example 30m or 3h.");let m=Number(t[1])*(t[2]==="h"?3600000:60000);if(m<300000||m>86400000)throw Error("--range must be between 5 minutes and 24 hours.");return m}function rs(N,t="%"){return N==null?"unavailable":`${N.toFixed(1)}${t}`}async function Ip(N,t){let m=await Ne();if(m.cloud?.provider!=="hetzner")throw Error("server:monitoring currently requires the Hetzner provider.");let A=t.env??process.env.CLOUD_ENV??"production",L=E(m,A),j=await de(L);if(!j?.serverId)throw Error(`No pinned Hetzner server was found for ${L}.`);if(![j.serverName,String(j.serverId),j.stackName].includes(N))throw Error(`Refusing to read ${N}: project state is pinned to ${j.serverName}.`);let G=rr(m),Z=new ze({apiToken:nr(G.apiToken,m)}),ee=await Z.getServer(j.serverId),ne=j.publicIp??ee.public_net.ipv4?.ip;if(!ne)throw Error(`Server ${ee.name} has no public IPv4 address.`);let oe=new Date,be=new Date(oe.getTime()-Rp(t.range)),we=Math.min(3600,Math.max(60,Ba(t.step,60))),Ce=await Bl({client:Z,serverId:ee.id,cores:Math.max(1,Number(ee.server_type.cores)||1),from:be,to:oe,step:we,remote:{host:ne,user:j.sshUser??G.sshUser,identityFile:G.sshPrivateKeyPath,connectTimeoutSec:15}});if(t.json){console.log(JSON.stringify({schemaVersion:1,server:ee.name,result:Ce},null,2));return}c(["Server","Window","CPU average / peak","RAM average / peak","Minimum available","Swap peak"],[[ee.name,`${Ce.from} to ${Ce.to}`,`${rs(Ce.summary.cpuAveragePercent)} / ${rs(Ce.summary.cpuPeakPercent)}`,`${rs(Ce.summary.memoryAveragePercent)} / ${rs(Ce.summary.memoryPeakPercent)}`,Ce.summary.memoryMinimumAvailableBytes==null?"unavailable":`${(Ce.summary.memoryMinimumAvailableBytes/1073741824).toFixed(2)} GB`,rs(Ce.summary.swapPeakPercent)]])}function zl(N){let t=N.targetType.prices?.find((m)=>m.location===N.location);return{serverId:N.serverId,serverName:N.serverName,location:N.location,from:N.currentType.name,to:N.targetType.name,capacityAvailable:N.capacityAvailable,alreadyComplete:N.alreadyComplete,upgradeDisk:N.upgradeDisk,target:{cores:N.targetType.cores,memoryGb:N.targetType.memory,diskGb:N.targetType.disk,architecture:N.targetType.architecture,cpuType:N.targetType.cpu_type},price:t?{hourlyNet:t.price_hourly.net,hourlyGross:t.price_hourly.gross,monthlyNet:t.price_monthly.net,monthlyGross:t.price_monthly.gross}:void 0}}function Pp(N){let t=zl(N);c(["Server","Location","Resize","Capacity","CPU / RAM / disk","Monthly"],[[`${t.serverName} (${t.serverId})`,t.location,`${t.from} -> ${t.to}`,t.capacityAvailable?"available":"waiting",`${t.target.cores??0} / ${t.target.memoryGb??0} GB / ${t.target.diskGb??0} GB`,t.price?.monthlyGross??t.price?.monthlyNet??"not reported"]])}async function xp(N,t,m){let A=await Ne();if(A.cloud?.provider!=="hetzner")throw Error("server:resize currently requires the Hetzner provider.");let L=m.env??process.env.CLOUD_ENV??"production",j=E(A,L),G=await de(j),Z=rr(A),ee=new ze({apiToken:nr(Z.apiToken,A)}),oe=G&&(N===G.serverName||N===String(G.serverId)||N===G.stackName)?await ee.getServer(G.serverId):(await ee.listServers()).find((Ke)=>Ke.name===N||String(Ke.id)===N);if(!oe)throw Error(`Hetzner server ${N} was not found.`);if(G?.serverId&&G.serverId!==oe.id)throw Error(`Refusing to resize ${N}: project state is pinned to server ${G.serverId}.`);let be=at(t),we=m.upgradeDisk!==!1,Ce=await Hn(ee,oe.id,be,we);if(m.json)console.log(JSON.stringify({schemaVersion:1,plan:zl(Ce)},null,2));else Pp(Ce);if(!m.apply){if(!m.json)e(`Preview only. Re-run with --apply --confirm ${oe.name} to execute.`);return}if(m.confirm!==oe.name)throw Error(`Resize requires --confirm ${oe.name}.`);let De=G?.publicIp??oe.public_net.ipv4?.ip;if(!De)throw Error(`Server ${oe.name} has no public IPv4 address for verification.`);let Se={host:De,user:G?.sshUser??Z.sshUser,identityFile:Z.sshPrivateKeyPath,connectTimeoutSec:15,sshTimeoutMs:600000,routeTimeoutMs:20000},xe=await Ko(j),Me=new Date().toISOString(),Ae={schemaVersion:1,operationId:xe?.targetType===be&&xe.serverId===oe.id?xe.operationId:crypto.randomUUID(),stackName:j,serverId:oe.id,serverName:oe.name,sourceType:Ce.currentType.name,targetType:be,upgradeDisk:we,phase:"planning",status:"running",attempts:xe?.targetType===be?xe.attempts:0,startedAt:xe?.targetType===be?xe.startedAt:Me,updatedAt:Me,manifest:xe?.targetType===be?xe.manifest:void 0};await lt(Ae);let Ee=Ba(m.pollSeconds,900)*1000,Te=Ba(m.maxWaitMinutes,0)*60000,Qe=Date.now();for(;;){let Ke=await Hn(ee,oe.id,be,we);if(!Ke.capacityAvailable&&!Ke.alreadyComplete){if(Ae={...Ae,phase:"waiting-capacity",status:"waiting-capacity",updatedAt:new Date().toISOString()},await lt(Ae),!m.wait){if(!m.json)e(`${be} has no capacity in ${Ke.location}. The server remains running and unchanged. Use --wait to poll safely.`);return}if(Te>0&&Date.now()-Qe>=Te)throw Error(`Timed out waiting for ${be} capacity in ${Ke.location}.`);if(!m.json)e(`Waiting ${Math.round(Ee/1000)} seconds for ${be} capacity...`);await Bun.sleep(Ee);continue}let Ye=await Jo(j);try{let et=await(async()=>{try{return Ae={...Ae,status:"running",attempts:Ae.attempts+1,updatedAt:new Date().toISOString()},await lt(Ae),await Vo({client:ee,serverId:oe.id,targetType:be,upgradeDisk:we,resumeFromOff:Ae.phase==="shutting-down"||Ae.phase==="resizing"||Ae.phase==="powering-on"||Ae.phase==="verifying",manifest:Ae.manifest,hooks:{preflight:async()=>{let Pt=await zo(Se);return Ae={...Ae,manifest:Pt,updatedAt:new Date().toISOString()},await lt(Ae),Pt},afterBoot:async(Pt,Bt,vt,Ot)=>Ho(Se,Bt,vt,Ot),onPhase:async(Pt,Bt)=>{if(Ae={...Ae,phase:Pt,status:Pt==="waiting-capacity"?"waiting-capacity":Pt==="complete"?"completed":"running",updatedAt:new Date().toISOString()},await lt(Ae),!m.json)e(`${Pt}${Bt?` ${JSON.stringify(Bt)}`:""}`)}}})}finally{await Ye()}})();if(Ae={...Ae,status:et.status==="completed"||et.status==="already-complete"?"completed":et.status==="recovered"?"recovered":"waiting-capacity",lastError:et.status==="recovered"?et.error:void 0,updatedAt:new Date().toISOString()},await lt(Ae),m.json)console.log(JSON.stringify({schemaVersion:1,result:et},null,2));else if(et.status==="completed"||et.status==="already-complete")n(`${oe.name} is on ${be} and passed full post-boot verification.`);else if(et.status==="recovered"&&et.retryable&&m.wait){e(`Capacity race recovered safely. Waiting ${Math.round(Ee/1000)} seconds before retry.`),await Bun.sleep(Ee);continue}else if(et.status==="recovered")throw Error(`Resize did not complete and the original server was recovered: ${et.error}`);return}catch(et){throw Ae={...Ae,status:"failed",lastError:et instanceof Error?et.message:String(et),updatedAt:new Date().toISOString()},await lt(Ae),et}}}async function Dp(N,t){let m=await Ne();if(m.cloud?.provider!=="hetzner")throw Error("server:optimize currently requires the Hetzner provider.");let A=t.env??process.env.CLOUD_ENV??"production",L=E(m,A),j=await de(L);if(!j?.serverId)throw Error(`No pinned Hetzner server was found for ${L}.`);if(![j.serverName,String(j.serverId),j.stackName].includes(N))throw Error(`Refusing to optimize ${N}: project state is pinned to ${j.serverName}.`);let G=rr(m),Z=new ze({apiToken:nr(G.apiToken,m)}),ee=await Z.getServer(j.serverId),ne=j.publicIp??ee.public_net.ipv4?.ip;if(!ne)throw Error(`Server ${ee.name} has no public IPv4 address.`);let oe=Li(m);if(t.json)console.log(JSON.stringify({schemaVersion:1,server:ee.name,plan:oe},null,2));else c(["Server","Firewall ports","Monitoring","Auto updates","Swap","SSH passwords"],[[ee.name,oe.firewallPorts.join(","),oe.monitoring?"on":"off",oe.autoUpdates?"on":"off",`${oe.swapGb} GB`,"disabled"]]);if(!t.apply){if(!t.json)e(`Preview only. Re-run with --apply --confirm ${ee.name} to execute.`);return}if(t.confirm!==ee.name)throw Error(`Optimization requires --confirm ${ee.name}.`);let be={host:ne,user:j.sshUser??G.sshUser,identityFile:G.sshPrivateKeyPath,connectTimeoutSec:15},we=await jr(be),Ce=we.routeProbes.filter((vt)=>!vt.ok),De=m.infrastructure?.compute,Se=X(De)?new Set(["nginx.service","bun-gateway.service","ts-cloud-nginx.service"]):new Set,xe=we.failedUnits.filter((vt)=>!Se.has(vt));if(xe.length>0)throw Error(`Preflight found failed services: ${xe.join(", ")}`);if(Ce.length>0)throw Error(`Preflight found unhealthy routes: ${Ce.map((vt)=>vt.domain).join(", ")}`);let Me=X(De)?[]:Object.values(m.sites??{}).flatMap((vt)=>typeof vt?.port==="number"&&![80,443].includes(vt.port)?[vt.port]:[]),Ae=Br({allowSsh:De?.allowSsh!==!1,sitePorts:Me,allowedPorts:De?.firewall?.allowedPorts}),Ee=(j.firewallId?(await Z.listFirewalls()).find((vt)=>vt.id===j.firewallId):void 0)??(await Z.listFirewalls()).find((vt)=>vt.name===`${m.project.slug}-${A}-app-fw`);if(!Ee)throw Error(`Managed firewall for ${ee.name} was not found.`);let Te=await Z.setFirewallRules(Ee.id,Ae);await Promise.all(Te.map((vt)=>Z.waitForAction(vt.id))),await qo(m,be);let[Qe,Ke]=await Promise.all([jr(be),Wo(be)]),Ye=Go(oe,Ke),et=Ia(we,Qe),Pt=Qe.routeProbes.filter((vt)=>!vt.ok);if(et.stoppedServices.length>0)Ye.push(`services stopped: ${et.stoppedServices.join(", ")}`);if(et.changedRouteFragments.length>0)Ye.push(`route fragments changed: ${et.changedRouteFragments.join(", ")}`);if(et.missingRouteIds.length>0)Ye.push(`routes disappeared: ${et.missingRouteIds.join(", ")}`);if(et.changedReleaseLinks.length>0)Ye.push(`release links changed: ${et.changedReleaseLinks.join(", ")}`);if(et.missingData.length>0)Ye.push(`databases or volumes disappeared: ${et.missingData.join(", ")}`);if(Pt.length>0)Ye.push(`unhealthy routes: ${Pt.map((vt)=>vt.domain).join(", ")}`);if(Ye.length>0)throw Error(`Host optimization verification failed: ${Ye.join("; ")}`);let Bt={serverId:ee.id,serverName:ee.name,services:Qe.runningServices.length,routes:Qe.routeIds.length,healthyDomains:Qe.routeProbes.length,releaseLinks:Qe.releaseLinks.length,databasesAndVolumes:Qe.dataCatalog.length,report:Ke};if(t.json)console.log(JSON.stringify({schemaVersion:1,result:Bt},null,2));else n(`${ee.name} passed full host, rpx route, service, release, and data verification.`)}async function Ep(N,t,m){let A=await Ne(),L=m.env??"production",j=E(A,L);await xi(async(G)=>{let Z=io(G,N),ee=G.store.list(G.controlPlane.project.id,!0),ne=Z.provider==="hetzner"&&Z.providerId?(()=>{try{let Ee=rr(A);return new ze({apiToken:nr(Ee.apiToken,A)})}catch{return null}})():null,oe=Z.providerId?Number(Z.providerId):Number.NaN,be=await de(j),we=be!=null&&be.serverId===oe,Ce=new Rr,De=Z.trustState==="pinned",Se={takenNames:async()=>{let Ee=ee.map((Te)=>Te.name);if(ne)Ee.push(...(await ne.listServers()).map((Te)=>Te.name));return Ee},inventoryName:()=>G.store.get(Z.id)?.name??Z.name,renameInventory:(Ee)=>{G.store.update(Z.id,{name:Ee})},...ne&&Number.isFinite(oe)?{providerName:async()=>(await ne.getServer(oe)).name,renameProvider:async(Ee)=>{await ne.renameServer(oe,Ee)}}:{},...we?{stateName:async()=>(await de(j))?.serverName,writeStateName:async(Ee)=>{let Te=await de(j);if(Te)await ct(j,{...Te,serverName:Ee})}}:{},...De?{remoteHostname:async()=>{let Ee=await Ce.exec(Z,"hostname");return Ee.code===0?Ee.stdout.trim():void 0},setRemoteHostname:async(Ee)=>{let Te=await Ce.exec(Z,_l(Ee));if(Te.code!==0)throw Error(Te.stderr.trim()||`hostname exited ${Te.code}`)}}:{}},xe=await Ml(Z.name,t,Se),Me=await Is(xe);if(!m.apply){let Ee=[ne?"":"provider record (no provider id or no API token)",we?"":"local state pin (none points at this server)",De?"":"box hostname (host key is not pinned — run server:validate first)"].filter(Boolean);if(m.json){console.log(JSON.stringify({schemaVersion:1,operation:xe.operation,target:xe.target,rename:{from:Z.name,to:t},notCovered:Ee,steps:Me.map((Te)=>({id:Te.step.id,title:Te.step.title,state:Te.state,change:Te.step.change,reason:Te.reason}))},null,2));return}for(let Te of Ps(xe,Me))console.log(Te);for(let Te of Ee)console.log(` not covered: ${Te}`);console.log(" Re-run with --apply to perform it.");return}let Ae=await xs(xe,Me,{log:(Ee)=>e(Ee),audit:(Ee)=>G.controlPlane.store.appendEvent({projectId:G.controlPlane.project.id,resourceId:Z.resourceId,type:`${Ee.operation}.${Ee.step}.${Ee.state}`,level:Ee.state==="failed"?"error":"info",payload:{target:Ee.target,renameTo:t,...Ee.error?{error:Ee.error}:{}}})});if(m.json)console.log(JSON.stringify({schemaVersion:1,outcome:Ae},null,2));if(!Ae.success){let Ee=Ae.steps.find((Te)=>Te.state==="failed");throw Error(`${xe.operation} stopped at '${Ee?.title}': ${Ee?.error}. Earlier steps stayed applied; re-run the same command to continue from here.`)}if(!m.json)n(`Renamed ${Z.name} to ${t}.`)})}function Ma(N){N.command("capabilities [server]","Show provider and target operation support").option("--json","Print structured JSON").action(async(t,m)=>{try{await xi(async(A)=>{let L=t?[io(A,t)]:A.store.list(A.controlPlane.project.id),j=L.flatMap((G)=>Object.entries(G.capabilities).map(([Z,ee])=>({server:G.name,provider:G.provider,action:Z,...ee})));if(m.json)console.log(JSON.stringify({schemaVersion:1,targets:j},null,2));else c(["Server","Provider","Action","Support","Explanation"],j.map((G)=>[G.server,G.provider,G.action,G.supported?"supported":"unsupported",G.reason??"—"]))})}catch(A){hr(A)}}),N.command("server:resize <name> <type>","Safely resize Hetzner compute with full host verification").option("--env <environment>","Deployment environment",{default:"production"}).option("--apply","Execute the reviewed resize plan").option("--confirm <name>","Exact server name required for mutation").option("--upgrade-disk","Permanently expand the root disk to the target size",{default:!0}).option("--wait","Poll capacity without taking the server offline until placement is available").option("--poll-seconds <seconds>","Capacity retry interval",{default:"900"}).option("--max-wait-minutes <minutes>","Stop waiting after this many minutes; 0 waits indefinitely",{default:"0"}).option("--json","Print structured JSON").action(async(t,m,A)=>{try{await xp(t,m,A)}catch(L){hr(L)}}),N.command("server:optimize <name>","Reconcile and verify a production Hetzner host").option("--env <environment>","Deployment environment",{default:"production"}).option("--apply","Apply the reviewed host optimization plan").option("--confirm <name>","Exact server name required for mutation").option("--json","Print structured JSON").action(async(t,m)=>{try{await Dp(t,m)}catch(A){hr(A)}}),N.command("server:monitoring <name>","Read historical Hetzner CPU, RAM, swap, disk, and network metrics").option("--env <environment>","Deployment environment",{default:"production"}).option("--range <duration>","Historical window from 5m to 24h",{default:"3h"}).option("--step <seconds>","Hetzner provider sample interval",{default:"60"}).option("--json","Print structured JSON").action(async(t,m)=>{try{await Ip(t,m)}catch(A){hr(A)}}),N.command("server:list","List fleet servers").option("--json","Print structured JSON").action(async(t)=>{try{await xi(async(m)=>{let A=m.store.list(m.controlPlane.project.id);if(t.json)console.log(JSON.stringify(A,null,2));else c(["Name","Provider ID","Provider / region","Status / trust","Roles","CPU / memory","Heartbeat"],A.map((L)=>[L.name,L.providerId??"—",`${L.provider} / ${L.region??"external"}`,`${L.status} / ${L.trustState}`,L.roles.join(","),`${L.capacity.cpu??0} / ${L.capacity.memoryBytes??0}`,L.heartbeatAt??"never"]))})}catch(m){hr(m)}}),N.command("server:create <name>","Enroll a provisioned or existing server").option("--provider <provider>","aws, hetzner, or ssh",{default:"ssh"}).option("--provider-id <id>","Stable provider identity").option("--endpoint <host>","SSH hostname or IP").option("--user <user>","Non-root SSH user",{default:"deploy"}).option("--credential-ref <ref>","Secret reference",{default:"secret://fleet/agent"}).option("--region <region>","Provider region").option("--roles <roles>","Comma-separated roles",{default:"application"}).option("--labels <labels>","Comma-separated key=value labels").action(async(t,m)=>{try{await xi(async(A)=>{let L=m.provider;if(!["aws","hetzner","ssh"].includes(L)||!m.endpoint)throw Error("A supported --provider and --endpoint are required; provisioning and enrollment are separate operations.");let j=A.service.enroll({organizationId:A.controlPlane.organization.id,projectId:A.controlPlane.project.id,name:t,provider:L,providerId:m.providerId,endpoint:m.endpoint,sshUser:m.user??"deploy",credentialRef:m.credentialRef??"secret://fleet/agent",region:m.region,roles:String(m.roles??"application").split(","),labels:Object.fromEntries(String(m.labels??"").split(",").map((G)=>G.split("=")).filter((G)=>G[0]&&G[1]))});n(`Enrolled ${j.name} as ${j.id}; no remote mutation was performed.`)})}catch(A){hr(A)}}),N.command("server:validate <name>","Pin trust and validate a server").option("--accept-host-key <fingerprint>","Accept reviewed rotation").option("--json","Print JSON").action(async(t,m)=>{try{await xi(async(A)=>{let L=io(A,t);if(L=await A.service.test(L.id),L.trustState==="rotation_pending"){if(!m.acceptHostKey)throw Error(`Host key changed to ${L.pendingHostKey}; review it first.`);L=A.service.reviewHostKey(L.id,m.acceptHostKey)}let j=await A.service.validate(L.id);if(m.json)console.log(JSON.stringify(j.validation,null,2));else c(["Severity","Code","Finding","Remediation"],(j.validation?.findings??[]).map((G)=>[G.severity,G.code,G.message,G.remediation??"—"]));if(!j.validation?.valid)process.exitCode=1})}catch(A){hr(A)}}),N.command("server:bootstrap <name>","Preview or queue bootstrap").option("--apply","Apply reviewed plan").action(async(t,m)=>{try{await xi(async(A)=>{let L=A.service.bootstrap(io(A,t).id,!!m.apply);if(L.preview)c(["Step"],L.steps.map((j)=>[j]));else n(`Bootstrap queued: ${L.operation?.id}`)})}catch(A){hr(A)}}),N.command("server:rename <name> <new-name>","Rename a server in place, without recreating it").option("--env <environment>","Deployment environment",{default:"production"}).option("--apply","Perform the reviewed rename plan").option("--json","Print structured JSON").action(async(t,m,A)=>{try{await Ep(t,m,A)}catch(L){hr(L)}}),N.command("server:drain <name>","Drain without terminating").option("--complete","Mark movement complete").action(async(t,m)=>{try{await xi(async(A)=>n(A.service.drain(io(A,t).id,!!m.complete).status))}catch(A){hr(A)}}),N.command("server:uncordon <name>","Return a server to scheduling").action(async(t)=>{try{await xi(async(m)=>{m.service.uncordon(io(m,t).id),n(`Uncordoned ${t}.`)})}catch(m){hr(m)}}),N.command("server:archive <name>","Archive inventory without termination").option("--confirm <name>","Exact name").action(async(t,m)=>{try{await xi(async(A)=>{A.service.archive(io(A,t).id,m.confirm??""),n(`Archived ${t}; provider infrastructure was not terminated.`)})}catch(A){hr(A)}}),N.command("server:ssh <name>","Open strict SSH using the enrolled endpoint").action(async(t)=>{try{await xi(async(m)=>{let A=io(m,t);if(A.trustState!=="pinned")throw Error("Validate and pin the server host key first.");let L=Bun.spawn(["ssh","-p",String(A.sshPort),"-o","StrictHostKeyChecking=yes",`${A.sshUser}@${A.endpoint}`],{stdin:"inherit",stdout:"inherit",stderr:"inherit"}),j=await L.exited;if(j)process.exitCode=j})}catch(m){hr(m)}});for(let[t,m]of[["server:logs <name>","Use the runtime log service"],["server:deploy <name>","Use immutable release deployment"],["server:reboot <name>","Reboot provider compute"],["server:destroy <name>","Terminate provider compute"],["server:recipe <name> <recipe>","Apply a server recipe"],["server:firewall:add <name> <rule>","Add firewall rule"],["server:firewall:list <name>","List firewall rules"],["server:firewall:remove <name> <rule>","Remove firewall rule"],["server:ssl:install <domain>","Install TLS"],["server:ssl:renew <domain>","Renew TLS"],["server:snapshot <name>","Create provider snapshot"],["server:snapshot:restore <name> <snapshot-id>","Restore provider snapshot"],["server:update <name>","Update OS packages"],["server:secure <name>","Apply OS hardening"]])N.command(t,m).action(async(...A)=>Vr(t.split(" ")[0],{target:String(A[0]??""),nextAction:"Use the dashboard capability view or the corresponding runtime, release, firewall, backup, or maintenance service."}))}import{existsSync as Ul,mkdirSync as Tp,readFileSync as Np,writeFileSync as Op}from"node:fs";import{join as Vl,resolve as Lp}from"node:path";var za=(N)=>{r(N instanceof Error?N.message:String(N)),process.exitCode=1};async function jp(){try{return await Ne()}catch{return}}function Fp(N){if(N===void 0)return;let t=Number(N);if(!Number.isInteger(t)||t<1||t>65535)throw Error(`--port must be a port number, not '${N}'.`);return t}function Wl(N,t,m){let A=N?.ssh?.hosts?.find((L)=>L.host===t);return new cr({hosts:t?[A??{host:t}]:N?.ssh?.hosts,user:m.user,port:Fp(m.port),privateKeyPath:m.key,hostKey:N?.ssh?.hostKey,sudo:N?.ssh?.sudo,profile:m.profile??N?.ssh?.profile,publicIp:N?.ssh?.publicIp,lan:N?.ssh?.lan})}var ql=1073741824;function Ua(N){N.command("ssh:preflight [host]","Check a bring-your-own Linux host before adopting it").option("--user <user>","SSH user (default: ssh.hosts[].user, then root)").option("--port <port>","SSH port (default: ssh.hosts[].port, then 22)").option("--key <path>","SSH private key (default: ssh.hosts[].privateKeyPath, then ~/.ssh/id_ed25519)").option("--profile <profile>","raspberry-pi or generic (default: ssh.profile, then generic)").option("--json","Print the facts and findings as JSON").action(async(t,m)=>{try{let A=await jp(),L=Wl(A,t,m),j=t??L.targetHost(),G=await L.ensureHostKey(j),{facts:Z,findings:ee}=await L.preflight(j);if(m.json)console.log(JSON.stringify({schemaVersion:1,host:j,hostKeyFingerprint:G.fingerprint,facts:Z,findings:ee},null,2));else{if(i(`Preflight ${j}`),G.pinnedNow)e(`Pinned host key ${G.fingerprint}`);if(e(`${Z.os} on ${Z.arch}, ${Z.cpuCores} cores, ${(Z.memoryBytes/ql).toFixed(1)} GiB memory, ${(Z.diskFreeBytes/ql).toFixed(1)} GiB free`),Z.piModel)e(Z.piModel);if(Z.lanIp)e(`LAN address ${Z.lanIp}`);if(console.log(Fr(ee)),ar(ee))r("The host is not ready; fix the errors above and run the preflight again.");else n("The host is ready to adopt.")}if(ar(ee))process.exitCode=1}catch(A){za(A)}}),N.command("ssh:bootstrap","Adopt the configured host: pin its key, run the preflight, then bootstrap it").option("--env <environment>","Deployment environment",{default:"production"}).option("--dry-run","Print the bootstrap script instead of running it").action(async(t)=>{try{let m=await Ne(),A=t.env??"production";if(t.dryRun){let G=sr(m),[Z]=G.hosts;console.log(or({config:m,environment:A,profile:G.profile,sudoUser:Z.user!=="root"?Z.user:void 0,lan:G.lan}));return}let L=Wl(m,void 0,{});i(`Adopt ${L.targetHost()}`);let j=await L.provisionComputeInfrastructure({config:m,environment:A});n(`${j.appPublicIp} is bootstrapped; deploy with: cloud deploy --env ${A}`)}catch(m){za(m)}}),N.command("ssh:first-boot","Write cloud-init first-boot files for a freshly flashed Raspberry Pi OS or Ubuntu image").option("--os <os>","raspberry-pi-os or ubuntu",{default:"raspberry-pi-os"}).option("--out <dir>","Directory to write user-data, network-config and meta-data into (never a mounted card; copy them yourself)").option("--hostname <name>","Hostname of the new host").option("--user <user>","Deploy user created on first boot (default: ssh.hosts[].user, then pi)").option("--key <path>","Public key authorized for the user",{default:"~/.ssh/id_ed25519.pub"}).option("--wifi-ssid <ssid>","Join this Wi-Fi network on first boot").option("--wifi-passphrase-env <name>","Environment variable holding the Wi-Fi passphrase",{default:"WIFI_PASSWORD"}).option("--wifi-country <cc>","Wi-Fi regulatory domain, e.g. DE").option("--timezone <tz>","IANA timezone, e.g. Europe/Berlin").option("--locale <locale>","System locale, e.g. en_US.UTF-8").option("--env <environment>","Deployment environment the embedded bootstrap is built for",{default:"production"}).option("--force","Overwrite files already in --out").action(async(t)=>{try{if(!t.out)throw Error("--out <dir> is required.");if(!t.hostname)throw Error("--hostname <name> is required.");let m=t.os??"raspberry-pi-os";if(!(m in $i))throw Error(`--os must be raspberry-pi-os or ubuntu, not '${m}'.`);let A=await Ne(),L=t.env??"production",j=sr(A,{hosts:A.ssh?.hosts?.length?void 0:[{host:t.hostname}],profile:m==="raspberry-pi-os"?"raspberry-pi":void 0}),G=t.user??(A.ssh?.hosts?.[0]?.user??"pi"),Z=Ur(t.key??"~/.ssh/id_ed25519.pub");if(!Ul(Z))throw Error(`Public key not found at ${Z}; pass --key <path to a .pub file>.`);let ee=Np(Z,"utf8").trim(),ne;if(t.wifiSsid){let De=t.wifiPassphraseEnv??"WIFI_PASSWORD",Se=process.env[De];if(!Se)throw Error(`--wifi-ssid needs the passphrase in $${De} (set it in the environment, not on the command line).`);if(!t.wifiCountry)throw Error("--wifi-country <cc> is required with --wifi-ssid.");ne={ssid:t.wifiSsid,passphrase:Se,country:t.wifiCountry}}let oe=or({config:A,environment:L,profile:j.profile,sudoUser:G!=="root"?G:void 0,lan:j.lan}),be=Oi({hostname:t.hostname,user:G,publicKey:ee,timezone:t.timezone,locale:t.locale,wifi:ne},oe,{os:m}),we=Lp(t.out);Tp(we,{recursive:!0});let Ce=Object.keys(be.files).filter((De)=>Ul(Vl(we,De)));if(Ce.length>0&&!t.force)throw Error(`${Ce.join(", ")} already exist in ${we}; pass --force to overwrite.`);for(let[De,Se]of Object.entries(be.files))Op(Vl(we,De),Se,{mode:384});i(`First boot for ${t.hostname}`),n(`Wrote ${Object.keys(be.files).join(", ")} to ${we}`),console.log(be.instructions)}catch(m){za(m)}})}async function Bp(){let N=await Ne(),t=y(process.cwd(),N),m=new gn(t.store),A=new fn(m,new Ie(t.store));return{controlPlane:t,store:m,service:A}}async function is(N){let t=await Bp();try{await N(t)}catch(m){r(m instanceof Error?m.message:String(m)),process.exitCode=1}finally{t.controlPlane.store.close()}}var Ts=(N)=>Object.fromEntries(String(N??"").split(",").map((t)=>t.split("=")).filter((t)=>t[0]&&t[1])),Gl=(N)=>Object.fromEntries(Object.entries(Ts(N)).map(([t,m])=>[t,Number(m)]));function Va(N){N.command("pool:list","List capacity pools and reservations").option("--json","Print structured JSON").action(async(t)=>is((m)=>{let A=m.store.listPools(m.controlPlane.project.id);if(t.json)console.log(JSON.stringify(A,null,2));else c(["Name","Purpose","Backend","Region / arch","Status","Capacity","Concurrency"],A.map((L)=>[L.name,L.purpose,L.backend,`${L.region??"any"} / ${L.architecture??"any"}`,L.status,JSON.stringify(L.capacity),String(L.concurrency)]))})),N.command("pool:create <name>","Create a capacity pool").option("--purpose <purpose>","application, build, worker, monitoring, or backup",{default:"application"}).option("--backend <backend>","server, ecs, or asg",{default:"server"}).option("--capacity <values>","cpu=4,memoryBytes=8589934592,diskBytes=...").option("--region <region>","Required region").option("--arch <architecture>","Required architecture").option("--labels <labels>","Pool key=value labels").option("--selector <labels>","Required server labels").option("--max <count>","Maximum workloads",{default:"10"}).option("--concurrency <count>","Build concurrency",{default:"1"}).action(async(t,m)=>is((A)=>{let{purpose:L,backend:j}=m;if(!["application","build","worker","monitoring","backup"].includes(L)||!["server","ecs","asg"].includes(j))throw Error("Unsupported pool purpose or backend.");let G=A.store.createPool({organizationId:A.controlPlane.organization.id,projectId:A.controlPlane.project.id,name:t,purpose:L,backend:j,region:m.region,architecture:m.arch,labels:Ts(m.labels),requiredServerLabels:Ts(m.selector),toleratedTaints:[],capacity:{cpu:0,memoryBytes:0,diskBytes:0,gpu:0,...Gl(m.capacity)},maxWorkloads:Number(m.max),costWeight:1,concurrency:Number(m.concurrency),ephemeralWorkspaces:!0,allowProductionSecrets:!1,status:"active"});n(`Created ${G.name} (${G.id}).`)})),N.command("pool:add-server <pool> <server>","Attach an enrolled server to a pool").action(async(t,m)=>is((A)=>{let L=A.store.listPools(A.controlPlane.project.id).find((G)=>G.id===t||G.name===t),j=new Ie(A.controlPlane.store).list(A.controlPlane.project.id).find((G)=>G.id===m||G.name===m);if(!L||!j)throw Error("Pool or server was not found.");A.store.addMember(L.id,j.id),n(`Attached ${j.name} to ${L.name}.`)})),N.command("placement:explain","Explain eligible and rejected placement targets").option("--purpose <purpose>","Workload purpose",{default:"application"}).option("--resources <values>","Requested resources").option("--region <region>","Required region").option("--arch <architecture>","Required architecture").option("--labels <labels>","Required pool labels").option("--json","Print structured JSON").action(async(t)=>is((m)=>{let A=m.service.explain(m.controlPlane.project.id,{purpose:t.purpose,resources:Gl(t.resources),region:t.region,architecture:t.arch,labels:Ts(t.labels)});if(t.json)console.log(JSON.stringify(A,null,2));else c(["Pool","Server","Eligible","Available","Fit / spread / cost","Reasons"],A.map((L)=>[L.poolName,L.serverId??"provider-managed",L.eligible?"yes":"no",JSON.stringify(L.available),`${L.score.fit.toFixed(2)} / ${L.score.spread} / ${L.score.cost}`,L.reasons.join("; ")||"eligible"]))})),N.command("pool:drain <pool>","Move stateless placements and block stateful placements").action(async(t)=>is((m)=>{let A=m.store.listPools(m.controlPlane.project.id).find((j)=>j.id===t||j.name===t);if(!A)throw Error("Pool was not found.");let L=m.service.drainPool(A.id);n(`Draining ${A.name}: moved ${L.moved.length}, blocked ${L.blocked.length} stateful placement(s).`)}))}async function Mp(){let N=await Ne(),t=y(process.cwd(),N),m=new hn(t.store),A=new yn(m);return{controlPlane:t,store:m,service:A}}async function fo(N){let t=await Mp();try{await N(t)}catch(m){r(m instanceof Error?m.message:String(m)),process.exitCode=1}finally{t.controlPlane.store.close()}}var os=(N,t)=>{let m=N.store.list(N.controlPlane.project.id).find((A)=>A.id===t||A.name===t);if(!m)throw Error("Regional topology was not found.");return m},_p=(N)=>N.split(",").map((t,m)=>{let[A,L="aws"]=t.split(":");return{region:String(A),provider:L,role:m===0?"primary":"secondary"}}),zp=(N)=>{let t=new Set(["s3","dynamodb","secrets"]),m=N.split(",").map((L)=>L.trim()),A=m.find((L)=>!t.has(L));if(A)throw Error(`Unsupported replication kind: ${A}`);return m};function Wa(N){N.command("region:list","List regional topology, traffic, and replication health").option("--json","Print structured JSON").action(async(t)=>fo((m)=>{let A=m.store.list(m.controlPlane.project.id).map((L)=>({topology:L,targets:m.store.targets(L.id),channels:m.store.channels(L.id),route:m.store.route(L.id),executions:m.store.executions(L.id)}));if(t.json)console.log(JSON.stringify(A,null,2));else c(["Name","Hostname","Active","Status","Revision","Replication"],A.map((L)=>[L.topology.name,L.topology.hostname,L.topology.activeRegion,L.topology.status,L.topology.revision??"—",`${L.channels.filter((j)=>j.status==="in_sync").length}/${L.channels.length} in sync`]))})),N.command("region:create <name>","Create a persistent multi-region topology").option("--hostname <hostname>","Traffic hostname").option("--regions <regions>","Comma-separated region[:provider], primary first").option("--replicate <kinds>","s3,dynamodb,secrets",{default:"s3,dynamodb,secrets"}).option("--max-lag <seconds>","Maximum failover lag",{default:"30"}).option("--cdn","Enable CloudFront edge state").option("--waf","Enable WAF edge state").action(async(t,m)=>fo((A)=>{if(!m.hostname||!m.regions)throw Error("--hostname and --regions are required.");let L=A.service.create({organizationId:A.controlPlane.organization.id,projectId:A.controlPlane.project.id,name:t,hostname:m.hostname,regions:_p(m.regions),trafficPolicy:"active_passive",dataPolicy:{replicate:zp(String(m.replicate)),maxLagSeconds:Number(m.maxLag),retainOnDestroy:!0},dnsProvider:"route53",cdnEnabled:!!m.cdn,wafEnabled:!!m.waf});n(`Created ${L.name} (${L.id}); run region:rollout with an immutable manifest.`)})),N.command("region:plan <name> <operation>","Preview exact regional execution steps").option("--target <region>","Failover or failback region").action(async(t,m,A)=>fo((L)=>c(["Step"],L.service.plan(os(L,t).id,m,A.target).map((j)=>[j])))),N.command("region:rollout <name> <revision>","Queue secondary-first regional stack rollout").option("--manifest <file>","Regional stack manifest JSON").action(async(t,m,A)=>fo(async(L)=>{let j=A.manifest?await Bun.file(A.manifest).json():{},G=L.service.enqueue({topologyId:os(L,t).id,kind:"rollout",revision:m,manifest:j});n(`Regional rollout queued: ${G.operation.id}`)})),N.command("region:failover <name> <region>","Queue health and RPO-gated failover").action(async(t,m)=>fo((A)=>{let L=A.service.enqueue({topologyId:os(A,t).id,kind:"failover",targetRegion:m});n(`Failover queued: ${L.operation.id}`)})),N.command("region:failback <name> <region>","Queue health and RPO-gated failback").action(async(t,m)=>fo((A)=>{let L=A.service.enqueue({topologyId:os(A,t).id,kind:"failback",targetRegion:m});n(`Failback queued: ${L.operation.id}`)})),N.command("region:destroy <name>","Drain traffic and delete regional stacks while retaining data").option("--confirm <name>","Exact topology name").action(async(t,m)=>fo((A)=>{let L=A.service.enqueue({topologyId:os(A,t).id,kind:"destroy",confirmation:m.confirm});n(`Regional teardown queued: ${L.operation.id}; replicated data remains retained.`)}))}var ss="0.16.19";async function Vp(){let N=await Ne(),t=y(process.cwd(),N),m=new Sn(t.store),A=new bn(m),L=["releases","artifacts","operations","logs","previews","snapshots","orphaned_resources"].map((j)=>new vn(j,t.store,t.project.id,t.organization.id));return{controlPlane:t,store:m,service:A,cleanup:L}}async function Bi(N){let t=await Vp();try{await N(t)}catch(m){r(m instanceof Error?m.message:String(m)),process.exitCode=1}finally{t.controlPlane.store.close()}}function qa(N){N.command("maintenance:list","List updates, campaigns, cleanup plans, and DR drills").option("--json","Print structured JSON").action(async(t)=>Bi((m)=>{let A={manifests:m.store.manifests(m.controlPlane.organization.id),windows:m.store.windows(m.controlPlane.project.id),campaigns:m.store.campaigns(m.controlPlane.project.id),cleanups:m.store.cleanups(m.controlPlane.project.id),drills:m.store.drills(m.controlPlane.project.id)},L=[...A.manifests.map((j)=>["update",j.version,j.compatibility.compatible?"compatible":"blocked",j.compatibility.reasons.join("; ")||j.channel]),...A.campaigns.map((j)=>["upgrade",j.id,j.status,j.currentStage??j.fromVersion]),...A.cleanups.map((j)=>["cleanup",j.kind,j.status,`${j.candidates.length} items / ${j.estimatedBytes} bytes`]),...A.drills.map((j)=>["DR drill",j.scenario,j.status,j.isolatedTarget])];if(t.json)console.log(JSON.stringify(A,null,2));else c(["Area","Name / version","Status","Detail"],L)})),N.command("maintenance:key:add <name> <pem>","Trust an Ed25519 update signing key").action(async(t,m)=>Bi(async(A)=>{let L=A.store.addTrustedKey({organizationId:A.controlPlane.organization.id,name:t,publicKeyPem:await Bun.file(m).text()});n(`Trusted ${L.name}: ${L.fingerprint}`)})),N.command("maintenance:manifest <document> <signature> <key>","Verify and import a signed update manifest").action(async(t,m,A)=>Bi(async(L)=>{let j=await Bun.file(t).json(),G=(await Bun.file(m).text()).trim(),Z=L.store.importManifest({organizationId:L.controlPlane.organization.id,keyId:A,document:j,signature:G,current:{schemaVersion:L.controlPlane.store.health().schemaVersion,currentVersion:ss,platform:process.platform,architecture:process.arch}});n(`Verified ${Z.version}; ${Z.compatibility.compatible?"compatible":"blocked: "+Z.compatibility.reasons.join("; ")}`)})),N.command("maintenance:window <name> <schedule>","Create an approved maintenance window").option("--timezone <timezone>","IANA timezone",{default:"UTC"}).option("--minutes <minutes>","Duration",{default:"60"}).action(async(t,m,A)=>Bi((L)=>{let j=L.store.createWindow({projectId:L.controlPlane.project.id,name:t,schedule:m,timezone:A.timezone,durationMinutes:Number(A.minutes),allowedOperations:["platform.upgrade"],requireApproval:!0});n(`Created ${j.name} (${j.id}).`)})),N.command("platform:upgrade <manifest> <backup>","Plan and queue a signed staged platform update").option("--strategy <strategy>","canary or rolling",{default:"canary"}).option("--batch <count>","Rolling batch size",{default:"1"}).action(async(t,m,A)=>Bi((L)=>{let j=new Ie(L.controlPlane.store).list(L.controlPlane.project.id).filter((ee)=>ee.status==="ready").map((ee)=>({serverId:ee.id,target:ee.name,previousVersion:ee.bootstrapVersion??ss}));if(!j.length)j.push({target:"control-plane",previousVersion:ss});let G=L.store.createCampaign({projectId:L.controlPlane.project.id,manifestId:t,fromVersion:ss,strategy:A.strategy==="rolling"?"rolling":"canary",batchSize:Number(A.batch),healthGate:{kind:"platform"},backupId:m,targets:j}),Z=L.service.enqueueCampaign(G.id);n(`Staged upgrade queued: ${Z.operation.id}`)})),N.command("cleanup:preview <kind>","Discover a bounded cleanup candidate set without deleting").option("--older-than <days>","Minimum age",{default:"30"}).action(async(t,m)=>Bi(async(A)=>{let L=await A.service.previewCleanup({projectId:A.controlPlane.project.id,kind:t,criteria:{olderThanDays:Number(m.olderThan)}},A.cleanup);c(["ID","Candidate","Bytes"],L.candidates.map((j)=>[j.id,j.label,String(j.bytes)])),e(`Apply with: cloud cleanup:apply ${L.id} --confirm "DELETE ${L.candidates.length} ${L.kind}"`)})),N.command("cleanup:apply <plan>","Apply an unchanged cleanup preview").option("--confirm <text>","Exact preview confirmation").action(async(t,m)=>Bi((A)=>{let L=A.service.enqueueCleanup(t,String(m.confirm??""));n(`Cleanup queued: ${L.operation.id}`)})),N.command("dr:plan <scenario> <target>","Plan an isolated disaster-recovery drill").option("--rpo <minutes>","RPO objective",{default:"60"}).option("--rto <minutes>","RTO objective",{default:"30"}).option("--recovery-point <id>","Recovery point").option("--topology <id>","Regional topology").action(async(t,m,A)=>Bi((L)=>{let j=L.store.createDrill({projectId:L.controlPlane.project.id,scenario:t,isolatedTarget:m,expectedRpoMinutes:Number(A.rpo),expectedRtoMinutes:Number(A.rto),recoveryPointId:A.recoveryPoint,topologyId:A.topology});n(`Planned isolated drill ${j.id}.`)})),N.command("dr:run <drill>","Queue an isolated disaster-recovery drill").action(async(t)=>Bi((m)=>{let A=m.service.enqueueDrill(t);n(`DR drill queued: ${A.operation.id}`)}))}async function Ga(){try{return(await Ne()).project.region||process.env.AWS_REGION||"us-east-1"}catch{return process.env.AWS_REGION||"us-east-1"}}function Ha(N){N.command("function:list","List all Lambda functions").option("--region <region>","AWS region").action(async(t)=>{i("Lambda Functions");let m=t?.region||await Ga(),A=new R(m);try{let{Functions:L=[]}=await A.listFunctions({MaxItems:50});if(!L.length){e("No functions found");return}c(["Name","Runtime","Memory","Timeout","Last Modified"],L.map((j)=>[j.FunctionName??"-",j.Runtime??"-",j.MemorySize?`${j.MemorySize} MB`:"-",j.Timeout?`${j.Timeout}s`:"-",j.LastModified??"-"]))}catch(L){r(`Failed to list functions: ${L.message}`),process.exitCode=1}}),N.command("function:invoke <name>","Invoke a Lambda function").option("--payload <json>","Event payload as JSON",{default:"{}"}).option("--async","Fire-and-forget (Event invocation)").option("--region <region>","AWS region").action(async(t,m)=>{i(`Invoking ${t}`);let A=m?.region||await Ga(),L=new R(A),j=new o("Invoking function...");j.start();try{let G=await L.invoke({FunctionName:t,InvocationType:m?.async?"Event":"RequestResponse",Payload:m?.payload||"{}",LogType:m?.async?"None":"Tail"});if(G.FunctionError){if(j.fail(`Function returned an error (${G.FunctionError})`),G.Payload)e(G.Payload);process.exitCode=1;return}if(j.succeed(`Invoked (status ${G.StatusCode})`),G.Payload)e(`
|
|
318
|
+
`)}async function kp(){let N=await Ne(),t=y(process.cwd(),N),m=new Ie(t.store),A=new mn(m,[new tt("aws"),new tt("hetzner"),new tt("ssh")]);return{controlPlane:t,store:m,service:A}}async function xi(N){let t=await kp();try{return await N(t)}finally{t.controlPlane.store.close()}}var io=(N,t)=>{let m=N.store.list(N.controlPlane.project.id).find((A)=>A.id===t||A.name===t);if(!m)throw Error(`Server ${t} was not found.`);return m},hr=(N)=>{r(N instanceof Error?N.message:String(N)),process.exitCode=1};function Ba(N,t){let m=Number.parseInt(N??"",10);return Number.isFinite(m)&&m>=0?m:t}function Rp(N="3h"){let t=N.match(/^(\d+)(m|h)$/);if(!t)throw Error("--range must use minutes or hours, for example 30m or 3h.");let m=Number(t[1])*(t[2]==="h"?3600000:60000);if(m<300000||m>86400000)throw Error("--range must be between 5 minutes and 24 hours.");return m}function rs(N,t="%"){return N==null?"unavailable":`${N.toFixed(1)}${t}`}async function Ip(N,t){let m=await Ne();if(m.cloud?.provider!=="hetzner")throw Error("server:monitoring currently requires the Hetzner provider.");let A=t.env??process.env.CLOUD_ENV??"production",L=E(m,A),j=await de(L);if(!j?.serverId)throw Error(`No pinned Hetzner server was found for ${L}.`);if(![j.serverName,String(j.serverId),j.stackName].includes(N))throw Error(`Refusing to read ${N}: project state is pinned to ${j.serverName}.`);let G=rr(m),Z=new ze({apiToken:nr(G.apiToken,m)}),ee=await Z.getServer(j.serverId),ne=j.publicIp??ee.public_net.ipv4?.ip;if(!ne)throw Error(`Server ${ee.name} has no public IPv4 address.`);let oe=new Date,be=new Date(oe.getTime()-Rp(t.range)),we=Math.min(3600,Math.max(60,Ba(t.step,60))),Ce=await Bl({client:Z,serverId:ee.id,cores:Math.max(1,Number(ee.server_type.cores)||1),from:be,to:oe,step:we,remote:{host:ne,user:j.sshUser??G.sshUser,identityFile:G.sshPrivateKeyPath,connectTimeoutSec:15}});if(t.json){console.log(JSON.stringify({schemaVersion:1,server:ee.name,result:Ce},null,2));return}c(["Server","Window","CPU average / peak","RAM average / peak","Minimum available","Swap peak"],[[ee.name,`${Ce.from} to ${Ce.to}`,`${rs(Ce.summary.cpuAveragePercent)} / ${rs(Ce.summary.cpuPeakPercent)}`,`${rs(Ce.summary.memoryAveragePercent)} / ${rs(Ce.summary.memoryPeakPercent)}`,Ce.summary.memoryMinimumAvailableBytes==null?"unavailable":`${(Ce.summary.memoryMinimumAvailableBytes/1073741824).toFixed(2)} GB`,rs(Ce.summary.swapPeakPercent)]])}function zl(N){let t=N.targetType.prices?.find((m)=>m.location===N.location);return{serverId:N.serverId,serverName:N.serverName,location:N.location,from:N.currentType.name,to:N.targetType.name,capacityAvailable:N.capacityAvailable,alreadyComplete:N.alreadyComplete,upgradeDisk:N.upgradeDisk,target:{cores:N.targetType.cores,memoryGb:N.targetType.memory,diskGb:N.targetType.disk,architecture:N.targetType.architecture,cpuType:N.targetType.cpu_type},price:t?{hourlyNet:t.price_hourly.net,hourlyGross:t.price_hourly.gross,monthlyNet:t.price_monthly.net,monthlyGross:t.price_monthly.gross}:void 0}}function Pp(N){let t=zl(N);c(["Server","Location","Resize","Capacity","CPU / RAM / disk","Monthly"],[[`${t.serverName} (${t.serverId})`,t.location,`${t.from} -> ${t.to}`,t.capacityAvailable?"available":"waiting",`${t.target.cores??0} / ${t.target.memoryGb??0} GB / ${t.target.diskGb??0} GB`,t.price?.monthlyGross??t.price?.monthlyNet??"not reported"]])}async function xp(N,t,m){let A=await Ne();if(A.cloud?.provider!=="hetzner")throw Error("server:resize currently requires the Hetzner provider.");let L=m.env??process.env.CLOUD_ENV??"production",j=E(A,L),G=await de(j),Z=rr(A),ee=new ze({apiToken:nr(Z.apiToken,A)}),oe=G&&(N===G.serverName||N===String(G.serverId)||N===G.stackName)?await ee.getServer(G.serverId):(await ee.listServers()).find((Ke)=>Ke.name===N||String(Ke.id)===N);if(!oe)throw Error(`Hetzner server ${N} was not found.`);if(G?.serverId&&G.serverId!==oe.id)throw Error(`Refusing to resize ${N}: project state is pinned to server ${G.serverId}.`);let be=at(t),we=m.upgradeDisk!==!1,Ce=await Hn(ee,oe.id,be,we);if(m.json)console.log(JSON.stringify({schemaVersion:1,plan:zl(Ce)},null,2));else Pp(Ce);if(!m.apply){if(!m.json)e(`Preview only. Re-run with --apply --confirm ${oe.name} to execute.`);return}if(m.confirm!==oe.name)throw Error(`Resize requires --confirm ${oe.name}.`);let De=G?.publicIp??oe.public_net.ipv4?.ip;if(!De)throw Error(`Server ${oe.name} has no public IPv4 address for verification.`);let Se={host:De,user:G?.sshUser??Z.sshUser,identityFile:Z.sshPrivateKeyPath,connectTimeoutSec:15,sshTimeoutMs:600000,routeTimeoutMs:20000},xe=await Ko(j),Me=new Date().toISOString(),Ae={schemaVersion:1,operationId:xe?.targetType===be&&xe.serverId===oe.id?xe.operationId:crypto.randomUUID(),stackName:j,serverId:oe.id,serverName:oe.name,sourceType:Ce.currentType.name,targetType:be,upgradeDisk:we,phase:"planning",status:"running",attempts:xe?.targetType===be?xe.attempts:0,startedAt:xe?.targetType===be?xe.startedAt:Me,updatedAt:Me,manifest:xe?.targetType===be?xe.manifest:void 0};await lt(Ae);let Ee=Ba(m.pollSeconds,900)*1000,Te=Ba(m.maxWaitMinutes,0)*60000,Qe=Date.now();for(;;){let Ke=await Hn(ee,oe.id,be,we);if(!Ke.capacityAvailable&&!Ke.alreadyComplete){if(Ae={...Ae,phase:"waiting-capacity",status:"waiting-capacity",updatedAt:new Date().toISOString()},await lt(Ae),!m.wait){if(!m.json)e(`${be} has no capacity in ${Ke.location}. The server remains running and unchanged. Use --wait to poll safely.`);return}if(Te>0&&Date.now()-Qe>=Te)throw Error(`Timed out waiting for ${be} capacity in ${Ke.location}.`);if(!m.json)e(`Waiting ${Math.round(Ee/1000)} seconds for ${be} capacity...`);await Bun.sleep(Ee);continue}let Ye=await Jo(j);try{let et=await(async()=>{try{return Ae={...Ae,status:"running",attempts:Ae.attempts+1,updatedAt:new Date().toISOString()},await lt(Ae),await Vo({client:ee,serverId:oe.id,targetType:be,upgradeDisk:we,resumeFromOff:Ae.phase==="shutting-down"||Ae.phase==="resizing"||Ae.phase==="powering-on"||Ae.phase==="verifying",manifest:Ae.manifest,hooks:{preflight:async()=>{let Pt=await zo(Se);return Ae={...Ae,manifest:Pt,updatedAt:new Date().toISOString()},await lt(Ae),Pt},afterBoot:async(Pt,Bt,vt,Ot)=>Ho(Se,Bt,vt,Ot),onPhase:async(Pt,Bt)=>{if(Ae={...Ae,phase:Pt,status:Pt==="waiting-capacity"?"waiting-capacity":Pt==="complete"?"completed":"running",updatedAt:new Date().toISOString()},await lt(Ae),!m.json)e(`${Pt}${Bt?` ${JSON.stringify(Bt)}`:""}`)}}})}finally{await Ye()}})();if(Ae={...Ae,status:et.status==="completed"||et.status==="already-complete"?"completed":et.status==="recovered"?"recovered":"waiting-capacity",lastError:et.status==="recovered"?et.error:void 0,updatedAt:new Date().toISOString()},await lt(Ae),m.json)console.log(JSON.stringify({schemaVersion:1,result:et},null,2));else if(et.status==="completed"||et.status==="already-complete")n(`${oe.name} is on ${be} and passed full post-boot verification.`);else if(et.status==="recovered"&&et.retryable&&m.wait){e(`Capacity race recovered safely. Waiting ${Math.round(Ee/1000)} seconds before retry.`),await Bun.sleep(Ee);continue}else if(et.status==="recovered")throw Error(`Resize did not complete and the original server was recovered: ${et.error}`);return}catch(et){throw Ae={...Ae,status:"failed",lastError:et instanceof Error?et.message:String(et),updatedAt:new Date().toISOString()},await lt(Ae),et}}}async function Dp(N,t){let m=await Ne();if(m.cloud?.provider!=="hetzner")throw Error("server:optimize currently requires the Hetzner provider.");let A=t.env??process.env.CLOUD_ENV??"production",L=E(m,A),j=await de(L);if(!j?.serverId)throw Error(`No pinned Hetzner server was found for ${L}.`);if(![j.serverName,String(j.serverId),j.stackName].includes(N))throw Error(`Refusing to optimize ${N}: project state is pinned to ${j.serverName}.`);let G=rr(m),Z=new ze({apiToken:nr(G.apiToken,m)}),ee=await Z.getServer(j.serverId),ne=j.publicIp??ee.public_net.ipv4?.ip;if(!ne)throw Error(`Server ${ee.name} has no public IPv4 address.`);let oe=Li(m);if(t.json)console.log(JSON.stringify({schemaVersion:1,server:ee.name,plan:oe},null,2));else c(["Server","Firewall ports","Monitoring","Auto updates","Swap","SSH passwords"],[[ee.name,oe.firewallPorts.join(","),oe.monitoring?"on":"off",oe.autoUpdates?"on":"off",`${oe.swapGb} GB`,"disabled"]]);if(!t.apply){if(!t.json)e(`Preview only. Re-run with --apply --confirm ${ee.name} to execute.`);return}if(t.confirm!==ee.name)throw Error(`Optimization requires --confirm ${ee.name}.`);let be={host:ne,user:j.sshUser??G.sshUser,identityFile:G.sshPrivateKeyPath,connectTimeoutSec:15},we=await jr(be),Ce=we.routeProbes.filter((vt)=>!vt.ok),De=m.infrastructure?.compute,Se=X(De)?new Set(["nginx.service","bun-gateway.service","ts-cloud-nginx.service"]):new Set,xe=we.failedUnits.filter((vt)=>!Se.has(vt));if(xe.length>0)throw Error(`Preflight found failed services: ${xe.join(", ")}`);if(Ce.length>0)throw Error(`Preflight found unhealthy routes: ${Ce.map((vt)=>vt.domain).join(", ")}`);let Me=X(De)?[]:Object.values(m.sites??{}).flatMap((vt)=>typeof vt?.port==="number"&&![80,443].includes(vt.port)?[vt.port]:[]),Ae=Br({allowSsh:De?.allowSsh!==!1,sitePorts:Me,allowedPorts:De?.firewall?.allowedPorts}),Ee=(j.firewallId?(await Z.listFirewalls()).find((vt)=>vt.id===j.firewallId):void 0)??(await Z.listFirewalls()).find((vt)=>vt.name===`${m.project.slug}-${A}-app-fw`);if(!Ee)throw Error(`Managed firewall for ${ee.name} was not found.`);let Te=await Z.setFirewallRules(Ee.id,Ae);await Promise.all(Te.map((vt)=>Z.waitForAction(vt.id))),await qo(m,be);let[Qe,Ke]=await Promise.all([jr(be),Wo(be)]),Ye=Go(oe,Ke),et=Ia(we,Qe),Pt=Qe.routeProbes.filter((vt)=>!vt.ok);if(et.stoppedServices.length>0)Ye.push(`services stopped: ${et.stoppedServices.join(", ")}`);if(et.changedRouteFragments.length>0)Ye.push(`route fragments changed: ${et.changedRouteFragments.join(", ")}`);if(et.missingRouteIds.length>0)Ye.push(`routes disappeared: ${et.missingRouteIds.join(", ")}`);if(et.changedReleaseLinks.length>0)Ye.push(`release links changed: ${et.changedReleaseLinks.join(", ")}`);if(et.missingData.length>0)Ye.push(`databases or volumes disappeared: ${et.missingData.join(", ")}`);if(Pt.length>0)Ye.push(`unhealthy routes: ${Pt.map((vt)=>vt.domain).join(", ")}`);if(Ye.length>0)throw Error(`Host optimization verification failed: ${Ye.join("; ")}`);let Bt={serverId:ee.id,serverName:ee.name,services:Qe.runningServices.length,routes:Qe.routeIds.length,healthyDomains:Qe.routeProbes.length,releaseLinks:Qe.releaseLinks.length,databasesAndVolumes:Qe.dataCatalog.length,report:Ke};if(t.json)console.log(JSON.stringify({schemaVersion:1,result:Bt},null,2));else n(`${ee.name} passed full host, rpx route, service, release, and data verification.`)}async function Ep(N,t,m){let A=await Ne(),L=m.env??"production",j=E(A,L);await xi(async(G)=>{let Z=io(G,N),ee=G.store.list(G.controlPlane.project.id,!0),ne=Z.provider==="hetzner"&&Z.providerId?(()=>{try{let Ee=rr(A);return new ze({apiToken:nr(Ee.apiToken,A)})}catch{return null}})():null,oe=Z.providerId?Number(Z.providerId):Number.NaN,be=await de(j),we=be!=null&&be.serverId===oe,Ce=new Rr,De=Z.trustState==="pinned",Se={takenNames:async()=>{let Ee=ee.map((Te)=>Te.name);if(ne)Ee.push(...(await ne.listServers()).map((Te)=>Te.name));return Ee},inventoryName:()=>G.store.get(Z.id)?.name??Z.name,renameInventory:(Ee)=>{G.store.update(Z.id,{name:Ee})},...ne&&Number.isFinite(oe)?{providerName:async()=>(await ne.getServer(oe)).name,renameProvider:async(Ee)=>{await ne.renameServer(oe,Ee)}}:{},...we?{stateName:async()=>(await de(j))?.serverName,writeStateName:async(Ee)=>{let Te=await de(j);if(Te)await ct(j,{...Te,serverName:Ee})}}:{},...De?{remoteHostname:async()=>{let Ee=await Ce.exec(Z,"hostname");return Ee.code===0?Ee.stdout.trim():void 0},setRemoteHostname:async(Ee)=>{let Te=await Ce.exec(Z,_l(Ee));if(Te.code!==0)throw Error(Te.stderr.trim()||`hostname exited ${Te.code}`)}}:{}},xe=await Ml(Z.name,t,Se),Me=await Is(xe);if(!m.apply){let Ee=[ne?"":"provider record (no provider id or no API token)",we?"":"local state pin (none points at this server)",De?"":"box hostname (host key is not pinned — run server:validate first)"].filter(Boolean);if(m.json){console.log(JSON.stringify({schemaVersion:1,operation:xe.operation,target:xe.target,rename:{from:Z.name,to:t},notCovered:Ee,steps:Me.map((Te)=>({id:Te.step.id,title:Te.step.title,state:Te.state,change:Te.step.change,reason:Te.reason}))},null,2));return}for(let Te of Ps(xe,Me))console.log(Te);for(let Te of Ee)console.log(` not covered: ${Te}`);console.log(" Re-run with --apply to perform it.");return}let Ae=await xs(xe,Me,{log:(Ee)=>e(Ee),audit:(Ee)=>G.controlPlane.store.appendEvent({projectId:G.controlPlane.project.id,resourceId:Z.resourceId,type:`${Ee.operation}.${Ee.step}.${Ee.state}`,level:Ee.state==="failed"?"error":"info",payload:{target:Ee.target,renameTo:t,...Ee.error?{error:Ee.error}:{}}})});if(m.json)console.log(JSON.stringify({schemaVersion:1,outcome:Ae},null,2));if(!Ae.success){let Ee=Ae.steps.find((Te)=>Te.state==="failed");throw Error(`${xe.operation} stopped at '${Ee?.title}': ${Ee?.error}. Earlier steps stayed applied; re-run the same command to continue from here.`)}if(!m.json)n(`Renamed ${Z.name} to ${t}.`)})}function Ma(N){N.command("capabilities [server]","Show provider and target operation support").option("--json","Print structured JSON").action(async(t,m)=>{try{await xi(async(A)=>{let L=t?[io(A,t)]:A.store.list(A.controlPlane.project.id),j=L.flatMap((G)=>Object.entries(G.capabilities).map(([Z,ee])=>({server:G.name,provider:G.provider,action:Z,...ee})));if(m.json)console.log(JSON.stringify({schemaVersion:1,targets:j},null,2));else c(["Server","Provider","Action","Support","Explanation"],j.map((G)=>[G.server,G.provider,G.action,G.supported?"supported":"unsupported",G.reason??"—"]))})}catch(A){hr(A)}}),N.command("server:resize <name> <type>","Safely resize Hetzner compute with full host verification").option("--env <environment>","Deployment environment",{default:"production"}).option("--apply","Execute the reviewed resize plan").option("--confirm <name>","Exact server name required for mutation").option("--upgrade-disk","Permanently expand the root disk to the target size",{default:!0}).option("--wait","Poll capacity without taking the server offline until placement is available").option("--poll-seconds <seconds>","Capacity retry interval",{default:"900"}).option("--max-wait-minutes <minutes>","Stop waiting after this many minutes; 0 waits indefinitely",{default:"0"}).option("--json","Print structured JSON").action(async(t,m,A)=>{try{await xp(t,m,A)}catch(L){hr(L)}}),N.command("server:optimize <name>","Reconcile and verify a production Hetzner host").option("--env <environment>","Deployment environment",{default:"production"}).option("--apply","Apply the reviewed host optimization plan").option("--confirm <name>","Exact server name required for mutation").option("--json","Print structured JSON").action(async(t,m)=>{try{await Dp(t,m)}catch(A){hr(A)}}),N.command("server:monitoring <name>","Read historical Hetzner CPU, RAM, swap, disk, and network metrics").option("--env <environment>","Deployment environment",{default:"production"}).option("--range <duration>","Historical window from 5m to 24h",{default:"3h"}).option("--step <seconds>","Hetzner provider sample interval",{default:"60"}).option("--json","Print structured JSON").action(async(t,m)=>{try{await Ip(t,m)}catch(A){hr(A)}}),N.command("server:list","List fleet servers").option("--json","Print structured JSON").action(async(t)=>{try{await xi(async(m)=>{let A=m.store.list(m.controlPlane.project.id);if(t.json)console.log(JSON.stringify(A,null,2));else c(["Name","Provider ID","Provider / region","Status / trust","Roles","CPU / memory","Heartbeat"],A.map((L)=>[L.name,L.providerId??"—",`${L.provider} / ${L.region??"external"}`,`${L.status} / ${L.trustState}`,L.roles.join(","),`${L.capacity.cpu??0} / ${L.capacity.memoryBytes??0}`,L.heartbeatAt??"never"]))})}catch(m){hr(m)}}),N.command("server:create <name>","Enroll a provisioned or existing server").option("--provider <provider>","aws, hetzner, or ssh",{default:"ssh"}).option("--provider-id <id>","Stable provider identity").option("--endpoint <host>","SSH hostname or IP").option("--user <user>","Non-root SSH user",{default:"deploy"}).option("--credential-ref <ref>","Secret reference",{default:"secret://fleet/agent"}).option("--region <region>","Provider region").option("--roles <roles>","Comma-separated roles",{default:"application"}).option("--labels <labels>","Comma-separated key=value labels").action(async(t,m)=>{try{await xi(async(A)=>{let L=m.provider;if(!["aws","hetzner","ssh"].includes(L)||!m.endpoint)throw Error("A supported --provider and --endpoint are required; provisioning and enrollment are separate operations.");let j=A.service.enroll({organizationId:A.controlPlane.organization.id,projectId:A.controlPlane.project.id,name:t,provider:L,providerId:m.providerId,endpoint:m.endpoint,sshUser:m.user??"deploy",credentialRef:m.credentialRef??"secret://fleet/agent",region:m.region,roles:String(m.roles??"application").split(","),labels:Object.fromEntries(String(m.labels??"").split(",").map((G)=>G.split("=")).filter((G)=>G[0]&&G[1]))});n(`Enrolled ${j.name} as ${j.id}; no remote mutation was performed.`)})}catch(A){hr(A)}}),N.command("server:validate <name>","Pin trust and validate a server").option("--accept-host-key <fingerprint>","Accept reviewed rotation").option("--json","Print JSON").action(async(t,m)=>{try{await xi(async(A)=>{let L=io(A,t);if(L=await A.service.test(L.id),L.trustState==="rotation_pending"){if(!m.acceptHostKey)throw Error(`Host key changed to ${L.pendingHostKey}; review it first.`);L=A.service.reviewHostKey(L.id,m.acceptHostKey)}let j=await A.service.validate(L.id);if(m.json)console.log(JSON.stringify(j.validation,null,2));else c(["Severity","Code","Finding","Remediation"],(j.validation?.findings??[]).map((G)=>[G.severity,G.code,G.message,G.remediation??"—"]));if(!j.validation?.valid)process.exitCode=1})}catch(A){hr(A)}}),N.command("server:bootstrap <name>","Preview or queue bootstrap").option("--apply","Apply reviewed plan").action(async(t,m)=>{try{await xi(async(A)=>{let L=A.service.bootstrap(io(A,t).id,!!m.apply);if(L.preview)c(["Step"],L.steps.map((j)=>[j]));else n(`Bootstrap queued: ${L.operation?.id}`)})}catch(A){hr(A)}}),N.command("server:rename <name> <new-name>","Rename a server in place, without recreating it").option("--env <environment>","Deployment environment",{default:"production"}).option("--apply","Perform the reviewed rename plan").option("--json","Print structured JSON").action(async(t,m,A)=>{try{await Ep(t,m,A)}catch(L){hr(L)}}),N.command("server:drain <name>","Drain without terminating").option("--complete","Mark movement complete").action(async(t,m)=>{try{await xi(async(A)=>n(A.service.drain(io(A,t).id,!!m.complete).status))}catch(A){hr(A)}}),N.command("server:uncordon <name>","Return a server to scheduling").action(async(t)=>{try{await xi(async(m)=>{m.service.uncordon(io(m,t).id),n(`Uncordoned ${t}.`)})}catch(m){hr(m)}}),N.command("server:archive <name>","Archive inventory without termination").option("--confirm <name>","Exact name").action(async(t,m)=>{try{await xi(async(A)=>{A.service.archive(io(A,t).id,m.confirm??""),n(`Archived ${t}; provider infrastructure was not terminated.`)})}catch(A){hr(A)}}),N.command("server:ssh <name>","Open strict SSH using the enrolled endpoint").action(async(t)=>{try{await xi(async(m)=>{let A=io(m,t);if(A.trustState!=="pinned")throw Error("Validate and pin the server host key first.");let L=Bun.spawn(["ssh","-p",String(A.sshPort),"-o","StrictHostKeyChecking=yes",`${A.sshUser}@${A.endpoint}`],{stdin:"inherit",stdout:"inherit",stderr:"inherit"}),j=await L.exited;if(j)process.exitCode=j})}catch(m){hr(m)}});for(let[t,m]of[["server:logs <name>","Use the runtime log service"],["server:deploy <name>","Use immutable release deployment"],["server:reboot <name>","Reboot provider compute"],["server:destroy <name>","Terminate provider compute"],["server:recipe <name> <recipe>","Apply a server recipe"],["server:firewall:add <name> <rule>","Add firewall rule"],["server:firewall:list <name>","List firewall rules"],["server:firewall:remove <name> <rule>","Remove firewall rule"],["server:ssl:install <domain>","Install TLS"],["server:ssl:renew <domain>","Renew TLS"],["server:snapshot <name>","Create provider snapshot"],["server:snapshot:restore <name> <snapshot-id>","Restore provider snapshot"],["server:update <name>","Update OS packages"],["server:secure <name>","Apply OS hardening"]])N.command(t,m).action(async(...A)=>Vr(t.split(" ")[0],{target:String(A[0]??""),nextAction:"Use the dashboard capability view or the corresponding runtime, release, firewall, backup, or maintenance service."}))}import{existsSync as Ul,mkdirSync as Tp,readFileSync as Np,writeFileSync as Op}from"node:fs";import{join as Vl,resolve as Lp}from"node:path";var za=(N)=>{r(N instanceof Error?N.message:String(N)),process.exitCode=1};async function jp(){try{return await Ne()}catch{return}}function Fp(N){if(N===void 0)return;let t=Number(N);if(!Number.isInteger(t)||t<1||t>65535)throw Error(`--port must be a port number, not '${N}'.`);return t}function Wl(N,t,m){let A=N?.ssh?.hosts?.find((L)=>L.host===t);return new cr({hosts:t?[A??{host:t}]:N?.ssh?.hosts,user:m.user,port:Fp(m.port),privateKeyPath:m.key,hostKey:N?.ssh?.hostKey,sudo:N?.ssh?.sudo,profile:m.profile??N?.ssh?.profile,publicIp:N?.ssh?.publicIp,lan:N?.ssh?.lan})}var ql=1073741824;function Ua(N){N.command("ssh:preflight [host]","Check a bring-your-own Linux host before adopting it").option("--user <user>","SSH user (default: ssh.hosts[].user, then root)").option("--port <port>","SSH port (default: ssh.hosts[].port, then 22)").option("--key <path>","SSH private key (default: ssh.hosts[].privateKeyPath, then ~/.ssh/id_ed25519)").option("--profile <profile>","raspberry-pi or generic (default: ssh.profile, then generic)").option("--json","Print the facts and findings as JSON").action(async(t,m)=>{try{let A=await jp(),L=Wl(A,t,m),j=t??L.targetHost(),G=await L.ensureHostKey(j),{facts:Z,findings:ee}=await L.preflight(j);if(m.json)console.log(JSON.stringify({schemaVersion:1,host:j,hostKeyFingerprint:G.fingerprint,facts:Z,findings:ee},null,2));else{if(i(`Preflight ${j}`),G.pinnedNow)e(`Pinned host key ${G.fingerprint}`);if(e(`${Z.os} on ${Z.arch}, ${Z.cpuCores} cores, ${(Z.memoryBytes/ql).toFixed(1)} GiB memory, ${(Z.diskFreeBytes/ql).toFixed(1)} GiB free`),Z.piModel)e(Z.piModel);if(Z.lanIp)e(`LAN address ${Z.lanIp}`);if(console.log(Fr(ee)),ar(ee))r("The host is not ready; fix the errors above and run the preflight again.");else n("The host is ready to adopt.")}if(ar(ee))process.exitCode=1}catch(A){za(A)}}),N.command("ssh:bootstrap","Adopt the configured host: pin its key, run the preflight, then bootstrap it").option("--env <environment>","Deployment environment",{default:"production"}).option("--dry-run","Print the bootstrap script instead of running it").action(async(t)=>{try{let m=await Ne(),A=t.env??"production";if(t.dryRun){let G=sr(m),[Z]=G.hosts;console.log(or({config:m,environment:A,profile:G.profile,sudoUser:Z.user!=="root"?Z.user:void 0,lan:G.lan}));return}let L=Wl(m,void 0,{});i(`Adopt ${L.targetHost()}`);let j=await L.provisionComputeInfrastructure({config:m,environment:A});n(`${j.appPublicIp} is bootstrapped; deploy with: cloud deploy --env ${A}`)}catch(m){za(m)}}),N.command("ssh:first-boot","Write cloud-init first-boot files for a freshly flashed Raspberry Pi OS or Ubuntu image").option("--os <os>","raspberry-pi-os or ubuntu",{default:"raspberry-pi-os"}).option("--out <dir>","Directory to write user-data, network-config and meta-data into (never a mounted card; copy them yourself)").option("--hostname <name>","Hostname of the new host").option("--user <user>","Deploy user created on first boot (default: ssh.hosts[].user, then pi)").option("--key <path>","Public key authorized for the user",{default:"~/.ssh/id_ed25519.pub"}).option("--wifi-ssid <ssid>","Join this Wi-Fi network on first boot").option("--wifi-passphrase-env <name>","Environment variable holding the Wi-Fi passphrase",{default:"WIFI_PASSWORD"}).option("--wifi-country <cc>","Wi-Fi regulatory domain, e.g. DE").option("--timezone <tz>","IANA timezone, e.g. Europe/Berlin").option("--locale <locale>","System locale, e.g. en_US.UTF-8").option("--env <environment>","Deployment environment the embedded bootstrap is built for",{default:"production"}).option("--force","Overwrite files already in --out").action(async(t)=>{try{if(!t.out)throw Error("--out <dir> is required.");if(!t.hostname)throw Error("--hostname <name> is required.");let m=t.os??"raspberry-pi-os";if(!(m in $i))throw Error(`--os must be raspberry-pi-os or ubuntu, not '${m}'.`);let A=await Ne(),L=t.env??"production",j=sr(A,{hosts:A.ssh?.hosts?.length?void 0:[{host:t.hostname}],profile:m==="raspberry-pi-os"?"raspberry-pi":void 0}),G=t.user??(A.ssh?.hosts?.[0]?.user??"pi"),Z=Ur(t.key??"~/.ssh/id_ed25519.pub");if(!Ul(Z))throw Error(`Public key not found at ${Z}; pass --key <path to a .pub file>.`);let ee=Np(Z,"utf8").trim(),ne;if(t.wifiSsid){let De=t.wifiPassphraseEnv??"WIFI_PASSWORD",Se=process.env[De];if(!Se)throw Error(`--wifi-ssid needs the passphrase in $${De} (set it in the environment, not on the command line).`);if(!t.wifiCountry)throw Error("--wifi-country <cc> is required with --wifi-ssid.");ne={ssid:t.wifiSsid,passphrase:Se,country:t.wifiCountry}}let oe=or({config:A,environment:L,profile:j.profile,sudoUser:G!=="root"?G:void 0,lan:j.lan}),be=Oi({hostname:t.hostname,user:G,publicKey:ee,timezone:t.timezone,locale:t.locale,wifi:ne},oe,{os:m}),we=Lp(t.out);Tp(we,{recursive:!0});let Ce=Object.keys(be.files).filter((De)=>Ul(Vl(we,De)));if(Ce.length>0&&!t.force)throw Error(`${Ce.join(", ")} already exist in ${we}; pass --force to overwrite.`);for(let[De,Se]of Object.entries(be.files))Op(Vl(we,De),Se,{mode:384});i(`First boot for ${t.hostname}`),n(`Wrote ${Object.keys(be.files).join(", ")} to ${we}`),console.log(be.instructions)}catch(m){za(m)}})}async function Bp(){let N=await Ne(),t=y(process.cwd(),N),m=new gn(t.store),A=new fn(m,new Ie(t.store));return{controlPlane:t,store:m,service:A}}async function is(N){let t=await Bp();try{await N(t)}catch(m){r(m instanceof Error?m.message:String(m)),process.exitCode=1}finally{t.controlPlane.store.close()}}var Ts=(N)=>Object.fromEntries(String(N??"").split(",").map((t)=>t.split("=")).filter((t)=>t[0]&&t[1])),Gl=(N)=>Object.fromEntries(Object.entries(Ts(N)).map(([t,m])=>[t,Number(m)]));function Va(N){N.command("pool:list","List capacity pools and reservations").option("--json","Print structured JSON").action(async(t)=>is((m)=>{let A=m.store.listPools(m.controlPlane.project.id);if(t.json)console.log(JSON.stringify(A,null,2));else c(["Name","Purpose","Backend","Region / arch","Status","Capacity","Concurrency"],A.map((L)=>[L.name,L.purpose,L.backend,`${L.region??"any"} / ${L.architecture??"any"}`,L.status,JSON.stringify(L.capacity),String(L.concurrency)]))})),N.command("pool:create <name>","Create a capacity pool").option("--purpose <purpose>","application, build, worker, monitoring, or backup",{default:"application"}).option("--backend <backend>","server, ecs, or asg",{default:"server"}).option("--capacity <values>","cpu=4,memoryBytes=8589934592,diskBytes=...").option("--region <region>","Required region").option("--arch <architecture>","Required architecture").option("--labels <labels>","Pool key=value labels").option("--selector <labels>","Required server labels").option("--max <count>","Maximum workloads",{default:"10"}).option("--concurrency <count>","Build concurrency",{default:"1"}).action(async(t,m)=>is((A)=>{let{purpose:L,backend:j}=m;if(!["application","build","worker","monitoring","backup"].includes(L)||!["server","ecs","asg"].includes(j))throw Error("Unsupported pool purpose or backend.");let G=A.store.createPool({organizationId:A.controlPlane.organization.id,projectId:A.controlPlane.project.id,name:t,purpose:L,backend:j,region:m.region,architecture:m.arch,labels:Ts(m.labels),requiredServerLabels:Ts(m.selector),toleratedTaints:[],capacity:{cpu:0,memoryBytes:0,diskBytes:0,gpu:0,...Gl(m.capacity)},maxWorkloads:Number(m.max),costWeight:1,concurrency:Number(m.concurrency),ephemeralWorkspaces:!0,allowProductionSecrets:!1,status:"active"});n(`Created ${G.name} (${G.id}).`)})),N.command("pool:add-server <pool> <server>","Attach an enrolled server to a pool").action(async(t,m)=>is((A)=>{let L=A.store.listPools(A.controlPlane.project.id).find((G)=>G.id===t||G.name===t),j=new Ie(A.controlPlane.store).list(A.controlPlane.project.id).find((G)=>G.id===m||G.name===m);if(!L||!j)throw Error("Pool or server was not found.");A.store.addMember(L.id,j.id),n(`Attached ${j.name} to ${L.name}.`)})),N.command("placement:explain","Explain eligible and rejected placement targets").option("--purpose <purpose>","Workload purpose",{default:"application"}).option("--resources <values>","Requested resources").option("--region <region>","Required region").option("--arch <architecture>","Required architecture").option("--labels <labels>","Required pool labels").option("--json","Print structured JSON").action(async(t)=>is((m)=>{let A=m.service.explain(m.controlPlane.project.id,{purpose:t.purpose,resources:Gl(t.resources),region:t.region,architecture:t.arch,labels:Ts(t.labels)});if(t.json)console.log(JSON.stringify(A,null,2));else c(["Pool","Server","Eligible","Available","Fit / spread / cost","Reasons"],A.map((L)=>[L.poolName,L.serverId??"provider-managed",L.eligible?"yes":"no",JSON.stringify(L.available),`${L.score.fit.toFixed(2)} / ${L.score.spread} / ${L.score.cost}`,L.reasons.join("; ")||"eligible"]))})),N.command("pool:drain <pool>","Move stateless placements and block stateful placements").action(async(t)=>is((m)=>{let A=m.store.listPools(m.controlPlane.project.id).find((j)=>j.id===t||j.name===t);if(!A)throw Error("Pool was not found.");let L=m.service.drainPool(A.id);n(`Draining ${A.name}: moved ${L.moved.length}, blocked ${L.blocked.length} stateful placement(s).`)}))}async function Mp(){let N=await Ne(),t=y(process.cwd(),N),m=new hn(t.store),A=new yn(m);return{controlPlane:t,store:m,service:A}}async function fo(N){let t=await Mp();try{await N(t)}catch(m){r(m instanceof Error?m.message:String(m)),process.exitCode=1}finally{t.controlPlane.store.close()}}var os=(N,t)=>{let m=N.store.list(N.controlPlane.project.id).find((A)=>A.id===t||A.name===t);if(!m)throw Error("Regional topology was not found.");return m},_p=(N)=>N.split(",").map((t,m)=>{let[A,L="aws"]=t.split(":");return{region:String(A),provider:L,role:m===0?"primary":"secondary"}}),zp=(N)=>{let t=new Set(["s3","dynamodb","secrets"]),m=N.split(",").map((L)=>L.trim()),A=m.find((L)=>!t.has(L));if(A)throw Error(`Unsupported replication kind: ${A}`);return m};function Wa(N){N.command("region:list","List regional topology, traffic, and replication health").option("--json","Print structured JSON").action(async(t)=>fo((m)=>{let A=m.store.list(m.controlPlane.project.id).map((L)=>({topology:L,targets:m.store.targets(L.id),channels:m.store.channels(L.id),route:m.store.route(L.id),executions:m.store.executions(L.id)}));if(t.json)console.log(JSON.stringify(A,null,2));else c(["Name","Hostname","Active","Status","Revision","Replication"],A.map((L)=>[L.topology.name,L.topology.hostname,L.topology.activeRegion,L.topology.status,L.topology.revision??"—",`${L.channels.filter((j)=>j.status==="in_sync").length}/${L.channels.length} in sync`]))})),N.command("region:create <name>","Create a persistent multi-region topology").option("--hostname <hostname>","Traffic hostname").option("--regions <regions>","Comma-separated region[:provider], primary first").option("--replicate <kinds>","s3,dynamodb,secrets",{default:"s3,dynamodb,secrets"}).option("--max-lag <seconds>","Maximum failover lag",{default:"30"}).option("--cdn","Enable CloudFront edge state").option("--waf","Enable WAF edge state").action(async(t,m)=>fo((A)=>{if(!m.hostname||!m.regions)throw Error("--hostname and --regions are required.");let L=A.service.create({organizationId:A.controlPlane.organization.id,projectId:A.controlPlane.project.id,name:t,hostname:m.hostname,regions:_p(m.regions),trafficPolicy:"active_passive",dataPolicy:{replicate:zp(String(m.replicate)),maxLagSeconds:Number(m.maxLag),retainOnDestroy:!0},dnsProvider:"route53",cdnEnabled:!!m.cdn,wafEnabled:!!m.waf});n(`Created ${L.name} (${L.id}); run region:rollout with an immutable manifest.`)})),N.command("region:plan <name> <operation>","Preview exact regional execution steps").option("--target <region>","Failover or failback region").action(async(t,m,A)=>fo((L)=>c(["Step"],L.service.plan(os(L,t).id,m,A.target).map((j)=>[j])))),N.command("region:rollout <name> <revision>","Queue secondary-first regional stack rollout").option("--manifest <file>","Regional stack manifest JSON").action(async(t,m,A)=>fo(async(L)=>{let j=A.manifest?await Bun.file(A.manifest).json():{},G=L.service.enqueue({topologyId:os(L,t).id,kind:"rollout",revision:m,manifest:j});n(`Regional rollout queued: ${G.operation.id}`)})),N.command("region:failover <name> <region>","Queue health and RPO-gated failover").action(async(t,m)=>fo((A)=>{let L=A.service.enqueue({topologyId:os(A,t).id,kind:"failover",targetRegion:m});n(`Failover queued: ${L.operation.id}`)})),N.command("region:failback <name> <region>","Queue health and RPO-gated failback").action(async(t,m)=>fo((A)=>{let L=A.service.enqueue({topologyId:os(A,t).id,kind:"failback",targetRegion:m});n(`Failback queued: ${L.operation.id}`)})),N.command("region:destroy <name>","Drain traffic and delete regional stacks while retaining data").option("--confirm <name>","Exact topology name").action(async(t,m)=>fo((A)=>{let L=A.service.enqueue({topologyId:os(A,t).id,kind:"destroy",confirmation:m.confirm});n(`Regional teardown queued: ${L.operation.id}; replicated data remains retained.`)}))}var ss="0.16.20";async function Vp(){let N=await Ne(),t=y(process.cwd(),N),m=new Sn(t.store),A=new bn(m),L=["releases","artifacts","operations","logs","previews","snapshots","orphaned_resources"].map((j)=>new vn(j,t.store,t.project.id,t.organization.id));return{controlPlane:t,store:m,service:A,cleanup:L}}async function Bi(N){let t=await Vp();try{await N(t)}catch(m){r(m instanceof Error?m.message:String(m)),process.exitCode=1}finally{t.controlPlane.store.close()}}function qa(N){N.command("maintenance:list","List updates, campaigns, cleanup plans, and DR drills").option("--json","Print structured JSON").action(async(t)=>Bi((m)=>{let A={manifests:m.store.manifests(m.controlPlane.organization.id),windows:m.store.windows(m.controlPlane.project.id),campaigns:m.store.campaigns(m.controlPlane.project.id),cleanups:m.store.cleanups(m.controlPlane.project.id),drills:m.store.drills(m.controlPlane.project.id)},L=[...A.manifests.map((j)=>["update",j.version,j.compatibility.compatible?"compatible":"blocked",j.compatibility.reasons.join("; ")||j.channel]),...A.campaigns.map((j)=>["upgrade",j.id,j.status,j.currentStage??j.fromVersion]),...A.cleanups.map((j)=>["cleanup",j.kind,j.status,`${j.candidates.length} items / ${j.estimatedBytes} bytes`]),...A.drills.map((j)=>["DR drill",j.scenario,j.status,j.isolatedTarget])];if(t.json)console.log(JSON.stringify(A,null,2));else c(["Area","Name / version","Status","Detail"],L)})),N.command("maintenance:key:add <name> <pem>","Trust an Ed25519 update signing key").action(async(t,m)=>Bi(async(A)=>{let L=A.store.addTrustedKey({organizationId:A.controlPlane.organization.id,name:t,publicKeyPem:await Bun.file(m).text()});n(`Trusted ${L.name}: ${L.fingerprint}`)})),N.command("maintenance:manifest <document> <signature> <key>","Verify and import a signed update manifest").action(async(t,m,A)=>Bi(async(L)=>{let j=await Bun.file(t).json(),G=(await Bun.file(m).text()).trim(),Z=L.store.importManifest({organizationId:L.controlPlane.organization.id,keyId:A,document:j,signature:G,current:{schemaVersion:L.controlPlane.store.health().schemaVersion,currentVersion:ss,platform:process.platform,architecture:process.arch}});n(`Verified ${Z.version}; ${Z.compatibility.compatible?"compatible":"blocked: "+Z.compatibility.reasons.join("; ")}`)})),N.command("maintenance:window <name> <schedule>","Create an approved maintenance window").option("--timezone <timezone>","IANA timezone",{default:"UTC"}).option("--minutes <minutes>","Duration",{default:"60"}).action(async(t,m,A)=>Bi((L)=>{let j=L.store.createWindow({projectId:L.controlPlane.project.id,name:t,schedule:m,timezone:A.timezone,durationMinutes:Number(A.minutes),allowedOperations:["platform.upgrade"],requireApproval:!0});n(`Created ${j.name} (${j.id}).`)})),N.command("platform:upgrade <manifest> <backup>","Plan and queue a signed staged platform update").option("--strategy <strategy>","canary or rolling",{default:"canary"}).option("--batch <count>","Rolling batch size",{default:"1"}).action(async(t,m,A)=>Bi((L)=>{let j=new Ie(L.controlPlane.store).list(L.controlPlane.project.id).filter((ee)=>ee.status==="ready").map((ee)=>({serverId:ee.id,target:ee.name,previousVersion:ee.bootstrapVersion??ss}));if(!j.length)j.push({target:"control-plane",previousVersion:ss});let G=L.store.createCampaign({projectId:L.controlPlane.project.id,manifestId:t,fromVersion:ss,strategy:A.strategy==="rolling"?"rolling":"canary",batchSize:Number(A.batch),healthGate:{kind:"platform"},backupId:m,targets:j}),Z=L.service.enqueueCampaign(G.id);n(`Staged upgrade queued: ${Z.operation.id}`)})),N.command("cleanup:preview <kind>","Discover a bounded cleanup candidate set without deleting").option("--older-than <days>","Minimum age",{default:"30"}).action(async(t,m)=>Bi(async(A)=>{let L=await A.service.previewCleanup({projectId:A.controlPlane.project.id,kind:t,criteria:{olderThanDays:Number(m.olderThan)}},A.cleanup);c(["ID","Candidate","Bytes"],L.candidates.map((j)=>[j.id,j.label,String(j.bytes)])),e(`Apply with: cloud cleanup:apply ${L.id} --confirm "DELETE ${L.candidates.length} ${L.kind}"`)})),N.command("cleanup:apply <plan>","Apply an unchanged cleanup preview").option("--confirm <text>","Exact preview confirmation").action(async(t,m)=>Bi((A)=>{let L=A.service.enqueueCleanup(t,String(m.confirm??""));n(`Cleanup queued: ${L.operation.id}`)})),N.command("dr:plan <scenario> <target>","Plan an isolated disaster-recovery drill").option("--rpo <minutes>","RPO objective",{default:"60"}).option("--rto <minutes>","RTO objective",{default:"30"}).option("--recovery-point <id>","Recovery point").option("--topology <id>","Regional topology").action(async(t,m,A)=>Bi((L)=>{let j=L.store.createDrill({projectId:L.controlPlane.project.id,scenario:t,isolatedTarget:m,expectedRpoMinutes:Number(A.rpo),expectedRtoMinutes:Number(A.rto),recoveryPointId:A.recoveryPoint,topologyId:A.topology});n(`Planned isolated drill ${j.id}.`)})),N.command("dr:run <drill>","Queue an isolated disaster-recovery drill").action(async(t)=>Bi((m)=>{let A=m.service.enqueueDrill(t);n(`DR drill queued: ${A.operation.id}`)}))}async function Ga(){try{return(await Ne()).project.region||process.env.AWS_REGION||"us-east-1"}catch{return process.env.AWS_REGION||"us-east-1"}}function Ha(N){N.command("function:list","List all Lambda functions").option("--region <region>","AWS region").action(async(t)=>{i("Lambda Functions");let m=t?.region||await Ga(),A=new R(m);try{let{Functions:L=[]}=await A.listFunctions({MaxItems:50});if(!L.length){e("No functions found");return}c(["Name","Runtime","Memory","Timeout","Last Modified"],L.map((j)=>[j.FunctionName??"-",j.Runtime??"-",j.MemorySize?`${j.MemorySize} MB`:"-",j.Timeout?`${j.Timeout}s`:"-",j.LastModified??"-"]))}catch(L){r(`Failed to list functions: ${L.message}`),process.exitCode=1}}),N.command("function:invoke <name>","Invoke a Lambda function").option("--payload <json>","Event payload as JSON",{default:"{}"}).option("--async","Fire-and-forget (Event invocation)").option("--region <region>","AWS region").action(async(t,m)=>{i(`Invoking ${t}`);let A=m?.region||await Ga(),L=new R(A),j=new o("Invoking function...");j.start();try{let G=await L.invoke({FunctionName:t,InvocationType:m?.async?"Event":"RequestResponse",Payload:m?.payload||"{}",LogType:m?.async?"None":"Tail"});if(G.FunctionError){if(j.fail(`Function returned an error (${G.FunctionError})`),G.Payload)e(G.Payload);process.exitCode=1;return}if(j.succeed(`Invoked (status ${G.StatusCode})`),G.Payload)e(`
|
|
319
319
|
Response:`),e(G.Payload);if(G.LogResult)e(`
|
|
320
320
|
Logs:`),e(Buffer.from(G.LogResult,"base64").toString("utf-8"))}catch(G){j.fail(`Invocation failed: ${G.message}`),process.exitCode=1}}),N.command("function:logs <name>","View recent function logs").option("--tail","Continuously stream new log events").option("--filter <pattern>","CloudWatch filter pattern").option("--since <minutes>","Look back this many minutes",{default:"15"}).option("--region <region>","AWS region").action(async(t,m)=>{i(`Logs for ${t}`);let A=m?.region||await Ga(),L=new re(A),j=t.startsWith("/aws/lambda/")?t:`/aws/lambda/${t}`,G=Number(m?.since??15),Z=(ee)=>{for(let ne of ee){let oe=ne.timestamp?new Date(ne.timestamp).toISOString():"";e(`${oe} ${(ne.message??"").trimEnd()}`)}};try{let ee=Date.now()-G*60000,{events:ne=[]}=await L.filterLogEvents({logGroupName:j,startTime:ee,filterPattern:m?.filter,limit:200});if(Z(ne),ne.length)ee=(ne[ne.length-1].timestamp??ee)+1;if(m?.tail){e(`
|
|
321
321
|
(streaming — Ctrl+C to stop)`);for(;;){await new Promise((be)=>setTimeout(be,3000));let{events:oe=[]}=await L.filterLogEvents({logGroupName:j,startTime:ee,filterPattern:m?.filter,limit:200});if(oe.length)Z(oe),ee=(oe[oe.length-1].timestamp??ee)+1}}}catch(ee){r(`Failed to read logs: ${ee.message}`),process.exitCode=1}})}async function Hl(N){let t=Bun.spawn(["docker",...N],{stdin:"inherit",stdout:"inherit",stderr:"pipe"}),[m,A]=await Promise.all([t.exited,new Response(t.stderr).text()]);return{ok:m===0,exitCode:m,command:["docker",...N].join(" "),stderr:A.trim()}}function Ka(N){N.command("container:build","Build a Docker image").option("--tag <tag>","Image tag",{default:"latest"}).option("--file <dockerfile>","Dockerfile",{default:"Dockerfile"}).option("--dry-run","Print the exact command").option("--json","Print result JSON").action(async(t)=>{let m=["build","--file",t.file??"Dockerfile","--tag",t.tag??"latest","."];if(t.dryRun){console.log(`docker ${m.join(" ")}`);return}let A=await Hl(m);if(t.json)console.log(JSON.stringify(A));if(!A.ok)r(A.stderr||`docker exited ${A.exitCode}`),process.exitCode=A.exitCode;else n(`Built ${t.tag??"latest"}.`)}),N.command("container:push","Push an already-tagged image").option("--image <image>","Full registry image reference").option("--dry-run","Print command").option("--json","Print JSON").action(async(t)=>{if(!t.image){r("--image with a full registry reference is required; credentials must come from docker credential helpers."),process.exitCode=2;return}if(t.dryRun){console.log(`docker push ${t.image}`);return}let m=await Hl(["push",t.image]);if(t.json)console.log(JSON.stringify(m));if(!m.ok)r(m.stderr),process.exitCode=m.exitCode;else n(`Pushed ${t.image}.`)}),N.command("container:deploy","Deploy a container image").action(async()=>Vr("container:deploy",{message:"Direct ECS mutation is not registered as a shared release driver.",nextAction:"Import the image as an application and use the immutable release deployment workflow."}))}function Ja(N){N.command("domain:list","List all domains").option("--provider <provider>","DNS provider: porkbun, godaddy, cloudflare, or route53").action(async(t)=>{i("Domains");try{let m=vi(t?.provider),A=ir(t?.provider)?.provider||"unknown",L=new o(`Fetching domains from ${A}...`);L.start();let j=await m.listDomains();if(L.succeed(`Found ${j.length} domain(s)`),j.length===0){e("No domains found in this provider");return}let G=j.map((Z)=>[Z,"Active","-",A.charAt(0).toUpperCase()+A.slice(1)]);c(["Domain","Status","SSL","Provider"],G)}catch(m){r(`Failed to list domains: ${m instanceof Error?m.message:String(m)}`)}}),N.command("domain:add <domain>","Add a new domain").option("--provider <provider>","DNS provider: porkbun, godaddy, cloudflare, or route53").action(async(t,m)=>{i(`Adding Domain: ${t}`);try{let A=vi(m?.provider),L=ir(m?.provider)?.provider||"unknown",j=new o(`Checking if ${L} can manage ${t}...`);if(j.start(),await A.canManageDomain(t))j.succeed(`Domain ${t} is already available in ${L}`),e(`
|
|
@@ -400,7 +400,7 @@ ${ee.instanceId}:`),e(ee.output?.trimEnd()||"(no output)")}catch(A){r(`History l
|
|
|
400
400
|
`),{runComputeRecipe:Z}=await import("./chunk-hagakkgm.js"),ee=await Z({driver:_({config:L}),slug:L.project.slug,environment:j,logger:f},{name:t,script:G,user:A?.user});for(let ne of ee.perInstance||[])e(`
|
|
401
401
|
${ne.instanceId}:`),e(ne.output?.trimEnd()||"(no output)");if(!ee.success)process.exitCode=1}catch(L){r(`Recipe failed: ${L.message}`),process.exitCode=1}}),N.command("db:restore-backup [from]","Restore the app database from an on-box ts-backups dump (latest, or a given file)").option("--env <environment>","Environment (production, staging, development)").action(async(t,m)=>{i("Database Restore");try{let A=await Ne(),L=m?.env||"production",{restoreDatabaseBackup:j}=await import("./chunk-hagakkgm.js"),G=await j({driver:_({config:A}),slug:A.project.slug,environment:L,logger:f},{database:C(A),from:t});for(let Z of G.perInstance||[])e(` ${Z.instanceId}: ${Z.output?.trim()||Z.status}`);if(!G.success)r(`Restore failed: ${G.error||"unknown error"}`),process.exitCode=1}catch(A){r(`Restore failed: ${A.message}`),process.exitCode=1}}),N.command("quick-deploy","Generate a push-to-deploy CI pipeline for your git provider (Forge Quick Deploy)").option("--env <environment>","Environment to deploy on push",{default:"production"}).option("--provider <provider>","CI provider (github, gitlab, bitbucket); defaults to the origin remote").option("--site <site>","Deploy only this configured site").option("--skip-dns-verification","Generate a deploy that skips DNS verification and record creation").option("--ssh-key-secret <name>","CI secret/variable containing the Hetzner deployment SSH private key",{default:"SSH_PRIVATE_KEY"}).option("--force","Overwrite an existing pipeline file").action(async(t)=>{i("Quick Deploy (push-to-deploy)");try{let m=await Ne(),{buildQuickDeployCi:A,inferQuickDeployProvider:L}=await import("./chunk-dmdg23a5.js"),j=t?.provider?.toLowerCase();if(j&&!["github","gitlab","bitbucket"].includes(j))throw Error(`Unsupported CI provider '${t?.provider}'. Use github, gitlab, or bitbucket.`);let G=j;if(!G)try{let ee=Nc("git remote get-url origin",{stdio:["ignore","pipe","ignore"]}).toString().trim();G=L(ee)}catch{}let Z=A(m,t?.env||"production",{provider:G,site:t?.site,skipDnsVerification:t?.skipDnsVerification,setup:yr("pantry.lock")?"pantry":"bun",sshPrivateKeySecret:t?.sshKeySecret});if(!Z){a("Could not resolve a GitHub, GitLab, or Bitbucket provider from --provider, the origin remote, or a configured site repository."),process.exitCode=1;return}if(yr(Z.path)&&!t?.force){a(`${Z.path} already exists — re-run with --force to overwrite.`);return}hd(Dm(Z.path),{recursive:!0}),xm(Z.path,Z.content),n(`Wrote ${Z.path} (${Z.provider}, deploys on push to '${Z.branch}').`),e("Next: commit it and add your provider credentials as CI secrets/variables.")}catch(m){r(`Quick deploy setup failed: ${m.message}`),process.exitCode=1}}),N.command("down","Put the serverless app into maintenance mode (503)").option("--env <environment>","Environment (production, staging, development)").option("--secret <secret>","Bypass secret (send as x-maintenance-bypass header)").action(async(t)=>{try{let m=await Ne(),A=t?.env||"production",{setMaintenance:L}=await import("./chunk-28ztnqjk.js");await L(m,A,!0,t?.secret)}catch(m){r(`Failed to enable maintenance mode: ${m.message}`),process.exitCode=1}}),N.command("up","Bring the serverless app out of maintenance mode").option("--env <environment>","Environment (production, staging, development)").action(async(t)=>{try{let m=await Ne(),A=t?.env||"production",{setMaintenance:L}=await import("./chunk-28ztnqjk.js");await L(m,A,!1)}catch(m){r(`Failed to disable maintenance mode: ${m.message}`),process.exitCode=1}}),N.command("command <cmd>","Run a command on the serverless CLI function (e.g. migrations)").option("--env <environment>","Environment (production, staging, development)").action(async(t,m)=>{try{let A=await Ne(),L=m?.env||"production",{runAndRecordCommand:j}=await import("./chunk-28ztnqjk.js"),{id:G,output:Z}=await j(A,L,t);if(e(Z),G>0)e(`
|
|
402
402
|
(recorded as #${G} — re-run with \`cloud command:again ${G}\`)`)}catch(A){r(`Command failed: ${A.message}`),process.exitCode=1}}),N.command("command:history","List recorded CLI-function command invocations").option("--env <environment>","Environment (production, staging, development)").option("--limit <n>","Show at most this many (most recent)",{default:"20"}).action(async(t)=>{try{let m=await Ne(),A=t?.env||"production",{listCommandHistory:L}=await import("./chunk-28ztnqjk.js"),j=await L(m,A);if(!j.length){e("No command history yet.");return}let G=Number(t?.limit??20);i(`Command history — ${m.project.slug} (${A})`),c(["#","When","Status","Command"],j.slice(-G).reverse().map((Z)=>[String(Z.id),Z.timestamp,Z.status,Z.command]))}catch(m){r(`Failed to read history: ${m.message}`),process.exitCode=1}}),N.command("command:again [id]","Re-run a recorded command (defaults to the most recent)").option("--env <environment>","Environment (production, staging, development)").action(async(t,m)=>{try{let A=await Ne(),L=m?.env||"production",{getCommandRecord:j,runAndRecordCommand:G}=await import("./chunk-28ztnqjk.js"),Z=await j(A,L,t?Number(t):void 0);if(!Z){r(t?`No command #${t} in history.`:"No command history to re-run."),process.exitCode=1;return}e(`Re-running #${Z.id}: ${Z.command}`);let ee=await G(A,L,Z.command);if(e(ee.output),ee.id>0)e(`
|
|
403
|
-
(recorded as #${ee.id})`)}catch(A){r(`Command failed: ${A.message}`),process.exitCode=1}}),N.command("serverless:db-shell <sql>","Run a SQL statement against a private serverless database (via the CLI function)").option("--env <environment>","Environment (production, staging, development)").action(async(t,m)=>{try{let A=await Ne(),L=m?.env||"production",{runDbQuery:j}=await import("./chunk-28ztnqjk.js"),G=await j(A,L,t);e(G)}catch(A){r(`Query failed: ${A.message}`),process.exitCode=1}}),N.command("serverless:db-scale <min> <max>","Rescale the serverless Aurora cluster (min/max ACUs)").option("--env <environment>","Environment (production, staging, development)").action(async(t,m,A)=>{i("Scaling serverless database");try{let L=await Ne(),j=A?.env||"production",G=Number(t),Z=Number(m);if(!(G>0)||!(Z>=G)){r("Provide valid capacities: min > 0 and max >= min (e.g. `serverless:db-scale 0.5 8`)."),process.exitCode=1;return}let{scaleServerlessDatabase:ee}=await import("./chunk-28ztnqjk.js");await ee(L,j,G,Z)}catch(L){r(`Scale failed: ${L.message}`),process.exitCode=1}}),N.command("serverless:db-restore","Restore the serverless Aurora cluster to a point in time (as a new cluster)").option("--env <environment>","Environment (production, staging, development)").option("--to <timestamp>","Restore to this ISO-8601 time (UTC)").option("--latest","Restore to the latest restorable time").option("--target <id>","New cluster identifier (defaults to <cluster>-restore-<stamp>)").action(async(t)=>{i("Restoring serverless database");try{let m=await Ne(),A=t?.env||"production",L;if(t?.to){if(L=new Date(t.to),Number.isNaN(L.getTime())){r(`Invalid --to timestamp: ${t.to} (use ISO-8601, e.g. 2026-06-18T10:00:00Z).`),process.exitCode=1;return}}let{restoreServerlessDatabase:j}=await import("./chunk-28ztnqjk.js");await j(m,A,{toTime:L,latest:t?.latest,target:t?.target})}catch(m){r(`Restore failed: ${m.message}`),process.exitCode=1}}),N.command("serverless:info","Show an operational summary of a deployed serverless app").option("--env <environment>","Environment (production, staging, development)").action(async(t)=>{try{let m=await Ne(),A=t?.env||"production",{serverlessInfo:L}=await import("./chunk-28ztnqjk.js"),j=await L(m,A);if(i(`${j.slug} (${j.environment})`),e(`Stack: ${j.stackStatus}`),e(`Region: ${j.region}`),j.endpoint)e(`URL: ${j.endpoint}`);if(j.assetUrl)e(`Assets: ${j.assetUrl}`);if(e(`Scheduler:${j.scheduler==="off"?" off":` ${j.scheduler}`}`),e(`Queues: ${j.queues.length?j.queues.join(", "):"none"}`),e(`Warming: ${j.provisionedConcurrency>0?`provisioned concurrency ×${j.provisionedConcurrency}`:"none / ping-warm"}`),j.lastRelease)e(`Release: ${j.lastRelease.sha.slice(0,12)} @ ${j.lastRelease.timestamp}`);c(["Function","Version","Provisioned"],j.functions.map((G)=>[G.name,G.version,G.provisioned?`${G.provisioned.status} ${G.provisioned.allocated}/${G.provisioned.requested}`:"—"]))}catch(m){r(`Failed to read info: ${m.message}`),process.exitCode=1}}),N.command("dashboard:build","Build the management dashboard with live data baked in").option("--env <environment>","Environment (production, staging, development)").option("--ui <dir>","UI directory (default ./ui)",{default:"ui"}).action(async(t)=>{i("Building management dashboard (live data)");try{let{existsSync:m}=await import("node:fs"),A=t?.ui||"ui";if(!m(`${A}/package.json`)){r(`No UI project at ${A}/ (expected ${A}/package.json). Pass --ui <dir>.`),process.exitCode=1;return}let L=await Ne(),j=t?.env||"production";p("Gathering live data from AWS");let G=null;if(L.environments?.[j]?.app){let{resolveDashboardData:oe}=await import("./chunk-y286zhty.js"),be=await oe(L,j).catch((we)=>(a(`Serverless data unavailable (${we.message}) — that view uses sample data.`),null));if(be)G={...G??{},...be}}if(L.infrastructure?.compute){let{resolveServerDashboardData:oe}=await import("./chunk-
|
|
403
|
+
(recorded as #${ee.id})`)}catch(A){r(`Command failed: ${A.message}`),process.exitCode=1}}),N.command("serverless:db-shell <sql>","Run a SQL statement against a private serverless database (via the CLI function)").option("--env <environment>","Environment (production, staging, development)").action(async(t,m)=>{try{let A=await Ne(),L=m?.env||"production",{runDbQuery:j}=await import("./chunk-28ztnqjk.js"),G=await j(A,L,t);e(G)}catch(A){r(`Query failed: ${A.message}`),process.exitCode=1}}),N.command("serverless:db-scale <min> <max>","Rescale the serverless Aurora cluster (min/max ACUs)").option("--env <environment>","Environment (production, staging, development)").action(async(t,m,A)=>{i("Scaling serverless database");try{let L=await Ne(),j=A?.env||"production",G=Number(t),Z=Number(m);if(!(G>0)||!(Z>=G)){r("Provide valid capacities: min > 0 and max >= min (e.g. `serverless:db-scale 0.5 8`)."),process.exitCode=1;return}let{scaleServerlessDatabase:ee}=await import("./chunk-28ztnqjk.js");await ee(L,j,G,Z)}catch(L){r(`Scale failed: ${L.message}`),process.exitCode=1}}),N.command("serverless:db-restore","Restore the serverless Aurora cluster to a point in time (as a new cluster)").option("--env <environment>","Environment (production, staging, development)").option("--to <timestamp>","Restore to this ISO-8601 time (UTC)").option("--latest","Restore to the latest restorable time").option("--target <id>","New cluster identifier (defaults to <cluster>-restore-<stamp>)").action(async(t)=>{i("Restoring serverless database");try{let m=await Ne(),A=t?.env||"production",L;if(t?.to){if(L=new Date(t.to),Number.isNaN(L.getTime())){r(`Invalid --to timestamp: ${t.to} (use ISO-8601, e.g. 2026-06-18T10:00:00Z).`),process.exitCode=1;return}}let{restoreServerlessDatabase:j}=await import("./chunk-28ztnqjk.js");await j(m,A,{toTime:L,latest:t?.latest,target:t?.target})}catch(m){r(`Restore failed: ${m.message}`),process.exitCode=1}}),N.command("serverless:info","Show an operational summary of a deployed serverless app").option("--env <environment>","Environment (production, staging, development)").action(async(t)=>{try{let m=await Ne(),A=t?.env||"production",{serverlessInfo:L}=await import("./chunk-28ztnqjk.js"),j=await L(m,A);if(i(`${j.slug} (${j.environment})`),e(`Stack: ${j.stackStatus}`),e(`Region: ${j.region}`),j.endpoint)e(`URL: ${j.endpoint}`);if(j.assetUrl)e(`Assets: ${j.assetUrl}`);if(e(`Scheduler:${j.scheduler==="off"?" off":` ${j.scheduler}`}`),e(`Queues: ${j.queues.length?j.queues.join(", "):"none"}`),e(`Warming: ${j.provisionedConcurrency>0?`provisioned concurrency ×${j.provisionedConcurrency}`:"none / ping-warm"}`),j.lastRelease)e(`Release: ${j.lastRelease.sha.slice(0,12)} @ ${j.lastRelease.timestamp}`);c(["Function","Version","Provisioned"],j.functions.map((G)=>[G.name,G.version,G.provisioned?`${G.provisioned.status} ${G.provisioned.allocated}/${G.provisioned.requested}`:"—"]))}catch(m){r(`Failed to read info: ${m.message}`),process.exitCode=1}}),N.command("dashboard:build","Build the management dashboard with live data baked in").option("--env <environment>","Environment (production, staging, development)").option("--ui <dir>","UI directory (default ./ui)",{default:"ui"}).action(async(t)=>{i("Building management dashboard (live data)");try{let{existsSync:m}=await import("node:fs"),A=t?.ui||"ui";if(!m(`${A}/package.json`)){r(`No UI project at ${A}/ (expected ${A}/package.json). Pass --ui <dir>.`),process.exitCode=1;return}let L=await Ne(),j=t?.env||"production";p("Gathering live data from AWS");let G=null;if(L.environments?.[j]?.app){let{resolveDashboardData:oe}=await import("./chunk-y286zhty.js"),be=await oe(L,j).catch((we)=>(a(`Serverless data unavailable (${we.message}) — that view uses sample data.`),null));if(be)G={...G??{},...be}}if(L.infrastructure?.compute){let{resolveServerDashboardData:oe}=await import("./chunk-gt7g41js.js"),be=await oe(L,j).catch(()=>null);if(be){if(be._serverReachable===!1)a("Server box not reachable over SSM — server view uses config + sample data.");G={...G??{},...be}}}p("Building dashboard");let{encodeDashboardPayload:Z}=await import("./chunk-swfmx4f8.js"),{execSync:ee}=await import("node:child_process"),{rmSync:ne}=await import("node:fs");for(let oe of[".stx/ssg-cache",".stx/cache"])ne(`${A}/${oe}`,{recursive:!0,force:!0});ee("bun run build",{cwd:A,stdio:"inherit",env:{...process.env,...G?{TSCLOUD_DASHBOARD_DATA:Z(G)}:{}}}),n(`Dashboard built → ${A}/dist${G?" (live data)":" (sample data)"}`)}catch(m){r(`Dashboard build failed: ${m.message}`),process.exitCode=1}}),N.command("serverless:build-php-layer","Build + publish the ts-cloud PHP runtime layer (requires Docker)").option("--arch <architecture>","x86_64 or arm64",{default:"x86_64"}).option("--php <version>","PHP version",{default:"8.3"}).option("--name <name>","Layer name",{default:"tscloud-php"}).option("--bucket <bucket>","S3 bucket to stage the layer zip (defaults to {slug}-layers)").option("--region <region>","AWS region").action(async(t)=>{i("Building PHP runtime layer");try{let m=await Ne().catch(()=>null),A=t?.region||m?.project.region||"us-east-1",L=t?.arch||"x86_64",j=t?.php||"8.3",G=`${t?.name||"tscloud-php"}-${j.replace(".","")}-${L}`,Z=t?.bucket||`${m?.project.slug||"tscloud"}-layers`,{buildPhpRuntimeLayerZip:ee}=await import("./chunk-6se7ygxa.js"),{S3Client:ne}=await import("./chunk-gp5w7e4c.js"),{LambdaClient:oe}=await import("./chunk-wagzxm7z.js"),be=ee({architecture:L,phpVersion:j,onStep:(xe)=>p(xe)});e(`Layer: ${be.fileCount} files, ${(be.zip.length/1024/1024).toFixed(1)} MB`);let we=new ne(A);if(!await we.bucketExists(Z))p(`Creating layer bucket ${Z}`),await we.createBucket(Z);let Ce=`layers/${G}.zip`;p("Uploading layer zip"),await we.putObject({bucket:Z,key:Ce,body:be.zip,contentType:"application/zip"}),p("Publishing layer version");let Se=await new oe(A).publishLayerVersion({LayerName:G,Description:`ts-cloud PHP ${j} runtime (${L})`,Content:{S3Bucket:Z,S3Key:Ce},CompatibleRuntimes:["provided.al2023"],CompatibleArchitectures:[L]});he(["PHP runtime layer published","",`ARN: ${Se.LayerVersionArn}`,"","Reference it in your config:",` app: { kind: 'php', layers: ['${Se.LayerVersionArn}'] }`,"or set TSCLOUD_PHP_LAYER_ARN before deploying."].join(`
|
|
404
404
|
`),"green")}catch(m){r(`Layer build failed: ${m.message}`),process.exitCode=1}}),N.command("serverless:build-node-layer","Build + publish a ts-cloud Node custom runtime layer (any version, incl. 24)").option("--arch <architecture>","x86_64 or arm64",{default:"x86_64"}).option("--node <version>","Node version (e.g. 24)",{default:"24"}).option("--name <name>","Layer name",{default:"tscloud-node"}).option("--bucket <bucket>","S3 bucket to stage the layer zip (defaults to {slug}-layers)").option("--region <region>","AWS region").action(async(t)=>{i("Building Node runtime layer");try{let m=await Ne().catch(()=>null),A=t?.region||m?.project.region||"us-east-1",L=t?.arch||"x86_64",j=t?.node||"24",{buildNodeRuntimeLayerZip:G}=await import("./chunk-6se7ygxa.js"),{S3Client:Z}=await import("./chunk-gp5w7e4c.js"),{LambdaClient:ee}=await import("./chunk-wagzxm7z.js"),ne=G({architecture:L,version:j,onStep:(xe)=>p(xe)}),oe=`${t?.name||"tscloud-node"}-${ne.version.split(".")[0]}-${L}`,be=t?.bucket||`${m?.project.slug||"tscloud"}-layers`;e(`Layer: Node ${ne.version}, ${(ne.zip.length/1024/1024).toFixed(1)} MB`);let we=new Z(A);if(!await we.bucketExists(be))p(`Creating layer bucket ${be}`),await we.createBucket(be);let Ce=`layers/${oe}.zip`;p("Uploading layer zip"),await we.putObject({bucket:be,key:Ce,body:ne.zip,contentType:"application/zip"}),p("Publishing layer version");let Se=await new ee(A).publishLayerVersion({LayerName:oe,Description:`ts-cloud Node ${ne.version} runtime (${L})`,Content:{S3Bucket:be,S3Key:Ce},CompatibleRuntimes:["provided.al2023"],CompatibleArchitectures:[L]});he(["Node runtime layer published","",`ARN: ${Se.LayerVersionArn}`,"","Reference it in your config:",` app: { kind: 'node', runtimeVersion: '${ne.version.split(".")[0]}', layers: ['${Se.LayerVersionArn}'] }`,"or set TSCLOUD_NODE_LAYER_ARN before deploying."].join(`
|
|
405
405
|
`),"green")}catch(m){r(`Layer build failed: ${m.message}`),process.exitCode=1}}),N.command("serverless:build-bun-layer","Build + publish a ts-cloud Bun custom runtime layer").option("--arch <architecture>","x86_64 or arm64",{default:"x86_64"}).option("--bun <version>",'Bun version (e.g. 1.3.13, or "latest")',{default:"latest"}).option("--name <name>","Layer name",{default:"tscloud-bun"}).option("--bucket <bucket>","S3 bucket to stage the layer zip (defaults to {slug}-layers)").option("--region <region>","AWS region").action(async(t)=>{i("Building Bun runtime layer");try{let m=await Ne().catch(()=>null),A=t?.region||m?.project.region||"us-east-1",L=t?.arch||"x86_64",j=t?.bun||"latest",{buildBunRuntimeLayerZip:G}=await import("./chunk-6se7ygxa.js"),{S3Client:Z}=await import("./chunk-gp5w7e4c.js"),{LambdaClient:ee}=await import("./chunk-wagzxm7z.js"),ne=G({architecture:L,version:j,onStep:(xe)=>p(xe)}),oe=`${t?.name||"tscloud-bun"}-${ne.version.replace(/\./g,"")}-${L}`,be=t?.bucket||`${m?.project.slug||"tscloud"}-layers`;e(`Layer: Bun ${ne.version}, ${(ne.zip.length/1024/1024).toFixed(1)} MB`);let we=new Z(A);if(!await we.bucketExists(be))p(`Creating layer bucket ${be}`),await we.createBucket(be);let Ce=`layers/${oe}.zip`;p("Uploading layer zip"),await we.putObject({bucket:be,key:Ce,body:ne.zip,contentType:"application/zip"}),p("Publishing layer version");let Se=await new ee(A).publishLayerVersion({LayerName:oe,Description:`ts-cloud Bun ${ne.version} runtime (${L})`,Content:{S3Bucket:be,S3Key:Ce},CompatibleRuntimes:["provided.al2023"],CompatibleArchitectures:[L]});he(["Bun runtime layer published","",`ARN: ${Se.LayerVersionArn}`,"","Reference it in your config:",` app: { kind: 'bun', layers: ['${Se.LayerVersionArn}'] }`,"or set TSCLOUD_BUN_LAYER_ARN before deploying."].join(`
|
|
406
406
|
`),"green")}catch(m){r(`Layer build failed: ${m.message}`),process.exitCode=1}}),N.command("deploy:status","Check deployment status").option("--stack <name>","Stack name").option("--env <environment>","Environment").action(async(t)=>{i("Deployment Status");try{let m=await Ne(),A=t?.env||"production",L=t?.stack||E(m,A),j=m.project.region||"us-east-1";e(`Stack: ${L}`),e(`Region: ${j}`);let G=new o("Checking deployment status...");G.start();let ee=await new v(j).describeStacks({stackName:L});if(ee.Stacks.length===0){G.fail("Stack not found"),fr("No deployment found for this environment");return}let ne=ee.Stacks[0];if(G.succeed("Status retrieved"),e(`
|
|
@@ -652,7 +652,7 @@ Send request?`,!0)){e("Operation cancelled");return}let ne=new o("Sending reques
|
|
|
652
652
|
Status: ${be.status} ${be.statusText}`),e(`
|
|
653
653
|
Response Headers:`),be.headers.forEach((De,Se)=>{e(` ${Se}: ${De}`)}),e(`
|
|
654
654
|
Response Body:`);try{let De=JSON.parse(Ce);console.log(JSON.stringify(De,null,2))}catch{console.log(Ce)}}catch(L){r(`Failed to test API: ${L.message}`),process.exit(1)}})}async function yo(N){let t=await Ne(),m=y(process.cwd(),t),A=new b(m.store,{workerId:`cli:${process.pid}`});try{return await N(A,m.project.id,m.organization.id)}finally{m.store.close()}}function ig(N){if(!N)return;if(!["queued","running","succeeded","failed","cancelled","timed_out"].includes(N))throw Error("State must be queued, running, succeeded, failed, cancelled, or timed_out");return N}function og(N,t){if(!N)return"—";let m=Math.max(0,new Date(t??Date.now()).getTime()-new Date(N).getTime());return m<1000?`${m}ms`:m<60000?`${Math.round(m/1000)}s`:`${Math.round(m/60000)}m`}function sl(N){N.command("ops:list","List durable deployment and mutation jobs").option("--state <state>","Filter queue state").option("--all-projects","Show all locally authorized projects").action(async(t)=>{try{await yo(async(m,A)=>{let L=m.list({projectId:t.allProjects?void 0:A,state:ig(t.state),limit:500});c(["ID","State","Operation","Target","Attempt","Step / blocked","Queued","Duration"],L.map(({operation:j,job:G,approximatePosition:Z})=>[j.id,j.state,j.kind,j.resourceId??j.environmentId??j.projectId??"global",`${j.attempt}/${G.maxAttempts}`,G.blockedReason??G.currentStep??(Z?`${Z.ahead} ahead`:"—"),j.createdAt,og(j.startedAt,j.finishedAt)]))})}catch(m){r(m instanceof Error?m.message:String(m))}}),N.command("ops:show <id>","Show a durable operation and its latest sanitized logs").option("--after <cursor>","Show logs after this sequence",{default:"0"}).action(async(t,m)=>{try{await yo(async(A)=>{let L=A.view(t);if(!L)throw Error(`Operation ${t} was not found`);e(JSON.stringify(L,null,2));for(let j of A.logs(t,{after:Number(m.after)||0,limit:500}))e(`${j.sequence} ${j.stream.toUpperCase()}${j.step?` [${j.step}]`:""} ${j.message}`)})}catch(A){r(A instanceof Error?A.message:String(A))}}),N.command("ops:cancel <id>","Cancel queued work or request running cancellation").option("--yes","Skip confirmation").action(async(t,m)=>{try{await yo(async(A)=>{let L=A.view(t);if(!L)throw Error(`Operation ${t} was not found`);if(!m.yes&&!await d(`Cancel ${L.operation.kind} (${t})?`,!1))return;let j=A.requestCancellation(t);n(`${j.state==="cancelled"?"Cancelled":"Cancellation requested for"} ${t}`)})}catch(A){r(A instanceof Error?A.message:String(A))}}),N.command("ops:retry <id>","Retry a terminal job using an allow-listed error class").option("--class <name>","Retryable error class").option("--delay <milliseconds>","Delay before the next attempt",{default:"0"}).action(async(t,m)=>{try{if(!m.class)throw Error("Pass --class with one of the retry classes shown by ops:show");await yo(async(A)=>{let L=A.retry(t,m.class,{delayMs:Number(m.delay)||0});n(`Retry queued: ${L.id} · attempt ${L.attempt+1}`)})}catch(A){r(A instanceof Error?A.message:String(A))}}),N.command("ops:concurrency","Show effective durable queue concurrency limits").action(async()=>{try{await yo(async(t)=>e(JSON.stringify(t.limits,null,2)))}catch(t){r(t instanceof Error?t.message:String(t))}}),N.command("ops:concurrency:set","Confirm and audit durable queue concurrency limits").option("--project <count>","Concurrent jobs per project").option("--environment <count>","Concurrent jobs per environment").option("--provider <count>","Concurrent jobs per provider").option("--builds <count>","Concurrent build slots").option("--confirm <text>",'Must equal "update queue limits"').action(async(t)=>{try{if(t.confirm!=="update queue limits")throw Error('Pass --confirm "update queue limits" to change production concurrency');let m={};for(let A of["project","environment","provider","builds"])if(t[A]!==void 0)m[A]=Number(t[A]);await yo(async(A,L,j)=>n(`Queue concurrency updated: ${JSON.stringify(A.configureConcurrency(m,{organizationId:j}))}`))}catch(m){r(m instanceof Error?m.message:String(m))}}),N.command("ops:history:clear","Clear terminal jobs after their retention policy expires").option("--before <date>","Also require completion before this timestamp").option("--yes","Skip confirmation").action(async(t)=>{try{await yo(async(m,A)=>{if(!t.yes&&!await d("Clear completed queue history whose retention has elapsed?",!1))return;let L=m.clearCompleted({projectId:A,before:t.before});n(`Cleared ${L} retained operation${L===1?"":"s"}.`)})}catch(m){r(m instanceof Error?m.message:String(m))}})}import{readFile as sg,writeFile as ag}from"node:fs/promises";function cg(N){if(N==null)return"—";if(N<60)return`${N}s`;if(N<3600)return`${Math.floor(N/60)}m`;if(N<86400)return`${Math.floor(N/3600)}h`;return`${Math.floor(N/86400)}d`}function lg(N){return N==null?"—":Xr(N)}function dg(N){return N.map((t)=>[t.id,t.name,t.provider,t.kind,t.status,t.desiredReplicas==null?"—":`${t.runningReplicas??0}/${t.desiredReplicas}`,t.image??t.runtime??"—",lg(t.resources?.memoryBytes??t.resources?.memoryLimitBytes),cg(t.ageSeconds)])}function ug(N,t){let m=t.search?.toLowerCase();return{...N,workloads:N.workloads.filter((A)=>(!t.provider||A.provider===t.provider)&&(!t.status||A.status===t.status)&&(!m||`${A.name} ${A.id} ${A.links.service??""} ${Object.values(A.tags).join(" ")}`.toLowerCase().includes(m)))}}async function vo(N){let t=await Ne(),m=N??Object.keys(t.environments??{})[0]??"production";if(!Object.hasOwn(t.environments??{},m))throw Error(`Environment ${m} was not found`);let A=new ge(t,m);return{config:t,env:m,service:A}}async function ca(N,t){if(t!==void 0)return t;return I(`Type ${N.name} to confirm`,"")}async function pg(N,t,m,A,L,j){return la(N,`runtime.${t}`,{workloadId:N.id,provider:N.provider,action:t,replicas:m??null},L,()=>j.run({workloadId:N.id,action:t,replicas:m,confirm:A,recentAuth:!0}))}async function la(N,t,m,A,L){let j=await Ne(),G=y(process.cwd(),j),Z=new b(G.store,{workerId:`cli:${process.pid}`});try{let ee=G.environments.get(A),ne=G.store.listResources(G.project.id,ee?.id).find((we)=>we.slug===N.links.service),oe=G.store.getActorByExternalId("system","cli")??G.store.createActor({kind:"system",externalId:"cli",displayName:"ts-cloud CLI",metadata:{source:"cli"}}),be=Z.enqueue({projectId:G.project.id,environmentId:ee?.id,resourceId:ne?.id,actorId:oe.id,kind:t,input:h(m),lockKey:ne?`resource:${ne.id}`:`runtime:${N.id}`,providerKey:N.provider,maxAttempts:1,timeoutSeconds:3600,resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;if(!Z.claim(be.id))throw Error(`Workload is locked by another operation. Inspect ${be.id} with cloud ops:show.`);try{let we=await L();if(we.stdout)Z.appendLog(be.id,we.stdout,{stream:"stdout"});if(we.stderr)Z.appendLog(be.id,we.stderr,{stream:"stderr"});if(we.ok)Z.complete(be.id,{ok:!0,command:we.command??null});else Z.fail(be.id,we.error??we.stderr??"Runtime operation failed",{ok:!1});return{result:we,operationId:be.id}}catch(we){throw Z.fail(be.id,we instanceof Error?we.message:String(we),{ok:!1,threw:!0}),we}}finally{G.store.close()}}function al(N){N.command("runtime:list","List services, containers, ECS tasks, and Lambda functions").option("--env <environment>","Target environment").option("--provider <provider>","Filter systemd, docker, ecs, or lambda").option("--status <status>","Filter normalized runtime status").option("--search <query>","Search names, IDs, services, and tags").option("--json","Print normalized JSON").action(async(t)=>{try{let{service:m}=await vo(t.env),A=ug(await m.inventory(),t);if(t.json)e(JSON.stringify(A,null,2));else{c(["ID","Name","Provider","Kind","Status","Replicas","Image / runtime","Memory","Age"],dg(A.workloads));for(let L of A.sources.filter((j)=>j.status!=="fresh"))a(`${L.id}: ${L.status}${L.message?` — ${L.message}`:""}`)}}catch(m){r(m instanceof Error?m.message:String(m)),process.exitCode=1}}),N.command("runtime:inspect <workload>","Inspect normalized config, replicas, networks, mounts, links, and capabilities").option("--env <environment>","Target environment").action(async(t,m)=>{try{let{service:A}=await vo(m.env),L=await A.workload(t);if(!L)throw Error("Workload was not found in this project and environment");e(JSON.stringify(L,null,2))}catch(A){r(A instanceof Error?A.message:String(A)),process.exitCode=1}}),N.command("runtime:logs <workload>","Read bounded logs for one authorized runtime target").option("--env <environment>","Target environment").option("--lines <count>","Maximum log lines",{default:"200"}).option("--json","Print structured JSON").action(async(t,m)=>{try{let{service:A}=await vo(m.env),L=await A.logs(t,{limit:Number(m.lines)||200});if(m.json)e(JSON.stringify(L,null,2));else for(let j of L.lines)console.log(`${j.timestamp??"—"} ${j.message}`)}catch(A){r(A instanceof Error?A.message:String(A)),process.exitCode=1}}),N.command("runtime:action <workload> <action>","Start, stop, restart, redeploy, or scale one workload").option("--env <environment>","Target environment").option("--replicas <count>","Desired replicas for scale").option("--confirm <name>","Exact workload name confirmation").action(async(t,m,A)=>{try{let L=m;if(!["start","stop","restart","redeploy","scale"].includes(L))throw Error("Action must be start, stop, restart, redeploy, or scale");let j=A.replicas==null?void 0:Number(A.replicas);if(L==="scale"&&(!Number.isInteger(j)||j<0))throw Error("Scale requires a non-negative integer --replicas value");let{env:G,service:Z}=await vo(A.env),ee=await Z.inventory(),ne=ee.workloads.find((we)=>we.id===t);if(!ne)throw Error("Workload was not found in this project and environment");let oe=new ge(await Ne(),G,{inventory:async()=>ee}),be=await pg(ne,L,j,await ca(ne,A.confirm),G,oe);if(!be.result.ok)throw Error(be.result.error??be.result.stderr??"Runtime operation failed");if(n(`${L} completed for ${ne.name} · operation ${be.operationId}`),be.result.stdout)e(be.result.stdout)}catch(L){r(L instanceof Error?L.message:String(L)),process.exitCode=1}}),N.command("runtime:exec <workload>","Run a scoped diagnostic preset or container command").option("--env <environment>","Target environment").option("--preset <preset>","Read-only preset: process, sockets, or filesystem").option("--command <command>","Free-form command (Docker containers only)").option("--confirm <name>","Exact workload name confirmation").action(async(t,m)=>{try{let{env:A,service:L}=await vo(m.env),G=(await L.inventory()).workloads.find((oe)=>oe.id===t);if(!G)throw Error("Workload was not found in this project and environment");let Z=["process","sockets","filesystem"].includes(String(m.preset))?m.preset:void 0;if(m.preset&&!Z)throw Error("Preset must be process, sockets, or filesystem");if(!Z&&!m.command)throw Error("Pass --preset or --command");let ee=await ca(G,m.confirm),ne=await la(G,"runtime.exec",{workloadId:t,provider:G.provider,preset:Z??null,freeForm:!!m.command},A,()=>L.exec({workloadId:t,preset:Z,command:m.command,confirm:ee,recentAuth:!0}));if(!ne.result.ok)throw Error(ne.result.error??ne.result.stderr??"Exec failed");if(ne.result.stdout)e(ne.result.stdout);if(ne.result.stderr)a(ne.result.stderr);n(`Exec completed for ${G.name} · operation ${ne.operationId}`)}catch(A){r(A instanceof Error?A.message:String(A)),process.exitCode=1}}),N.command("runtime:download <workload> <remote> <local>","Download a bounded file from a service-owned path").option("--env <environment>","Target environment").option("--confirm <name>","Exact workload name confirmation").action(async(t,m,A,L)=>{try{let{env:j,service:G}=await vo(L.env),ee=(await G.inventory()).workloads.find((be)=>be.id===t);if(!ee)throw Error("Workload was not found in this project and environment");let ne=await ca(ee,L.confirm),oe=await la(ee,"runtime.file.read",{workloadId:t,provider:ee.provider,path:m},j,()=>G.readFile({workloadId:t,path:m,confirm:ne,recentAuth:!0}));if(!oe.result.ok||!oe.result.contentBase64)throw Error(oe.result.error??"File download failed");await ag(A,Buffer.from(oe.result.contentBase64,"base64")),n(`Downloaded ${oe.result.size??0} bytes to ${A} · operation ${oe.operationId}${oe.result.truncated?" (truncated)":""}`)}catch(j){r(j instanceof Error?j.message:String(j)),process.exitCode=1}}),N.command("runtime:upload <workload> <local> <remote>","Upload and atomically replace a file in a service-owned path").option("--env <environment>","Target environment").option("--confirm <name>","Exact workload name confirmation").action(async(t,m,A,L)=>{try{let{env:j,service:G}=await vo(L.env),ee=(await G.inventory()).workloads.find((we)=>we.id===t);if(!ee)throw Error("Workload was not found in this project and environment");let ne=await ca(ee,L.confirm),oe=(await sg(m)).toString("base64"),be=await la(ee,"runtime.file.write",{workloadId:t,provider:ee.provider,path:A,bytes:Buffer.from(oe,"base64").byteLength},j,()=>G.writeFile({workloadId:t,path:A,contentBase64:oe,confirm:ne,recentAuth:!0}));if(!be.result.ok)throw Error(be.result.error??"File upload failed");n(`Uploaded ${be.result.size??0} bytes to ${A} · operation ${be.operationId}`)}catch(j){r(j instanceof Error?j.message:String(j)),process.exitCode=1}})}function mg(N,t=new Date){let m=N.to?new Date(N.to):t;if(!Number.isFinite(m.getTime()))throw Error("--to must be a valid ISO-8601 instant");if(N.from){let j=new Date(N.from);if(!Number.isFinite(j.getTime()))throw Error("--from must be a valid ISO-8601 instant");return{from:j.toISOString(),to:m.toISOString()}}let A=String(N.range??"1h").match(/^(\d+)(m|h|d)$/);if(!A)throw Error("--range must use minutes, hours, or days (for example 30m, 6h, or 7d)");let L=A[2]==="m"?60000:A[2]==="h"?3600000:86400000;return{from:new Date(m.getTime()-Number(A[1])*L).toISOString(),to:m.toISOString()}}async function vs(N){let t=await Ne(),m=N??Object.keys(t.environments??{})[0]??"production";if(!Object.hasOwn(t.environments??{},m))throw Error(`Environment ${m} was not found`);let A=y(process.cwd(),t),L=A.environments.get(m),j=new Ge(A.store);return{config:t,env:m,controlPlane:A,environmentRecord:L,telemetry:j}}function Vd(N,t,m){let A=(j)=>j?.split(",").map((G)=>G.trim()).filter(Boolean)||void 0,L=A(N.kind)?.filter((j)=>["metric","log","trace","request","event"].includes(j));return{projectId:t,environmentId:m,...mg(N),kinds:L,names:A(N.name),sources:A(N.source),text:N.text,limit:Math.min(5000,Math.max(1,Number(N.limit)||200))}}function fg(N){let t=["timestamp","kind","source","name","level","value","unit","message","traceId","requestId","deploymentId","releaseId","workloadId"];return[t.join(","),...N.map((m)=>t.map((A)=>`"${String(m[A]??"").replaceAll('"','""')}"`).join(","))].join(`
|
|
655
|
-
`)}function cl(N){N.command("telemetry:collect","Collect normalized host/runtime or AWS telemetry into the local control plane").option("--env <environment>","Target environment").option("--force","Bypass the provider-query cache").option("--json","Print structured JSON").action(async(t)=>{let m=await vs(t.env);try{let A=await jn({controlPlane:m.controlPlane.store,projectId:m.controlPlane.project.id,environmentId:m.environmentRecord?.id,config:m.config,environment:m.env,force:t.force});if(t.json)e(JSON.stringify(A,null,2));else n(`Collected ${A.collected} normalized records${A.cached?" (cached provider result)":""}.`),c(["Source","Freshness","Lag","Sampling","Retention"],A.statuses.map((L)=>[L.source,L.freshness,L.lagSeconds==null?"—":`${L.lagSeconds}s`,`${Math.round(L.samplingRate*100)}%`,`${L.retentionDays}d`]))}finally{m.controlPlane.store.close()}}),N.command("telemetry:query","Query bounded normalized metrics, logs, traces, requests, and events").option("--env <environment>","Target environment").option("--from <instant>","ISO-8601 start").option("--to <instant>","ISO-8601 end").option("--range <duration>","Relative window such as 1h or 7d",{default:"1h"}).option("--kind <kinds>","Comma-separated kinds").option("--name <names>","Comma-separated signal names").option("--source <sources>","Comma-separated sources").option("--text <query>","Search name/message").option("--limit <count>","Maximum records",{default:"200"}).option("--json","Print structured JSON").action(async(t)=>{let m=await vs(t.env);try{let A=m.telemetry.query(Vd(t,m.controlPlane.project.id,m.environmentRecord?.id));if(t.json)e(JSON.stringify(A,null,2));else c(["Time","Kind","Source","Signal","Value / message","Correlation"],A.records.map((L)=>[L.timestamp,L.kind,L.source,L.name,L.message??(L.value==null?"—":`${L.value} ${L.unit??""}`),L.requestId??L.traceId??L.releaseId??L.deploymentId??"—"]));if(A.truncated)a("More records are available; narrow the window or use the dashboard cursor explorer.")}finally{m.controlPlane.store.close()}}),N.command("telemetry:export <file>","Export a bounded telemetry query as JSON or CSV").option("--env <environment>","Target environment").option("--from <instant>","ISO-8601 start").option("--to <instant>","ISO-8601 end").option("--range <duration>","Relative window",{default:"1h"}).option("--kind <kinds>","Comma-separated kinds").option("--name <names>","Comma-separated signal names").option("--source <sources>","Comma-separated sources").option("--text <query>","Search name/message").option("--limit <count>","Maximum records",{default:"5000"}).action(async(t,m)=>{let A=await vs(m.env);try{let L=Vd(m,A.controlPlane.project.id,A.environmentRecord?.id),j=A.telemetry.query(L);await Bun.write(t,t.toLowerCase().endsWith(".csv")?fg(j.records):JSON.stringify({exportedAt:new Date().toISOString(),query:L,...j},null,2)),n(`Exported ${j.records.length} records to ${t}${j.truncated?" (bounded result)":""}.`)}finally{A.controlPlane.store.close()}}),N.command("telemetry:compact","Downsample old metrics and enforce configured retention").option("--env <environment>","Target environment").action(async(t)=>{let m=await vs(t.env);try{let A=We(m.controlPlane.store,m.controlPlane.project.id);e(JSON.stringify(m.telemetry.enforceRetention(A,m.controlPlane.project.id),null,2))}finally{m.controlPlane.store.close()}}),N.command("telemetry:policy","Show or update sampling, retention, and local storage cost assumptions").option("--env <environment>","Target environment").option("--raw-days <days>","Raw retention days").option("--downsample-days <days>","Downsample after days").option("--sampling <rate>","Sampling rate from 0.01 to 1").option("--storage-usd-gb-month <amount>","Local storage cost assumption").option("--json","Print structured JSON").action(async(t)=>{let m=await vs(t.env);try{let A={};if(t.rawDays!=null)A.rawDays=Number(t.rawDays);if(t.downsampleDays!=null)A.downsampleAfterDays=Number(t.downsampleDays);if(t.sampling!=null)A.samplingRate=Number(t.sampling);if(t.storageUsdGbMonth!=null)A.estimatedStorageUsdPerGbMonth=Number(t.storageUsdGbMonth);let L=Object.keys(A).length?Xn(m.controlPlane.store,m.controlPlane.project.id,A):We(m.controlPlane.store,m.controlPlane.project.id),G=m.telemetry.status(m.controlPlane.project.id,m.environmentRecord?.id,L.rawDays,L.samplingRate).reduce((ee,ne)=>ee+ne.estimatedDailyBytes*30,0),Z={policy:L,estimatedMonthlyBytes:G,estimatedMonthlyCostUsd:Qn(G,L),costEstimateConfigured:L.estimatedStorageUsdPerGbMonth>0};if(t.json)e(JSON.stringify(Z,null,2));else e(JSON.stringify(L,null,2)),e(Z.costEstimateConfigured?`Estimated local storage: $${Z.estimatedMonthlyCostUsd}/month`:"Storage cost remains unavailable until --storage-usd-gb-month is set.")}finally{m.controlPlane.store.close()}})}async function co(N){let t=await Ne(),m=N??Object.keys(t.environments??{})[0]??"production";if(!Object.hasOwn(t.environments??{},m))throw Error(`Environment ${m} was not found`);let A=y(process.cwd(),t),L=A.environments.get(m),j=new pt(A.store,{encryptionKey:k(process.cwd())});return{config:t,env:m,controlPlane:A,environmentRecord:L,alerts:j}}function Wd(N){return new dr(N,{emailImpl:async(t)=>{let{email:m}=await import("./chunk-3ay4kfaw.js");return m.send(t)}})}function ll(N){N.command("health:list","List configured health checks and latest results").option("--env <environment>","Target environment").option("--json","Print structured JSON").action(async(t)=>{let m=await co(t.env);try{let A=m.alerts.listHealthChecks(m.controlPlane.project.id,m.environmentRecord?.id).map((L)=>({...L,latest:m.alerts.listHealthResults(L.id,1)[0]}));if(t.json)e(JSON.stringify(A,null,2));else c(["ID","Name","Kind","Target","Status","Interval","Enabled"],A.map((L)=>[L.id,L.name,L.kind,L.target,L.latest?.status??"no data",`${L.intervalSeconds}s`,L.enabled?"yes":"no"]))}finally{m.controlPlane.store.close()}}),N.command("health:run <check>","Run one health check and evaluate linked alert rules").option("--env <environment>","Target environment").option("--test","Preview without persisting results or incidents").action(async(t,m)=>{let A=await co(m.env);try{let L=A.alerts.getHealthCheck(t)??A.alerts.listHealthChecks(A.controlPlane.project.id,A.environmentRecord?.id).find((Z)=>Z.name===t);if(!L)throw Error("Health check was not found");let j=new Oe(A.alerts);if(m.test){let Z=await j.probe(L);e(JSON.stringify({...Z,productionIncidentCreated:!1},null,2));return}let G=await j.runAndEvaluate(L);if(e(JSON.stringify(G,null,2)),G.result.status==="healthy")n(`${L.name} is healthy.`);else a(`${L.name} is ${G.result.status}.`)}finally{A.controlPlane.store.close()}}),N.command("alerts:list","List pending, firing, silenced, and resolved alerts").option("--env <environment>","Target environment").option("--state <states>","Comma-separated states").option("--json","Print structured JSON").action(async(t)=>{let m=await co(t.env);try{let A=m.alerts.listAlerts(m.controlPlane.project.id,{environmentId:m.environmentRecord?.id,states:t.state?.split(",").filter(Boolean)});if(t.json)e(JSON.stringify(A,null,2));else c(["ID","State","Severity","Title","Owner","First seen","Last seen"],A.map((L)=>[L.id,L.state,L.severity,L.title,L.ownerActorId??"unassigned",L.firstSeenAt,L.lastSeenAt]))}finally{m.controlPlane.store.close()}}),N.command("alerts:evaluate","Evaluate persisted telemetry rules now").option("--env <environment>","Target environment").action(async(t)=>{let m=await co(t.env);try{let A=Wr(m.alerts,m.controlPlane.project.id,m.environmentRecord?.id);e(JSON.stringify(A,null,2))}finally{m.controlPlane.store.close()}}),N.command("alerts:ack <alert>","Acknowledge an alert as the CLI actor").option("--env <environment>","Target environment").action(async(t,m)=>{let A=await co(m.env);try{let L=A.controlPlane.store.getActorByExternalId("system","cli")??A.controlPlane.store.createActor({kind:"system",externalId:"cli",displayName:"ts-cloud CLI"});n(`Acknowledged ${A.alerts.acknowledge(t,L.id).title}.`)}finally{A.controlPlane.store.close()}}),N.command("notifications:list","List notification channels, routes, and recent delivery diagnostics").option("--env <environment>","Target environment").option("--json","Print structured JSON").action(async(t)=>{let m=await co(t.env);try{let A={channels:m.alerts.listChannels(m.controlPlane.organization.id),routes:m.alerts.listRoutes(m.controlPlane.organization.id),deliveries:m.alerts.listDeliveries({limit:100})};if(t.json)e(JSON.stringify(A,null,2));else c(["Channel","Type","Status","Tested","Error"],A.channels.map((L)=>[L.name,L.kind,L.status,L.lastTestedAt??"never",L.lastError??"—"])),c(["Event","State","Attempts","Status","Error"],A.deliveries.map((L)=>[L.eventType,L.state,`${L.attempt}/${L.maxAttempts}`,String(L.responseStatus??"—"),L.error??"—"]))}finally{m.controlPlane.store.close()}}),N.command("notifications:test <channel>","Send a channel test without creating a production incident").option("--env <environment>","Target environment").action(async(t,m)=>{let A=await co(m.env);try{let L=A.alerts.getChannel(t)??A.alerts.listChannels(A.controlPlane.organization.id).find((G)=>G.name===t);if(!L)throw Error("Notification channel was not found");let j=await Wd(A.alerts).testChannel(L.id);if(j.ok)n("Test delivered; no production incident was created.");else throw Error(j.error)}finally{A.controlPlane.store.close()}}),N.command("notifications:retry <delivery>","Retry one failed notification delivery").option("--env <environment>","Target environment").action(async(t,m)=>{let A=await co(m.env);try{let L=A.alerts.getDelivery(t);if(!L)throw Error("Notification delivery was not found");A.alerts.updateDelivery(t,{state:"retrying",attempt:Math.max(0,L.attempt-1),nextAttemptAt:new Date().toISOString()}),e(JSON.stringify(await Wd(A.alerts).deliver(t),null,2))}finally{A.controlPlane.store.close()}})}async function gg(N,t){let m=await Ne(),A=y(process.cwd(),m),L=!N&&t?new $r(A.store).get(t):void 0,j=L?.environmentId?A.store.listEnvironments(A.project.id).find((Ce)=>Ce.id===L.environmentId)?.slug:void 0,G=N??j??Object.keys(m.environments??{})[0]??"production";if(!Object.hasOwn(m.environments??{},G))throw A.store.close(),Error(`Environment ${G} was not found`);let Z=A.environments.get(G);if(!Z)throw A.store.close(),Error(`Environment ${G} was not found in the control plane`);let ee=new $r(A.store),ne=new b(A.store,{workerId:`cli:${process.pid}`}),oe=new Mn(ee,{queue:ne}),be=A.store.listResources(A.project.id,Z.id);Or(ee,m,{organization:A.organization,project:A.project,environment:Z,resources:be});let we=A.store.getActorByExternalId("system","cli")??A.store.createActor({kind:"system",externalId:"cli",displayName:"ts-cloud CLI"});return{config:m,env:G,controlPlane:A,environmentRecord:Z,resources:be,store:ee,queue:ne,service:oe,actor:we}}async function mi(N,t,m){let A=await gg(N,m);try{return await t(A)}finally{A.controlPlane.store.close()}}async function Zr(N){try{await N()}catch(t){r(t instanceof Error?t.message:String(t))}}function Lo(N,t){let m=N.store.list(N.controlPlane.project.id,{environmentId:N.environmentRecord.id}),A=N.store.get(t)??m.find((L)=>L.name===t);if(!A||A.environmentId!==N.environmentRecord.id)throw Error(`Scheduled job ${t} was not found in ${N.env}`);return A}function bo(N,t,m,A){N.controlPlane.store.appendEvent({organizationId:N.controlPlane.organization.id,projectId:N.controlPlane.project.id,resourceId:A,actorId:N.actor.id,type:`job.${t}`,payload:m})}function qd(N,t,m){if(N.environmentRecord.kind==="production"&&m!==t)throw Error(`Production ${t} requires --confirm ${t}`)}function hg(N){if(!N)return{};if(!/^(?:secret|ssm|arn|env):\/\//.test(N))throw Error("Payloads must use a secret://, ssm://, arn://, or env:// reference");return{input:N}}function yg(N){return N.map((t)=>[t.id,t.enabled?"enabled":"disabled",t.provider,t.name,t.expression,t.timezone,t.nextRunAt??"—",t.reconciliationStatus])}function dl(N){N.command("jobs:list","List server cron, EventBridge, and recurring control-plane jobs").option("--env <environment>","Target environment").option("--json","Print structured JSON").action(async(t)=>Zr(async()=>mi(t.env,async(m)=>{let A=m.store.list(m.controlPlane.project.id,{environmentId:m.environmentRecord.id});if(t.json)e(JSON.stringify(A,null,2));else c(["ID","State","Provider","Name","Expression","Timezone","Next run","Reconciliation"],yg(A))}))),N.command("jobs:preview <expression>","Preview the next runs without creating production work").option("--timezone <timezone>","IANA timezone",{default:"UTC"}).option("--from <date>","Preview from an ISO timestamp").option("--count <count>","Number of runs",{default:"5"}).action(async(t,m)=>Zr(async()=>{let A=ot(t,m.timezone??"UTC",m.from?new Date(m.from):new Date,Number(m.count)||5);e(JSON.stringify({...A,productionExecutionCreated:!1},null,2))})),N.command("jobs:add <name> <expression>","Create a managed recurring job").option("--env <environment>","Target environment").option("--timezone <timezone>","IANA timezone",{default:"UTC"}).option("--operation <id>","Safe server operation target (scheduler, backup, or worker)").option("--resource <id>","Resource ID or slug").option("--starts-at <date>","Schedule window start").option("--ends-at <date>","Schedule window end").option("--flexible-minutes <count>","Provider flexible window",{default:"0"}).option("--missed <policy>","skip or catch_up",{default:"skip"}).option("--overlap <policy>","allow, forbid, or replace",{default:"forbid"}).option("--attempts <count>","Maximum attempts",{default:"3"}).option("--backoff <seconds>","Retry backoff seconds",{default:"30"}).option("--timeout <seconds>","Execution timeout",{default:"900"}).option("--dead-letter <reference>","Dead-letter ARN or secret reference").option("--payload-ref <reference>","Referenced payload; inline values are forbidden").option("--disabled","Create disabled").action(async(t,m,A)=>Zr(async()=>mi(A.env,async(L)=>{if(!["skip","catch_up"].includes(A.missed??"skip"))throw Error("--missed must be skip or catch_up");if(!["allow","forbid","replace"].includes(A.overlap??"forbid"))throw Error("--overlap must be allow, forbid, or replace");let j=V(L.config),Z={workers:L.store.listWorkers(L.controlPlane.project.id,L.environmentRecord.id).map((Ce)=>({name:Ce.name}))},ee;if(j==="server"){let Ce=kr(L.config,Z).filter((Se)=>!Se.danger&&["scheduler","backup","worker"].includes(Se.group)),De=A.operation?Ce.find((Se)=>Se.id===A.operation):Ce.length===1?Ce[0]:void 0;if(!De)throw Error(`Choose a safe target with --operation. Available: ${Ce.map((Se)=>Se.id).join(", ")||"none"}`);ee={kind:"dashboard_operation",operationId:De.id}}else ee={kind:"serverless_scheduler",action:"run"};let ne=j==="server"?"server":"eventbridge",oe=Ln({provider:ne,expression:m,flexibleMinutes:Number(A.flexibleMinutes)||0,missedRunPolicy:A.missed??"skip",overlapPolicy:A.overlap??"forbid"});if(!oe.supported)throw Error(oe.notes.join(" "));let be=A.resource?L.resources.find((Ce)=>Ce.id===A.resource||Ce.slug===A.resource):void 0;if(A.resource&&!be)throw Error(`Resource ${A.resource} was not found in ${L.env}`);let we=L.store.create({organizationId:L.controlPlane.organization.id,projectId:L.controlPlane.project.id,environmentId:L.environmentRecord.id,resourceId:be?.id,name:t,provider:ne,expression:m,timezone:A.timezone??"UTC",startsAt:A.startsAt,endsAt:A.endsAt,flexibleMinutes:Number(A.flexibleMinutes)||0,target:ee,payloadRefs:hg(A.payloadRef),missedRunPolicy:A.missed??"skip",overlapPolicy:A.overlap??"forbid",retryPolicy:{maxAttempts:Number(A.attempts)||3,backoffSeconds:Number(A.backoff)||30,deadLetterRef:A.deadLetter},timeoutSeconds:Number(A.timeout)||900,enabled:!A.disabled,origin:"managed",ownerActorId:L.actor.id,observedState:{},reconciliationStatus:"pending"});bo(L,"created",{jobId:we.id,provider:we.provider,expression:we.normalizedExpression},we.resourceId),n(`Created ${we.name} (${we.id}); next run ${we.nextRunAt??"outside the active window"}`)}))),N.command("jobs:update <job>","Update a managed job schedule and policies").option("--env <environment>","Target environment").option("--expression <expression>","Cron, preset, or rate expression").option("--timezone <timezone>","IANA timezone").option("--missed <policy>","skip or catch_up").option("--overlap <policy>","allow, forbid, or replace").option("--timeout <seconds>","Execution timeout").action(async(t,m)=>Zr(async()=>mi(m.env,async(A)=>{let L=Lo(A,t);if(L.origin==="config")throw Error("Config-defined schedules must be edited in cloud.config.ts and reconciled");if(m.missed&&!["skip","catch_up"].includes(m.missed))throw Error("--missed must be skip or catch_up");if(m.overlap&&!["allow","forbid","replace"].includes(m.overlap))throw Error("--overlap must be allow, forbid, or replace");let j=A.store.updateSchedule(L.id,{expression:m.expression,timezone:m.timezone,missedRunPolicy:m.missed,overlapPolicy:m.overlap,timeoutSeconds:m.timeout==null?void 0:Number(m.timeout)});bo(A,"updated",{jobId:j.id,expression:j.normalizedExpression,version:j.version},j.resourceId),n(`Updated ${j.name}; next run ${j.nextRunAt??"outside the active window"}`)}))),N.command("jobs:run <job>","Queue a manual run through the durable operation worker").option("--env <environment>","Target environment").action(async(t,m)=>Zr(async()=>mi(m.env,async(A)=>{let L=Lo(A,t),j=A.service.enqueue(L,{trigger:"manual",actorId:A.actor.id});bo(A,"run_queued",{jobId:L.id,executionId:j.id},L.resourceId),n(`Queued execution ${j.id}; inspect it with cloud jobs:history "${L.name}"`)}))),N.command("jobs:dispatch <job>","Dispatch an externally triggered schedule into the durable queue").option("--env <environment>","Target environment").option("--scheduled-for <date>","Provider scheduled timestamp").option("--scheduled","Mark this as a provider schedule trigger").action(async(t,m)=>Zr(async()=>mi(m.env,async(A)=>{let L=Lo(A,t);if(!L.enabled)throw Error(`${L.name} is disabled`);let j=m.scheduledFor?new Date(m.scheduledFor):new Date;if(!m.scheduledFor)j.setUTCSeconds(0,0);let G=j.toISOString(),Z=A.service.enqueue(L,{trigger:m.scheduled?"scheduled":"external",scheduledFor:G,actorId:A.actor.id}),ee=it(L.normalizedExpression,L.timezone,j,1)[0];A.store.markScheduled(L.id,G,ee),n(`Accepted ${L.name} for ${G} as ${Z.id}`)},t)));for(let t of["enable","disable"])N.command(`jobs:${t} <job>`,`${t==="enable"?"Enable":"Disable"} a scheduled job`).option("--env <environment>","Target environment").option("--confirm <text>",`Production ${t} confirmation`).action(async(m,A)=>Zr(async()=>mi(A.env,async(L)=>{let j=Lo(L,m);if(t==="disable")qd(L,t,A.confirm);let G=L.store.setEnabled(j.id,t==="enable");bo(L,t==="enable"?"enabled":"disabled",{jobId:G.id},G.resourceId),n(`${G.name} is ${G.enabled?"enabled":"disabled"}`)})));N.command("jobs:delete <job>","Delete a managed schedule").option("--env <environment>","Target environment").option("--confirm <text>","Must be delete in production").action(async(t,m)=>Zr(async()=>mi(m.env,async(A)=>{let L=Lo(A,t);qd(A,"delete",m.confirm),A.store.remove(L.id),bo(A,"deleted",{jobId:L.id,name:L.name},L.resourceId),n(`Deleted ${L.name}`)}))),N.command("jobs:history <job>","Show execution attempts, output, errors, and redacted logs").option("--env <environment>","Target environment").option("--limit <count>","Maximum executions",{default:"100"}).option("--logs","Print execution logs").option("--json","Print structured JSON").action(async(t,m)=>Zr(async()=>mi(m.env,async(A)=>{let L=Lo(A,t),j=A.store.listExecutions(L.id,Number(m.limit)||100).map((G)=>({...G,logs:m.logs&&G.operationId?A.queue.logs(G.operationId,{limit:500}):[]}));if(m.json)e(JSON.stringify(j,null,2));else if(c(["ID","Status","Trigger","Scheduled for","Attempt","Started","Finished","Error"],j.map((G)=>[G.id,G.status,G.trigger,G.scheduledFor,String(G.attempt),G.startedAt??"—",G.finishedAt??"—",G.error??"—"])),m.logs)for(let G of j)for(let Z of G.logs)e(`${G.id} ${Z.sequence} ${Z.stream.toUpperCase()} ${Z.message}`)}))),N.command("jobs:reconcile","Import declarative schedules and workers without destructive deletion").option("--env <environment>","Target environment").action(async(t)=>Zr(async()=>mi(t.env,async(m)=>{let A=Or(m.store,m.config,{organization:m.controlPlane.organization,project:m.controlPlane.project,environment:m.environmentRecord,resources:m.resources});bo(m,"reconciled",A),n(`Reconciled ${A.jobs} schedules and ${A.workers} workers; retained ${A.drifted} missing definitions as drifted`)}))),N.command("workers:list","List configured systemd, ECS, and Lambda workers").option("--env <environment>","Target environment").option("--json","Print structured JSON").action(async(t)=>Zr(async()=>mi(t.env,async(m)=>{let A=m.store.listWorkers(m.controlPlane.project.id,m.environmentRecord.id);if(t.json)e(JSON.stringify(A,null,2));else c(["ID","Provider","Name","Queue","Processes","Timeout","Restart","Reconciliation"],A.map((L)=>[L.id,L.provider,L.name,L.queue,String(L.processes),`${L.timeoutSeconds}s`,L.restartPolicy,L.reconciliationStatus]))}))),N.command("workers:restart <worker>","Gracefully restart an allowlisted systemd worker").option("--env <environment>","Target environment").option("--confirm <name>","Exact worker name confirmation").action(async(t,m)=>Zr(async()=>mi(m.env,async(A)=>{let L=A.store.listWorkers(A.controlPlane.project.id,A.environmentRecord.id),j=A.store.getWorker(t)??L.find((ee)=>ee.name===t);if(!j||j.environmentId!==A.environmentRecord.id)throw Error(`Worker ${t} was not found in ${A.env}`);if(m.confirm!==j.name)throw Error(`Restart requires --confirm "${j.name}"`);if(j.provider!=="systemd")throw Error(`${j.provider} workers are provider/config managed and do not expose a safe restart adapter`);let G=$n(String(j.target.operationId??""),A.config,{workers:L.map((ee)=>({name:ee.name}))});if(!G||G.danger||G.group!=="worker")throw Error("The allowlisted worker restart operation is unavailable");let Z=await _r(A.config,A.env,G);if(A.store.reconcileWorker(j.id,Z.ok?"in_sync":"unavailable",{...j.observedState,lastRestartAt:new Date().toISOString(),command:Z.command??null,error:Z.error??Z.stderr??null}),bo(A,"worker_restarted",{workerId:j.id,ok:Z.ok},j.resourceId),!Z.ok)throw Error(Z.error??Z.stderr??"Worker restart failed");n(`Restarted ${j.name}`)})))}function ul(N){N.command("tunnel","Start a local tunnel to expose your local server").option("--port <number>","Local port to expose",{default:"3000"}).option("--subdomain <name>","Custom subdomain (if available)").option("--host <hostname>","Local hostname",{default:"localhost"}).option("--server <url>","Tunnel server URL",{default:"localtunnel.dev"}).option("--verbose","Enable verbose logging").action(async(t)=>{i("Local Tunnel");let m=Number.parseInt(t.port);if(e(`Local server: ${t.host}:${m}`),e(`Tunnel server: ${t.server}`),t.subdomain)e(`Requested subdomain: ${t.subdomain}`);let A=new o("Connecting to tunnel server...");A.start();try{let L;try{let ne=await import("localtunnels");L=ne.TunnelClient}catch{A.fail("localtunnels package not found"),e(`
|
|
655
|
+
`)}function cl(N){N.command("telemetry:collect","Collect normalized host/runtime or AWS telemetry into the local control plane").option("--env <environment>","Target environment").option("--force","Bypass the provider-query cache").option("--json","Print structured JSON").action(async(t)=>{let m=await vs(t.env);try{let A=await jn({controlPlane:m.controlPlane.store,projectId:m.controlPlane.project.id,environmentId:m.environmentRecord?.id,config:m.config,environment:m.env,force:t.force});if(t.json)e(JSON.stringify(A,null,2));else n(`Collected ${A.collected} normalized records${A.cached?" (cached provider result)":""}.`),c(["Source","Freshness","Lag","Sampling","Retention"],A.statuses.map((L)=>[L.source,L.freshness,L.lagSeconds==null?"—":`${L.lagSeconds}s`,`${Math.round(L.samplingRate*100)}%`,`${L.retentionDays}d`]))}finally{m.controlPlane.store.close()}}),N.command("telemetry:query","Query bounded normalized metrics, logs, traces, requests, and events").option("--env <environment>","Target environment").option("--from <instant>","ISO-8601 start").option("--to <instant>","ISO-8601 end").option("--range <duration>","Relative window such as 1h or 7d",{default:"1h"}).option("--kind <kinds>","Comma-separated kinds").option("--name <names>","Comma-separated signal names").option("--source <sources>","Comma-separated sources").option("--text <query>","Search name/message").option("--limit <count>","Maximum records",{default:"200"}).option("--json","Print structured JSON").action(async(t)=>{let m=await vs(t.env);try{let A=m.telemetry.query(Vd(t,m.controlPlane.project.id,m.environmentRecord?.id));if(t.json)e(JSON.stringify(A,null,2));else c(["Time","Kind","Source","Signal","Value / message","Correlation"],A.records.map((L)=>[L.timestamp,L.kind,L.source,L.name,L.message??(L.value==null?"—":`${L.value} ${L.unit??""}`),L.requestId??L.traceId??L.releaseId??L.deploymentId??"—"]));if(A.truncated)a("More records are available; narrow the window or use the dashboard cursor explorer.")}finally{m.controlPlane.store.close()}}),N.command("telemetry:export <file>","Export a bounded telemetry query as JSON or CSV").option("--env <environment>","Target environment").option("--from <instant>","ISO-8601 start").option("--to <instant>","ISO-8601 end").option("--range <duration>","Relative window",{default:"1h"}).option("--kind <kinds>","Comma-separated kinds").option("--name <names>","Comma-separated signal names").option("--source <sources>","Comma-separated sources").option("--text <query>","Search name/message").option("--limit <count>","Maximum records",{default:"5000"}).action(async(t,m)=>{let A=await vs(m.env);try{let L=Vd(m,A.controlPlane.project.id,A.environmentRecord?.id),j=A.telemetry.query(L);await Bun.write(t,t.toLowerCase().endsWith(".csv")?fg(j.records):JSON.stringify({exportedAt:new Date().toISOString(),query:L,...j},null,2)),n(`Exported ${j.records.length} records to ${t}${j.truncated?" (bounded result)":""}.`)}finally{A.controlPlane.store.close()}}),N.command("telemetry:compact","Downsample old metrics and enforce configured retention").option("--env <environment>","Target environment").action(async(t)=>{let m=await vs(t.env);try{let A=We(m.controlPlane.store,m.controlPlane.project.id);e(JSON.stringify(m.telemetry.enforceRetention(A,m.controlPlane.project.id),null,2))}finally{m.controlPlane.store.close()}}),N.command("telemetry:policy","Show or update sampling, retention, and local storage cost assumptions").option("--env <environment>","Target environment").option("--raw-days <days>","Raw retention days").option("--downsample-days <days>","Downsample after days").option("--sampling <rate>","Sampling rate from 0.01 to 1").option("--storage-usd-gb-month <amount>","Local storage cost assumption").option("--json","Print structured JSON").action(async(t)=>{let m=await vs(t.env);try{let A={};if(t.rawDays!=null)A.rawDays=Number(t.rawDays);if(t.downsampleDays!=null)A.downsampleAfterDays=Number(t.downsampleDays);if(t.sampling!=null)A.samplingRate=Number(t.sampling);if(t.storageUsdGbMonth!=null)A.estimatedStorageUsdPerGbMonth=Number(t.storageUsdGbMonth);let L=Object.keys(A).length?Xn(m.controlPlane.store,m.controlPlane.project.id,A):We(m.controlPlane.store,m.controlPlane.project.id),G=m.telemetry.status(m.controlPlane.project.id,m.environmentRecord?.id,L.rawDays,L.samplingRate).reduce((ee,ne)=>ee+ne.estimatedDailyBytes*30,0),Z={policy:L,estimatedMonthlyBytes:G,estimatedMonthlyCostUsd:Qn(G,L),costEstimateConfigured:L.estimatedStorageUsdPerGbMonth>0};if(t.json)e(JSON.stringify(Z,null,2));else e(JSON.stringify(L,null,2)),e(Z.costEstimateConfigured?`Estimated local storage: $${Z.estimatedMonthlyCostUsd}/month`:"Storage cost remains unavailable until --storage-usd-gb-month is set.")}finally{m.controlPlane.store.close()}})}async function co(N){let t=await Ne(),m=N??Object.keys(t.environments??{})[0]??"production";if(!Object.hasOwn(t.environments??{},m))throw Error(`Environment ${m} was not found`);let A=y(process.cwd(),t),L=A.environments.get(m),j=new pt(A.store,{encryptionKey:k(process.cwd())});return{config:t,env:m,controlPlane:A,environmentRecord:L,alerts:j}}function Wd(N){return new dr(N,{emailImpl:async(t)=>{let{email:m}=await import("./chunk-ysv52qcc.js");return m.send(t)}})}function ll(N){N.command("health:list","List configured health checks and latest results").option("--env <environment>","Target environment").option("--json","Print structured JSON").action(async(t)=>{let m=await co(t.env);try{let A=m.alerts.listHealthChecks(m.controlPlane.project.id,m.environmentRecord?.id).map((L)=>({...L,latest:m.alerts.listHealthResults(L.id,1)[0]}));if(t.json)e(JSON.stringify(A,null,2));else c(["ID","Name","Kind","Target","Status","Interval","Enabled"],A.map((L)=>[L.id,L.name,L.kind,L.target,L.latest?.status??"no data",`${L.intervalSeconds}s`,L.enabled?"yes":"no"]))}finally{m.controlPlane.store.close()}}),N.command("health:run <check>","Run one health check and evaluate linked alert rules").option("--env <environment>","Target environment").option("--test","Preview without persisting results or incidents").action(async(t,m)=>{let A=await co(m.env);try{let L=A.alerts.getHealthCheck(t)??A.alerts.listHealthChecks(A.controlPlane.project.id,A.environmentRecord?.id).find((Z)=>Z.name===t);if(!L)throw Error("Health check was not found");let j=new Oe(A.alerts);if(m.test){let Z=await j.probe(L);e(JSON.stringify({...Z,productionIncidentCreated:!1},null,2));return}let G=await j.runAndEvaluate(L);if(e(JSON.stringify(G,null,2)),G.result.status==="healthy")n(`${L.name} is healthy.`);else a(`${L.name} is ${G.result.status}.`)}finally{A.controlPlane.store.close()}}),N.command("alerts:list","List pending, firing, silenced, and resolved alerts").option("--env <environment>","Target environment").option("--state <states>","Comma-separated states").option("--json","Print structured JSON").action(async(t)=>{let m=await co(t.env);try{let A=m.alerts.listAlerts(m.controlPlane.project.id,{environmentId:m.environmentRecord?.id,states:t.state?.split(",").filter(Boolean)});if(t.json)e(JSON.stringify(A,null,2));else c(["ID","State","Severity","Title","Owner","First seen","Last seen"],A.map((L)=>[L.id,L.state,L.severity,L.title,L.ownerActorId??"unassigned",L.firstSeenAt,L.lastSeenAt]))}finally{m.controlPlane.store.close()}}),N.command("alerts:evaluate","Evaluate persisted telemetry rules now").option("--env <environment>","Target environment").action(async(t)=>{let m=await co(t.env);try{let A=Wr(m.alerts,m.controlPlane.project.id,m.environmentRecord?.id);e(JSON.stringify(A,null,2))}finally{m.controlPlane.store.close()}}),N.command("alerts:ack <alert>","Acknowledge an alert as the CLI actor").option("--env <environment>","Target environment").action(async(t,m)=>{let A=await co(m.env);try{let L=A.controlPlane.store.getActorByExternalId("system","cli")??A.controlPlane.store.createActor({kind:"system",externalId:"cli",displayName:"ts-cloud CLI"});n(`Acknowledged ${A.alerts.acknowledge(t,L.id).title}.`)}finally{A.controlPlane.store.close()}}),N.command("notifications:list","List notification channels, routes, and recent delivery diagnostics").option("--env <environment>","Target environment").option("--json","Print structured JSON").action(async(t)=>{let m=await co(t.env);try{let A={channels:m.alerts.listChannels(m.controlPlane.organization.id),routes:m.alerts.listRoutes(m.controlPlane.organization.id),deliveries:m.alerts.listDeliveries({limit:100})};if(t.json)e(JSON.stringify(A,null,2));else c(["Channel","Type","Status","Tested","Error"],A.channels.map((L)=>[L.name,L.kind,L.status,L.lastTestedAt??"never",L.lastError??"—"])),c(["Event","State","Attempts","Status","Error"],A.deliveries.map((L)=>[L.eventType,L.state,`${L.attempt}/${L.maxAttempts}`,String(L.responseStatus??"—"),L.error??"—"]))}finally{m.controlPlane.store.close()}}),N.command("notifications:test <channel>","Send a channel test without creating a production incident").option("--env <environment>","Target environment").action(async(t,m)=>{let A=await co(m.env);try{let L=A.alerts.getChannel(t)??A.alerts.listChannels(A.controlPlane.organization.id).find((G)=>G.name===t);if(!L)throw Error("Notification channel was not found");let j=await Wd(A.alerts).testChannel(L.id);if(j.ok)n("Test delivered; no production incident was created.");else throw Error(j.error)}finally{A.controlPlane.store.close()}}),N.command("notifications:retry <delivery>","Retry one failed notification delivery").option("--env <environment>","Target environment").action(async(t,m)=>{let A=await co(m.env);try{let L=A.alerts.getDelivery(t);if(!L)throw Error("Notification delivery was not found");A.alerts.updateDelivery(t,{state:"retrying",attempt:Math.max(0,L.attempt-1),nextAttemptAt:new Date().toISOString()}),e(JSON.stringify(await Wd(A.alerts).deliver(t),null,2))}finally{A.controlPlane.store.close()}})}async function gg(N,t){let m=await Ne(),A=y(process.cwd(),m),L=!N&&t?new $r(A.store).get(t):void 0,j=L?.environmentId?A.store.listEnvironments(A.project.id).find((Ce)=>Ce.id===L.environmentId)?.slug:void 0,G=N??j??Object.keys(m.environments??{})[0]??"production";if(!Object.hasOwn(m.environments??{},G))throw A.store.close(),Error(`Environment ${G} was not found`);let Z=A.environments.get(G);if(!Z)throw A.store.close(),Error(`Environment ${G} was not found in the control plane`);let ee=new $r(A.store),ne=new b(A.store,{workerId:`cli:${process.pid}`}),oe=new Mn(ee,{queue:ne}),be=A.store.listResources(A.project.id,Z.id);Or(ee,m,{organization:A.organization,project:A.project,environment:Z,resources:be});let we=A.store.getActorByExternalId("system","cli")??A.store.createActor({kind:"system",externalId:"cli",displayName:"ts-cloud CLI"});return{config:m,env:G,controlPlane:A,environmentRecord:Z,resources:be,store:ee,queue:ne,service:oe,actor:we}}async function mi(N,t,m){let A=await gg(N,m);try{return await t(A)}finally{A.controlPlane.store.close()}}async function Zr(N){try{await N()}catch(t){r(t instanceof Error?t.message:String(t))}}function Lo(N,t){let m=N.store.list(N.controlPlane.project.id,{environmentId:N.environmentRecord.id}),A=N.store.get(t)??m.find((L)=>L.name===t);if(!A||A.environmentId!==N.environmentRecord.id)throw Error(`Scheduled job ${t} was not found in ${N.env}`);return A}function bo(N,t,m,A){N.controlPlane.store.appendEvent({organizationId:N.controlPlane.organization.id,projectId:N.controlPlane.project.id,resourceId:A,actorId:N.actor.id,type:`job.${t}`,payload:m})}function qd(N,t,m){if(N.environmentRecord.kind==="production"&&m!==t)throw Error(`Production ${t} requires --confirm ${t}`)}function hg(N){if(!N)return{};if(!/^(?:secret|ssm|arn|env):\/\//.test(N))throw Error("Payloads must use a secret://, ssm://, arn://, or env:// reference");return{input:N}}function yg(N){return N.map((t)=>[t.id,t.enabled?"enabled":"disabled",t.provider,t.name,t.expression,t.timezone,t.nextRunAt??"—",t.reconciliationStatus])}function dl(N){N.command("jobs:list","List server cron, EventBridge, and recurring control-plane jobs").option("--env <environment>","Target environment").option("--json","Print structured JSON").action(async(t)=>Zr(async()=>mi(t.env,async(m)=>{let A=m.store.list(m.controlPlane.project.id,{environmentId:m.environmentRecord.id});if(t.json)e(JSON.stringify(A,null,2));else c(["ID","State","Provider","Name","Expression","Timezone","Next run","Reconciliation"],yg(A))}))),N.command("jobs:preview <expression>","Preview the next runs without creating production work").option("--timezone <timezone>","IANA timezone",{default:"UTC"}).option("--from <date>","Preview from an ISO timestamp").option("--count <count>","Number of runs",{default:"5"}).action(async(t,m)=>Zr(async()=>{let A=ot(t,m.timezone??"UTC",m.from?new Date(m.from):new Date,Number(m.count)||5);e(JSON.stringify({...A,productionExecutionCreated:!1},null,2))})),N.command("jobs:add <name> <expression>","Create a managed recurring job").option("--env <environment>","Target environment").option("--timezone <timezone>","IANA timezone",{default:"UTC"}).option("--operation <id>","Safe server operation target (scheduler, backup, or worker)").option("--resource <id>","Resource ID or slug").option("--starts-at <date>","Schedule window start").option("--ends-at <date>","Schedule window end").option("--flexible-minutes <count>","Provider flexible window",{default:"0"}).option("--missed <policy>","skip or catch_up",{default:"skip"}).option("--overlap <policy>","allow, forbid, or replace",{default:"forbid"}).option("--attempts <count>","Maximum attempts",{default:"3"}).option("--backoff <seconds>","Retry backoff seconds",{default:"30"}).option("--timeout <seconds>","Execution timeout",{default:"900"}).option("--dead-letter <reference>","Dead-letter ARN or secret reference").option("--payload-ref <reference>","Referenced payload; inline values are forbidden").option("--disabled","Create disabled").action(async(t,m,A)=>Zr(async()=>mi(A.env,async(L)=>{if(!["skip","catch_up"].includes(A.missed??"skip"))throw Error("--missed must be skip or catch_up");if(!["allow","forbid","replace"].includes(A.overlap??"forbid"))throw Error("--overlap must be allow, forbid, or replace");let j=V(L.config),Z={workers:L.store.listWorkers(L.controlPlane.project.id,L.environmentRecord.id).map((Ce)=>({name:Ce.name}))},ee;if(j==="server"){let Ce=kr(L.config,Z).filter((Se)=>!Se.danger&&["scheduler","backup","worker"].includes(Se.group)),De=A.operation?Ce.find((Se)=>Se.id===A.operation):Ce.length===1?Ce[0]:void 0;if(!De)throw Error(`Choose a safe target with --operation. Available: ${Ce.map((Se)=>Se.id).join(", ")||"none"}`);ee={kind:"dashboard_operation",operationId:De.id}}else ee={kind:"serverless_scheduler",action:"run"};let ne=j==="server"?"server":"eventbridge",oe=Ln({provider:ne,expression:m,flexibleMinutes:Number(A.flexibleMinutes)||0,missedRunPolicy:A.missed??"skip",overlapPolicy:A.overlap??"forbid"});if(!oe.supported)throw Error(oe.notes.join(" "));let be=A.resource?L.resources.find((Ce)=>Ce.id===A.resource||Ce.slug===A.resource):void 0;if(A.resource&&!be)throw Error(`Resource ${A.resource} was not found in ${L.env}`);let we=L.store.create({organizationId:L.controlPlane.organization.id,projectId:L.controlPlane.project.id,environmentId:L.environmentRecord.id,resourceId:be?.id,name:t,provider:ne,expression:m,timezone:A.timezone??"UTC",startsAt:A.startsAt,endsAt:A.endsAt,flexibleMinutes:Number(A.flexibleMinutes)||0,target:ee,payloadRefs:hg(A.payloadRef),missedRunPolicy:A.missed??"skip",overlapPolicy:A.overlap??"forbid",retryPolicy:{maxAttempts:Number(A.attempts)||3,backoffSeconds:Number(A.backoff)||30,deadLetterRef:A.deadLetter},timeoutSeconds:Number(A.timeout)||900,enabled:!A.disabled,origin:"managed",ownerActorId:L.actor.id,observedState:{},reconciliationStatus:"pending"});bo(L,"created",{jobId:we.id,provider:we.provider,expression:we.normalizedExpression},we.resourceId),n(`Created ${we.name} (${we.id}); next run ${we.nextRunAt??"outside the active window"}`)}))),N.command("jobs:update <job>","Update a managed job schedule and policies").option("--env <environment>","Target environment").option("--expression <expression>","Cron, preset, or rate expression").option("--timezone <timezone>","IANA timezone").option("--missed <policy>","skip or catch_up").option("--overlap <policy>","allow, forbid, or replace").option("--timeout <seconds>","Execution timeout").action(async(t,m)=>Zr(async()=>mi(m.env,async(A)=>{let L=Lo(A,t);if(L.origin==="config")throw Error("Config-defined schedules must be edited in cloud.config.ts and reconciled");if(m.missed&&!["skip","catch_up"].includes(m.missed))throw Error("--missed must be skip or catch_up");if(m.overlap&&!["allow","forbid","replace"].includes(m.overlap))throw Error("--overlap must be allow, forbid, or replace");let j=A.store.updateSchedule(L.id,{expression:m.expression,timezone:m.timezone,missedRunPolicy:m.missed,overlapPolicy:m.overlap,timeoutSeconds:m.timeout==null?void 0:Number(m.timeout)});bo(A,"updated",{jobId:j.id,expression:j.normalizedExpression,version:j.version},j.resourceId),n(`Updated ${j.name}; next run ${j.nextRunAt??"outside the active window"}`)}))),N.command("jobs:run <job>","Queue a manual run through the durable operation worker").option("--env <environment>","Target environment").action(async(t,m)=>Zr(async()=>mi(m.env,async(A)=>{let L=Lo(A,t),j=A.service.enqueue(L,{trigger:"manual",actorId:A.actor.id});bo(A,"run_queued",{jobId:L.id,executionId:j.id},L.resourceId),n(`Queued execution ${j.id}; inspect it with cloud jobs:history "${L.name}"`)}))),N.command("jobs:dispatch <job>","Dispatch an externally triggered schedule into the durable queue").option("--env <environment>","Target environment").option("--scheduled-for <date>","Provider scheduled timestamp").option("--scheduled","Mark this as a provider schedule trigger").action(async(t,m)=>Zr(async()=>mi(m.env,async(A)=>{let L=Lo(A,t);if(!L.enabled)throw Error(`${L.name} is disabled`);let j=m.scheduledFor?new Date(m.scheduledFor):new Date;if(!m.scheduledFor)j.setUTCSeconds(0,0);let G=j.toISOString(),Z=A.service.enqueue(L,{trigger:m.scheduled?"scheduled":"external",scheduledFor:G,actorId:A.actor.id}),ee=it(L.normalizedExpression,L.timezone,j,1)[0];A.store.markScheduled(L.id,G,ee),n(`Accepted ${L.name} for ${G} as ${Z.id}`)},t)));for(let t of["enable","disable"])N.command(`jobs:${t} <job>`,`${t==="enable"?"Enable":"Disable"} a scheduled job`).option("--env <environment>","Target environment").option("--confirm <text>",`Production ${t} confirmation`).action(async(m,A)=>Zr(async()=>mi(A.env,async(L)=>{let j=Lo(L,m);if(t==="disable")qd(L,t,A.confirm);let G=L.store.setEnabled(j.id,t==="enable");bo(L,t==="enable"?"enabled":"disabled",{jobId:G.id},G.resourceId),n(`${G.name} is ${G.enabled?"enabled":"disabled"}`)})));N.command("jobs:delete <job>","Delete a managed schedule").option("--env <environment>","Target environment").option("--confirm <text>","Must be delete in production").action(async(t,m)=>Zr(async()=>mi(m.env,async(A)=>{let L=Lo(A,t);qd(A,"delete",m.confirm),A.store.remove(L.id),bo(A,"deleted",{jobId:L.id,name:L.name},L.resourceId),n(`Deleted ${L.name}`)}))),N.command("jobs:history <job>","Show execution attempts, output, errors, and redacted logs").option("--env <environment>","Target environment").option("--limit <count>","Maximum executions",{default:"100"}).option("--logs","Print execution logs").option("--json","Print structured JSON").action(async(t,m)=>Zr(async()=>mi(m.env,async(A)=>{let L=Lo(A,t),j=A.store.listExecutions(L.id,Number(m.limit)||100).map((G)=>({...G,logs:m.logs&&G.operationId?A.queue.logs(G.operationId,{limit:500}):[]}));if(m.json)e(JSON.stringify(j,null,2));else if(c(["ID","Status","Trigger","Scheduled for","Attempt","Started","Finished","Error"],j.map((G)=>[G.id,G.status,G.trigger,G.scheduledFor,String(G.attempt),G.startedAt??"—",G.finishedAt??"—",G.error??"—"])),m.logs)for(let G of j)for(let Z of G.logs)e(`${G.id} ${Z.sequence} ${Z.stream.toUpperCase()} ${Z.message}`)}))),N.command("jobs:reconcile","Import declarative schedules and workers without destructive deletion").option("--env <environment>","Target environment").action(async(t)=>Zr(async()=>mi(t.env,async(m)=>{let A=Or(m.store,m.config,{organization:m.controlPlane.organization,project:m.controlPlane.project,environment:m.environmentRecord,resources:m.resources});bo(m,"reconciled",A),n(`Reconciled ${A.jobs} schedules and ${A.workers} workers; retained ${A.drifted} missing definitions as drifted`)}))),N.command("workers:list","List configured systemd, ECS, and Lambda workers").option("--env <environment>","Target environment").option("--json","Print structured JSON").action(async(t)=>Zr(async()=>mi(t.env,async(m)=>{let A=m.store.listWorkers(m.controlPlane.project.id,m.environmentRecord.id);if(t.json)e(JSON.stringify(A,null,2));else c(["ID","Provider","Name","Queue","Processes","Timeout","Restart","Reconciliation"],A.map((L)=>[L.id,L.provider,L.name,L.queue,String(L.processes),`${L.timeoutSeconds}s`,L.restartPolicy,L.reconciliationStatus]))}))),N.command("workers:restart <worker>","Gracefully restart an allowlisted systemd worker").option("--env <environment>","Target environment").option("--confirm <name>","Exact worker name confirmation").action(async(t,m)=>Zr(async()=>mi(m.env,async(A)=>{let L=A.store.listWorkers(A.controlPlane.project.id,A.environmentRecord.id),j=A.store.getWorker(t)??L.find((ee)=>ee.name===t);if(!j||j.environmentId!==A.environmentRecord.id)throw Error(`Worker ${t} was not found in ${A.env}`);if(m.confirm!==j.name)throw Error(`Restart requires --confirm "${j.name}"`);if(j.provider!=="systemd")throw Error(`${j.provider} workers are provider/config managed and do not expose a safe restart adapter`);let G=$n(String(j.target.operationId??""),A.config,{workers:L.map((ee)=>({name:ee.name}))});if(!G||G.danger||G.group!=="worker")throw Error("The allowlisted worker restart operation is unavailable");let Z=await _r(A.config,A.env,G);if(A.store.reconcileWorker(j.id,Z.ok?"in_sync":"unavailable",{...j.observedState,lastRestartAt:new Date().toISOString(),command:Z.command??null,error:Z.error??Z.stderr??null}),bo(A,"worker_restarted",{workerId:j.id,ok:Z.ok},j.resourceId),!Z.ok)throw Error(Z.error??Z.stderr??"Worker restart failed");n(`Restarted ${j.name}`)})))}function ul(N){N.command("tunnel","Start a local tunnel to expose your local server").option("--port <number>","Local port to expose",{default:"3000"}).option("--subdomain <name>","Custom subdomain (if available)").option("--host <hostname>","Local hostname",{default:"localhost"}).option("--server <url>","Tunnel server URL",{default:"localtunnel.dev"}).option("--verbose","Enable verbose logging").action(async(t)=>{i("Local Tunnel");let m=Number.parseInt(t.port);if(e(`Local server: ${t.host}:${m}`),e(`Tunnel server: ${t.server}`),t.subdomain)e(`Requested subdomain: ${t.subdomain}`);let A=new o("Connecting to tunnel server...");A.start();try{let L;try{let ne=await import("localtunnels");L=ne.TunnelClient}catch{A.fail("localtunnels package not found"),e(`
|
|
656
656
|
To use tunnels, install the localtunnels package:`),e(" bun add localtunnels"),e(`
|
|
657
657
|
Or use the standalone CLI:`),e(" bunx localtunnels --port 3000");return}let j=t.server.replace(/^(wss?|https?):\/\//,""),G=t.server.startsWith("wss://")||t.server.startsWith("https://")||j==="localtunnel.dev",Z=new L({localPort:m,localHost:t.host,subdomain:t.subdomain,host:j,port:G?443:80,secure:G,verbose:t.verbose});Z.on("connected",(ne)=>{A.succeed("Connected!"),n(`
|
|
658
658
|
Your tunnel URL: ${ne.url}`),e(`Subdomain: ${ne.subdomain}`),e(`
|