@stacksjs/buddy 0.70.39 → 0.70.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +2 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -182,7 +182,7 @@ host:${W}
182
182
  </SelectObjectContentRequest>`;return await this.client.request({service:"s3",region:this.region,method:"POST",path:`/${Q}/${$}`,queryParams:{select:"","select-type":"2"},headers:{"Content-Type":"application/xml"},body:X,rawResponse:!0})}}var J9=p(()=>{d2()});var G9={};f7(G9,{startSmtpServer:()=>vJ,SmtpServer:()=>n2});import*as Y9 from"net";import*as Y2 from"tls";import*as O7 from"fs";import*as V7 from"crypto";class n2{config;ses;s3;server;tlsServer;sessions=new Map;constructor(Q){if(this.config={port:587,tlsPort:465,host:"0.0.0.0",...Q},this.ses=new p2(Q.region||"us-east-1"),Q.sentBucket)this.s3=new r2(Q.region||"us-east-1")}async start(){if(this.server=Y9.createServer((Q)=>{this.handleConnection(Q,!1)}),this.server.listen(this.config.port,this.config.host,()=>{console.log(`SMTP server listening on ${this.config.host}:${this.config.port} (STARTTLS)`)}),this.config.tls?.key&&this.config.tls?.cert){let Q={key:O7.readFileSync(this.config.tls.key),cert:O7.readFileSync(this.config.tls.cert)};this.tlsServer=Y2.createServer(Q,($)=>{this.handleConnection($,!0)}),this.tlsServer.listen(this.config.tlsPort,this.config.host,()=>{console.log(`SMTP server listening on ${this.config.host}:${this.config.tlsPort} (TLS)`)})}}async stop(){if(this.server)this.server.close();if(this.tlsServer)this.tlsServer.close();for(let Q of this.sessions.values())Q.socket.destroy();this.sessions.clear()}handleConnection(Q,$){let J=V7.randomUUID(),Y={id:J,socket:Q,secure:$,state:"greeting",authenticated:!1,rcptTo:[],dataBuffer:"",tlsUpgraded:$};this.sessions.set(J,Y),console.log(`SMTP connection from ${Q.remoteAddress} (session: ${J.slice(0,8)})`),this.send(Y,`220 ${this.config.domain} ESMTP Mail Server`),Y.state="ready";let G="";Q.on("data",async(z)=>{G+=z.toString();let W;while((W=G.indexOf(`\r
183
183
  `))!==-1){let X=G.slice(0,W);if(G=G.slice(W+2),Y.state==="data")await this.handleDataLine(Y,X);else await this.handleCommand(Y,X)}}),Q.on("close",()=>{console.log(`SMTP session ${J.slice(0,8)} closed`),this.sessions.delete(J)}),Q.on("error",(z)=>{console.error(`SMTP session ${J.slice(0,8)} error:`,z.message),this.sessions.delete(J)})}send(Q,$){if(!Q.socket.destroyed)Q.socket.write(`${$}\r
184
184
  `)}async handleCommand(Q,$){let J=$.trim();if(!J)return;let Y=J.split(" ")[0].toUpperCase(),G=J.slice(Y.length).trim();switch(console.log(`SMTP CMD [${Q.username||"anon"}]: ${Y} ${G.includes("AUTH")?"***":G}`),Y){case"EHLO":case"HELO":await this.handleEhlo(Q,G);break;case"STARTTLS":await this.handleStartTls(Q);break;case"AUTH":await this.handleAuth(Q,G);break;case"MAIL":await this.handleMailFrom(Q,G);break;case"RCPT":await this.handleRcptTo(Q,G);break;case"DATA":await this.handleData(Q);break;case"RSET":this.resetSession(Q),this.send(Q,"250 OK");break;case"NOOP":this.send(Q,"250 OK");break;case"QUIT":this.send(Q,`221 ${this.config.domain} closing connection`),Q.socket.end();break;default:this.send(Q,"500 Unrecognized command")}}async handleEhlo(Q,$){let J=[`250-${this.config.domain} Hello ${$}`,"250-SIZE 26214400","250-8BITMIME","250-PIPELINING"];if(!Q.secure&&this.config.tls?.key)J.push("250-STARTTLS");J.push("250-AUTH PLAIN LOGIN"),J.push("250 OK");for(let Y of J)this.send(Q,Y)}async handleStartTls(Q){if(Q.secure||Q.tlsUpgraded){this.send(Q,"503 TLS already active");return}if(!this.config.tls?.key||!this.config.tls?.cert){this.send(Q,"454 TLS not available");return}this.send(Q,"220 Ready to start TLS");let $={key:O7.readFileSync(this.config.tls.key),cert:O7.readFileSync(this.config.tls.cert),isServer:!0},J=new Y2.TLSSocket(Q.socket,$);Q.socket=J,Q.secure=!0,Q.tlsUpgraded=!0,this.resetSession(Q)}async handleAuth(Q,$){let J=$.split(" "),Y=J[0].toUpperCase();if(Y==="PLAIN")if(J[1])await this.handleAuthPlain(Q,J[1]);else this.send(Q,"334 "),Q.state="ready";else if(Y==="LOGIN"){this.send(Q,"334 VXNlcm5hbWU6");let G=Q.socket.listeners("data")[0];Q.socket.removeAllListeners("data");let z="username",W="";Q.socket.on("data",async(X)=>{try{let H=X.toString().trim();if(z==="username")W=Buffer.from(H,"base64").toString("utf-8"),z="password",this.send(Q,"334 UGFzc3dvcmQ6");else if(z==="password"){let q=Buffer.from(H,"base64").toString("utf-8");Q.socket.removeAllListeners("data"),Q.socket.on("data",G),await this.authenticateUser(Q,W,q)}}catch(H){Q.socket.removeAllListeners("data"),Q.socket.on("data",G),this.send(Q,"535 Authentication failed"),console.error(`SMTP AUTH LOGIN error: ${H.message}`)}})}else this.send(Q,"504 Unrecognized authentication mechanism")}async handleAuthPlain(Q,$){try{let Y=Buffer.from($,"base64").toString("utf-8").split("\x00"),G=Y.length===3?Y[1]:Y[0],z=Y.length===3?Y[2]:Y[1];await this.authenticateUser(Q,G,z)}catch(J){this.send(Q,"535 Authentication failed")}}async authenticateUser(Q,$,J){let Y=$.includes("@")?$.split("@")[0]:$,G=this.config.users[Y],z=G?(()=>{try{let W=Buffer.from(G.password,"utf-8"),X=Buffer.from(J,"utf-8");if(W.length!==X.length){let H=Math.max(W.length,X.length),q=Buffer.alloc(H),Z=Buffer.alloc(H);return q.set(W),Z.set(X),V7.timingSafeEqual(q,Z),!1}return V7.timingSafeEqual(W,X)}catch{return!1}})():!1;if(G&&z)Q.authenticated=!0,Q.username=Y,Q.email=G.email,this.send(Q,"235 Authentication successful"),console.log(`SMTP AUTH success: ${Y}`);else this.send(Q,"535 Authentication failed"),console.log(`SMTP AUTH failed: ${$}`)}async handleMailFrom(Q,$){if(!Q.authenticated){this.send(Q,"530 Authentication required");return}let J=$.match(/FROM:\s*<([^>]*)>/i);if(!J){this.send(Q,"501 Syntax error in MAIL FROM");return}let Y=J[1];if(!Y.endsWith(`@${this.config.domain}`)){this.send(Q,`553 Sender address must be from @${this.config.domain}`);return}Q.mailFrom=Y,Q.state="mail",this.send(Q,"250 OK")}async handleRcptTo(Q,$){if(!Q.authenticated){this.send(Q,"530 Authentication required");return}if(!Q.mailFrom){this.send(Q,"503 MAIL FROM required first");return}let J=$.match(/TO:\s*<([^>]*)>/i);if(!J){this.send(Q,"501 Syntax error in RCPT TO");return}Q.rcptTo.push(J[1]),Q.state="rcpt",this.send(Q,"250 OK")}async handleData(Q){if(!Q.authenticated){this.send(Q,"530 Authentication required");return}if(Q.rcptTo.length===0){this.send(Q,"503 RCPT TO required first");return}Q.state="data",Q.dataBuffer="",this.send(Q,"354 Start mail input; end with <CRLF>.<CRLF>")}async handleDataLine(Q,$){if($===".")await this.sendEmail(Q);else{let J=$.startsWith(".")?$.slice(1):$;Q.dataBuffer+=`${J}\r
185
- `}}async sendEmail(Q){try{let $=Q.dataBuffer,J=await this.ses.sendRawEmail({source:Q.mailFrom,destinations:Q.rcptTo,rawMessage:$});if(console.log(`SMTP: Email sent via SES, MessageId: ${J.MessageId}`),this.s3&&this.config.sentBucket)try{let Y=`${this.config.sentPrefix||"sent/"}${Q.email}/${Date.now()}-${J.MessageId}`;await this.s3.putObject({bucket:this.config.sentBucket,key:Y,body:$,contentType:"message/rfc822"}),console.log(`SMTP: Email stored in S3: ${Y}`)}catch(Y){console.error("SMTP: Failed to store sent email in S3 (email was sent successfully):",Y.message)}this.send(Q,`250 OK Message accepted, ID: ${J.MessageId}`),this.resetSession(Q)}catch($){console.error("SMTP: Failed to send email:",$.message),this.send(Q,`451 Failed to send: ${$.message}`),this.resetSession(Q)}}resetSession(Q){Q.state="ready",Q.mailFrom=void 0,Q.rcptTo=[],Q.dataBuffer=""}}async function vJ(Q){let $=new n2(Q);return await $.start(),$}var z9=p(()=>{$9();J9()});import k0 from"process";import{bold as v7,dim as x0,green as G8,intro as z8,log as e,onUnknownSubcommand as W8}from"@stacksjs/cli";import{storage as w3}from"@stacksjs/storage";function _G(Q){Q.command("about","Display diagnostic information about Stacks").action(async()=>{e.debug("Running `buddy about` ..."),await z8("buddy about");try{let J=(await w3.readPackageJson("./package.json")).version||"unknown",Y=k0.versions.bun||"N/A",G=k0.versions.node||"N/A",z=k0.platform,W=k0.arch,X=k0.version,H=k0.env.NODE_ENV||k0.env.APP_ENV||"development";if(e.info(""),e.info(G8(v7("Stacks Framework"))),e.info(x0("\u2500".repeat(50))),e.info(""),e.info(v7("Version Information:")),e.info(` Stacks: ${x0(J)}`),e.info(` Bun: ${x0(Y)}`),G!=="N/A")e.info(` Node: ${x0(G)}`);e.info(""),e.info(v7("Environment:")),e.info(` Mode: ${x0(H)}`),e.info(` OS: ${x0(`${z} ${W}`)}`),e.info(` Runtime: ${x0(X)}`),e.info(""),e.info(v7("Configuration:")),e.info(` Cache: ${x0("file")}`),e.info(` Debug: ${x0(k0.env.DEBUG?"enabled":"disabled")}`),e.info("")}catch($){e.error("Failed to retrieve system information:",$),k0.exit(1)}}),W8(Q,"about")}import n0 from"process";import{runAction as S7}from"@stacksjs/actions";import{intro as E7,log as N7,onUnknownSubcommand as X8,outro as a0}from"@stacksjs/cli";import{Action as C7}from"@stacksjs/enums";import{ExitCode as i0}from"@stacksjs/types";function RG(Q){let $={setup:"Set up authentication (migrations + personal access client)",token:"Create a personal access client token",client:"Create a new OAuth client",prune:"Prune expired and revoked tokens",project:"Target a specific project",verbose:"Enable verbose output"};Q.command("auth:setup",$.setup).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{N7.debug("Running `buddy auth:setup` ...",J);let Y=await E7("buddy auth:setup"),G=await S7(C7.AuthSetup,J);if(G.isErr)await a0("While setting up authentication, there was an issue",{startTime:Y,useSeconds:!0},G.error),n0.exit(i0.FatalError);await a0("Authentication setup completed successfully.",{startTime:Y,useSeconds:!0}),n0.exit(i0.Success)}),Q.command("auth:token",$.token).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{N7.debug("Running `buddy auth:token` ...",J);let Y=await E7("buddy auth:token"),G=await S7(C7.CreatePersonalAccessClient,J);if(G.isErr)await a0("While creating the personal access client token, there was an issue",{startTime:Y,useSeconds:!0},G.error),n0.exit(i0.FatalError);await a0("Personal access client token created successfully.",{startTime:Y,useSeconds:!0}),n0.exit(i0.Success)}),Q.command("auth:client",$.client).option("-n, --name [name]","Client name",{default:"OAuth Client"}).option("-r, --redirect [redirect]","Redirect URI",{default:"http://localhost"}).option("--personal","Create a personal access client",{default:!1}).option("--password","Create a password grant client",{default:!1}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{N7.debug("Running `buddy auth:client` ...",J);let Y=await E7("buddy auth:client"),G=await S7(C7.AuthClient,J);if(G.isErr)await a0("While creating the OAuth client, there was an issue",{startTime:Y,useSeconds:!0},G.error),n0.exit(i0.FatalError);await a0("OAuth client created successfully.",{startTime:Y,useSeconds:!0}),n0.exit(i0.Success)}),Q.command("auth:prune",$.prune).option("--expired","Prune expired tokens (default: true)",{default:!0}).option("--revoked","Prune revoked tokens (default: true)",{default:!0}).option("-d, --days [days]","Prune revoked tokens older than N days",{default:7}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{N7.debug("Running `buddy auth:prune` ...",J);let Y=await E7("buddy auth:prune"),G=await S7(C7.AuthPrune,J);if(G.isErr)await a0("While pruning tokens, there was an issue",{startTime:Y,useSeconds:!0},G.error),n0.exit(i0.FatalError);await a0("Token pruning completed successfully.",{startTime:Y,useSeconds:!0}),n0.exit(i0.Success)}),X8(Q,"auth")}import l$ from"process";import{intro as Z2,log as I0,onUnknownSubcommand as q8,outro as h7}from"@stacksjs/cli";import{Action as Y0}from"@stacksjs/enums";import{ExitCode as d$}from"@stacksjs/types";var K2;async function G0(...Q){if(!K2)K2=(await import("@stacksjs/actions")).runAction;return K2(...Q)}function AG(Q){let $={build:"Build any of your libraries (packages) for production use",components:"Build your component library",webComponents:"Build your framework agnostic web component library",elements:"An alias to the -w flag",buddy:"Build the Buddy binary",functions:"Build your function library",desktop:"Build the Desktop Application",pages:"Build your frontend",docs:"Build your documentation",framework:"Build Stacks framework",cli:"Automagically build the CLI",server:"Build the Stacks cloud server (Docker image)",select:"What are you trying to build?",project:"Target a specific project",verbose:"Enable verbose output"};Q.command("build [type]",$.build).option("-c, --components",$.components).option("-w, --web-components",$.webComponents).option("-e, --elements",$.elements).option("-f, --functions",$.functions).option("-p, --views",$.pages).option("--pages",$.pages).option("-d, --docs",$.docs).option("-b, --buddy",$.buddy,{default:!1}).option("-s, --stacks",$.framework,{default:!1}).option("--project [project]",$.project,{default:!1}).option("--server",$.server,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J,Y)=>{switch(I0.debug("Running `buddy build` ...",Y),J){case"components":Y.components=!0;break;case"web-components":Y.webComponents=!0;break;case"functions":Y.functions=!0;break;case"views":Y.views=!0;break;case"docs":Y.docs=!0;break;case"buddy":Y.buddy=!0;break;case"cli":Y.buddy=!0;break;case"stacks":Y.stacks=!0;break;case"server":Y.server=!0;break;default:break}if(H8(Y))Y.stacks=!0;if(Y.docs)await G0(Y0.BuildDocs);if(Y.components)await G0(Y0.BuildComponentLibs);if(Y.webComponents)await G0(Y0.BuildWebComponentLib);if(Y.functions)await G0(Y0.BuildFunctionLib);if(Y.views)await G0(Y0.BuildViews);if(Y.stacks)await G0(Y0.BuildStacks);if(Y.buddy)await G0(Y0.BuildCli);if(Y.server)await G0(Y0.BuildServer);l$.exit(d$.Success)}),Q.command("build:components","Automagically build component libraries for production use & npm/CDN distribution").alias("prod:components").option("-c, --components",$.components,{default:!0}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{I0.debug("Running `buddy build:components` ...",J),await G0(Y0.BuildComponentLibs,J)}),Q.command("build:cli",$.cli).alias("prod:cli").option("-b, --buddy",$.buddy,{default:!0}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{I0.debug("Running `buddy build:cli` ...",J),await G0(Y0.BuildCli,J)}),Q.command("build:server",$.server).alias("prod:server").alias("build:docker").option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{I0.debug("Running `buddy build:server` ...",J),await G0(Y0.BuildServer,J)}),Q.command("build:functions","Automagically build function library for npm/CDN distribution").option("-f, --functions",$.functions,{default:!0}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{I0.debug("Running `buddy build:functions` ...",J),await G0(Y0.BuildFunctionLib,J)}),Q.command("build:web-components","Automagically build Web Component library for npm/CDN distribution").alias("build:wc").alias("prod:web-components").alias("prod:wc").option("-w, --web-components",$.webComponents,{default:!0}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{I0.debug("Running `buddy build:web-components` ...",J),await G0(Y0.BuildWebComponentLib,J)}),Q.command("build:docs","Automagically build your documentation site.").alias("prod:docs").alias("build:documentation").alias("prod:documentation").option("-d, --docs",$.docs,{default:!0}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{I0.debug("Running `buddy build:docs` ...",J),await G0(Y0.BuildDocs,J)}),Q.command("build:core","Automagically build the Stacks core.").option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{I0.debug("Running `buddy build:core` ...",J);let Y=await Z2("buddy build:core"),G=await G0(Y0.BuildCore,J);if(G.isErr)I0.error("Failed to build the Stacks core.",G.error),l$.exit(d$.FatalError);await h7("Core packages built successfully",{startTime:Y,useSeconds:!0})}),Q.command("build:desktop",$.desktop).alias("prod:desktop").option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{I0.debug("Running `buddy build:desktop` ...",J);let Y=await Z2("buddy build:desktop"),G=await G0(Y0.BuildDesktop,J);if(G.isErr)await h7("While running the build:desktop command, there was an issue",{startTime:Y,useSeconds:!0},G.error),l$.exit(d$.FatalError);console.log(""),await h7("Exited",{startTime:Y,useSeconds:!0}),l$.exit(d$.Success)}),Q.command("build:stacks","Build the Stacks framework.").option("-s, --stacks",$.framework,{default:!0}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{I0.debug("Running `buddy build:stacks` ...",J);let Y=await Z2("buddy build:stacks"),G=await G0(Y0.BuildStacks,J);if(G.isErr)I0.error("Failed to build Stacks.",G.error),l$.exit(d$.FatalError);await h7("Stacks built successfully",{startTime:Y,useSeconds:!0})}),q8(Q,"build")}function H8(Q){return!Q.components&&!Q.webComponents&&!Q.elements&&!Q.functions&&!Q.views&&!Q.docs&&!Q.stacks&&!Q.buddy&&!Q.server}import Z8 from"process";import{runAction as K8}from"@stacksjs/actions";import{intro as _8,log as U8,onUnknownSubcommand as L8,outro as M3}from"@stacksjs/cli";import{Action as F8}from"@stacksjs/enums";import{ExitCode as O8}from"@stacksjs/types";function CG(Q){let $={changelog:"Create a CHANGELOG.md file",quiet:"Minimal output",dryRun:"Do not write the file, just output the changes",project:"Target a specific project",verbose:"Enable verbose output"};Q.command("changelog",$.changelog).option("-q, --quiet",$.quiet,{default:!1}).option("-d, --dry-run",$.dryRun,{default:!1}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{U8.debug("Running `buddy changelog` ...",J);let Y=await _8("buddy changelog"),G=await K8(F8.Changelog,J);if(G.isErr)await M3("While running the changelog command, there was an issue",{...J,startTime:Y,useSeconds:!0},G.error),Z8.exit(O8.FatalError);await M3("Generated CHANGELOG.md",{...J,startTime:Y,useSeconds:!0,type:"success"})}),L8(Q,"changelog")}import _2 from"process";import{runAction as V8}from"@stacksjs/actions";import{intro as B8,log as T3,onUnknownSubcommand as R8,outro as I3}from"@stacksjs/cli";import{Action as w8}from"@stacksjs/enums";import{ExitCode as U2}from"@stacksjs/types";function gG(Q){let $={clean:"Removes all node_modules & lock files",project:"Target a specific project",verbose:"Enable verbose output"};Q.command("clean",$.clean).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{if(T3.debug("Running `buddy clean` ...",J),!Q.isForce&&!Q.isNoInteraction){let{confirm:z}=await import("@stacksjs/cli");if(!await z({message:"This will remove all node_modules and lock files. Continue?",initial:!1}))T3.info("Clean cancelled"),_2.exit(U2.Success)}let Y=await B8("buddy clean"),G=await V8(w8.Clean,J);if(G.isErr)await I3("While running the clean command, there was an issue",{startTime:Y,useSeconds:!0},G.error),_2.exit(U2.FatalError);await I3("Cleaned up",{startTime:Y,useSeconds:!0,message:"Cleaned up"}),_2.exit(U2.Success)}),R8(Q,"clean")}import b from"process";import{intro as w$,italic as V2,log as y,onUnknownSubcommand as E8,outro as r,prompts as a$,runCommand as S3,underline as E3}from"@stacksjs/cli";import{addJumpBox as N8,deleteCdkRemnants as C8,deleteIamUsers as h8,deleteJumpBox as B2,deleteLogGroups as D8,deleteParameterStore as b8,deleteStacksBuckets as y8,deleteStacksFunctions as k8,deleteSubnets as x8,deleteVpcs as g8,getCloudFrontDistributionId as N3,getJumpBoxInstanceId as u8}from"@stacksjs/cloud";import{path as C3}from"@stacksjs/path";import{ExitCode as l}from"@stacksjs/types";function i$(Q){if(!Q||typeof Q!=="object")return!1;let $=Q;if(typeof $.isErr==="function")return $.isErr();return!!$.isErr}function s$(Q){if(!Q||typeof Q!=="object")return"Unknown error";return String(Q.error||"Unknown error")}function m8(Q){if(!Q||typeof Q!=="object")return;return Q.value}function oG(Q){let $={cloud:"Interact with the Stacks Cloud",ssh:"SSH into the Stacks Cloud",add:"Add a resource to the Stacks Cloud",remove:"Remove the Stacks Cloud. In case it fails, try again",optimizeCost:"Remove certain resources that may be re-applied at a later time",cleanUp:"Remove all resources that were retained during the cloud deletion",invalidateCache:"Invalidate the CloudFront cache",diff:"Show the diff of the current, undeployed cloud changes ",paths:"The paths to invalidate",project:"Target a specific project",verbose:"Enable verbose output"};Q.command("cloud",$.cloud).option("--ssh",$.ssh,{default:!1}).option("--connect",$.ssh,{default:!1}).option("--invalidate-cache",$.invalidateCache,{default:!1}).option("--paths [paths]",$.paths).option("--diff",$.diff,{default:!1}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{y.debug("Running `buddy cloud` ...",J);let Y=performance.now();if(J.ssh||J.connect){let G=await u8(),z=await S3(`aws ssm start-session --target ${G}`,{...J,cwd:C3.projectPath(),stdin:"pipe"});if(i$(z))await r("While running the cloud command, there was an issue",{startTime:Y,useSeconds:!0},s$(z)),b.exit(l.FatalError);await r("Exited",{startTime:Y,useSeconds:!0}),b.exit(l.Success)}if(J.invalidateCache){let{confirm:G}=await a$({name:"confirm",type:"confirm",message:"Would you like to invalidate the CDN (CloudFront) cache?"});if(!G)await r("Exited",{startTime:Y,useSeconds:!0}),b.exit(l.Success);y.info("Invalidating the CloudFront cache...");let{AWSCloudFrontClient:z}=await import("@stacksjs/ts-cloud"),W=new z,X=await N3();try{let H=await W.invalidateAll(X);y.success(`Invalidation created: ${H}`),y.info("Status: pending")}catch(H){y.error(`Failed to invalidate CloudFront cache: ${H.message}`)}await r("Exited",{startTime:Y,useSeconds:!0}),b.exit(l.Success)}if(J.diff){try{let{InfrastructureGenerator:G}=await import("@stacksjs/ts-cloud"),{CloudFormationClient:z}=await import("@stacksjs/ts-cloud/aws"),{tsCloud:W}=await Promise.resolve().then(() => (n$(),r$)),X=b.env.APP_ENV||b.env.NODE_ENV||"production",q=new G({config:W,environment:X}).generate().toJSON(),Z=`${W.project?.slug||"stacks"}-${X}`,K=new z(b.env.AWS_REGION||"us-east-1"),_="{}";try{_=(await K.getTemplate(Z)).TemplateBody}catch{y.info("No deployed stack found. Showing full template as diff.")}if(_===q)y.info("No changes detected.");else y.info("Changes detected between deployed and local template:"),y.info(`Current template: ${_.length} bytes`),y.info(`New template: ${q.length} bytes`)}catch(G){y.error(`Failed to compute diff: ${G.message}`)}await r("Cloud diff complete",{startTime:Y,useSeconds:!0}),b.exit(l.Success)}y.info("Not implemented yet. Read more about `buddy cloud` here: https://stacksjs.com/docs/cloud"),b.exit(l.Success)}),Q.command("cloud:add",$.add).option("--jump-box","Remove the jump-box",{default:!1}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{y.debug("Running `buddy cloud:add` ...",J);let Y=await w$("buddy cloud:add");if(J.jumpBox){let{confirm:G}=await a$({name:"confirm",type:"confirm",message:"Would you like to add a jump-box to your cloud?"});if(!G)await r("Exited",{startTime:Y,useSeconds:!0}),b.exit(l.Success);y.info("The jump-box is getting added to your cloud resources..."),y.info("This takes a few moments, please be patient."),await new Promise((W)=>setTimeout(W,2000));let z=await N8();if(i$(z))await r("While running the cloud:add command, there was an issue",{startTime:Y,useSeconds:!0},s$(z)),b.exit(l.FatalError);y.info(V2("View the jump-box in the AWS console:")),y.info(E3("https://us-east-1.console.aws.amazon.com/ec2/home?region=us-east-1#Instances:instanceState=running")),y.info(V2("Once it finished initializing, you may SSH into it:")),y.info(E3("buddy cloud --ssh")),await r("Your jump-box was added.",{startTime:Y,useSeconds:!0}),b.exit(l.Success)}y.info("This functionality is not yet implemented."),b.exit(l.Success)}),Q.command("cloud:remove",$.remove).alias("cloud:destroy").alias("cloud:rm").alias("undeploy").option("--jump-box","Remove the jump-box",{default:!1}).option("--force","Force deletion of stack in bad state",{default:!1}).option("--yes","Skip confirmation prompts",{default:!1}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{y.debug("Running `buddy cloud:remove` ...",J);let Y=await w$("buddy cloud:remove");if(J.jumpBox){let{confirm:z}=await a$({name:"confirm",type:"confirm",message:"Would you like to remove your jump-box for now?"});if(!z)await r("Exited",{startTime:Y,useSeconds:!0}),b.exit(l.Success);let W=await B2();if(i$(W))await r("While removing your jump-box, there was an issue",{startTime:Y,useSeconds:!0},s$(W)),b.exit(l.FatalError);await r("Your jump-box was removed.",{startTime:Y,useSeconds:!0}),b.exit(l.Success)}console.log(""),console.log("Removing cloud infrastructure..."),console.log(` ${V2("This typically takes 2-5 minutes.")}`),console.log("");let G=b.env.APP_ENV||b.env.NODE_ENV||"production";if(!b.env.AWS_ACCESS_KEY_ID||!b.env.AWS_SECRET_ACCESS_KEY){let{existsSync:z,readFileSync:W}=await import("fs"),{projectPath:X}=await import("@stacksjs/path"),H=[X(`.env.${G}`),X(".env")];for(let q of H)if(z(q)){let K=W(q,"utf-8").split(`
185
+ `}}async sendEmail(Q){try{let $=Q.dataBuffer,J=await this.ses.sendRawEmail({source:Q.mailFrom,destinations:Q.rcptTo,rawMessage:$});if(console.log(`SMTP: Email sent via SES, MessageId: ${J.MessageId}`),this.s3&&this.config.sentBucket)try{let Y=`${this.config.sentPrefix||"sent/"}${Q.email}/${Date.now()}-${J.MessageId}`;await this.s3.putObject({bucket:this.config.sentBucket,key:Y,body:$,contentType:"message/rfc822"}),console.log(`SMTP: Email stored in S3: ${Y}`)}catch(Y){console.error("SMTP: Failed to store sent email in S3 (email was sent successfully):",Y.message)}this.send(Q,`250 OK Message accepted, ID: ${J.MessageId}`),this.resetSession(Q)}catch($){console.error("SMTP: Failed to send email:",$.message),this.send(Q,`451 Failed to send: ${$.message}`),this.resetSession(Q)}}resetSession(Q){Q.state="ready",Q.mailFrom=void 0,Q.rcptTo=[],Q.dataBuffer=""}}async function vJ(Q){let $=new n2(Q);return await $.start(),$}var z9=p(()=>{$9();J9()});import k0 from"process";import{bold as v7,dim as x0,green as G8,intro as z8,log as e,onUnknownSubcommand as W8}from"@stacksjs/cli";import{storage as w3}from"@stacksjs/storage";function _G(Q){Q.command("about","Display diagnostic information about Stacks").action(async()=>{e.debug("Running `buddy about` ..."),await z8("buddy about");try{let J=(await w3.readPackageJson("./package.json")).version||"unknown",Y=k0.versions.bun||"N/A",G=k0.versions.node||"N/A",z=k0.platform,W=k0.arch,X=k0.version,H=k0.env.NODE_ENV||k0.env.APP_ENV||"development";if(e.info(""),e.info(G8(v7("Stacks Framework"))),e.info(x0("\u2500".repeat(50))),e.info(""),e.info(v7("Version Information:")),e.info(` Stacks: ${x0(J)}`),e.info(` Bun: ${x0(Y)}`),G!=="N/A")e.info(` Node: ${x0(G)}`);e.info(""),e.info(v7("Environment:")),e.info(` Mode: ${x0(H)}`),e.info(` OS: ${x0(`${z} ${W}`)}`),e.info(` Runtime: ${x0(X)}`),e.info(""),e.info(v7("Configuration:")),e.info(` Cache: ${x0("file")}`),e.info(` Debug: ${x0(k0.env.DEBUG?"enabled":"disabled")}`),e.info("")}catch($){e.error("Failed to retrieve system information:",$),k0.exit(1)}}),W8(Q,"about")}import n0 from"process";import{runAction as S7}from"@stacksjs/actions";import{intro as E7,log as N7,onUnknownSubcommand as X8,outro as a0}from"@stacksjs/cli";import{Action as C7}from"@stacksjs/enums";import{ExitCode as i0}from"@stacksjs/types";function RG(Q){let $={setup:"Set up authentication (migrations + personal access client)",token:"Create a personal access client token",client:"Create a new OAuth client",prune:"Prune expired and revoked tokens",project:"Target a specific project",verbose:"Enable verbose output"};Q.command("auth:setup",$.setup).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{N7.debug("Running `buddy auth:setup` ...",J);let Y=await E7("buddy auth:setup"),G=await S7(C7.AuthSetup,J);if(G.isErr)await a0("While setting up authentication, there was an issue",{startTime:Y,useSeconds:!0},G.error),n0.exit(i0.FatalError);await a0("Authentication setup completed successfully.",{startTime:Y,useSeconds:!0}),n0.exit(i0.Success)}),Q.command("auth:token",$.token).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{N7.debug("Running `buddy auth:token` ...",J);let Y=await E7("buddy auth:token"),G=await S7(C7.CreatePersonalAccessClient,J);if(G.isErr)await a0("While creating the personal access client token, there was an issue",{startTime:Y,useSeconds:!0},G.error),n0.exit(i0.FatalError);await a0("Personal access client token created successfully.",{startTime:Y,useSeconds:!0}),n0.exit(i0.Success)}),Q.command("auth:client",$.client).option("-n, --name [name]","Client name",{default:"OAuth Client"}).option("-r, --redirect [redirect]","Redirect URI",{default:"http://localhost"}).option("--personal","Create a personal access client",{default:!1}).option("--password","Create a password grant client",{default:!1}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{N7.debug("Running `buddy auth:client` ...",J);let Y=await E7("buddy auth:client"),G=await S7(C7.AuthClient,J);if(G.isErr)await a0("While creating the OAuth client, there was an issue",{startTime:Y,useSeconds:!0},G.error),n0.exit(i0.FatalError);await a0("OAuth client created successfully.",{startTime:Y,useSeconds:!0}),n0.exit(i0.Success)}),Q.command("auth:prune",$.prune).option("--expired","Prune expired tokens (default: true)",{default:!0}).option("--revoked","Prune revoked tokens (default: true)",{default:!0}).option("-d, --days [days]","Prune revoked tokens older than N days",{default:7}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{N7.debug("Running `buddy auth:prune` ...",J);let Y=await E7("buddy auth:prune"),G=await S7(C7.AuthPrune,J);if(G.isErr)await a0("While pruning tokens, there was an issue",{startTime:Y,useSeconds:!0},G.error),n0.exit(i0.FatalError);await a0("Token pruning completed successfully.",{startTime:Y,useSeconds:!0}),n0.exit(i0.Success)}),X8(Q,"auth")}import l$ from"process";import{intro as Z2,log as I0,onUnknownSubcommand as q8,outro as h7}from"@stacksjs/cli";import{Action as Y0}from"@stacksjs/enums";import{ExitCode as d$}from"@stacksjs/types";var K2;async function G0(...Q){if(!K2)K2=(await import("@stacksjs/actions")).runAction;return K2(...Q)}function AG(Q){let $={build:"Build any of your libraries (packages) for production use",components:"Build your component library",webComponents:"Build your framework agnostic web component library",elements:"An alias to the -w flag",buddy:"Build the Buddy binary",functions:"Build your function library",desktop:"Build the Desktop Application",pages:"Build your frontend",docs:"Build your documentation",framework:"Build Stacks framework",cli:"Automagically build the CLI",server:"Build the Stacks cloud server (Docker image)",select:"What are you trying to build?",project:"Target a specific project",verbose:"Enable verbose output"};Q.command("build [type]",$.build).option("-c, --components",$.components).option("-w, --web-components",$.webComponents).option("-e, --elements",$.elements).option("-f, --functions",$.functions).option("-p, --views",$.pages).option("--pages",$.pages).option("-d, --docs",$.docs).option("-b, --buddy",$.buddy,{default:!1}).option("-s, --stacks",$.framework,{default:!1}).option("--project [project]",$.project,{default:!1}).option("--server",$.server,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J,Y)=>{switch(I0.debug("Running `buddy build` ...",Y),J){case"components":Y.components=!0;break;case"web-components":Y.webComponents=!0;break;case"functions":Y.functions=!0;break;case"views":Y.views=!0;break;case"docs":Y.docs=!0;break;case"buddy":Y.buddy=!0;break;case"cli":Y.buddy=!0;break;case"stacks":Y.stacks=!0;break;case"server":Y.server=!0;break;default:break}if(H8(Y))Y.stacks=!0;if(Y.docs)await G0(Y0.BuildDocs);if(Y.components)await G0(Y0.BuildComponentLibs);if(Y.webComponents)await G0(Y0.BuildWebComponentLib);if(Y.functions)await G0(Y0.BuildFunctionLib);if(Y.views)await G0(Y0.BuildViews);if(Y.stacks)await G0(Y0.BuildStacks);if(Y.buddy)await G0(Y0.BuildCli);if(Y.server)await G0(Y0.BuildServer);l$.exit(d$.Success)}),Q.command("build:components","Automagically build component libraries for production use & npm/CDN distribution").alias("prod:components").option("-c, --components",$.components,{default:!0}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{I0.debug("Running `buddy build:components` ...",J),await G0(Y0.BuildComponentLibs,J)}),Q.command("build:cli",$.cli).alias("prod:cli").option("-b, --buddy",$.buddy,{default:!0}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{I0.debug("Running `buddy build:cli` ...",J),await G0(Y0.BuildCli,J)}),Q.command("build:server",$.server).alias("prod:server").alias("build:docker").option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{I0.debug("Running `buddy build:server` ...",J),await G0(Y0.BuildServer,J)}),Q.command("build:functions","Automagically build function library for npm/CDN distribution").option("-f, --functions",$.functions,{default:!0}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{I0.debug("Running `buddy build:functions` ...",J),await G0(Y0.BuildFunctionLib,J)}),Q.command("build:web-components","Automagically build Web Component library for npm/CDN distribution").alias("build:wc").alias("prod:web-components").alias("prod:wc").option("-w, --web-components",$.webComponents,{default:!0}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{I0.debug("Running `buddy build:web-components` ...",J),await G0(Y0.BuildWebComponentLib,J)}),Q.command("build:docs","Automagically build your documentation site.").alias("prod:docs").alias("build:documentation").alias("prod:documentation").option("-d, --docs",$.docs,{default:!0}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{I0.debug("Running `buddy build:docs` ...",J),await G0(Y0.BuildDocs,J)}),Q.command("build:core","Automagically build the Stacks core.").option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{I0.debug("Running `buddy build:core` ...",J);let Y=await Z2("buddy build:core"),G=await G0(Y0.BuildCore,J);if(G.isErr)I0.error("Failed to build the Stacks core.",G.error),l$.exit(d$.FatalError);await h7("Core packages built successfully",{startTime:Y,useSeconds:!0})}),Q.command("build:desktop",$.desktop).alias("prod:desktop").option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{I0.debug("Running `buddy build:desktop` ...",J);let Y=await Z2("buddy build:desktop"),G=await G0(Y0.BuildDesktop,J);if(G.isErr)await h7("While running the build:desktop command, there was an issue",{startTime:Y,useSeconds:!0},G.error),l$.exit(d$.FatalError);console.log(""),await h7("Exited",{startTime:Y,useSeconds:!0}),l$.exit(d$.Success)}),Q.command("build:stacks","Build the Stacks framework.").option("-s, --stacks",$.framework,{default:!0}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{I0.debug("Running `buddy build:stacks` ...",J);let Y=await Z2("buddy build:stacks"),G=await G0(Y0.BuildStacks,J);if(G.isErr)I0.error("Failed to build Stacks.",G.error),l$.exit(d$.FatalError);await h7("Stacks built successfully",{startTime:Y,useSeconds:!0})}),q8(Q,"build")}function H8(Q){return!Q.components&&!Q.webComponents&&!Q.elements&&!Q.functions&&!Q.views&&!Q.docs&&!Q.stacks&&!Q.buddy&&!Q.server}import Z8 from"process";import{runAction as K8}from"@stacksjs/actions";import{intro as _8,log as U8,onUnknownSubcommand as L8,outro as M3}from"@stacksjs/cli";import{Action as F8}from"@stacksjs/enums";import{ExitCode as O8}from"@stacksjs/types";function CG(Q){let $={changelog:"Create a CHANGELOG.md file",quiet:"Minimal output",dryRun:"Do not write the file, just output the changes",from:"Start git revision for generated changelog",project:"Target a specific project",to:"End git revision for generated changelog",verbose:"Enable verbose output",version:"Version heading to use for the generated changelog entry"};Q.command("changelog",$.changelog).option("-q, --quiet",$.quiet,{default:!1}).option("-d, --dry-run",$.dryRun,{default:!1}).option("-p, --project [project]",$.project,{default:!1}).option("--from <revision>",$.from).option("--to <revision>",$.to).option("--version <version>",$.version).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{U8.debug("Running `buddy changelog` ...",J);let Y=await _8("buddy changelog"),G=await K8(F8.Changelog,J);if(G.isErr)await M3("While running the changelog command, there was an issue",{...J,startTime:Y,useSeconds:!0},G.error),Z8.exit(O8.FatalError);await M3("Generated CHANGELOG.md",{...J,startTime:Y,useSeconds:!0,type:"success"})}),L8(Q,"changelog")}import _2 from"process";import{runAction as V8}from"@stacksjs/actions";import{intro as B8,log as T3,onUnknownSubcommand as R8,outro as I3}from"@stacksjs/cli";import{Action as w8}from"@stacksjs/enums";import{ExitCode as U2}from"@stacksjs/types";function gG(Q){let $={clean:"Removes all node_modules & lock files",project:"Target a specific project",verbose:"Enable verbose output"};Q.command("clean",$.clean).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{if(T3.debug("Running `buddy clean` ...",J),!Q.isForce&&!Q.isNoInteraction){let{confirm:z}=await import("@stacksjs/cli");if(!await z({message:"This will remove all node_modules and lock files. Continue?",initial:!1}))T3.info("Clean cancelled"),_2.exit(U2.Success)}let Y=await B8("buddy clean"),G=await V8(w8.Clean,J);if(G.isErr)await I3("While running the clean command, there was an issue",{startTime:Y,useSeconds:!0},G.error),_2.exit(U2.FatalError);await I3("Cleaned up",{startTime:Y,useSeconds:!0,message:"Cleaned up"}),_2.exit(U2.Success)}),R8(Q,"clean")}import b from"process";import{intro as w$,italic as V2,log as y,onUnknownSubcommand as E8,outro as r,prompts as a$,runCommand as S3,underline as E3}from"@stacksjs/cli";import{addJumpBox as N8,deleteCdkRemnants as C8,deleteIamUsers as h8,deleteJumpBox as B2,deleteLogGroups as D8,deleteParameterStore as b8,deleteStacksBuckets as y8,deleteStacksFunctions as k8,deleteSubnets as x8,deleteVpcs as g8,getCloudFrontDistributionId as N3,getJumpBoxInstanceId as u8}from"@stacksjs/cloud";import{path as C3}from"@stacksjs/path";import{ExitCode as l}from"@stacksjs/types";function i$(Q){if(!Q||typeof Q!=="object")return!1;let $=Q;if(typeof $.isErr==="function")return $.isErr();return!!$.isErr}function s$(Q){if(!Q||typeof Q!=="object")return"Unknown error";return String(Q.error||"Unknown error")}function m8(Q){if(!Q||typeof Q!=="object")return;return Q.value}function oG(Q){let $={cloud:"Interact with the Stacks Cloud",ssh:"SSH into the Stacks Cloud",add:"Add a resource to the Stacks Cloud",remove:"Remove the Stacks Cloud. In case it fails, try again",optimizeCost:"Remove certain resources that may be re-applied at a later time",cleanUp:"Remove all resources that were retained during the cloud deletion",invalidateCache:"Invalidate the CloudFront cache",diff:"Show the diff of the current, undeployed cloud changes ",paths:"The paths to invalidate",project:"Target a specific project",verbose:"Enable verbose output"};Q.command("cloud",$.cloud).option("--ssh",$.ssh,{default:!1}).option("--connect",$.ssh,{default:!1}).option("--invalidate-cache",$.invalidateCache,{default:!1}).option("--paths [paths]",$.paths).option("--diff",$.diff,{default:!1}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{y.debug("Running `buddy cloud` ...",J);let Y=performance.now();if(J.ssh||J.connect){let G=await u8(),z=await S3(`aws ssm start-session --target ${G}`,{...J,cwd:C3.projectPath(),stdin:"pipe"});if(i$(z))await r("While running the cloud command, there was an issue",{startTime:Y,useSeconds:!0},s$(z)),b.exit(l.FatalError);await r("Exited",{startTime:Y,useSeconds:!0}),b.exit(l.Success)}if(J.invalidateCache){let{confirm:G}=await a$({name:"confirm",type:"confirm",message:"Would you like to invalidate the CDN (CloudFront) cache?"});if(!G)await r("Exited",{startTime:Y,useSeconds:!0}),b.exit(l.Success);y.info("Invalidating the CloudFront cache...");let{AWSCloudFrontClient:z}=await import("@stacksjs/ts-cloud"),W=new z,X=await N3();try{let H=await W.invalidateAll(X);y.success(`Invalidation created: ${H}`),y.info("Status: pending")}catch(H){y.error(`Failed to invalidate CloudFront cache: ${H.message}`)}await r("Exited",{startTime:Y,useSeconds:!0}),b.exit(l.Success)}if(J.diff){try{let{InfrastructureGenerator:G}=await import("@stacksjs/ts-cloud"),{CloudFormationClient:z}=await import("@stacksjs/ts-cloud/aws"),{tsCloud:W}=await Promise.resolve().then(() => (n$(),r$)),X=b.env.APP_ENV||b.env.NODE_ENV||"production",q=new G({config:W,environment:X}).generate().toJSON(),Z=`${W.project?.slug||"stacks"}-${X}`,K=new z(b.env.AWS_REGION||"us-east-1"),_="{}";try{_=(await K.getTemplate(Z)).TemplateBody}catch{y.info("No deployed stack found. Showing full template as diff.")}if(_===q)y.info("No changes detected.");else y.info("Changes detected between deployed and local template:"),y.info(`Current template: ${_.length} bytes`),y.info(`New template: ${q.length} bytes`)}catch(G){y.error(`Failed to compute diff: ${G.message}`)}await r("Cloud diff complete",{startTime:Y,useSeconds:!0}),b.exit(l.Success)}y.info("Not implemented yet. Read more about `buddy cloud` here: https://stacksjs.com/docs/cloud"),b.exit(l.Success)}),Q.command("cloud:add",$.add).option("--jump-box","Remove the jump-box",{default:!1}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{y.debug("Running `buddy cloud:add` ...",J);let Y=await w$("buddy cloud:add");if(J.jumpBox){let{confirm:G}=await a$({name:"confirm",type:"confirm",message:"Would you like to add a jump-box to your cloud?"});if(!G)await r("Exited",{startTime:Y,useSeconds:!0}),b.exit(l.Success);y.info("The jump-box is getting added to your cloud resources..."),y.info("This takes a few moments, please be patient."),await new Promise((W)=>setTimeout(W,2000));let z=await N8();if(i$(z))await r("While running the cloud:add command, there was an issue",{startTime:Y,useSeconds:!0},s$(z)),b.exit(l.FatalError);y.info(V2("View the jump-box in the AWS console:")),y.info(E3("https://us-east-1.console.aws.amazon.com/ec2/home?region=us-east-1#Instances:instanceState=running")),y.info(V2("Once it finished initializing, you may SSH into it:")),y.info(E3("buddy cloud --ssh")),await r("Your jump-box was added.",{startTime:Y,useSeconds:!0}),b.exit(l.Success)}y.info("This functionality is not yet implemented."),b.exit(l.Success)}),Q.command("cloud:remove",$.remove).alias("cloud:destroy").alias("cloud:rm").alias("undeploy").option("--jump-box","Remove the jump-box",{default:!1}).option("--force","Force deletion of stack in bad state",{default:!1}).option("--yes","Skip confirmation prompts",{default:!1}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{y.debug("Running `buddy cloud:remove` ...",J);let Y=await w$("buddy cloud:remove");if(J.jumpBox){let{confirm:z}=await a$({name:"confirm",type:"confirm",message:"Would you like to remove your jump-box for now?"});if(!z)await r("Exited",{startTime:Y,useSeconds:!0}),b.exit(l.Success);let W=await B2();if(i$(W))await r("While removing your jump-box, there was an issue",{startTime:Y,useSeconds:!0},s$(W)),b.exit(l.FatalError);await r("Your jump-box was removed.",{startTime:Y,useSeconds:!0}),b.exit(l.Success)}console.log(""),console.log("Removing cloud infrastructure..."),console.log(` ${V2("This typically takes 2-5 minutes.")}`),console.log("");let G=b.env.APP_ENV||b.env.NODE_ENV||"production";if(!b.env.AWS_ACCESS_KEY_ID||!b.env.AWS_SECRET_ACCESS_KEY){let{existsSync:z,readFileSync:W}=await import("fs"),{projectPath:X}=await import("@stacksjs/path"),H=[X(`.env.${G}`),X(".env")];for(let q of H)if(z(q)){let K=W(q,"utf-8").split(`
186
186
  `);for(let _ of K){let U=_.trim();if(U.startsWith("#")||!U.includes("="))continue;let[L,...F]=U.split("="),O=F.join("=").replace(/^["']|["']$/g,"");if(L==="AWS_ACCESS_KEY_ID"||L==="AWS_SECRET_ACCESS_KEY"||L==="AWS_REGION"||L==="AWS_ACCOUNT_ID")b.env[L]=O}break}}delete b.env.AWS_PROFILE;try{let{undeployStack:z}=await Promise.resolve().then(() => (v3(),f3)),W=b.env.AWS_REGION||"us-east-1";await z({environment:G,region:W,verbose:J.verbose}),await r("Cloud infrastructure removed",{startTime:Y,useSeconds:!0}),b.exit(l.Success)}catch(z){console.log(""),console.error("\u2717 Failed to remove cloud infrastructure");let W=String(z.message||z);if(W.includes("security token")||W.includes("credentials"))console.log(""),console.error(" AWS credentials are invalid or expired"),console.log(" Check your AWS credentials in .env.production:"),console.log(" - AWS_ACCESS_KEY_ID"),console.log(" - AWS_SECRET_ACCESS_KEY");else if(W.includes("region")||W.includes("AWS_REGION"))console.log(""),console.error(" AWS Region not configured"),console.log(" Add AWS_REGION to your .env.production file");else if(W.includes("AccessDenied"))console.log(""),console.error(" Access denied"),console.log(" Your AWS credentials may not have permission to delete stacks");else console.error(` ${W}`);if(console.log(""),console.log("Troubleshooting:"),console.log(" ./buddy cloud:cleanup - Clean up resources manually"),console.log(" --verbose - Show detailed error information"),console.log(""),J.verbose)console.error("Error details:",z);await r("Failed to remove infrastructure",{startTime:Y,useSeconds:!0}),b.exit(l.FatalError)}}),Q.command("cloud:optimize-cost",$.optimizeCost).option("--jump-box","Remove the jump-box",{default:!0}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{y.debug("Running `buddy cloud:optimize-cost` ...",J);let Y=await w$("buddy cloud:optimize-cost");if(J.jumpBox){let{confirm:G}=await a$({name:"confirm",type:"confirm",message:"Would you like to remove your jump-box to optimize your costs?"});if(!G)await r("Exited",{startTime:Y,useSeconds:!0}),b.exit(l.Success);await B2(),await r("Your jump-box was removed & cost optimizations are applied.",{startTime:Y,useSeconds:!0}),b.exit(l.Success)}await r("No cost optimization was applied",{startTime:Y,useSeconds:!0}),b.exit(l.Success)}),Q.command("cloud:cleanup",$.cleanUp).alias("cloud:clean-up").option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{y.debug("Running `buddy cloud:cleanup` ...",J);let Y=await w$("buddy cloud:cleanup");delete b.env.AWS_PROFILE,y.info("Cleaning up your cloud resources will take a while to complete. Please be patient."),await new Promise((W)=>setTimeout(W,2000));let G=[{label:"jump-boxes",fn:B2,ignoreErrors:["Jump-box not found"]},{label:"retained S3 buckets",fn:y8},{label:"retained Lambda functions",fn:k8,ignoreErrors:["No stacks functions found"]},{label:"remaining Stacks logs",fn:D8},{label:"stored parameters",fn:b8},{label:"VPCs",fn:g8},{label:"Subnets",fn:x8},{label:"CDK remnants",fn:C8},{label:"IAM users",fn:h8}],z=[];for(let W of G){y.info(`Removing any ${W.label}...`);try{let X=await W.fn();if(i$(X)){let H=s$(X);if(!W.ignoreErrors?.includes(H))y.warn(`${W.label} cleanup issue: ${H}`),z.push({label:W.label,error:H})}else{let H=m8(X);if(H)y.info(String(H))}}catch(X){let H=X.message||"AWS SDK error";y.warn(`${W.label} cleanup skipped: ${H}`),z.push({label:W.label,error:H})}}if(z.length>0){y.warn(`Cleanup completed with ${z.length} issue(s):`);for(let{label:W,error:X}of z)y.warn(` - ${W}: ${X}`)}await r("AWS resources have been removed",{startTime:Y,useSeconds:!0}),b.exit(l.Success)}),Q.command("cloud:invalidate-cache",$.invalidateCache).option("--paths [paths]",$.paths,{default:!1}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{y.debug("Running `buddy cloud:invalidate-cache` ...",J);let Y=await w$("buddy cloud:invalidate-cache"),{confirm:G}=await a$({name:"confirm",type:"confirm",message:"Would you like to invalidate the CloudFront cache?"});if(!G)await r("Exited",{startTime:Y,useSeconds:!0}),b.exit(l.Success);y.info("Invalidating the CloudFront cache...");let z=await N3();if(!z)await r("Could not resolve CloudFront distribution ID",{startTime:Y,useSeconds:!0},"Ensure your cloud stack is deployed before invalidating cache."),b.exit(l.FatalError);let W=J.paths?String(J.paths):"/*",X=await S3(`aws cloudfront create-invalidation --distribution-id ${z} --paths ${W}`,{...J,cwd:C3.projectPath(),stdin:"pipe"});if(i$(X))await r("While running the cloud command, there was an issue",{startTime:Y,useSeconds:!0},s$(X)),b.exit(l.FatalError);await r("Exited",{startTime:Y,useSeconds:!0}),b.exit(l.Success)}),Q.command("cloud:diff",$.diff).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{y.debug("Running `buddy cloud:diff` ...",J);let Y=await w$("buddy cloud:diff");try{let{InfrastructureGenerator:G}=await import("@stacksjs/ts-cloud"),{CloudFormationClient:z}=await import("@stacksjs/ts-cloud/aws"),{tsCloud:W}=await Promise.resolve().then(() => (n$(),r$)),X=b.env.APP_ENV||b.env.NODE_ENV||"production",q=new G({config:W,environment:X}).generate().toJSON(),Z=`${W.project?.slug||"stacks"}-${X}`,K=new z(b.env.AWS_REGION||"us-east-1"),_="{}";try{_=(await K.getTemplate(Z)).TemplateBody}catch{y.info("No deployed stack found. Showing full template as diff.")}if(_===q)y.info("No changes detected.");else y.info("Changes detected between deployed and local template:"),y.info(`Current template: ${_.length} bytes`),y.info(`New template: ${q.length} bytes`)}catch(G){await r("While running the cloud diff command, there was an issue",{startTime:Y,useSeconds:!0},G.message),b.exit(l.FatalError)}await r("Cloud diff complete",{startTime:Y,useSeconds:!0}),b.exit(l.Success)}),E8(Q,"cloud")}import{runCommit as c8}from"@stacksjs/actions";import{log as l8}from"@stacksjs/logging";import{onUnknownSubcommand as d8}from"@stacksjs/cli";function Jz(Q){let $={commit:"Commit your stashed changes",project:"Target a specific project",verbose:"Enable verbose output"};Q.command("commit",$.commit).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{l8.debug("Running `buddy commit` ...",J),await c8(J)}),d8(Q,"commit")}import p8 from"process";import{log as r8,onUnknownSubcommand as n8}from"@stacksjs/cli";function Wz(Q){let $={completion:"Generate shell completion scripts",shell:"Shell type (bash, zsh, fish)"};Q.command("completion [shell]",$.completion).option("-s, --shell [shell]",$.shell).example("buddy completion bash").example("buddy completion zsh").example("buddy completion fish").example("buddy completion bash > /usr/local/etc/bash_completion.d/buddy").action(async(J,Y)=>{r8.debug("Running `buddy completion` ...",Y);let G=J||Y.shell||"bash",W=(Q.commands||[]).map((X)=>X.name).filter(Boolean);switch(G){case"bash":console.log(a8(W));break;case"zsh":console.log(i8(W));break;case"fish":console.log(s8(W));break;default:console.error(`Unknown shell: ${G}`),console.error("Supported shells: bash, zsh, fish"),p8.exit(1)}}),n8(Q,"completion")}function a8(Q){return`# buddy completion for bash
187
187
 
188
188
  _buddy_completion() {
@@ -300,7 +300,7 @@ us-east-1
300
300
  ${z}
301
301
  `,q=await z5(X,{cwd:W5.projectPath(),stdin:"pipe",input:H});if(q.isErr)await h3("While running the cloud command, there was an issue",{startTime:$,useSeconds:!0},q.error),s0.exit(y7.FatalError);if(Q?.quiet)return;await h3("Exited",{startTime:$,useSeconds:!0})}m7();import{chmodSync as f5}from"fs";import g0 from"process";import{runAction as v5}from"@stacksjs/actions";import{bold as S5,cyan as E5,dim as N5,intro as C5,log as n,onUnknownSubcommand as h5,runCommand as c7}from"@stacksjs/cli";import{Action as D5}from"@stacksjs/enums";import{resolve as k3}from"@stacksjs/path";import{isFolder as b5}from"@stacksjs/storage";import{ExitCode as o0}from"@stacksjs/types";import{useOnline as y5}from"@stacksjs/utils";function uz(Q){let $={name:"The name of the project",command:"Create a new Stacks project",ui:"Are you building a UI?",components:"Are you building UI components?",webComponents:"Automagically built optimized custom elements/web components?",vue:"Automagically built a Vue component library?",views:"How about views?",functions:"Are you developing functions/composables?",api:"Are you building an API?",database:"Do you need a database?",notifications:"Do you need notifications? e.g. email, SMS, push or chat notifications",cache:"Do you need caching?",email:"Do you need email?",project:"Target a specific project",verbose:"Enable verbose output"};Q.command("new [name]",$.command).alias("create [name]").option("-n, --name [name]",$.name,{default:!1}).option("-u, --ui",$.ui,{default:!0}).option("-c, --components",$.components,{default:!0}).option("-w, --web-components",$.webComponents,{default:!0}).option("-v, --vue",$.vue,{default:!0}).option("-p, --views",$.views,{default:!0}).option("-f, --functions",$.functions,{default:!0}).option("-a, --api",$.api,{default:!0}).option("-d, --database",$.database,{default:!0}).option("-ca, --cache",$.cache,{default:!1}).option("-e, --email",$.email,{default:!1}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J,Y)=>{n.debug("Running `buddy new <name>` ...",Y);let G=await C5("buddy new");J=J??Y.name;let z=k3(g0.cwd(),J);k5(z),x5();let W=await g5(J,z,Y);if(W.isErr)n.error(W.error),g0.exit(o0.FatalError);if(await m5(z,Y),u5(z),await c5(z,Y),G){let X=performance.now()-G;n.success(N5(`[${X.toFixed(2)}ms] Completed`))}n.info(S5("Welcome to the Stacks Framework! \u269B\uFE0F")),n.info("To learn more, visit https://stacksjs.com"),g0.exit(o0.Success)}),h5(Q,"new")}function k5(Q){if(b5(Q))n.error(`Path ${Q} already exists`),g0.exit(o0.FatalError)}function x5(){if(!y5())n.info("It appears you are disconnected from the internet."),n.info("The Stacks setup requires a brief internet connection for setup."),n.info("For instance, it installs your dependencies from."),g0.exit(o0.FatalError)}async function g5(Q,$,J){n.info("Setting up your stack.");let Y=await c7(`bunx --bun @stacksjs/gitit stacks ${Q}`,J);return n.success(`Successfully scaffolded your project at ${E5($)}`),Y}function u5(Q){for(let $ of["buddy","bootstrap"])try{f5(k3(Q,$),493)}catch{}}async function m5(Q,$){n.info("Ensuring your environment is ready..."),await T$(),await I$(Q),n.success("Environment is ready")}async function c5(Q,$){n.info("Installing & setting up Stacks"),n.info("Running bun install...");let J=await c7("bun install",{...$,cwd:Q});if(J?.isErr)n.error(J.error),g0.exit(o0.FatalError);if(n.info("Copying .env.example \u2192 .env"),J=await c7("cp .env.example .env",{...$,cwd:Q}),J?.isErr)n.error(J.error),g0.exit(o0.FatalError);n.info("Generating application key...");let Y=await v5(D5.KeyGenerate,{...$,cwd:Q});if(Y.isErr)n.error(Y.error),g0.exit(o0.FatalError);if(n.info("Initializing git repository..."),J=await c7("git init",{...$,cwd:Q}),J.isErr)n.error(J.error),g0.exit(o0.FatalError);n.success("Installed & set-up \uD83D\uDE80")}import{existsSync as j0,readFileSync as t0,readdirSync as o5,statSync as t5}from"fs";import{homedir as A$}from"os";import{join as _$}from"path";import E from"process";import{runAction as e5}from"@stacksjs/actions";import{italic as Q7,onUnknownSubcommand as $6,outro as l7,prompts as j$}from"@stacksjs/cli";import{app as p3,email as c,cloud as l3}from"@stacksjs/config";import{runAction as l5}from"@stacksjs/actions";import{config as g3}from"@stacksjs/config";import{Action as d5}from"@stacksjs/enums";import{err as rz,handleError as nz,ok as az}from"@stacksjs/error-handling";import{log as Z0}from"@stacksjs/logging";import{path as p5}from"@stacksjs/path";import{fs as x3}from"@stacksjs/storage";import{Route53Client as r5,Route53DomainsClient as u3}from"@stacksjs/ts-cloud";function n5(Q){if(!Q)return;return Q.replace(/^https?:\/\//,"").replace(/\/$/,"")}function a5(Q){if(!/^[a-zA-Z0-9.-]+$/.test(Q))throw Error(`Invalid nameserver value: ${Q}`);return Q}function T2(Q){try{let $=p5.projectConfigPath("dns.ts"),Y=x3.readFileSync($,"utf-8").replace(/nameservers: \[.*?\]/s,`nameservers: [${Q.map((G)=>`'${a5(G)}'`).join(", ")}]`);x3.writeFileSync($,Y,"utf-8"),Z0.info("Nameservers have been set.")}catch($){Z0.error("Error updating nameservers:",$)}}async function i5(Q){if(Z0.debug("Getting nameservers for domain:",Q),!Q)return[];try{return(await new u3().getDomainDetail({DomainName:Q}))?.Nameservers?.map((Y)=>Y.Name)||[]}catch($){return Z0.debug("Domain not registered via Route53 Domains:",$),[]}}async function s5(Q,$){if(!$)$=g3.app.url;let J=await i5($);if(!J||J.length===0)return Z0.debug("Domain is not registered via Route53 Domains - skipping automatic nameserver update"),T2(Q),!1;if(JSON.stringify(J.sort())!==JSON.stringify(Q.sort())){Z0.info("Updating your domain nameservers to match the ones in your hosted zone..."),Z0.debug("Hosted zone nameservers:",Q),Z0.debug("Domain nameservers:",J);try{return await new u3().updateDomainNameservers({DomainName:$,Nameservers:Q.map((G)=>({Name:G}))}),T2(Q),Z0.info("Nameservers updated."),!0}catch(Y){return Z0.debug("Failed to update nameservers via Route53 Domains:",Y),T2(Q),!1}}return Z0.success("Your nameservers are up to date."),!0}async function m3(Q){if(Z0.debug("Checking if domain has been added to cloud..."),!Q)Q=g3.app.url;if(Q=n5(Q),!Q)return!1;Z0.debug("domainName:",Q);let $=new r5,J=await $.listHostedZonesByName({DNSName:Q});if(Z0.debug("Existing hosted zones:",J),!J||!J.HostedZones||J.HostedZones.length===0)return!1;let Y=J.HostedZones.find((G)=>G.Name===`${Q}.`);if(Y){Z0.debug("Hosted zone found:",Y);let z=(await $.getHostedZone({Id:Y.Id})).DelegationSet?.NameServers||[];return await s5(z,Q),!0}return!1}async function c3(Q){return await l5(d5.DomainsAdd,Q)}m7();import{env as Q6}from"@stacksjs/env";import{Action as J6}from"@stacksjs/enums";import{path as E0}from"@stacksjs/path";import{ExitCode as K0}from"@stacksjs/types";var R={info:(...Q)=>console.log("\u2139",...Q),success:(...Q)=>console.log("\u2713",...Q),warn:(...Q)=>console.log("\u26A0",...Q),error:(...Q)=>console.error("\u2717",...Q),debug:(...Q)=>{if(E.argv.includes("--verbose")||E.argv.includes("-v"))console.log("\uD83D\uDD0D",...Q)}},r3="github.com/mail-os/mail",Y6=`${r3}@0.1.0`,n3="linux-x86_64",I2=["mail","mail-x86_64-linux","mail-x86_64-linux-gnu"];function G6(Q,$,J=8){let Y=new Set($),G=[];if(!j0(Q))return G;function z(W,X){if(X>J)return;for(let H of o5(W)){if(H===".git"||H==="node_modules")continue;let q=_$(W,H),Z=t5(q);if(Z.isDirectory())z(q,X+1);else if(Z.isFile()&&Y.has(H))G.push(q)}}return z(Q,0),G}function A2(Q){let $=t0(Q).slice(0,4);return $[0]===127&&$[1]===69&&$[2]===76&&$[3]===70}function z6(){let Q=_$(A$(),"Code","Tools","pantry","packages","ts-pantry","bin","cli.ts");if(j0(Q))return{command:"bun",args:[Q]};let $=E0.projectPath("pantry/.bin/pantry");if(j0($))return{command:$,args:[]};let J=_$(A$(),".local","share","pantry","global","bin","pantry");if(j0(J))return{command:J,args:[]};return{command:"pantry",args:[]}}async function W6(){let{execFileSync:Q}=await import("child_process"),$=z6();Q($.command,[...$.args,"install",Y6,"--install-dir",E0.projectPath("pantry"),"--platform",n3,"--quiet"],{cwd:E0.projectPath(),stdio:E.argv.includes("--verbose")||E.argv.includes("-v")?"inherit":"pipe",env:E.env})}async function X6(){let Q=[...I2.map(($)=>E0.projectPath(`pantry/.bin/${$}`)),...I2.map(($)=>_$(A$(),".local","share","pantry","global","bin",$))];for(let $ of Q)if(j0($)&&A2($))return $;for(let $ of[E0.projectPath("pantry"),_$(A$(),".local","share","pantry")])for(let J of G6($,I2))if(A2(J))return J;return null}async function q6(Q=!1){let $=E0.projectPath();await T$(),await I$($),await u7({cwd:$,verbose:Q}),await g7($)}function H6(){let Q=_$(A$(),".aws","credentials"),$=_$(A$(),".aws","config");if(!j0(Q))return{};try{let Y=t0(Q,"utf-8").split(`
302
302
  `),G=["default","stacks"],z="",W={},X={};for(let q of Y){let Z=q.trim(),K=Z.match(/^\[(.+)\]$/);if(K){z=K[1],X[z]={};continue}let _=Z.match(/^(\w+)\s*=\s*(.+)$/);if(_&&z){let[,U,L]=_;if(U==="aws_access_key_id")X[z].accessKeyId=L;else if(U==="aws_secret_access_key")X[z].secretAccessKey=L}}for(let q of G)if(X[q]?.accessKeyId&&X[q]?.secretAccessKey){W=X[q],R.debug(`Using AWS credentials from ~/.aws/credentials [${q}] profile`);break}if(!W.accessKeyId){for(let[q,Z]of Object.entries(X))if(Z.accessKeyId&&Z.secretAccessKey){W=Z,R.debug(`Using AWS credentials from ~/.aws/credentials [${q}] profile`);break}}let H;if(j0($)){let Z=t0($,"utf-8").match(/region\s*=\s*(.+)/);if(Z)H=Z[1].trim()}return{...W,region:H}}catch(J){return R.debug("Failed to read AWS credentials file:",J),{}}}async function d3(Q,$,J,Y){J.info("Setting up email DNS records...");try{let{SESClient:G}=await import("@stacksjs/ts-cloud"),{Route53Client:z}=await import("@stacksjs/ts-cloud"),W=new G($),X=new z($);J.info(`Getting DKIM tokens for ${Q}...`);let q=(await W.getEmailIdentity(Q)).DkimAttributes?.Tokens||[];if(q.length===0){J.warn("No DKIM tokens found - domain may not be set up in SES yet");return}J.info(`Found ${q.length} DKIM tokens`);let K=(await X.listHostedZones()).HostedZones?.find((F)=>F.Name===`${Q}.`);if(!K){J.warn(`Hosted zone not found for ${Q} - DNS records must be added manually`),J.info("DKIM records needed:");for(let F of q)J.info(` CNAME: ${F}._domainkey.${Q} -> ${F}.dkim.amazonses.com`);J.info(` MX: ${Q} -> 10 inbound-smtp.${$}.amazonaws.com`);return}let _=K.Id?.replace("/hostedzone/","");J.info(`Found hosted zone: ${_}`);for(let F of q){let O=`${F}._domainkey.${Q}`,M=`${F}.dkim.amazonses.com`;try{await X.changeResourceRecordSets({HostedZoneId:_,ChangeBatch:{Changes:[{Action:"UPSERT",ResourceRecordSet:{Name:O,Type:"CNAME",TTL:300,ResourceRecords:[{Value:M}]}}]}}),J.success(`Added DKIM record: ${F}._domainkey`)}catch(T){J.warn(`Failed to add DKIM record: ${T.message}`)}}let U=Y?.mailSubdomain||"mail",L=Y?.mode==="server"?`10 ${U}.${Q}`:`10 inbound-smtp.${$}.amazonaws.com`;try{await X.changeResourceRecordSets({HostedZoneId:_,ChangeBatch:{Changes:[{Action:"UPSERT",ResourceRecordSet:{Name:Q,Type:"MX",TTL:300,ResourceRecords:[{Value:L}]}}]}}),J.success(`Added MX record: ${L}`)}catch(F){J.warn(`Failed to add MX record: ${F.message}`)}try{await X.changeResourceRecordSets({HostedZoneId:_,ChangeBatch:{Changes:[{Action:"UPSERT",ResourceRecordSet:{Name:Q,Type:"TXT",TTL:300,ResourceRecords:[{Value:'"v=spf1 include:amazonses.com ~all"'}]}}]}}),J.success("Added SPF record")}catch(F){J.warn(`Failed to add SPF record: ${F.message}`)}try{await X.changeResourceRecordSets({HostedZoneId:_,ChangeBatch:{Changes:[{Action:"UPSERT",ResourceRecordSet:{Name:`_dmarc.${Q}`,Type:"TXT",TTL:300,ResourceRecords:[{Value:`"v=DMARC1;p=quarantine;pct=25;rua=mailto:dmarcreports@${Q}"`}]}}]}}),J.success("Added DMARC record")}catch(F){J.warn(`Failed to add DMARC record: ${F.message}`)}try{let O=`${E.env.APP_NAME?.toLowerCase().replace(/[^a-z0-9]/g,"-")||"stacks"}-email-rules`;await W.setActiveReceiptRuleSet(O),J.success(`Activated email receipt rule set: ${O}`)}catch(F){J.warn(`Failed to activate receipt rule set: ${F.message}`)}J.success("Email DNS records configured!"),J.info("Note: DKIM verification may take 5-15 minutes to complete")}catch(G){J.warn(`Failed to set up email DNS records: ${G.message}`),J.info("You can manually set up DNS records using: buddy email:verify")}}async function Z6(Q,$,J,Y){try{let{DynamoDBClient:G}=await import("@stacksjs/ts-cloud"),z=await import("crypto"),W=new G(J),X=`${Q}-mail-users`,H=c?.mailboxes||[];if(H.length===0){let q=`admin@${$}`,Z=z.randomBytes(16).toString("hex"),K=z.createHash("sha256").update(Z).digest("hex");try{await W.putItem({TableName:X,Item:{email:{S:q},passwordHash:{S:K},createdAt:{S:new Date().toISOString()},displayName:{S:"Admin"}}}),Y.success(`Created default mail user: ${q}`),Y.info(`Password: ${Z}`),Y.info("Save this password - it will not be shown again!")}catch(_){if(_.message?.includes("ConditionalCheckFailedException")||_.message?.includes("already exists"))Y.debug("Default mail user already exists");else throw _}}else for(let q of H){let Z=q,K=typeof q==="string"?`${q}@${$}`:`${Z.name||Z.address?.split("@")[0]}@${$}`,_=typeof q==="object"&&Z.password?Z.password:z.randomBytes(16).toString("hex"),U=z.createHash("sha256").update(_).digest("hex");try{if(await W.putItem({TableName:X,Item:{email:{S:K},passwordHash:{S:U},createdAt:{S:new Date().toISOString()},displayName:{S:typeof q==="object"?Z.displayName||Z.name||K:q}}}),Y.success(`Created mail user: ${K}`),typeof q!=="object"||!Z.password)Y.info(` Password: ${_}`)}catch(L){if(L.message?.includes("ConditionalCheckFailedException"))Y.debug(`Mail user ${K} already exists`);else Y.warn(`Failed to create mail user ${K}: ${L.message}`)}}}catch(G){Y.warn(`Failed to create mail users: ${G.message}`)}}async function j2(Q,$,J){try{let{S3Client:Y}=await import("@stacksjs/ts-cloud"),G=new Y($);if(J==="serverless"){let W=E0.frameworkPath("core/mail-server/server.ts");if(j0(W)){let H=t0(W,"utf-8");await G.putObject({bucket:Q,key:"mail-server/server.ts",body:H,contentType:"text/typescript"}),R.success("Uploaded serverless mail server code to S3")}let X=E0.frameworkPath("core/mail-server/package.json");if(j0(X)){let H=t0(X,"utf-8");await G.putObject({bucket:Q,key:"mail-server/package.json",body:H,contentType:"application/json"})}return}let z=!1;try{await W6();let W=await X6();if(W&&j0(W)&&A2(W)){R.info(`Uploading Pantry mail binary: ${W}`);let X=t0(W);await G.putObject({bucket:Q,key:"mail-server/smtp-server",body:X,contentType:"application/octet-stream"}),R.success("Uploaded Linux x86_64 mail server binary to S3"),z=!0}}catch(W){R.debug(`Pantry mail install failed: ${W.message}`)}if(!z)R.warn(`No Pantry-provided ${n3} mail binary found. Release ${r3}, then run the Pantry binary sync for that package.`)}catch(Y){R.debug(`Could not upload mail server to S3 (bucket may not exist yet): ${Y.message}`)}}function FW(Q){let $={deploy:"Deploy your project",project:"Target a specific project",production:"Deploy to production",development:"Deploy to development",staging:"Deploy to staging",yes:"Confirm all prompts by default",domain:"Specify a domain to deploy to",verbose:"Enable verbose output"};Q.command("deploy [env]",$.deploy).option("--domain",$.domain,{default:void 0}).option("-p, --project [project]",$.project,{default:!1}).option("--prod",$.production,{default:!0}).option("--dev",$.development,{default:!1}).option("--yes",$.yes,{default:!1}).option("--staging",$.staging,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J,Y)=>{R.debug("Running `buddy deploy` ...",Y),await q6(Y.verbose===!0);let G=J||"production";if(E.env.AWS_ACCESS_KEY_ID&&E.env.AWS_SECRET_ACCESS_KEY)delete E.env.AWS_PROFILE;let z=performance.now();console.log(""),console.log("\uD83D\uDE80 Deploy"),console.log("");let W;if(G==="production"||G==="prod"){let Z=E0.projectPath(".env.production");if(j0(Z)){let _=t0(Z,"utf-8").match(/^APP_URL=(.+)$/m);if(_)W=_[1].trim(),R.debug("Using APP_URL from .env.production:",W)}}let X=Q6.APP_URL,H=Y.domain||W||X||p3.url;if((Y.prod||G==="production"||G==="prod")&&!Y.yes)await K6();if(!H)R.info("No domain found in your .env.production or ./config/app.ts"),R.info("Please ensure your domain is properly configured."),R.info("For more info, check out the docs or join our Discord."),E.exit(K0.FatalError);R.info(`Deploying to ${Q7(H)} (${G})`),await F6(Y),Y.domain=await _6(H,Y,z);let q=await e5(J6.Deploy,Y);if(q.isErr)await l7("While running the `buddy deploy`, there was an issue",{startTime:z,useSeconds:!0},q.error),E.exit(K0.FatalError);await l7("Project deployed.",{startTime:z,useSeconds:!0})}),$6(Q,"deploy")}async function K6(){if(!await j$.confirm({message:"Are you sure you want to deploy to production?",initial:!0}))R.info("Aborting deployment..."),E.exit(K0.InvalidArgument)}async function _6(Q,$,J){if(R.debug("Configuring domain...",Q),!Q)R.info("We could not identify a domain to deploy to."),R.warn("Please set your .env or ./config/app.ts properly."),R.info("Alternatively, specify a domain to deploy via the `--domain` flag."),console.log(""),R.info(" \u27A1\uFE0F Example: `buddy deploy --domain example.com`"),console.log(""),E.exit(K0.FatalError);if(Q.includes("localhost"))R.info("You are deploying to a local environment."),R.warn("Please set your .env or ./config/app.ts properly. The domain we are deploying cannot be a `localhost` domain."),R.info("Alternatively, specify a domain to deploy via the `--domain` flag."),console.log(""),R.info(" \u27A1\uFE0F Example: `buddy deploy --domain example.com`"),console.log(""),E.exit(K0.FatalError);if(await m3(Q))return R.info("Domain is properly configured"),R.info("Your cloud is deploying..."),R.info(`${Q7("This may take a while...")}`),Q;console.log(""),R.info(` \uD83D\uDC4B It appears to be your first ${Q7(Q)} deployment.`),console.log(""),R.info(Q7("Let\u2019s ensure it is all connected properly.")),R.info(Q7("One moment...")),console.log("");let Y=await c3({...$,deploy:!0,startTime:J});if(Y.isErr)await l7("While running the `buddy deploy`, there was an issue",{startTime:J,useSeconds:!0},Y.error),E.exit(K0.FatalError);await l7("Added your domain.",{startTime:J,useSeconds:!0}),E.exit(K0.Success)}async function U6(){let Q=await j$.text({message:"AWS Access Key ID:",validate:(G)=>G.length>0?!0:"Access Key ID is required"});if(!Q)R.info("Deployment cancelled"),E.exit(K0.Success);let $=await j$.password({message:"AWS Secret Access Key:",validate:(G)=>G.length>0?!0:"Secret Access Key is required"});if(!$)R.info("Deployment cancelled"),E.exit(K0.Success);let J=await j$.text({message:"AWS Region:",initial:"us-east-1"});if(!J)R.info("Deployment cancelled"),E.exit(K0.Success);let{setEnv:Y}=await import("@stacksjs/env");await Y("AWS_ACCESS_KEY_ID",Q,{file:".env.production",encrypt:!0}),await Y("AWS_SECRET_ACCESS_KEY",$,{file:".env.production",encrypt:!0}),await Y("AWS_REGION",J||"us-east-1",{file:".env.production"}),E.env.AWS_ACCESS_KEY_ID=Q,E.env.AWS_SECRET_ACCESS_KEY=$,E.env.AWS_REGION=J||"us-east-1",R.success("AWS credentials saved securely to .env.production"),console.log("")}function L6(){let Q=E.env.APP_ENV||E.env.NODE_ENV||"production",$=[E0.projectPath(`.env.${Q}`),E0.projectPath(".env")];for(let J of $){if(!j0(J))continue;try{let G=t0(J,"utf-8").split(`
303
- `),z,W,X,H;for(let q of G){let Z=q.trim();if(Z.startsWith("#")||!Z.includes("="))continue;let[K,..._]=Z.split("="),U=_.join("=").trim();if(K==="AWS_ACCESS_KEY_ID"&&U)z=U;else if(K==="AWS_SECRET_ACCESS_KEY"&&U)W=U;else if(K==="AWS_REGION"&&U)X=U;else if(K==="AWS_ACCOUNT_ID"&&U)H=U}if(z&&W)return R.debug(`Found AWS credentials in ${J}`),{accessKeyId:z,secretAccessKey:W,region:X,accountId:H}}catch(Y){R.debug(`Failed to read ${J} file:`,Y)}}return{}}async function F6(Q){let $=!1;try{R.info("Ensuring AWS cloud stack exists...");let J=E.env.AWS_ACCESS_KEY_ID&&E.env.AWS_SECRET_ACCESS_KEY;if(!J){let F=L6();if(F.accessKeyId&&F.secretAccessKey){if(E.env.AWS_ACCESS_KEY_ID=F.accessKeyId,E.env.AWS_SECRET_ACCESS_KEY=F.secretAccessKey,F.region&&!E.env.AWS_REGION)E.env.AWS_REGION=F.region;if(F.accountId&&!E.env.AWS_ACCOUNT_ID)E.env.AWS_ACCOUNT_ID=F.accountId;J=!0;let O=E.env.APP_ENV||E.env.NODE_ENV||"production";R.success(`Using AWS credentials from .env.${O}`)}}if(!J){let F=H6();if(F.accessKeyId&&F.secretAccessKey){if(E.env.AWS_ACCESS_KEY_ID=F.accessKeyId,E.env.AWS_SECRET_ACCESS_KEY=F.secretAccessKey,F.region&&!E.env.AWS_REGION)E.env.AWS_REGION=F.region;J=!0,R.success("Using AWS credentials from ~/.aws/credentials")}}if(!J){if(R.info("AWS credentials not found in .env or ~/.aws/credentials."),R.info("You can either:"),R.info(" 1. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY in .env.production"),R.info(" 2. Add credentials to ~/.aws/credentials"),R.info(" 3. Configure them interactively below"),console.log(""),Q?.yes)R.info("Skipping credential setup (--yes flag provided)"),E.exit(K0.FatalError);let F=await j$.confirm({message:"Would you like to configure AWS credentials now?",initial:!0});if(R.debug("setupCredentials response:",F,typeof F),F===void 0||F===!1){if(F===void 0)console.log(""),R.info("Deployment cancelled"),E.exit(K0.Success);return console.log(""),R.info("Skipping cloud infrastructure check"),R.info("You can configure AWS credentials later by running: buddy configure:aws"),!0}await U6()}else R.success("AWS credentials found");let Y=(E.env.APP_NAME||p3.name||"stacks").toLowerCase().replace(/[^a-z0-9-]/g,"-"),G=`${Y}-cloud`,{AWSCloudFormationClient:z}=await import("@stacksjs/ts-cloud"),W=new z(E.env.AWS_REGION||"us-east-1"),X=!1,H=!1;try{let F=(await W.describeStacks({stackName:G})).Stacks?.[0];if(F){X=!0,R.success("Cloud stack exists");let{AWSCloudFormationClient:O}=await import("@stacksjs/ts-cloud"),T=await new O(E.env.AWS_REGION||"us-east-1").listStackResources(G),f=T.StackResourceSummaries?.some((i)=>i.LogicalResourceId==="EmailBucket"),P=T.StackResourceSummaries?.some((i)=>i.LogicalResourceId==="OutboundEmailLambda"),I=T.StackResourceSummaries?.some((i)=>i.LogicalResourceId==="EmailConversionLambda"),j=T.StackResourceSummaries?.some((i)=>i.LogicalResourceId==="EmailNotificationTopic"),A=T.StackResourceSummaries?.some((i)=>i.LogicalResourceId==="MailApiLambda"),h=T.StackResourceSummaries?.some((i)=>i.LogicalResourceId==="MailUsersTable"),V=T.StackResourceSummaries?.some((i)=>i.LogicalResourceId==="MailServerInstance"),N=F.Outputs?.find((i)=>i.OutputKey==="EmailDomain")?.OutputValue,B=(c?.from?.address?.includes("@")?c.from.address.split("@")[1]:void 0)||"stacksjs.com";if(!f&&c?.server?.scan!==void 0)R.info("Email infrastructure not found in stack, will update..."),H=!0;else if(N&&N!==B)R.info(`Email domain changed: ${N} -> ${B}, will update...`),H=!0;else if(f&&(!P||!I||!j))R.info("Email infrastructure incomplete, will update..."),H=!0;else if(f&&(!A||!h))R.info("Mail API infrastructure missing, will update..."),H=!0;else if(f&&!V&&c?.server?.enabled)R.info("Mail server EC2 instance missing, will update..."),H=!0;let v=(F.Outputs||[]).find((i)=>i.OutputKey==="MailServerMode")?.OutputValue,B0=c?.server?.mode||"serverless";if(v&&v!==B0)R.info(`Mail server mode changed: ${v} -> ${B0}, will update...`),H=!0;if(V&&c?.server?.enabled){if(E.env.FORCE_MAIL_UPDATE==="true")R.info("Forcing mail server update..."),H=!0}if(!H)return!0}}catch(F){R.debug(`Stack not found: ${F.message}`)}if(!X)R.info("Cloud stack not found, will be created by deploy action");return!0}catch(J){if(!$){if(R.error("Error checking cloud infrastructure"),R.error(`Error: ${J.message||J}`),Q?.verbose)console.error(J)}E.exit(K0.FatalError)}}import x from"process";import{bold as J7,cyan as m0,dim as Q0,green as Y7,intro as P2,log as N0,onUnknownSubcommand as V6,outro as U$,prompts as B6,runCommand as R6}from"@stacksjs/cli";import{Action as i3}from"@stacksjs/enums";import{libsPath as w6}from"@stacksjs/path";import{ExitCode as u0}from"@stacksjs/types";var a3="0.70.39";var f2;async function A0(){if(!f2)f2=await import("@stacksjs/actions");return f2}function AW(Q){let $={dev:"Start development server",frontend:"Start the frontend development server",components:"Start the Components development server",desktop:"Start the Desktop App development server",dashboard:"Start the Dashboard development server",api:"Start the local API development server",email:"Start the Email development server",docs:"Start the Documentation development server",systemTray:"Start the System Tray development server",interactive:"Get asked which development server to start",select:"Which development server are you trying to start?",withLocalhost:"Include the localhost URL in the output",project:"Target a specific project",verbose:"Enable verbose output"};Q.command("dev [server]",$.dev).option("-f, --frontend",$.frontend).option("-a, --api",$.api).option("-e, --email",$.email).option("-c, --components",$.components).option("-d, --dashboard",$.dashboard).option("-k, --desktop",$.desktop).option("-o, --docs",$.docs).option("-s, --system-tray",$.systemTray).option("-i, --interactive",$.interactive,{default:!1}).option("-l, --with-localhost",$.withLocalhost,{default:!1}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J,Y)=>{let G=Bun.nanoseconds(),z=J||(Y.frontend?"frontend":void 0)||(Y.api?"api":void 0)||(Y.components?"components":void 0)||(Y.dashboard?"dashboard":void 0)||(Y.desktop?"desktop":void 0)||(Y.systemTray||Y["system-tray"]?"system-tray":void 0)||(Y.docs?"docs":void 0);if(z){let W={...Y},X=await A0();switch(z){case"frontend":await X.runFrontendDevServer(W);break;case"api":await X.runApiDevServer(W);break;case"components":await X.runComponentsDevServer(W);break;case"dashboard":await X.runDashboardDevServer(W);break;case"desktop":await X.runDesktopDevServer(W);break;case"system-tray":await X.runSystemTrayDevServer(W);break;case"docs":await X.runDocsDevServer(W);break;default:N0.error(`Unknown server: ${z}`),x.exit(u0.InvalidArgument)}}else if(P6(Y)){let X=(await B6({type:"select",name:"value",message:$.select,choices:[{value:"all",title:"All"},{value:"frontend",title:"Frontend"},{value:"api",title:"Backend"},{value:"dashboard",title:"Dashboard"},{value:"desktop",title:"Desktop"},{value:"email",title:"Email"},{value:"components",title:"Components"},{value:"docs",title:"Documentation"}]})).value;if(X==="components")await(await A0()).runComponentsDevServer(Y);else if(X==="api")await(await A0()).runApiDevServer(Y);else if(X==="dashboard")await(await A0()).runDashboardDevServer(Y);else if(X==="docs")await(await A0()).runDocsDevServer(Y);else N0.error("Invalid option during interactive mode"),x.exit(u0.InvalidArgument)}else await M6(Y,G);U$("Exited",{startTime:G,useSeconds:!0}),x.exit(u0.Success)}),Q.command("dev:components",$.components).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{let Y=await P2("buddy dev:components"),G=await R6("bun run dev",{cwd:w6("components/vue")});if(J.verbose)N0.info("buddy dev:components result",G);if(G.isErr)await U$("While running the dev:components command, there was an issue",{startTime:Y,useSeconds:!0},G.error),x.exit(u0.FatalError);console.log(""),await U$("Exited",{startTime:Y,useSeconds:!0}),x.exit(u0.Success)}),Q.command("dev:docs",$.docs).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{let Y=await P2("buddy dev:docs"),G=await(await A0()).runAction(i3.DevDocs,J);if(G.isErr)await U$("While running the dev:docs command, there was an issue",{startTime:Y,useSeconds:!0},G.error),x.exit(u0.FatalError);console.log(""),await U$("Exited",{startTime:Y,useSeconds:!0}),x.exit(u0.Success)}),Q.command("dev:desktop",$.desktop).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{let Y=await P2("buddy dev:desktop"),G=await(await A0()).runAction(i3.DevDesktop,J);if(G.isErr)await U$("While running the dev:desktop command, there was an issue",{startTime:Y,useSeconds:!0},G.error),x.exit(u0.FatalError);console.log(""),await U$("Exited",{startTime:Y,useSeconds:!0}),x.exit(u0.Success)}),Q.command("dev:api",$.api).option("-p, --project [project]",$.project,{default:!1}).option("--no-watch-types","Skip the model/config type-regeneration watcher",{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{let Y=await A0();if(J.watchTypes!==!1)Y.watchTypes(J).catch((G)=>{N0.warn("[dev:api] type watcher exited:",G)});await Y.runApiDevServer(J)}),Q.command("dev:frontend",$.frontend).alias("dev:pages").alias("dev:views").option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{await(await A0()).runFrontendDevServer(J)}),Q.command("dev:dashboard",$.dashboard).alias("dev:admin").option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{await(await A0()).runDashboardDevServer(J)}),Q.command("dev:system-tray",$.systemTray).alias("dev:tray").option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{await(await A0()).runSystemTrayDevServer(J)}),V6(Q,"dev")}async function M6(Q,$){let J=x.env.APP_URL,Y=Number(x.env.PORT)||3000,G=Number(x.env.PORT_API)||3008,z=Number(x.env.PORT_DOCS)||3006,W=Number(x.env.PORT_ADMIN)||3002,X=x.env.STACKS_DEV_DASHBOARD==="1",H=J&&J!=="localhost"&&!J.includes("localhost:"),q=H?J.replace(/^https?:\/\//,""):null,Z=q?`api.${q}`:null,K=q?`docs.${q}`:null,_=q?`dashboard.${q}`:null,U=q?`https://${q}`:`http://localhost:${Y}`,L=Z?`https://${Z}`:`http://localhost:${G}`,F=K?`https://${K}`:`http://localhost:${z}`,O=_?`https://${_}`:`http://localhost:${W}`;if(console.log(),console.log(` ${J7(m0("stacks"))} ${Q0(`v${a3}`)}`),console.log(),console.log(` ${Y7("\u279C")} ${J7("Frontend")}: ${m0(U)}`),console.log(` ${Y7("\u279C")} ${J7("API")}: ${m0(L)}`),console.log(` ${Y7("\u279C")} ${J7("Docs")}: ${m0(F)}`),X)console.log(` ${Y7("\u279C")} ${J7("Dashboard")}: ${m0(O)}`);if(Q.verbose&&q){if(console.log(` ${Q0("\u279C")} ${Q0("Proxy")}: ${Q0(`localhost:${Y} \u2192 ${q}`)}`),console.log(` ${Q0("\u279C")} ${Q0("Proxy")}: ${Q0(`localhost:${G} \u2192 ${Z}`)}`),console.log(` ${Q0("\u279C")} ${Q0("Proxy")}: ${Q0(`localhost:${z} \u2192 ${K}`)}`),X)console.log(` ${Q0("\u279C")} ${Q0("Proxy")}: ${Q0(`localhost:${W} \u2192 ${_}`)}`)}if(console.log(),x.env.STACKS_PROXY_MANAGED="1",x.env.STACKS_DEV_NO_KILL!=="1")try{await Bun.spawn(["pkill","-9","-f","bun --watch storage/framework/core/actions/src/dev/"],{stdout:"ignore",stderr:"ignore"}).exited,await new Promise((V)=>setTimeout(V,200))}catch{}let M=!1,T=1500,f=()=>{if(M)return;M=!0;try{x.kill(-x.pid,"SIGTERM")}catch{try{x.kill(0,"SIGTERM")}catch{}}setTimeout(()=>{try{x.kill(0,"SIGKILL")}catch{x.exit(1)}},T).unref()};x.on("SIGINT",f),x.on("SIGTERM",f);let P={...Q,quiet:!0},I=await A0(),j=[{name:"Frontend",port:Y},{name:"API",port:G},{name:"Docs",port:z},...X?[{name:"Dashboard",port:W}]:[]],A=30000,h=!1;Promise.all(j.map((V)=>j6(V.port,A))).then(async(V)=>{if(h)return;h=!0;let N=V.map((B,v)=>B?null:j[v].name).filter((B)=>B!==null);if($){let B=(Bun.nanoseconds()-$)/1e6,v=N.length?`ready in ${(B/1000).toFixed(1)}s \u2014 ${N.join(", ")} did not bind within ${A/1000}s`:`ready in ${(B/1000).toFixed(1)}s`;console.log(` ${Q0(v)}
303
+ `),z,W,X,H;for(let q of G){let Z=q.trim();if(Z.startsWith("#")||!Z.includes("="))continue;let[K,..._]=Z.split("="),U=_.join("=").trim();if(K==="AWS_ACCESS_KEY_ID"&&U)z=U;else if(K==="AWS_SECRET_ACCESS_KEY"&&U)W=U;else if(K==="AWS_REGION"&&U)X=U;else if(K==="AWS_ACCOUNT_ID"&&U)H=U}if(z&&W)return R.debug(`Found AWS credentials in ${J}`),{accessKeyId:z,secretAccessKey:W,region:X,accountId:H}}catch(Y){R.debug(`Failed to read ${J} file:`,Y)}}return{}}async function F6(Q){let $=!1;try{R.info("Ensuring AWS cloud stack exists...");let J=E.env.AWS_ACCESS_KEY_ID&&E.env.AWS_SECRET_ACCESS_KEY;if(!J){let F=L6();if(F.accessKeyId&&F.secretAccessKey){if(E.env.AWS_ACCESS_KEY_ID=F.accessKeyId,E.env.AWS_SECRET_ACCESS_KEY=F.secretAccessKey,F.region&&!E.env.AWS_REGION)E.env.AWS_REGION=F.region;if(F.accountId&&!E.env.AWS_ACCOUNT_ID)E.env.AWS_ACCOUNT_ID=F.accountId;J=!0;let O=E.env.APP_ENV||E.env.NODE_ENV||"production";R.success(`Using AWS credentials from .env.${O}`)}}if(!J){let F=H6();if(F.accessKeyId&&F.secretAccessKey){if(E.env.AWS_ACCESS_KEY_ID=F.accessKeyId,E.env.AWS_SECRET_ACCESS_KEY=F.secretAccessKey,F.region&&!E.env.AWS_REGION)E.env.AWS_REGION=F.region;J=!0,R.success("Using AWS credentials from ~/.aws/credentials")}}if(!J){if(R.info("AWS credentials not found in .env or ~/.aws/credentials."),R.info("You can either:"),R.info(" 1. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY in .env.production"),R.info(" 2. Add credentials to ~/.aws/credentials"),R.info(" 3. Configure them interactively below"),console.log(""),Q?.yes)R.info("Skipping credential setup (--yes flag provided)"),E.exit(K0.FatalError);let F=await j$.confirm({message:"Would you like to configure AWS credentials now?",initial:!0});if(R.debug("setupCredentials response:",F,typeof F),F===void 0||F===!1){if(F===void 0)console.log(""),R.info("Deployment cancelled"),E.exit(K0.Success);return console.log(""),R.info("Skipping cloud infrastructure check"),R.info("You can configure AWS credentials later by running: buddy configure:aws"),!0}await U6()}else R.success("AWS credentials found");let Y=(E.env.APP_NAME||p3.name||"stacks").toLowerCase().replace(/[^a-z0-9-]/g,"-"),G=`${Y}-cloud`,{AWSCloudFormationClient:z}=await import("@stacksjs/ts-cloud"),W=new z(E.env.AWS_REGION||"us-east-1"),X=!1,H=!1;try{let F=(await W.describeStacks({stackName:G})).Stacks?.[0];if(F){X=!0,R.success("Cloud stack exists");let{AWSCloudFormationClient:O}=await import("@stacksjs/ts-cloud"),T=await new O(E.env.AWS_REGION||"us-east-1").listStackResources(G),f=T.StackResourceSummaries?.some((i)=>i.LogicalResourceId==="EmailBucket"),P=T.StackResourceSummaries?.some((i)=>i.LogicalResourceId==="OutboundEmailLambda"),I=T.StackResourceSummaries?.some((i)=>i.LogicalResourceId==="EmailConversionLambda"),j=T.StackResourceSummaries?.some((i)=>i.LogicalResourceId==="EmailNotificationTopic"),A=T.StackResourceSummaries?.some((i)=>i.LogicalResourceId==="MailApiLambda"),h=T.StackResourceSummaries?.some((i)=>i.LogicalResourceId==="MailUsersTable"),V=T.StackResourceSummaries?.some((i)=>i.LogicalResourceId==="MailServerInstance"),N=F.Outputs?.find((i)=>i.OutputKey==="EmailDomain")?.OutputValue,B=(c?.from?.address?.includes("@")?c.from.address.split("@")[1]:void 0)||"stacksjs.com";if(!f&&c?.server?.scan!==void 0)R.info("Email infrastructure not found in stack, will update..."),H=!0;else if(N&&N!==B)R.info(`Email domain changed: ${N} -> ${B}, will update...`),H=!0;else if(f&&(!P||!I||!j))R.info("Email infrastructure incomplete, will update..."),H=!0;else if(f&&(!A||!h))R.info("Mail API infrastructure missing, will update..."),H=!0;else if(f&&!V&&c?.server?.enabled)R.info("Mail server EC2 instance missing, will update..."),H=!0;let v=(F.Outputs||[]).find((i)=>i.OutputKey==="MailServerMode")?.OutputValue,B0=c?.server?.mode||"serverless";if(v&&v!==B0)R.info(`Mail server mode changed: ${v} -> ${B0}, will update...`),H=!0;if(V&&c?.server?.enabled){if(E.env.FORCE_MAIL_UPDATE==="true")R.info("Forcing mail server update..."),H=!0}if(!H)return!0}}catch(F){R.debug(`Stack not found: ${F.message}`)}if(!X)R.info("Cloud stack not found, will be created by deploy action");return!0}catch(J){if(!$){if(R.error("Error checking cloud infrastructure"),R.error(`Error: ${J.message||J}`),Q?.verbose)console.error(J)}E.exit(K0.FatalError)}}import x from"process";import{bold as J7,cyan as m0,dim as Q0,green as Y7,intro as P2,log as N0,onUnknownSubcommand as V6,outro as U$,prompts as B6,runCommand as R6}from"@stacksjs/cli";import{Action as i3}from"@stacksjs/enums";import{libsPath as w6}from"@stacksjs/path";import{ExitCode as u0}from"@stacksjs/types";var a3="0.70.40";var f2;async function A0(){if(!f2)f2=await import("@stacksjs/actions");return f2}function AW(Q){let $={dev:"Start development server",frontend:"Start the frontend development server",components:"Start the Components development server",desktop:"Start the Desktop App development server",dashboard:"Start the Dashboard development server",api:"Start the local API development server",email:"Start the Email development server",docs:"Start the Documentation development server",systemTray:"Start the System Tray development server",interactive:"Get asked which development server to start",select:"Which development server are you trying to start?",withLocalhost:"Include the localhost URL in the output",project:"Target a specific project",verbose:"Enable verbose output"};Q.command("dev [server]",$.dev).option("-f, --frontend",$.frontend).option("-a, --api",$.api).option("-e, --email",$.email).option("-c, --components",$.components).option("-d, --dashboard",$.dashboard).option("-k, --desktop",$.desktop).option("-o, --docs",$.docs).option("-s, --system-tray",$.systemTray).option("-i, --interactive",$.interactive,{default:!1}).option("-l, --with-localhost",$.withLocalhost,{default:!1}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J,Y)=>{let G=Bun.nanoseconds(),z=J||(Y.frontend?"frontend":void 0)||(Y.api?"api":void 0)||(Y.components?"components":void 0)||(Y.dashboard?"dashboard":void 0)||(Y.desktop?"desktop":void 0)||(Y.systemTray||Y["system-tray"]?"system-tray":void 0)||(Y.docs?"docs":void 0);if(z){let W={...Y},X=await A0();switch(z){case"frontend":await X.runFrontendDevServer(W);break;case"api":await X.runApiDevServer(W);break;case"components":await X.runComponentsDevServer(W);break;case"dashboard":await X.runDashboardDevServer(W);break;case"desktop":await X.runDesktopDevServer(W);break;case"system-tray":await X.runSystemTrayDevServer(W);break;case"docs":await X.runDocsDevServer(W);break;default:N0.error(`Unknown server: ${z}`),x.exit(u0.InvalidArgument)}}else if(P6(Y)){let X=(await B6({type:"select",name:"value",message:$.select,choices:[{value:"all",title:"All"},{value:"frontend",title:"Frontend"},{value:"api",title:"Backend"},{value:"dashboard",title:"Dashboard"},{value:"desktop",title:"Desktop"},{value:"email",title:"Email"},{value:"components",title:"Components"},{value:"docs",title:"Documentation"}]})).value;if(X==="components")await(await A0()).runComponentsDevServer(Y);else if(X==="api")await(await A0()).runApiDevServer(Y);else if(X==="dashboard")await(await A0()).runDashboardDevServer(Y);else if(X==="docs")await(await A0()).runDocsDevServer(Y);else N0.error("Invalid option during interactive mode"),x.exit(u0.InvalidArgument)}else await M6(Y,G);U$("Exited",{startTime:G,useSeconds:!0}),x.exit(u0.Success)}),Q.command("dev:components",$.components).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{let Y=await P2("buddy dev:components"),G=await R6("bun run dev",{cwd:w6("components/vue")});if(J.verbose)N0.info("buddy dev:components result",G);if(G.isErr)await U$("While running the dev:components command, there was an issue",{startTime:Y,useSeconds:!0},G.error),x.exit(u0.FatalError);console.log(""),await U$("Exited",{startTime:Y,useSeconds:!0}),x.exit(u0.Success)}),Q.command("dev:docs",$.docs).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{let Y=await P2("buddy dev:docs"),G=await(await A0()).runAction(i3.DevDocs,J);if(G.isErr)await U$("While running the dev:docs command, there was an issue",{startTime:Y,useSeconds:!0},G.error),x.exit(u0.FatalError);console.log(""),await U$("Exited",{startTime:Y,useSeconds:!0}),x.exit(u0.Success)}),Q.command("dev:desktop",$.desktop).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{let Y=await P2("buddy dev:desktop"),G=await(await A0()).runAction(i3.DevDesktop,J);if(G.isErr)await U$("While running the dev:desktop command, there was an issue",{startTime:Y,useSeconds:!0},G.error),x.exit(u0.FatalError);console.log(""),await U$("Exited",{startTime:Y,useSeconds:!0}),x.exit(u0.Success)}),Q.command("dev:api",$.api).option("-p, --project [project]",$.project,{default:!1}).option("--no-watch-types","Skip the model/config type-regeneration watcher",{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{let Y=await A0();if(J.watchTypes!==!1)Y.watchTypes(J).catch((G)=>{N0.warn("[dev:api] type watcher exited:",G)});await Y.runApiDevServer(J)}),Q.command("dev:frontend",$.frontend).alias("dev:pages").alias("dev:views").option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{await(await A0()).runFrontendDevServer(J)}),Q.command("dev:dashboard",$.dashboard).alias("dev:admin").option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{await(await A0()).runDashboardDevServer(J)}),Q.command("dev:system-tray",$.systemTray).alias("dev:tray").option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J)=>{await(await A0()).runSystemTrayDevServer(J)}),V6(Q,"dev")}async function M6(Q,$){let J=x.env.APP_URL,Y=Number(x.env.PORT)||3000,G=Number(x.env.PORT_API)||3008,z=Number(x.env.PORT_DOCS)||3006,W=Number(x.env.PORT_ADMIN)||3002,X=x.env.STACKS_DEV_DASHBOARD==="1",H=J&&J!=="localhost"&&!J.includes("localhost:"),q=H?J.replace(/^https?:\/\//,""):null,Z=q?`api.${q}`:null,K=q?`docs.${q}`:null,_=q?`dashboard.${q}`:null,U=q?`https://${q}`:`http://localhost:${Y}`,L=Z?`https://${Z}`:`http://localhost:${G}`,F=K?`https://${K}`:`http://localhost:${z}`,O=_?`https://${_}`:`http://localhost:${W}`;if(console.log(),console.log(` ${J7(m0("stacks"))} ${Q0(`v${a3}`)}`),console.log(),console.log(` ${Y7("\u279C")} ${J7("Frontend")}: ${m0(U)}`),console.log(` ${Y7("\u279C")} ${J7("API")}: ${m0(L)}`),console.log(` ${Y7("\u279C")} ${J7("Docs")}: ${m0(F)}`),X)console.log(` ${Y7("\u279C")} ${J7("Dashboard")}: ${m0(O)}`);if(Q.verbose&&q){if(console.log(` ${Q0("\u279C")} ${Q0("Proxy")}: ${Q0(`localhost:${Y} \u2192 ${q}`)}`),console.log(` ${Q0("\u279C")} ${Q0("Proxy")}: ${Q0(`localhost:${G} \u2192 ${Z}`)}`),console.log(` ${Q0("\u279C")} ${Q0("Proxy")}: ${Q0(`localhost:${z} \u2192 ${K}`)}`),X)console.log(` ${Q0("\u279C")} ${Q0("Proxy")}: ${Q0(`localhost:${W} \u2192 ${_}`)}`)}if(console.log(),x.env.STACKS_PROXY_MANAGED="1",x.env.STACKS_DEV_NO_KILL!=="1")try{await Bun.spawn(["pkill","-9","-f","bun --watch storage/framework/core/actions/src/dev/"],{stdout:"ignore",stderr:"ignore"}).exited,await new Promise((V)=>setTimeout(V,200))}catch{}let M=!1,T=1500,f=()=>{if(M)return;M=!0;try{x.kill(-x.pid,"SIGTERM")}catch{try{x.kill(0,"SIGTERM")}catch{}}setTimeout(()=>{try{x.kill(0,"SIGKILL")}catch{x.exit(1)}},T).unref()};x.on("SIGINT",f),x.on("SIGTERM",f);let P={...Q,quiet:!0},I=await A0(),j=[{name:"Frontend",port:Y},{name:"API",port:G},{name:"Docs",port:z},...X?[{name:"Dashboard",port:W}]:[]],A=30000,h=!1;Promise.all(j.map((V)=>j6(V.port,A))).then(async(V)=>{if(h)return;h=!0;let N=V.map((B,v)=>B?null:j[v].name).filter((B)=>B!==null);if($){let B=(Bun.nanoseconds()-$)/1e6,v=N.length?`ready in ${(B/1000).toFixed(1)}s \u2014 ${N.join(", ")} did not bind within ${A/1000}s`:`ready in ${(B/1000).toFixed(1)}s`;console.log(` ${Q0(v)}
304
304
  `)}if(x.env.STACKS_PRINT_ROUTES==="1")await I6(G).catch(()=>{})}).catch(()=>{}),await Promise.all([I.runFrontendDevServer(P).catch((V)=>{if(Q.verbose)N0.error(`Frontend: ${V}`)}),I.runApiDevServer(P).catch((V)=>{if(Q.verbose)N0.error(`API: ${V}`)}),I.runDocsDevServer(P).catch((V)=>{if(Q.verbose)N0.error(`Docs: ${V}`)}),X?I.runDashboardDevServer(P).catch((V)=>{if(Q.verbose)N0.error(`Dashboard: ${V}`)}):Promise.resolve(),H?A6(Q).catch((V)=>{if(Q.verbose)N0.warn(`Proxy: ${V}`)}):Promise.resolve()])}var T6={GET:m0,POST:Y7,PUT:m0,PATCH:m0,DELETE:m0,OPTIONS:Q0};async function I6(Q){try{let $=new AbortController,J=setTimeout(()=>$.abort(),1500),Y=await fetch(`http://127.0.0.1:${Q}/__routes`,{signal:$.signal}).catch(()=>null);if(clearTimeout(J),!Y||!Y.ok)return;let G=await Y.json();if(!Array.isArray(G)||G.length===0)return;let z=[...G].sort((X,H)=>X.path.localeCompare(H.path)||X.method.localeCompare(H.method)),W=Math.max(...z.map((X)=>X.path.length));console.log(` ${Q0("Registered routes")}
305
305
  `);for(let X of z){let q=(T6[X.method.toUpperCase()]??Q0)(X.method.toUpperCase().padEnd(6)),Z=X.path.padEnd(W),K=X.name?` ${Q0(`(${X.name})`)}`:"";console.log(` ${q} ${Z}${K}`)}console.log()}catch{}}async function j6(Q,$){let J=Date.now()+$;while(Date.now()<J){if(await new Promise((G)=>{let z=new AbortController,W=setTimeout(()=>z.abort(),800);fetch(`http://127.0.0.1:${Q}/__health`,{signal:z.signal,redirect:"manual"}).then(()=>{clearTimeout(W),G(!0)}).catch(()=>{clearTimeout(W),G(!1)})}))return!0;await new Promise((G)=>setTimeout(G,250))}return!1}async function A6(Q){let $=x.env.APP_URL;if(!$||$==="localhost"||$.includes("localhost:"))return;let J=$.replace(/^https?:\/\//,""),Y=`api.${J}`,G=`docs.${J}`,z=`dashboard.${J}`,W=Number(x.env.PORT)||3000,X=Number(x.env.PORT_API)||3008,H=Number(x.env.PORT_DOCS)||3006,q=Number(x.env.PORT_ADMIN)||3002,Z=`${x.env.HOME}/.stacks/ssl`,K=Q.verbose??!1,_=x.env.STACKS_DEV_DASHBOARD==="1";try{let{startProxies:U}=await import("@stacksjs/rpx");await U({proxies:[{from:`localhost:${W}`,to:J,cleanUrls:!1,pathRewrites:[{from:"/api",to:`localhost:${X}`,stripPrefix:!1}]},{from:`localhost:${X}`,to:Y,cleanUrls:!1},{from:`localhost:${H}`,to:G,cleanUrls:!1},..._?[{from:`localhost:${q}`,to:z,cleanUrls:!1}]:[]],https:{basePath:Z,validityDays:825},regenerateUntrustedCerts:!1,verbose:K})}catch(U){if(Q.verbose)N0.warn("Reverse proxy not available, skipping HTTPS"),N0.warn(String(U))}}function P6(Q){return Q.interactive}import s3 from"process";import{log as o3,onUnknownSubcommand as f6}from"@stacksjs/cli";import{config as v6}from"@stacksjs/config";import{DnsClient as S6,formatOutput as E6}from"@stacksjs/dnsx";import{ExitCode as t3}from"@stacksjs/types";function CW(Q){let $={dns:"Lists the DNS records for a domain",query:"Host name or IP address to query",type:"Type of the DNS record being queried (A, MX, NS\u2026)",nameserver:"Address of the nameserver to send packets to",class:"Network class of the DNS record being queried (IN, CH, HS)",udp:"Use the DNS protocol over UDP",tcp:"Use the DNS protocol over TCP",tls:"Use the DNS-over-TLS protocol",https:"Use the DNS-over-HTTPS protocol",short:"Short mode: display nothing but the first result",json:"Display the output as JSON",project:"Target a specific project",verbose:"Enable verbose output"};Q.command("dns [domain]",$.dns).option("-q, --query <query>",$.query).option("-t, --type <type>",$.type,{default:"A"}).option("-n, --nameserver <nameserver>",$.nameserver).option("--class <class>",$.class).option("-U, --udp",$.udp).option("-T, --tcp",$.tcp).option("-S, --tls",$.tls).option("-H, --https",$.https).option("-1, --short",$.short,{default:!1}).option("-J, --json",$.json,{default:!1}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(J,Y)=>{o3.debug("Running `buddy dns [domain]` ...",Y);let G=J||v6.app.url;try{let z=new S6({domains:[G],type:Y.type,nameserver:Y.nameserver,class:Y.class,udp:Y.udp,tcp:Y.tcp,tls:Y.tls,https:Y.https,short:Y.short,json:Y.json,verbose:Y.verbose}),W=performance.now(),X=await z.query(),H=performance.now()-W,q=E6(X,{json:Y.json??!1,short:Y.short??!1,showDuration:H,colors:{enabled:!0},rawSeconds:!1});console.log(q)}catch(z){o3.error(`DNS query failed: ${z instanceof Error?z.message:String(z)}`),s3.exit(t3.FatalError)}s3.exit(t3.Success)}),f6(Q,"dns")}import c0 from"process";import{bold as e3,dim as v2,green as $1,intro as N6,log as R0,onUnknownSubcommand as C6,red as h6,yellow as Q1}from"@stacksjs/cli";import{storage as J1}from"@stacksjs/storage";async function G7(Q,$,J){let Y=Date.now();try{let G=new AbortController,z=setTimeout(()=>G.abort(),2000),W=await Promise.race([J(),new Promise((X,H)=>G.signal.addEventListener("abort",()=>H(Error("timed out (>2s)"))))]);clearTimeout(z),Q.push({name:$,status:"pass",message:`${W} (${Date.now()-Y}ms)`})}catch(G){Q.push({name:$,status:"fail",message:G instanceof Error?G.message:String(G)})}}function kW(Q){Q.command("doctor","Run health checks on your Stacks installation").action(async()=>{R0.debug("Running `buddy doctor` ..."),await N6("buddy doctor");let $=[],J=c0.versions.bun;if(J)if(Number.parseInt(J.split(".")[0]||"0",10)>=1)$.push({name:"Bun Runtime",status:"pass",message:`v${J}`});else $.push({name:"Bun Runtime",status:"warn",message:`v${J} (v1.0+ recommended)`});else $.push({name:"Bun Runtime",status:"fail",message:"Not found"});let Y=c0.versions.node;if(Y)if(Number.parseInt(Y.split(".")[0]||"0",10)>=18)$.push({name:"Node.js",status:"pass",message:`v${Y}`});else $.push({name:"Node.js",status:"warn",message:`v${Y} (v18+ recommended)`});try{let q=await J1.readPackageJson("./package.json");if(q.name)$.push({name:"package.json",status:"pass",message:`Found: ${q.name}`})}catch{$.push({name:"package.json",status:"fail",message:"Not found in current directory"})}try{await J1.readTextFile(".env"),$.push({name:".env file",status:"pass",message:"Found"})}catch{$.push({name:".env file",status:"warn",message:"Not found (optional)"})}let G=c0.env.APP_KEY;if(G&&G.length>0)$.push({name:"APP_KEY",status:G.length>=32?"pass":"warn",message:G.length>=32?"Set (\u226532 chars)":`Set but short (${G.length} chars; \u226532 recommended)`});else $.push({name:"APP_KEY",status:"fail",message:"Not set \u2014 features that depend on it (encrypted columns, signed URLs, env decryption) will refuse to run. Run `buddy key:generate`."});await G7($,"Database",async()=>{let{db:q}=await import("@stacksjs/database");return await q.unsafe?.("SELECT 1"),"Reachable"}),await G7($,"Cache",async()=>{let{cache:q}=await import("@stacksjs/cache"),Z=`__doctor_${Date.now()}`;await q.set(Z,1,5);let K=await q.get(Z);if(await q.del(Z),K!==1)throw Error("round-trip failed");return"Round-trip ok"}),await G7($,"Queue driver",async()=>{let{config:q}=await import("@stacksjs/config");return`Driver: ${q.queue?.default??"sync"}`}),await G7($,"Mail driver",async()=>{let{config:q}=await import("@stacksjs/config");return`Driver: ${q.email?.default??"log"}`});let z=Boolean(c0.env.AWS_ACCESS_KEY_ID&&c0.env.AWS_SECRET_ACCESS_KEY),W=Boolean(c0.env.AWS_PROFILE)||Boolean(c0.env.AWS_ROLE_ARN);if(z||W)$.push({name:"AWS credentials",status:"pass",message:z?"Static keys in env":"IAM role configured"});else $.push({name:"AWS credentials",status:"warn",message:"Not configured (cloud / SES / S3 commands will fail)"});await G7($,".env decryption",async()=>{let q=await import("fs");if(!q.existsSync(".env"))return"No .env (skipped)";let Z=q.readFileSync(".env","utf8");if(!/(?:^|=)(?:enc|encrypted):/m.test(Z))return"No encrypted values";let K=c0.env.DOTENV_PRIVATE_KEY;if(!K)throw Error("Encrypted values present but DOTENV_PRIVATE_KEY is unset");let{parse:_}=await import("@stacksjs/env"),{errors:U}=_(Z,{privateKey:K});if(U.length>0)throw Error(U.join("; "));return"All encrypted values decrypt cleanly"}),R0.info(""),R0.info(e3("Health Check Results:")),R0.info(v2("\u2500".repeat(60))),R0.info("");let X=!1,H=!1;for(let q of $){let Z="",K=(_)=>_;if(q.status==="pass")Z="\u2713",K=$1;else if(q.status==="warn")Z="\u26A0",K=Q1,H=!0;else Z="\u2717",K=h6,X=!0;R0.info(`${K(Z)} ${e3(q.name.padEnd(20))} ${v2(q.message)}`)}if(R0.info(""),R0.info(v2("\u2500".repeat(60))),R0.info(""),X)R0.error("Some critical checks failed. Please address the issues above."),c0.exit(1);else if(H)R0.info(Q1("Some checks have warnings. Your system should work but may have issues."));else R0.success($1("All checks passed! Your Stacks installation looks healthy."));R0.info("")}),C6(Q,"doctor")}import e0 from"process";import{runAction as Y1}from"@stacksjs/actions";import{bgCyan as D6,bold as b6,intro as S2,italic as L$,log as d7,onUnknownSubcommand as y6,outro as $$,prompts as G1}from"@stacksjs/cli";import{config as z1}from"@stacksjs/config";import{addDomain as k6}from"@stacksjs/dns";import{Action as W1}from"@stacksjs/enums";import{ExitCode as Q$}from"@stacksjs/types";function rW(Q){let $={purchase:"Purchase a domain",add:"Add a domain to your cloud",remove:"Remove a domain from your cloud",skip:"Skip the confirmation prompt",project:"Target a specific project",verbose:"Enable verbose output"},J=z1.dns.contactInfo;Q.command("domains:purchase <domain>",$.purchase).option("--years <years>","Number of years to purchase the domain for",{default:1}).option("--privacy","Enable privacy protection",{default:!0}).option("--auto-renew","Enable auto-renew",{default:!0}).option("--first-name <firstName>","Registrant first name",{default:J?.firstName}).option("--last-name <lastName>","Registrant last name",{default:J?.lastName}).option("--organization <organization>","Registrant organization name",{default:J?.organizationName}).option("--address-line1 <address>","Registrant address line 1",{default:J?.addressLine1}).option("--address-line2 <address>","Registrant address line 2",{default:J?.addressLine2}).option("--city <city>","Registrant city",{default:J?.city}).option("--state <state>","Registrant state",{default:J?.state}).option("--country <country>","Registrant country code",{default:J?.countryCode}).option("--zip <zip>","Registrant zip",{default:J?.zip}).option("--phone <phone>","Registrant phone",{default:J?.phoneNumber}).option("--email <email>","Registrant email",{default:J?.email}).option("--admin-first-name <firstName>","Admin first name",{default:J?.admin?.firstName||J?.firstName}).option("--admin-last-name <lastName>","Admin last name",{default:J?.admin?.lastName||J?.lastName}).option("--admin-organization <organization>","Admin organization",{default:J?.admin?.organizationName||J?.organizationName}).option("--admin-address-line1 <address>","Admin address line 1",{default:J?.admin?.addressLine1||J?.addressLine1}).option("--admin-address-line2 <address>","Admin address line 2",{default:J?.admin?.addressLine2||J?.addressLine2}).option("--admin-city <city>","Admin city",{default:J?.admin?.city||J?.city}).option("--admin-state <state>","Admin state",{default:J?.admin?.state||J?.state}).option("--admin-country <country>","Admin country code",{default:J?.admin?.countryCode||J?.countryCode}).option("--admin-zip <zip>","Admin zip",{default:J?.admin?.zip||J?.zip}).option("--admin-phone <phone>","Admin phone number",{default:J?.admin?.phoneNumber||J?.phoneNumber}).option("--admin-email <email>","Admin email",{default:J?.admin?.email||J?.email}).option("--tech-first-name <firstName>","Tech first name",{default:J?.tech?.firstName||J?.firstName}).option("--tech-last-name <lastName>","Tech last name",{default:J?.tech?.lastName||J?.lastName}).option("--tech-organization <organization>","Tech organization name",{default:J?.tech?.organizationName||J?.organizationName}).option("--tech-address-line1 <address>","Tech address line 1",{default:J?.tech?.addressLine1||J?.addressLine1}).option("--tech-address-line2 <address>","Tech address line 2",{default:J?.tech?.addressLine2||J?.addressLine2}).option("--tech-city <city>","Tech city",{default:J?.tech?.city||J?.city}).option("--tech-state <state>","Tech state",{default:J?.tech?.state||J?.state}).option("--tech-country <country>","Tech country",{default:J?.tech?.countryCode||J?.countryCode}).option("--tech-zip <zip>","Tech zip",{default:J?.tech?.zip||J?.zip}).option("--tech-phone <phone>","Tech phone",{default:J?.tech?.phoneNumber||J?.phoneNumber}).option("--tech-email <email>","Tech email",{default:J?.tech?.email||J?.email}).option("--privacy-admin","Enable privacy protection for admin",{default:J?.privacyAdmin||J?.privacy||!0}).option("--privacy-tech","Enable privacy protection for tech",{default:J?.privacyTech||J?.privacy||!0}).option("--privacy-registrant","Enable privacy protection for registrant",{default:J?.privacyRegistrant||J?.privacy||!0}).option("--contact-type <type>","Contact type",{default:"person"}).option("-p, --project [project]",$.project,{default:!1}).option("--verbose",$.verbose,{default:!1}).action(async(Y,G)=>{d7.debug("Running `buddy domains:purchase <domain>` ...",G),G.domain=Y;let z=await S2("buddy domains:purchase"),W=await Y1(W1.DomainsPurchase,G);if(W.isErr)await $$("While running the domains:purchase command, there was an issue",{startTime:z,useSeconds:!0},W.error),e0.exit(Q$.FatalError);let{confirm:X}=await G1({name:"confirm",type:"confirm",message:`Would you like to set ${Y} as your APP_URL?`});if(!X)await $$(`Alrighty! ${L$(Y)} was added to your account.`,{startTime:z,useSeconds:!0,type:"success"}),d7.info(`Please note, you may need to validate your email address. Check your ${L$(G.registrantEmail)} inbox.`),e0.exit(Q$.Success);let{writeEnv:H}=await import("@stacksjs/env");H("APP_URL",Y);let q=`Great! ${L$(Y)} was added to your account.`;q+=`
306
306
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stacksjs/buddy",
3
3
  "type": "module",
4
- "version": "0.70.39",
4
+ "version": "0.70.40",
5
5
  "description": "Meet Buddy. The Stacks runtime.",
6
6
  "author": "Chris Breuer",
7
7
  "contributors": [