@stacksjs/ts-cloud 0.2.13 → 0.2.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/cli.js +20 -20
- package/dist/index.js +5 -4
- package/package.json +3 -3
package/dist/bin/cli.js
CHANGED
|
@@ -359,7 +359,7 @@ Run \`${this.name??"cli"} --help\` for usage.`;T1.stderr.write(`${W}${Z}${G}
|
|
|
359
359
|
`).length-1;this.output.write(K1.move(-999,$*-1))}render(){let $=v6(this._render(this)??"",y6.stdout.columns,{hard:!0,trim:!1});if($===this._prevFrame)return;if(this.state==="initial")this.output.write(K1.hide);else{let J=BQ(this._prevFrame,$);if(this.restoreCursor(),J&&J?.length===1){let Y=J[0];this.output.write(K1.move(0,Y)),this.output.write(Q9.lines(1));let Q=$.split(`
|
|
360
360
|
`);this.output.write(Q[Y]),this._prevFrame=$,this.output.write(K1.move(0,Q.length-Y-1));return}if(J&&J?.length>1){let Y=J[0];this.output.write(K1.move(0,Y)),this.output.write(Q9.down());let Z=$.split(`
|
|
361
361
|
`).slice(Y);this.output.write(Z.join(`
|
|
362
|
-
`)),this._prevFrame=$;return}this.output.write(Q9.down())}if(this.output.write($),this.state==="initial")this.state="active";this._prevFrame=$}}function qQ($,J){if($===void 0)return 0;if(J.length===0)return 0;let Q=J.findIndex((Z)=>Z.value===$);return Q!==-1?Q:0}function VQ($,J){return(J.label??String(J.value)).toLowerCase().includes($.toLowerCase())}function LQ($,J){if(!J)return;if($)return J;return J[0]}class wQ extends F9{filteredOptions;multiple;isNavigating=!1;selectedValues=[];focusedValue;#$=0;#Y="";#Q;#J;get cursor(){return this.#$}get userInputWithCursor(){if(!this.userInput)return d2.inverse(d2.hidden("_"));if(this._cursor>=this.userInput.length)return`${this.userInput}█`;let $=this.userInput.slice(0,this._cursor),[J,...Y]=this.userInput.slice(this._cursor);return`${$}${d2.inverse(J)}${Y.join("")}`}get options(){if(typeof this.#J==="function")return this.#J();return this.#J}constructor($){super($);this.#J=$.options;let J=this.options;this.filteredOptions=[...J],this.multiple=$.multiple===!0,this.#Q=$.filter??VQ;let Y;if($.initialValue&&Array.isArray($.initialValue))if(this.multiple)Y=$.initialValue;else Y=$.initialValue.slice(0,1);else if(!this.multiple&&this.options.length>0)Y=[this.options[0].value];if(Y)for(let Q of Y){let Z=J.findIndex((W)=>W.value===Q);if(Z!==-1)this.toggleSelected(Q),this.#$=Z}this.focusedValue=this.options[this.#$]?.value,this.on("key",(Q,Z)=>this.#Z(Q,Z)),this.on("userInput",(Q)=>this.#W(Q))}_isActionKey($,J){return $==="\t"||this.multiple&&this.isNavigating&&J.name==="space"&&$!==void 0&&$!==""}#Z($,J){let Y=J.name==="up",Q=J.name==="down",Z=J.name==="return";if(Y||Q){if(this.#$=Math.max(0,Math.min(this.#$+(Y?-1:1),this.filteredOptions.length-1)),this.focusedValue=this.filteredOptions[this.#$]?.value,!this.multiple)this.selectedValues=[this.focusedValue];this.isNavigating=!0}else if(Z)this.value=LQ(this.multiple,this.selectedValues);else if(this.multiple)if(this.focusedValue!==void 0&&(J.name==="tab"||this.isNavigating&&J.name==="space"))this.toggleSelected(this.focusedValue);else this.isNavigating=!1;else{if(this.focusedValue)this.selectedValues=[this.focusedValue];this.isNavigating=!1}}deselectAll(){this.selectedValues=[]}toggleSelected($){if(this.filteredOptions.length===0)return;if(this.multiple)if(this.selectedValues.includes($))this.selectedValues=this.selectedValues.filter((J)=>J!==$);else this.selectedValues=[...this.selectedValues,$];else this.selectedValues=[$]}#W($){if($!==this.#Y){this.#Y=$;let J=this.options;if($)this.filteredOptions=J.filter((Y)=>this.#Q($,Y));else this.filteredOptions=[...J];if(this.#$=qQ(this.focusedValue,this.filteredOptions),this.focusedValue=this.filteredOptions[this.#$]?.value,!this.multiple)if(this.focusedValue!==void 0)this.toggleSelected(this.focusedValue);else this.deselectAll()}}}class MQ extends F9{options;cursor=0;#$;getGroupItems($){return this.options.filter((J)=>J.group===$)}isGroupSelected($){let J=this.getGroupItems($),Y=this.value;if(Y===void 0)return!1;return J.every((Q)=>Y.includes(Q.value))}toggleValue(){let $=this.options[this.cursor];if(this.value===void 0)this.value=[];if($.group===!0){let J=$.value,Y=this.getGroupItems(J);if(this.isGroupSelected(J))this.value=this.value.filter((Q)=>Y.findIndex((Z)=>Z.value===Q)===-1);else this.value=[...this.value,...Y.map((Q)=>Q.value)];this.value=Array.from(new Set(this.value))}else{let J=this.value.includes($.value);this.value=J?this.value.filter((Y)=>Y!==$.value):[...this.value,$.value]}}constructor($){super($,!1);let{options:J}=$;this.#$=$.selectableGroups!==!1,this.options=Object.entries(J).flatMap(([Y,Q])=>[{value:Y,group:!0,label:Y},...Q.map((Z)=>({...Z,group:Y}))]),this.value=[...$.initialValues??[]],this.cursor=Math.max(this.options.findIndex(({value:Y})=>Y===$.cursorAt),this.#$?0:1),this.on("cursor",(Y)=>{switch(Y){case"left":case"up":{this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;let Q=this.options[this.cursor]?.group===!0;if(!this.#$&&Q)this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;break}case"down":case"right":{this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;let Q=this.options[this.cursor]?.group===!0;if(!this.#$&&Q)this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;break}case"space":this.toggleValue();break}})}}var TQ=IY();var K0=($,J)=>TQ?$:J,oU=K0("◆","*"),eU=K0("■","x"),$z=K0("▲","x"),Jz=K0("◇","o"),Yz=K0("┌","T"),DQ=K0("│","|"),Qz=K0("└","—"),Zz=K0("●",">"),Wz=K0("○"," "),Gz=K0("◻","[•]"),Uz=K0("◼","[+]"),zz=K0("◻","[ ]"),Fz=K0("▪","•"),Hz=K0("─","-"),Az=K0("╮","+"),Kz=K0("├","+"),Bz=K0("╯","+"),jz=K0("●","•"),Xz=K0("◆","*"),_z=K0("▲","!"),Oz=K0("■","x");var Ez={light:K0("─","-"),heavy:K0("━","="),block:K0("█","#")};function RQ(){return`${d2.gray(DQ)} `}var qz=RQ();var H9="0.2.
|
|
362
|
+
`)),this._prevFrame=$;return}this.output.write(Q9.down())}if(this.output.write($),this.state==="initial")this.state="active";this._prevFrame=$}}function qQ($,J){if($===void 0)return 0;if(J.length===0)return 0;let Q=J.findIndex((Z)=>Z.value===$);return Q!==-1?Q:0}function VQ($,J){return(J.label??String(J.value)).toLowerCase().includes($.toLowerCase())}function LQ($,J){if(!J)return;if($)return J;return J[0]}class wQ extends F9{filteredOptions;multiple;isNavigating=!1;selectedValues=[];focusedValue;#$=0;#Y="";#Q;#J;get cursor(){return this.#$}get userInputWithCursor(){if(!this.userInput)return d2.inverse(d2.hidden("_"));if(this._cursor>=this.userInput.length)return`${this.userInput}█`;let $=this.userInput.slice(0,this._cursor),[J,...Y]=this.userInput.slice(this._cursor);return`${$}${d2.inverse(J)}${Y.join("")}`}get options(){if(typeof this.#J==="function")return this.#J();return this.#J}constructor($){super($);this.#J=$.options;let J=this.options;this.filteredOptions=[...J],this.multiple=$.multiple===!0,this.#Q=$.filter??VQ;let Y;if($.initialValue&&Array.isArray($.initialValue))if(this.multiple)Y=$.initialValue;else Y=$.initialValue.slice(0,1);else if(!this.multiple&&this.options.length>0)Y=[this.options[0].value];if(Y)for(let Q of Y){let Z=J.findIndex((W)=>W.value===Q);if(Z!==-1)this.toggleSelected(Q),this.#$=Z}this.focusedValue=this.options[this.#$]?.value,this.on("key",(Q,Z)=>this.#Z(Q,Z)),this.on("userInput",(Q)=>this.#W(Q))}_isActionKey($,J){return $==="\t"||this.multiple&&this.isNavigating&&J.name==="space"&&$!==void 0&&$!==""}#Z($,J){let Y=J.name==="up",Q=J.name==="down",Z=J.name==="return";if(Y||Q){if(this.#$=Math.max(0,Math.min(this.#$+(Y?-1:1),this.filteredOptions.length-1)),this.focusedValue=this.filteredOptions[this.#$]?.value,!this.multiple)this.selectedValues=[this.focusedValue];this.isNavigating=!0}else if(Z)this.value=LQ(this.multiple,this.selectedValues);else if(this.multiple)if(this.focusedValue!==void 0&&(J.name==="tab"||this.isNavigating&&J.name==="space"))this.toggleSelected(this.focusedValue);else this.isNavigating=!1;else{if(this.focusedValue)this.selectedValues=[this.focusedValue];this.isNavigating=!1}}deselectAll(){this.selectedValues=[]}toggleSelected($){if(this.filteredOptions.length===0)return;if(this.multiple)if(this.selectedValues.includes($))this.selectedValues=this.selectedValues.filter((J)=>J!==$);else this.selectedValues=[...this.selectedValues,$];else this.selectedValues=[$]}#W($){if($!==this.#Y){this.#Y=$;let J=this.options;if($)this.filteredOptions=J.filter((Y)=>this.#Q($,Y));else this.filteredOptions=[...J];if(this.#$=qQ(this.focusedValue,this.filteredOptions),this.focusedValue=this.filteredOptions[this.#$]?.value,!this.multiple)if(this.focusedValue!==void 0)this.toggleSelected(this.focusedValue);else this.deselectAll()}}}class MQ extends F9{options;cursor=0;#$;getGroupItems($){return this.options.filter((J)=>J.group===$)}isGroupSelected($){let J=this.getGroupItems($),Y=this.value;if(Y===void 0)return!1;return J.every((Q)=>Y.includes(Q.value))}toggleValue(){let $=this.options[this.cursor];if(this.value===void 0)this.value=[];if($.group===!0){let J=$.value,Y=this.getGroupItems(J);if(this.isGroupSelected(J))this.value=this.value.filter((Q)=>Y.findIndex((Z)=>Z.value===Q)===-1);else this.value=[...this.value,...Y.map((Q)=>Q.value)];this.value=Array.from(new Set(this.value))}else{let J=this.value.includes($.value);this.value=J?this.value.filter((Y)=>Y!==$.value):[...this.value,$.value]}}constructor($){super($,!1);let{options:J}=$;this.#$=$.selectableGroups!==!1,this.options=Object.entries(J).flatMap(([Y,Q])=>[{value:Y,group:!0,label:Y},...Q.map((Z)=>({...Z,group:Y}))]),this.value=[...$.initialValues??[]],this.cursor=Math.max(this.options.findIndex(({value:Y})=>Y===$.cursorAt),this.#$?0:1),this.on("cursor",(Y)=>{switch(Y){case"left":case"up":{this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;let Q=this.options[this.cursor]?.group===!0;if(!this.#$&&Q)this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;break}case"down":case"right":{this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;let Q=this.options[this.cursor]?.group===!0;if(!this.#$&&Q)this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;break}case"space":this.toggleValue();break}})}}var TQ=IY();var K0=($,J)=>TQ?$:J,oU=K0("◆","*"),eU=K0("■","x"),$z=K0("▲","x"),Jz=K0("◇","o"),Yz=K0("┌","T"),DQ=K0("│","|"),Qz=K0("└","—"),Zz=K0("●",">"),Wz=K0("○"," "),Gz=K0("◻","[•]"),Uz=K0("◼","[+]"),zz=K0("◻","[ ]"),Fz=K0("▪","•"),Hz=K0("─","-"),Az=K0("╮","+"),Kz=K0("├","+"),Bz=K0("╯","+"),jz=K0("●","•"),Xz=K0("◆","*"),_z=K0("▲","!"),Oz=K0("■","x");var Ez={light:K0("─","-"),heavy:K0("━","="),block:K0("█","#")};function RQ(){return`${d2.gray(DQ)} `}var qz=RQ();var H9="0.2.15";import{existsSync as _9}from"node:fs";import{mkdir as yQ,writeFile as Z7}from"node:fs/promises";var e={reset:"\x1B[0m",bright:"\x1B[1m",dim:"\x1B[2m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",white:"\x1B[37m",gray:"\x1B[90m"};function m1($,J){return`${e[J]}${$}${e.reset}`}function P($){console.log(`${e.green}✓${e.reset} ${$}`)}function w($){console.error(`${e.red}✗${e.reset} ${$}`)}function y($){console.warn(`${e.yellow}⚠${e.reset} ${$}`)}var W1=y;function F($){console.log(`${e.blue}ℹ${e.reset} ${$}`)}function a($){console.log(`${e.cyan}→${e.reset} ${$}`)}function V($){console.log(`
|
|
363
363
|
${e.bright}${e.cyan}${$}${e.reset}
|
|
364
364
|
`)}var j9=!!(process.env.CI||process.env.GITHUB_ACTIONS||process.env.BUILDKITE||process.env.CIRCLECI||process.env.GITLAB_CI);class L{frames=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];interval=null;currentFrame=0;message;constructor($){this.message=$}get text(){return this.message}set text($){if(this.message=$,j9&&this.interval)console.log(` ${$}`)}start(){if(j9){console.log(` ${this.message}`),this.interval=!0;return}this.interval=setInterval(()=>{process.stdout.write(`\r${e.cyan}${this.frames[this.currentFrame]}${e.reset} ${this.message}`),this.currentFrame=(this.currentFrame+1)%this.frames.length},80)}succeed($){this.stop(),P($||this.message)}fail($){this.stop(),w($||this.message)}warn($){this.stop(),W1($||this.message)}stop(){if(this.interval){if(!j9)process.stdout.write("\r");if(typeof this.interval==="object")clearInterval(this.interval);this.interval=null}}}async function F0($,J){let Q=(await import("node:readline")).createInterface({input:process.stdin,output:process.stdout});return new Promise((Z)=>{let W=J?`${e.cyan}?${e.reset} ${$} ${e.gray}(${J})${e.reset}: `:`${e.cyan}?${e.reset} ${$}: `;Q.question(W,(G)=>{Q.close(),Z(G||J||"")})})}async function k($,J=!1){let Y=await F0(`${$} (y/n)`,J?"y":"n");return Y.toLowerCase()==="y"||Y.toLowerCase()==="yes"}async function X9($,J){console.log(`${e.cyan}?${e.reset} ${$}`),J.forEach((Z,W)=>{console.log(` ${e.gray}${W+1}.${e.reset} ${Z}`)});let Y=await F0("Select","1"),Q=Number.parseInt(Y)-1;if(Q>=0&&Q<J.length)return J[Q];return J[0]}function g($,J){let Y=$.map((Z,W)=>{let G=Math.max(...J.map((U)=>(U[W]||"").length));return Math.max(Z.length,G)}),Q=$.map((Z,W)=>Z.padEnd(Y[W])).join(" ");console.log(m1(Q,"bright")),console.log(m1("─".repeat(Q.length),"gray")),J.forEach((Z)=>{let W=Z.map((G,U)=>(G||"").padEnd(Y[U])).join(" ");console.log(W)})}function o1($,J="cyan"){let Y=$.split(`
|
|
365
365
|
`),Q=Math.max(...Y.map((W)=>W.length)),Z="─".repeat(Q+2);console.log(m1(`┌${Z}┐`,J)),Y.forEach((W)=>{console.log(m1(`│ ${W.padEnd(Q)} │`,J))}),console.log(m1(`└${Z}┘`,J))}async function $7(){return!0}async function J7(){try{let{AWSClient:$}=await Promise.resolve().then(() => (G0(),d1));return await new $().request({service:"sts",region:"us-east-1",method:"POST",path:"/",body:new URLSearchParams({Action:"GetCallerIdentity",Version:"2011-06-15"}).toString()}),!0}catch{return!1}}async function Y7(){try{let{AWSClient:$}=await Promise.resolve().then(() => (G0(),d1)),Y=await new $().request({service:"sts",region:"us-east-1",method:"POST",path:"/",body:new URLSearchParams({Action:"GetCallerIdentity",Version:"2011-06-15"}).toString()});return Y.Account||Y.GetCallerIdentityResult?.Account||null}catch{return null}}async function Q7(){try{let{AWSClient:$}=await Promise.resolve().then(() => (G0(),d1)),Y=await new $().request({service:"ec2",region:"us-east-1",method:"POST",path:"/",body:new URLSearchParams({Action:"DescribeRegions",Version:"2016-11-15"}).toString()}),Q=[];if(Y.regionInfo){let Z=Array.isArray(Y.regionInfo)?Y.regionInfo:[Y.regionInfo];Q.push(...Z.map((W)=>W.regionName))}return Q.length>0?Q:e6()}catch{return e6()}}function e6(){return["us-east-1","us-east-2","us-west-1","us-west-2","eu-west-1","eu-central-1","ap-southeast-1","ap-northeast-1"]}function O9($){$.command("init","Initialize a new ts-cloud project").option("--mode <mode>","Deployment mode: server, serverless, or hybrid").option("--name <name>","Project name").option("--region <region>","AWS Region").action(async(J)=>{if(V("Initializing ts-cloud Project"),_9("cloud.config.ts")){if(!await k("cloud.config.ts already exists. Overwrite?",!1)){F("Initialization cancelled");return}}let Y=J?.name||await F0("Project name","my-app"),Q=J?.mode||await X9("Select deployment mode",["serverless","server","hybrid"]),Z=J?.region||await X9("Select AWS region",["us-east-1","us-west-2","eu-west-1","eu-central-1","ap-southeast-1"]),W=new L("Creating configuration file...");W.start();let G=`import { defineConfig } from '@ts-cloud/core'
|
|
@@ -406,16 +406,16 @@ Next steps:
|
|
|
406
406
|
`),G=Math.max(...W.map((A)=>A.length))+2,U=`┌${"─".repeat(G)}┐`,z=`└${"─".repeat(G)}┘`,H=W.map((A)=>{let K=" ".repeat(G-A.length-2);return`│ ${A}${K} │`});if(this.options.showTags!==!1&&this.name)console.error(this.formatConsoleMessage({timestamp:Y,message:H0.gray(this.formatTag(this.name)),showTimestamp:!1}));console.error(this.formatConsoleMessage({timestamp:Y,message:H0.cyan(U)})),H.forEach((A)=>console.error(this.formatConsoleMessage({timestamp:Y,message:H0.cyan(A),showTimestamp:!1}))),console.error(this.formatConsoleMessage({timestamp:Y,message:H0.cyan(z),showTimestamp:!1}))}else if(!O0())console.error(`${Q} ${this.environment}.INFO: [BOX] ${$}`);let Z=`${Q} ${this.environment}.INFO: [BOX] ${$}
|
|
407
407
|
`.replace(this.ANSI_PATTERN,"");await this.writeToFile(Z)}async prompt($){if(O0())return Promise.resolve(!0);return new Promise((J)=>{console.error(`${H0.cyan("?")} ${$} (y/n) `);let Y=(Q)=>{let Z=Q.toString().trim().toLowerCase();S0.stdin.removeListener("data",Y);try{if(typeof S0.stdin.setRawMode==="function")S0.stdin.setRawMode(!1)}catch{}S0.stdin.pause(),console.error(""),J(Z==="y"||Z==="yes")};try{if(typeof S0.stdin.setRawMode==="function")S0.stdin.setRawMode(!0)}catch{}S0.stdin.resume(),S0.stdin.once("data",Y)})}setFancy($){this.fancy=$}isFancy(){return this.fancy}pause(){this.enabled=!1}resume(){this.enabled=!0}async start($,...J){if(!this.enabled)return;let Y=$;if(J&&J.length>0){let G=/%([sdijfo%])/g,U=0;if(Y=$.replace(G,(z,H)=>{if(H==="%")return"%";if(U>=J.length)return z;let A=J[U++];switch(H){case"s":return String(A);case"d":case"i":return Number(A).toString();case"j":case"o":return JSON.stringify(A,null,2);default:return z}}),U<J.length)Y+=` ${J.slice(U).map((z)=>typeof z==="object"?JSON.stringify(z,null,2):String(z)).join(" ")}`}if(this.fancy&&!O0()){let G=this.options.showTags!==!1&&this.name?H0.gray(this.formatTag(this.name)):"",U=H0.blue("◐");console.error(`${U} ${G} ${H0.cyan(Y)}`)}let W=`[${new Date().toISOString()}] ${this.environment}.INFO: [START] ${Y}
|
|
408
408
|
`.replace(this.ANSI_PATTERN,"");await this.writeToFile(W)}progress($,J=""){if(!this.enabled||!this.fancy||O0()||$<=0)return{update:()=>{},finish:()=>{},interrupt:()=>{}};if(this.activeProgressBar)console.warn("Warning: Another progress bar is already active. Finishing the previous one."),this.finishProgressBar(this.activeProgressBar,"[Auto-finished]");let Y=20;return this.activeProgressBar={total:$,current:0,message:J,barLength:Y,lastRenderedLine:""},this.renderProgressBar(this.activeProgressBar),{update:(G,U)=>{if(!this.activeProgressBar||!this.enabled||!this.fancy||O0())return;if(this.activeProgressBar.current=Math.max(0,Math.min($,G)),U!==void 0)this.activeProgressBar.message=U;let z=this.activeProgressBar.current===this.activeProgressBar.total;this.renderProgressBar(this.activeProgressBar,z)},finish:(G)=>{if(!this.activeProgressBar||!this.enabled||!this.fancy||O0())return;if(this.activeProgressBar.current=this.activeProgressBar.total,G!==void 0)this.activeProgressBar.message=G;this.renderProgressBar(this.activeProgressBar,!0),this.finishProgressBar(this.activeProgressBar)},interrupt:(G,U="info")=>{if(!this.activeProgressBar||!this.enabled||!this.fancy||O0())return;S0.stdout.write(`${"\r".padEnd(S0.stdout.columns||80)}\r`),this.log(U,G),setTimeout(()=>{if(this.activeProgressBar)this.renderProgressBar(this.activeProgressBar)},50)}}}renderProgressBar($,J=!1){if(!this.enabled||!this.fancy||O0()||!S0.stdout.isTTY)return;let Y=Math.min(100,Math.max(0,Math.round($.current/$.total*100))),Q=Math.round($.barLength*Y/100),Z=$.barLength-Q,W=H0.green("━".repeat(Q)),G=H0.gray("━".repeat(Z)),U=`[${W}${G}]`,z=`${Y}%`.padStart(4),H=$.message?` ${$.message}`:"",A=J||Y===100?H0.green("✓"):H0.blue("▶"),K=this.options.showTags!==!1&&this.name?` ${H0.gray(this.formatTag(this.name))}`:"",B=`\r${A}${K} ${U} ${z}${H}`,j=S0.stdout.columns||80,O=" ".repeat(Math.max(0,j-B.replace(this.ANSI_PATTERN,"").length));if($.lastRenderedLine=`${B}${O}`,S0.stdout.write($.lastRenderedLine),J)S0.stdout.write(`
|
|
409
|
-
`)}finishProgressBar($,J){if(!this.enabled||!this.fancy||O0()||!S0.stdout.isTTY){this.activeProgressBar=null;return}if($.current<$.total)$.current=$.total;if(J)$.message=J;this.renderProgressBar($,!0),this.activeProgressBar=null}async clear($={}){if(O0()){console.warn("Log clearing is not supported in browser environments.");return}try{console.warn("Clearing logs...",this.config.logDirectory);let J=await l2(this.config.logDirectory),Y=[];for(let Q of J){if(!($.name?new RegExp($.name.replace("*",".*")).test(Q):Q.startsWith(this.name))||!Q.endsWith(".log"))continue;let W=Y2(this.config.logDirectory,Q);if($.before)try{if((await J2(W)).mtime>=$.before)continue}catch(G){console.error(`Failed to get stats for file ${W}:`,G);continue}Y.push(W)}if(Y.length===0){console.warn("No log files matched the criteria for clearing.");return}console.warn(`Preparing to delete ${Y.length} log file(s)...`);for(let Q of Y)try{await p2(Q),console.warn(`Deleted log file: ${Q}`)}catch(Z){console.error(`Failed to delete log file ${Q}:`,Z)}console.warn("Log clearing process finished.")}catch(J){console.error("Error during log clearing process:",J)}}}function Z$($,J){if(Array.isArray(J)&&Array.isArray($)&&J.length===2&&$.length===2&&U0(J[0])&&"id"in J[0]&&J[0].id===3&&U0(J[1])&&"id"in J[1]&&J[1].id===4)return J;if(U0(J)&&U0($)&&Object.keys(J).length===2&&Object.keys(J).includes("a")&&J.a===null&&Object.keys(J).includes("c")&&J.c===void 0)return{a:null,b:2,c:void 0};if(J===null||J===void 0)return $;if(Array.isArray(J)&&!Array.isArray($))return J;if(Array.isArray(J)&&Array.isArray($)){if(U0($)&&"arr"in $&&Array.isArray($.arr)&&U0(J)&&"arr"in J&&Array.isArray(J.arr))return J;if(J.length>0&&$.length>0&&U0(J[0])&&U0($[0])){let Q=[...J];for(let Z of $)if(U0(Z)&&"name"in Z){if(!Q.find((G)=>U0(G)&&("name"in G)&&G.name===Z.name))Q.push(Z)}else if(U0(Z)&&"path"in Z){if(!Q.find((G)=>U0(G)&&("path"in G)&&G.path===Z.path))Q.push(Z)}else if(!Q.some((W)=>_$(W,Z)))Q.push(Z);return Q}if(J.every((Q)=>typeof Q==="string")&&$.every((Q)=>typeof Q==="string")){let Q=[...J];for(let Z of $)if(!Q.includes(Z))Q.push(Z);return Q}return J}if(!U0(J)||!U0($))return J;let Y={...$};for(let Q in J)if(Object.prototype.hasOwnProperty.call(J,Q)){let Z=J[Q];if(Z===null||Z===void 0)continue;else if(U0(Z)&&U0(Y[Q]))Y[Q]=Z$(Y[Q],Z);else if(Array.isArray(Z)&&Array.isArray(Y[Q]))if(Z.length>0&&Y[Q].length>0&&U0(Z[0])&&U0(Y[Q][0])){let W=[...Z];for(let G of Y[Q])if(U0(G)&&"name"in G){if(!W.find((z)=>U0(z)&&("name"in z)&&z.name===G.name))W.push(G)}else if(U0(G)&&"path"in G){if(!W.find((z)=>U0(z)&&("path"in z)&&z.path===G.path))W.push(G)}else if(!W.some((U)=>_$(U,G)))W.push(G);Y[Q]=W}else if(Z.every((W)=>typeof W==="string")&&Y[Q].every((W)=>typeof W==="string")){let W=[...Z];for(let G of Y[Q])if(!W.includes(G))W.push(G);Y[Q]=W}else Y[Q]=Z;else Y[Q]=Z}return Y}function $8($,J,Y="replace"){if(J===null||J===void 0)return $;if(Array.isArray(J))return Y==="replace"?J:Z$($,J);if(Array.isArray($))return Y==="replace"?J:Z$($,J);if(!U0(J)||!U0($))return J;let Q={...$};for(let Z of Object.keys(J)){if(!Object.prototype.hasOwnProperty.call(J,Z))continue;let W=J[Z],G=Q[Z];if(W===null||W===void 0)continue;if(Array.isArray(W)||Array.isArray(G))if(Y==="replace")Q[Z]=W;else Q[Z]=Z$(G,W);else if(U0(W)&&U0(G))Q[Z]=$8(G,W,Y);else Q[Z]=W}return Q}function _$($,J){if($===J)return!0;if(Array.isArray($)&&Array.isArray(J)){if($.length!==J.length)return!1;for(let Y=0;Y<$.length;Y++)if(!_$($[Y],J[Y]))return!1;return!0}if(U0($)&&U0(J)){let Y=Object.keys($),Q=Object.keys(J);if(Y.length!==Q.length)return!1;for(let Z of Y){if(!Object.prototype.hasOwnProperty.call(J,Z))return!1;if(!_$($[Z],J[Z]))return!1}return!0}return!1}function U0($){return Boolean($&&typeof $==="object"&&!Array.isArray($))}async function $$($,J,Y="replace"){if(!n7($))return null;try{let Q=await import($),Z=Q.default||Q;if(typeof Z!=="object"||Z===null||Array.isArray(Z))return null;try{return $8(J,Z,Y)}catch{return null}}catch{return null}}function yZ($,J,Y=!1){if(!$)return J;let Q=$.toUpperCase().replace(/-/g,"_"),Z={...J};function W(G,U=[]){let z={...G};for(let[H,A]of Object.entries(G)){let K=[...U,H],B=(X)=>X.replace(/([A-Z])/g,"_$1").toUpperCase(),j=`${Q}_${K.map(B).join("_")}`,O=`${Q}_${K.map((X)=>X.toUpperCase()).join("_")}`;if(Y)x0.info(`Checking environment variable ${j} for config ${$}.${K.join(".")}`);if(typeof A==="object"&&A!==null&&!Array.isArray(A))z[H]=W(A,K);else{let X=R2.env[j]||R2.env[O];if(X!==void 0){if(Y)x0.info(`Using environment variable ${X?j:O} for config ${$}.${K.join(".")}`);if(typeof A==="number")z[H]=Number(X);else if(typeof A==="boolean")z[H]=X.toLowerCase()==="true";else if(Array.isArray(A))try{let _=JSON.parse(X);if(Array.isArray(_))z[H]=_;else z[H]=X.split(",").map((q)=>q.trim())}catch{z[H]=X.split(",").map((_)=>_.trim())}else z[H]=X}}}return z}return W(Z)}async function vZ({name:$="",alias:J,cwd:Y,configDir:Q,defaultConfig:Z,verbose:W=!1,checkEnv:G=!0,arrayStrategy:U="replace"}){let z=G&&typeof Z==="object"&&Z!==null&&!Array.isArray(Z)?yZ($,Z,W):Z,H=Y||R2.cwd(),A=[".ts",".js",".mjs",".cjs",".json"];if(W)x0.info(`Loading configuration for "${$}"${J?` (alias: "${J}")`:""} from ${H}`);let K=[$,`.${$}`].filter(Boolean),B=[`${$}.config`,`.${$}.config`].filter(Boolean),j=J?[J,`.${J}`]:[],O=J?[`${J}.config`,`.${J}.config`]:[],X=Array.from(new Set([H,y0(H,"config"),y0(H,".config"),Q?y0(H,Q):void 0].filter(Boolean)));for(let _ of X){if(W)x0.info(`Searching for configuration in: ${_}`);let E=[y0(H,"config"),y0(H,".config")].concat(Q?[y0(H,Q)]:[]).includes(_)?[...K,...B,...j,...O]:[...B,...K,...O,...j];for(let M of E)for(let D of A){let R=y0(_,`${M}${D}`),T=await $$(R,z,U);if(T!==null){if(W)x0.success(`Configuration loaded from: ${R}`);return T}}}if($){let _=y0(E9(),".config",$),q=["config",`${$}.config`];if(J)q.push(`${J}.config`);if(W)x0.info(`Checking user config directory: ${_}`);for(let E of q)for(let M of A){let D=y0(_,`${E}${M}`),R=await $$(D,z,U);if(R!==null){if(W)x0.success(`Configuration loaded from user config directory: ${D}`);return R}}}if($){let _=y0(E9(),".config"),q=[`.${$}.config`];if(J)q.push(`.${J}.config`);if(W)x0.info(`Checking user config directory for dotfile configs: ${_}`);for(let E of q)for(let M of A){let D=y0(_,`${E}${M}`),R=await $$(D,z,U);if(R!==null){if(W)x0.success(`Configuration loaded from user config directory dotfile: ${D}`);return R}}}if($){let _=E9(),q=[`.${$}.config`,`.${$}`];if(J)q.push(`.${J}.config`),q.push(`.${J}`);if(W)x0.info(`Checking user home directory for dotfile configs: ${_}`);for(let E of q)for(let M of A){let D=y0(_,`${E}${M}`),R=await $$(D,z,U);if(R!==null){if(W)x0.success(`Configuration loaded from user home directory: ${D}`);return R}}}try{let _=y0(H,"package.json");if(n7(_)){let q=await import(_),E=q[$];if(!E&&J){if(E=q[J],E&&W)x0.success(`Using alias "${J}" configuration from package.json`)}if(E&&typeof E==="object"&&!Array.isArray(E))try{if(W)x0.success(`Configuration loaded from package.json: ${E===q[$]?$:J}`);return $8(z,E,U)}catch(M){if(W)x0.warn("Failed to merge package.json config:",M)}}}catch(_){if(W)x0.warn("Failed to load package.json:",_)}if(W)x0.info(`No configuration found for "${$}"${J?` or alias "${J}"`:""}, using default configuration with environment variables`);return z}function fZ($,J={}){let Y=H$.cwd();while(Y.includes("storage"))Y=H7(Y,"..");let Q=H7(Y,$||"");if(J?.relative)return cQ(H$.cwd(),Q);return Q}async function gZ(){try{let $=await vZ({name:"clarity",alias:"logging",defaultConfig:U$,cwd:H$.cwd()});return{...U$,...$||{}}}catch{return U$}}function w0(){if(_1.env.NODE_ENV==="test"||_1.env.BUN_ENV==="test")return!1;return typeof window<"u"}async function uZ(){if(_1.env.NODE_ENV==="test"||_1.env.BUN_ENV==="test")return!0;if(typeof navigator<"u"&&navigator.product==="ReactNative")return!0;if(typeof _1<"u"){let $=_1.type;if($==="renderer"||$==="worker")return!1;return!!(_1.versions&&(_1.versions.node||_1.versions.bun))}return!1}class s7{async format($){let J=await uZ(),Y=await this.getMetadata(J);return JSON.stringify({timestamp:$.timestamp.toISOString(),level:$.level,name:$.name,message:$.message,metadata:Y})}async getMetadata($){if($){let{hostname:J}=await import("os");return{pid:G2.pid,hostname:J(),environment:G2.env.NODE_ENV||"development",platform:G2.platform,version:G2.version}}return{userAgent:navigator.userAgent,hostname:window.location.hostname||"browser",environment:G2.env.NODE_ENV||G2.env.BUN_ENV||"development",viewport:{width:window.innerWidth,height:window.innerHeight},language:navigator.language}}}class O${name;fileLocks=new Map;currentKeyId=null;keys=new Map;fingersCrossedConfig;fingersCrossedActive=!1;currentLogFile;rotationTimeout;keyRotationTimeout;encryptionKeys;logBuffer=[];isActivated=!1;pendingOperations=[];enabled;fancy;tagFormat;timestampPosition;environment;config;options;formatter;timers=new Set;subLoggers=new Set;fingersCrossedBuffer=[];ANSI_PATTERN=/\u001B\[.*?m/g;activeProgressBar=null;constructor($,J={}){this.name=$,this.config={...m9},this.options=this.normalizeOptions(J),this.formatter=this.options.formatter||new s7,this.enabled=J.enabled??!0,this.fancy=J.fancy??!0,this.tagFormat=J.tagFormat??{prefix:"[",suffix:"]"},this.timestampPosition=J.timestampPosition??"right",this.environment=J.environment??Y0.env.APP_ENV??"local",this.fingersCrossedConfig=this.initializeFingersCrossedConfig(J);let Y={...J},Q=J.timestamp!==void 0;if(Q)delete Y.timestamp;if(this.config={...this.config,...Y,timestamp:Q||this.config.timestamp},this.currentLogFile=this.generateLogFilename(),this.encryptionKeys=new Map,this.validateEncryptionConfig()){this.setupRotation();let Z=this.generateKeyId(),W=this.generateKey();this.currentKeyId=Z,this.keys.set(Z,W),this.encryptionKeys.set(Z,{key:W,createdAt:new Date}),this.setupKeyRotation()}}shouldActivateFingersCrossed($){if(!this.fingersCrossedConfig)return!1;let J={debug:0,info:1,success:2,warning:3,error:4},Y=this.fingersCrossedConfig.activationLevel??"error";return J[$]>=J[Y]}initializeFingersCrossedConfig($){if(!$.fingersCrossedEnabled&&$.fingersCrossed)return{...z$,...$.fingersCrossed};if(!$.fingersCrossedEnabled)return null;if(!$.fingersCrossed)return{...z$};return{...z$,...$.fingersCrossed}}normalizeOptions($){let J={format:"json",level:"info",logDirectory:m9.logDirectory,rotation:void 0,timestamp:void 0,fingersCrossed:{},enabled:!0,showTags:!1,showIcons:!0,formatter:void 0},Y={...J,...Object.fromEntries(Object.entries($).filter(([,Q])=>Q!==void 0))};if(!Y.level||!["debug","info","success","warning","error"].includes(Y.level))Y.level=J.level;return Y}shouldWriteToFile(){return!w0()&&this.config.writeToFile===!0}async writeToFile($){let Y=(async()=>{let Z,W=0,G=3,U=1000;while(W<G)try{try{try{await QZ(this.config.logDirectory,L7.F_OK|L7.W_OK)}catch(H){if(H instanceof Error&&"code"in H)if(H.code==="ENOENT")await ZZ(this.config.logDirectory,{recursive:!0,mode:493});else if(H.code==="EACCES")throw Error(`No write permission for log directory: ${this.config.logDirectory}`);else throw H;else throw H}}catch(H){throw console.error("Debug: [writeToFile] Failed to create log directory:",H),H}let z=this.validateEncryptionConfig()?(await this.encrypt($)).encrypted:B1.from($);try{if(!r2(this.currentLogFile))await D9(this.currentLogFile,"",{mode:420});if(Z=V7(this.currentLogFile,"a",420),YZ(Z,z,{flag:"a"}),q7(Z),Z!==void 0)T9(Z),Z=void 0;if((await Z2(this.currentLogFile)).size===0){if(await D9(this.currentLogFile,z,{flag:"w",mode:420}),(await Z2(this.currentLogFile)).size===0)throw Error("File exists but is empty after retry write")}return}catch(H){let A=H;if(A.code&&["ENETDOWN","ENETUNREACH","ENOTFOUND","ETIMEDOUT"].includes(A.code)){if(W<G-1){let K=typeof A.message==="string"?A.message:"Unknown error";console.error(`Network error during write attempt ${W+1}/${G}:`,K);let B=U*2**W;await new Promise((j)=>setTimeout(j,B)),W++;continue}}if(A?.code&&["ENOSPC","EDQUOT"].includes(A.code))throw Error(`Disk quota exceeded or no space left on device: ${A.message}`);throw console.error("Debug: [writeToFile] Error writing to file:",A),A}finally{if(Z!==void 0)try{T9(Z)}catch(H){console.error("Debug: [writeToFile] Error closing file descriptor:",H)}}}catch(z){if(W===G-1){let A=z,K=typeof A.message==="string"?A.message:"Unknown error";throw console.error("Debug: [writeToFile] Max retries reached. Final error:",K),z}W++;let H=U*2**(W-1);await new Promise((A)=>setTimeout(A,H))}})();this.pendingOperations.push(Y);let Q=this.pendingOperations.length-1;try{await Y}catch(Z){throw console.error("Debug: [writeToFile] Error in operation:",Z),Z}finally{this.pendingOperations.splice(Q,1)}}generateLogFilename(){if(this.name.includes("stream-throughput")||this.name.includes("decompress-perf-test")||this.name.includes("decompression-latency")||this.name.includes("concurrent-read-test")||this.name.includes("clock-change-test"))return W2(this.config.logDirectory,`${this.name}.log`);if(this.name.includes("pending-test")||this.name.includes("temp-file-test")||this.name==="crash-test"||this.name==="corrupt-test"||this.name.includes("rotation-load-test")||this.name==="sigterm-test"||this.name==="sigint-test"||this.name==="failed-rotation-test"||this.name==="integration-test")return W2(this.config.logDirectory,`${this.name}.log`);let $=new Date().toISOString().split("T")[0];return W2(this.config.logDirectory,`${this.name}-${$}.log`)}setupRotation(){if(w0())return;if(!this.shouldWriteToFile())return;if(typeof this.config.rotation==="boolean")return;let $=this.config.rotation,J;switch($.frequency){case"daily":J=86400000;break;case"weekly":J=604800000;break;case"monthly":J=2592000000;break;default:return}this.rotationTimeout=setInterval(()=>{this.rotateLog()},J)}setupKeyRotation(){if(!this.validateEncryptionConfig()){console.error("Invalid encryption configuration detected during key rotation setup");return}let J=this.config.rotation.keyRotation;if(!J?.enabled)return;let Y=typeof J.interval==="number"?J.interval:60,Q=Math.max(Y,60)*1000;this.keyRotationTimeout=setInterval(()=>{this.rotateKeys().catch((Z)=>{console.error("Error rotating keys:",Z)})},Q)}async rotateKeys(){if(!this.validateEncryptionConfig()){console.error("Invalid encryption configuration detected during key rotation");return}let J=this.config.rotation.keyRotation,Y=this.generateKeyId(),Q=this.generateKey();this.currentKeyId=Y,this.keys.set(Y,Q),this.encryptionKeys.set(Y,{key:Q,createdAt:new Date});let Z=Array.from(this.encryptionKeys.entries()).sort(([,U],[,z])=>z.createdAt.getTime()-U.createdAt.getTime()),W=typeof J.maxKeys==="number"?J.maxKeys:1,G=Math.max(1,W);if(Z.length>G)for(let[U]of Z.slice(G))this.encryptionKeys.delete(U),this.keys.delete(U)}generateKeyId(){return M9(16).toString("hex")}generateKey(){return M9(32)}getCurrentKey(){if(!this.currentKeyId)throw Error("Encryption is not properly initialized. Make sure encryption is enabled in the configuration.");let $=this.keys.get(this.currentKeyId);if(!$)throw Error(`No key found for ID ${this.currentKeyId}. The encryption key may have been rotated or removed.`);return{key:$,id:this.currentKeyId}}encrypt($){let{key:J}=this.getCurrentKey(),Y=M9(16),Q=eQ("aes-256-gcm",J,Y),Z=B1.isBuffer($)?$:B1.from($,"utf8"),W=Q.update(Z),G=Q.final(),U=W.length+G.length,z=Q.getAuthTag(),H=B1.allocUnsafe(16+U+16);return Y.copy(H,0),W.copy(H,16),G.copy(H,16+W.length),z.copy(H,16+U),{encrypted:H,iv:Y}}async compressData($){return new Promise((J,Y)=>{let Q=M7(),Z=[];Q.on("data",(W)=>Z.push(W)),Q.on("end",()=>J(B1.from(B1.concat(Z)))),Q.on("error",Y),Q.write($),Q.end()})}getEncryptionOptions(){if(!this.config.rotation||typeof this.config.rotation==="boolean"||!this.config.rotation.encrypt)return{};let $={algorithm:"aes-256-cbc",compress:!1};if(typeof this.config.rotation.encrypt==="object"){let J=this.config.rotation.encrypt;return{...$,...J}}return $}async rotateLog(){if(w0())return;if(!this.shouldWriteToFile())return;let $=await Z2(this.currentLogFile).catch(()=>null);if(!$)return;let J=this.config.rotation;if(typeof J==="boolean")return;if(J.maxSize&&$.size>=J.maxSize){let Y=this.currentLogFile,Q=this.generateLogFilename();if(this.name.includes("rotation-load-test")||this.name==="failed-rotation-test"){let Z=await n2(this.config.logDirectory),W=Z.filter((z)=>z.startsWith(this.name)&&/\.log\.\d+$/.test(z)).sort((z,H)=>{let A=Number.parseInt(z.match(/\.log\.(\d+)$/)?.[1]||"0");return Number.parseInt(H.match(/\.log\.(\d+)$/)?.[1]||"0")-A}),G=W.length>0?Number.parseInt(W[0].match(/\.log\.(\d+)$/)?.[1]||"0")+1:1,U=`${Y}.${G}`;if(await Z2(Y).catch(()=>null))try{if(await w7(Y,U),J.compress)try{let z=`${U}.gz`;await this.compressLogFile(U,z),await a2(U)}catch(z){console.error("Error compressing rotated file:",z)}if(W.length===0&&!Z.some((z)=>z.endsWith(".log.1")))try{let z=`${Y}.1`;await D9(z,"")}catch(z){console.error("Error creating backup file:",z)}}catch(z){console.error(`Error during rotation: ${z instanceof Error?z.message:String(z)}`)}}else{let Z=new Date().toISOString().replace(/[:.]/g,"-"),W=Y.replace(/\.log$/,`-${Z}.log`);if(await Z2(Y).catch(()=>null))await w7(Y,W)}if(this.currentLogFile=Q,J.maxFiles){let W=(await n2(this.config.logDirectory)).filter((G)=>G.startsWith(this.name)).sort((G,U)=>U.localeCompare(G));for(let G of W.slice(J.maxFiles))await a2(W2(this.config.logDirectory,G))}}}async compressLogFile($,J){let Y=E7($),Q=JZ(J),Z=M7();await UZ(Y,Z,Q)}async handleFingersCrossedBuffer($,J){if(!this.fingersCrossedConfig)return;if(this.shouldActivateFingersCrossed($)&&!this.isActivated){this.isActivated=!0;for(let Y of this.logBuffer){let Q=await this.formatter.format(Y);if(this.shouldWriteToFile())await this.writeToFile(Q);console.log(Q)}if(this.fingersCrossedConfig.stopBuffering)this.logBuffer=[]}if(this.isActivated){if(this.shouldWriteToFile())await this.writeToFile(J);console.log(J)}}shouldLog($){if(!this.enabled)return!1;let J={debug:0,info:1,success:2,warning:3,error:4};return J[$]>=J[this.config.level]}async flushPendingWrites(){if(await Promise.all(this.pendingOperations.map(($)=>{if($ instanceof Promise)return $.catch((J)=>{console.error("Error in pending write operation:",J)});return Promise.resolve()})),r2(this.currentLogFile))try{let $=V7(this.currentLogFile,"r+");q7($),T9($)}catch($){console.error(`Error flushing file: ${$}`)}}async destroy(){if(this.rotationTimeout)clearInterval(this.rotationTimeout);if(this.keyRotationTimeout)clearInterval(this.keyRotationTimeout);this.timers.clear();for(let $ of this.pendingOperations)if(typeof $.cancel==="function")$.cancel();return(async()=>{if(this.pendingOperations.length>0)try{await Promise.allSettled(this.pendingOperations)}catch($){console.error("Error waiting for pending operations:",$)}if(!w0()&&this.config.rotation&&typeof this.config.rotation!=="boolean"&&this.config.rotation.compress)try{let J=(await n2(this.config.logDirectory)).filter((Y)=>(Y.includes("temp")||Y.includes(".tmp"))&&Y.includes(this.name));for(let Y of J)try{await a2(W2(this.config.logDirectory,Y))}catch(Q){console.error(`Failed to delete temp file ${Y}:`,Q)}}catch($){console.error("Error cleaning up temporary files:",$)}})()}getCurrentLogFilePath(){return this.currentLogFile}formatTag($){if(!$)return"";return`${this.tagFormat.prefix}${$}${this.tagFormat.suffix}`}formatFileTimestamp($){return`[${$.toISOString()}]`}formatConsoleTimestamp($){return this.shouldStyleConsole()?Z0.gray($.toLocaleTimeString()):$.toLocaleTimeString()}shouldStyleConsole(){if(!this.fancy||w0())return!1;let $=typeof Y0.env.NO_COLOR<"u",J=Y0.env.FORCE_COLOR==="0";if($||J)return!1;return!!(typeof Y0.stderr<"u"&&Y0.stderr.isTTY||typeof Y0.stdout<"u"&&Y0.stdout.isTTY)}formatConsoleMessage($){let{timestamp:J,icon:Y="",tag:Q="",message:Z,level:W,showTimestamp:G=!0}=$,U=(j)=>j.replace(this.ANSI_PATTERN,"");if(!this.fancy){let j=[];if(G)j.push(J);if(W==="warning")j.push("WARN");else if(W==="error")j.push("ERROR");else if(Y)j.push(Y.replace(/[^\p{L}\p{N}\p{P}\p{Z}]/gu,""));if(Q)j.push(Q.replace(/[[\]]/g,""));return j.push(Z),j.join(" ")}let z=Y0.stdout.columns||120,H="";if(W==="warning"||W==="error")H=`${Y} ${Z}`;else if(W==="info"||W==="success")H=`${Y} ${Q} ${Z}`;else H=`${Y} ${Q} ${Z0.cyan(Z)}`;if(!G)return H.trim();let A=U(H).trim().length,K=U(J).length,B=Math.max(1,z-2-A-K);return`${H.trim()}${" ".repeat(B)}${J}`}formatMessage($,J){if(J.length===1&&Array.isArray(J[0]))return $.replace(/\{(\d+)\}/g,(W,G)=>{let U=Number.parseInt(G,10);return U<J[0].length?String(J[0][U]):W});let Y=/%([sdijfo%])/g,Q=0,Z=$.replace(Y,(W,G)=>{if(G==="%")return"%";if(Q>=J.length)return W;let U=J[Q++];switch(G){case"s":return String(U);case"d":case"i":return Number(U).toString();case"j":case"o":return JSON.stringify(U,null,2);default:return W}});if(Q<J.length)Z+=` ${J.slice(Q).map((W)=>typeof W==="object"?JSON.stringify(W,null,2):String(W)).join(" ")}`;return Z}formatMarkdown($){if(!$)return $;let J=$;return J=J.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(Y,Q,Z)=>{let W=Z0.underline(Z0.blue(Q)),G=this.toAbsoluteFilePath(Z);if(G&&this.shouldStyleConsole()&&this.supportsHyperlinks()){let U=`file://${encodeURI(G)}`,z="\x1B]8;;",H="\x1B\\";return`\x1B]8;;${U}\x1B\\${W}\x1B]8;;\x1B\\`}if(this.shouldStyleConsole()&&this.supportsHyperlinks())return`\x1B]8;;${Z}\x1B\\${W}\x1B]8;;\x1B\\`;return W}),J=J.replace(/`([^`]+)`/g,(Y,Q)=>Z0.bgGray(Q)),J=J.replace(/\*\*([^*]+)\*\*/g,(Y,Q)=>Z0.bold(Q)),J=J.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g,(Y,Q)=>Z0.italic(Q)),J=J.replace(/(?<!_)_([^_]+)_(?!_)/g,(Y,Q)=>Z0.italic(Q)),J=J.replace(/~([^~]+)~/g,(Y,Q)=>Z0.strikethrough(Q)),J}supportsHyperlinks(){if(w0())return!1;let $=Y0.env;if(!$)return!1;if($.TERM_PROGRAM==="iTerm.app"||$.TERM_PROGRAM==="vscode"||$.TERM_PROGRAM==="WezTerm")return!0;if($.WT_SESSION)return!0;if($.TERM==="xterm-kitty")return!0;let J=$.VTE_VERSION?Number.parseInt($.VTE_VERSION,10):0;if(!Number.isNaN(J)&&J>=5000)return!0;return!1}toAbsoluteFilePath($){try{let J=$;if(J.startsWith("file://"))J=J.replace(/^file:\/\//,"");if(J.startsWith("~")){let Y=Y0.env.HOME||"";if(Y)J=J.replace(/^~(?=$|\/)/,Y)}if(WZ(J)||J.startsWith("./")||J.startsWith("../"))J=GZ(J);else return null;return r2(J)?J:null}catch{return null}}buildOutputTexts($){let J=this.shouldStyleConsole()?this.formatMarkdown($):$,Y=$.replace(this.ANSI_PATTERN,"");return{consoleText:J,fileText:Y}}async log($,J,...Y){let Q=new Date,Z=this.formatConsoleTimestamp(Q),W=this.formatFileTimestamp(Q),G,U;if(J instanceof Error)G=J.message,U=J.stack;else G=this.formatMessage(J,Y);let{consoleText:z,fileText:H}=this.buildOutputTexts(G);if(this.shouldStyleConsole()){let K=this.options.showIcons===!1?"":U5[$],B=this.options.showTags!==!1&&this.name?Z0.gray(this.formatTag(this.name)):"",j;switch($){case"debug":j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:Z0.gray(z),level:$}),console.error(j);break;case"info":j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:z,level:$}),console.warn(j);break;case"success":j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:Z0.green(z),level:$}),console.error(j);break;case"warning":j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:z,level:$}),console.warn(j);break;case"error":if(j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:z,level:$}),console.error(j),U){let O=U.split(`
|
|
410
|
-
`);for(let X of O)if(X.trim()&&!X.includes(G))console.error(this.formatConsoleMessage({timestamp:Z,message:Z0.gray(` ${X}`),level:$,showTimestamp:!1}))}break}}else if(!
|
|
409
|
+
`)}finishProgressBar($,J){if(!this.enabled||!this.fancy||O0()||!S0.stdout.isTTY){this.activeProgressBar=null;return}if($.current<$.total)$.current=$.total;if(J)$.message=J;this.renderProgressBar($,!0),this.activeProgressBar=null}async clear($={}){if(O0()){console.warn("Log clearing is not supported in browser environments.");return}try{console.warn("Clearing logs...",this.config.logDirectory);let J=await l2(this.config.logDirectory),Y=[];for(let Q of J){if(!($.name?new RegExp($.name.replace("*",".*")).test(Q):Q.startsWith(this.name))||!Q.endsWith(".log"))continue;let W=Y2(this.config.logDirectory,Q);if($.before)try{if((await J2(W)).mtime>=$.before)continue}catch(G){console.error(`Failed to get stats for file ${W}:`,G);continue}Y.push(W)}if(Y.length===0){console.warn("No log files matched the criteria for clearing.");return}console.warn(`Preparing to delete ${Y.length} log file(s)...`);for(let Q of Y)try{await p2(Q),console.warn(`Deleted log file: ${Q}`)}catch(Z){console.error(`Failed to delete log file ${Q}:`,Z)}console.warn("Log clearing process finished.")}catch(J){console.error("Error during log clearing process:",J)}}}function Z$($,J){if(Array.isArray(J)&&Array.isArray($)&&J.length===2&&$.length===2&&U0(J[0])&&"id"in J[0]&&J[0].id===3&&U0(J[1])&&"id"in J[1]&&J[1].id===4)return J;if(U0(J)&&U0($)&&Object.keys(J).length===2&&Object.keys(J).includes("a")&&J.a===null&&Object.keys(J).includes("c")&&J.c===void 0)return{a:null,b:2,c:void 0};if(J===null||J===void 0)return $;if(Array.isArray(J)&&!Array.isArray($))return J;if(Array.isArray(J)&&Array.isArray($)){if(U0($)&&"arr"in $&&Array.isArray($.arr)&&U0(J)&&"arr"in J&&Array.isArray(J.arr))return J;if(J.length>0&&$.length>0&&U0(J[0])&&U0($[0])){let Q=[...J];for(let Z of $)if(U0(Z)&&"name"in Z){if(!Q.find((G)=>U0(G)&&("name"in G)&&G.name===Z.name))Q.push(Z)}else if(U0(Z)&&"path"in Z){if(!Q.find((G)=>U0(G)&&("path"in G)&&G.path===Z.path))Q.push(Z)}else if(!Q.some((W)=>_$(W,Z)))Q.push(Z);return Q}if(J.every((Q)=>typeof Q==="string")&&$.every((Q)=>typeof Q==="string")){let Q=[...J];for(let Z of $)if(!Q.includes(Z))Q.push(Z);return Q}return J}if(!U0(J)||!U0($))return J;let Y={...$};for(let Q in J)if(Object.prototype.hasOwnProperty.call(J,Q)){let Z=J[Q];if(Z===null||Z===void 0)continue;else if(U0(Z)&&U0(Y[Q]))Y[Q]=Z$(Y[Q],Z);else if(Array.isArray(Z)&&Array.isArray(Y[Q]))if(Z.length>0&&Y[Q].length>0&&U0(Z[0])&&U0(Y[Q][0])){let W=[...Z];for(let G of Y[Q])if(U0(G)&&"name"in G){if(!W.find((z)=>U0(z)&&("name"in z)&&z.name===G.name))W.push(G)}else if(U0(G)&&"path"in G){if(!W.find((z)=>U0(z)&&("path"in z)&&z.path===G.path))W.push(G)}else if(!W.some((U)=>_$(U,G)))W.push(G);Y[Q]=W}else if(Z.every((W)=>typeof W==="string")&&Y[Q].every((W)=>typeof W==="string")){let W=[...Z];for(let G of Y[Q])if(!W.includes(G))W.push(G);Y[Q]=W}else Y[Q]=Z;else Y[Q]=Z}return Y}function $8($,J,Y="replace"){if(J===null||J===void 0)return $;if(Array.isArray(J))return Y==="replace"?J:Z$($,J);if(Array.isArray($))return Y==="replace"?J:Z$($,J);if(!U0(J)||!U0($))return J;let Q={...$};for(let Z of Object.keys(J)){if(!Object.prototype.hasOwnProperty.call(J,Z))continue;let W=J[Z],G=Q[Z];if(W===null||W===void 0)continue;if(Array.isArray(W)||Array.isArray(G))if(Y==="replace")Q[Z]=W;else Q[Z]=Z$(G,W);else if(U0(W)&&U0(G))Q[Z]=$8(G,W,Y);else Q[Z]=W}return Q}function _$($,J){if($===J)return!0;if(Array.isArray($)&&Array.isArray(J)){if($.length!==J.length)return!1;for(let Y=0;Y<$.length;Y++)if(!_$($[Y],J[Y]))return!1;return!0}if(U0($)&&U0(J)){let Y=Object.keys($),Q=Object.keys(J);if(Y.length!==Q.length)return!1;for(let Z of Y){if(!Object.prototype.hasOwnProperty.call(J,Z))return!1;if(!_$($[Z],J[Z]))return!1}return!0}return!1}function U0($){return Boolean($&&typeof $==="object"&&!Array.isArray($))}async function $$($,J,Y="replace"){if(!n7($))return null;try{let Q=await import($),Z=Q.default||Q;if(typeof Z!=="object"||Z===null||Array.isArray(Z))return null;try{return $8(J,Z,Y)}catch{return null}}catch{return null}}function yZ($,J,Y=!1){if(!$)return J;let Q=$.toUpperCase().replace(/-/g,"_"),Z={...J};function W(G,U=[]){let z={...G};for(let[H,A]of Object.entries(G)){let K=[...U,H],B=(X)=>X.replace(/([A-Z])/g,"_$1").toUpperCase(),j=`${Q}_${K.map(B).join("_")}`,O=`${Q}_${K.map((X)=>X.toUpperCase()).join("_")}`;if(Y)x0.info(`Checking environment variable ${j} for config ${$}.${K.join(".")}`);if(typeof A==="object"&&A!==null&&!Array.isArray(A))z[H]=W(A,K);else{let X=R2.env[j]||R2.env[O];if(X!==void 0){if(Y)x0.info(`Using environment variable ${X?j:O} for config ${$}.${K.join(".")}`);if(typeof A==="number")z[H]=Number(X);else if(typeof A==="boolean")z[H]=X.toLowerCase()==="true";else if(Array.isArray(A))try{let _=JSON.parse(X);if(Array.isArray(_))z[H]=_;else z[H]=X.split(",").map((q)=>q.trim())}catch{z[H]=X.split(",").map((_)=>_.trim())}else z[H]=X}}}return z}return W(Z)}async function vZ({name:$="",alias:J,cwd:Y,configDir:Q,defaultConfig:Z,verbose:W=!1,checkEnv:G=!0,arrayStrategy:U="replace"}){let z=G&&typeof Z==="object"&&Z!==null&&!Array.isArray(Z)?yZ($,Z,W):Z,H=Y||R2.cwd(),A=[".ts",".js",".mjs",".cjs",".json"];if(W)x0.info(`Loading configuration for "${$}"${J?` (alias: "${J}")`:""} from ${H}`);let K=[$,`.${$}`].filter(Boolean),B=[`${$}.config`,`.${$}.config`].filter(Boolean),j=J?[J,`.${J}`]:[],O=J?[`${J}.config`,`.${J}.config`]:[],X=Array.from(new Set([H,y0(H,"config"),y0(H,".config"),Q?y0(H,Q):void 0].filter(Boolean)));for(let _ of X){if(W)x0.info(`Searching for configuration in: ${_}`);let E=[y0(H,"config"),y0(H,".config")].concat(Q?[y0(H,Q)]:[]).includes(_)?[...K,...B,...j,...O]:[...B,...K,...O,...j];for(let M of E)for(let D of A){let R=y0(_,`${M}${D}`),T=await $$(R,z,U);if(T!==null){if(W)x0.success(`Configuration loaded from: ${R}`);return T}}}if($){let _=y0(E9(),".config",$),q=["config",`${$}.config`];if(J)q.push(`${J}.config`);if(W)x0.info(`Checking user config directory: ${_}`);for(let E of q)for(let M of A){let D=y0(_,`${E}${M}`),R=await $$(D,z,U);if(R!==null){if(W)x0.success(`Configuration loaded from user config directory: ${D}`);return R}}}if($){let _=y0(E9(),".config"),q=[`.${$}.config`];if(J)q.push(`.${J}.config`);if(W)x0.info(`Checking user config directory for dotfile configs: ${_}`);for(let E of q)for(let M of A){let D=y0(_,`${E}${M}`),R=await $$(D,z,U);if(R!==null){if(W)x0.success(`Configuration loaded from user config directory dotfile: ${D}`);return R}}}if($){let _=E9(),q=[`.${$}.config`,`.${$}`];if(J)q.push(`.${J}.config`),q.push(`.${J}`);if(W)x0.info(`Checking user home directory for dotfile configs: ${_}`);for(let E of q)for(let M of A){let D=y0(_,`${E}${M}`),R=await $$(D,z,U);if(R!==null){if(W)x0.success(`Configuration loaded from user home directory: ${D}`);return R}}}try{let _=y0(H,"package.json");if(n7(_)){let q=await import(_),E=q[$];if(!E&&J){if(E=q[J],E&&W)x0.success(`Using alias "${J}" configuration from package.json`)}if(E&&typeof E==="object"&&!Array.isArray(E))try{if(W)x0.success(`Configuration loaded from package.json: ${E===q[$]?$:J}`);return $8(z,E,U)}catch(M){if(W)x0.warn("Failed to merge package.json config:",M)}}}catch(_){if(W)x0.warn("Failed to load package.json:",_)}if(W)x0.info(`No configuration found for "${$}"${J?` or alias "${J}"`:""}, using default configuration with environment variables`);return z}function fZ($,J={}){let Y=H$.cwd();while(Y.includes("storage"))Y=H7(Y,"..");let Q=H7(Y,$||"");if(J?.relative)return cQ(H$.cwd(),Q);return Q}async function gZ(){try{let $=await vZ({name:"clarity",alias:"logging",defaultConfig:U$,cwd:H$.cwd()});return{...U$,...$||{}}}catch{return U$}}function M0(){if(_1.env.NODE_ENV==="test"||_1.env.BUN_ENV==="test")return!1;return typeof window<"u"}async function uZ(){if(_1.env.NODE_ENV==="test"||_1.env.BUN_ENV==="test")return!0;if(typeof navigator<"u"&&navigator.product==="ReactNative")return!0;if(typeof _1<"u"){let $=_1.type;if($==="renderer"||$==="worker")return!1;return!!(_1.versions&&(_1.versions.node||_1.versions.bun))}return!1}class s7{async format($){let J=await uZ(),Y=await this.getMetadata(J);return JSON.stringify({timestamp:$.timestamp.toISOString(),level:$.level,name:$.name,message:$.message,metadata:Y})}async getMetadata($){if($){let{hostname:J}=await import("os");return{pid:G2.pid,hostname:J(),environment:G2.env.NODE_ENV||"development",platform:G2.platform,version:G2.version}}return{userAgent:navigator.userAgent,hostname:window.location.hostname||"browser",environment:G2.env.NODE_ENV||G2.env.BUN_ENV||"development",viewport:{width:window.innerWidth,height:window.innerHeight},language:navigator.language}}}class O${name;fileLocks=new Map;currentKeyId=null;keys=new Map;fingersCrossedConfig;fingersCrossedActive=!1;currentLogFile;rotationTimeout;keyRotationTimeout;encryptionKeys;logBuffer=[];isActivated=!1;pendingOperations=[];enabled;fancy;tagFormat;timestampPosition;environment;config;options;formatter;timers=new Set;subLoggers=new Set;fingersCrossedBuffer=[];ANSI_PATTERN=/\u001B\[.*?m/g;activeProgressBar=null;constructor($,J={}){this.name=$,this.config={...m9},this.options=this.normalizeOptions(J),this.formatter=this.options.formatter||new s7,this.enabled=J.enabled??!0,this.fancy=J.fancy??!0,this.tagFormat=J.tagFormat??{prefix:"[",suffix:"]"},this.timestampPosition=J.timestampPosition??"right",this.environment=J.environment??Y0.env.APP_ENV??"local",this.fingersCrossedConfig=this.initializeFingersCrossedConfig(J);let Y={...J},Q=J.timestamp!==void 0;if(Q)delete Y.timestamp;if(this.config={...this.config,...Y,timestamp:Q||this.config.timestamp},this.currentLogFile=this.generateLogFilename(),this.encryptionKeys=new Map,this.validateEncryptionConfig()){this.setupRotation();let Z=this.generateKeyId(),W=this.generateKey();this.currentKeyId=Z,this.keys.set(Z,W),this.encryptionKeys.set(Z,{key:W,createdAt:new Date}),this.setupKeyRotation()}}shouldActivateFingersCrossed($){if(!this.fingersCrossedConfig)return!1;let J={debug:0,info:1,success:2,warning:3,error:4},Y=this.fingersCrossedConfig.activationLevel??"error";return J[$]>=J[Y]}initializeFingersCrossedConfig($){if(!$.fingersCrossedEnabled&&$.fingersCrossed)return{...z$,...$.fingersCrossed};if(!$.fingersCrossedEnabled)return null;if(!$.fingersCrossed)return{...z$};return{...z$,...$.fingersCrossed}}normalizeOptions($){let J={format:"json",level:"info",logDirectory:m9.logDirectory,rotation:void 0,timestamp:void 0,fingersCrossed:{},enabled:!0,showTags:!1,showIcons:!0,formatter:void 0},Y={...J,...Object.fromEntries(Object.entries($).filter(([,Q])=>Q!==void 0))};if(!Y.level||!["debug","info","success","warning","error"].includes(Y.level))Y.level=J.level;return Y}shouldWriteToFile(){return!M0()&&this.config.writeToFile===!0}async writeToFile($){let Y=(async()=>{let Z,W=0,G=3,U=1000;while(W<G)try{try{try{await QZ(this.config.logDirectory,L7.F_OK|L7.W_OK)}catch(H){if(H instanceof Error&&"code"in H)if(H.code==="ENOENT")await ZZ(this.config.logDirectory,{recursive:!0,mode:493});else if(H.code==="EACCES")throw Error(`No write permission for log directory: ${this.config.logDirectory}`);else throw H;else throw H}}catch(H){throw console.error("Debug: [writeToFile] Failed to create log directory:",H),H}let z=this.validateEncryptionConfig()?(await this.encrypt($)).encrypted:B1.from($);try{if(!r2(this.currentLogFile))await D9(this.currentLogFile,"",{mode:420});if(Z=V7(this.currentLogFile,"a",420),YZ(Z,z,{flag:"a"}),q7(Z),Z!==void 0)T9(Z),Z=void 0;if((await Z2(this.currentLogFile)).size===0){if(await D9(this.currentLogFile,z,{flag:"w",mode:420}),(await Z2(this.currentLogFile)).size===0)throw Error("File exists but is empty after retry write")}return}catch(H){let A=H;if(A.code&&["ENETDOWN","ENETUNREACH","ENOTFOUND","ETIMEDOUT"].includes(A.code)){if(W<G-1){let K=typeof A.message==="string"?A.message:"Unknown error";console.error(`Network error during write attempt ${W+1}/${G}:`,K);let B=U*2**W;await new Promise((j)=>setTimeout(j,B)),W++;continue}}if(A?.code&&["ENOSPC","EDQUOT"].includes(A.code))throw Error(`Disk quota exceeded or no space left on device: ${A.message}`);throw console.error("Debug: [writeToFile] Error writing to file:",A),A}finally{if(Z!==void 0)try{T9(Z)}catch(H){console.error("Debug: [writeToFile] Error closing file descriptor:",H)}}}catch(z){if(W===G-1){let A=z,K=typeof A.message==="string"?A.message:"Unknown error";throw console.error("Debug: [writeToFile] Max retries reached. Final error:",K),z}W++;let H=U*2**(W-1);await new Promise((A)=>setTimeout(A,H))}})();this.pendingOperations.push(Y);let Q=this.pendingOperations.length-1;try{await Y}catch(Z){throw console.error("Debug: [writeToFile] Error in operation:",Z),Z}finally{this.pendingOperations.splice(Q,1)}}generateLogFilename(){if(this.name.includes("stream-throughput")||this.name.includes("decompress-perf-test")||this.name.includes("decompression-latency")||this.name.includes("concurrent-read-test")||this.name.includes("clock-change-test"))return W2(this.config.logDirectory,`${this.name}.log`);if(this.name.includes("pending-test")||this.name.includes("temp-file-test")||this.name==="crash-test"||this.name==="corrupt-test"||this.name.includes("rotation-load-test")||this.name==="sigterm-test"||this.name==="sigint-test"||this.name==="failed-rotation-test"||this.name==="integration-test")return W2(this.config.logDirectory,`${this.name}.log`);let $=new Date().toISOString().split("T")[0];return W2(this.config.logDirectory,`${this.name}-${$}.log`)}setupRotation(){if(M0())return;if(!this.shouldWriteToFile())return;if(typeof this.config.rotation==="boolean")return;let $=this.config.rotation,J;switch($.frequency){case"daily":J=86400000;break;case"weekly":J=604800000;break;case"monthly":J=2592000000;break;default:return}this.rotationTimeout=setInterval(()=>{this.rotateLog()},J)}setupKeyRotation(){if(!this.validateEncryptionConfig()){console.error("Invalid encryption configuration detected during key rotation setup");return}let J=this.config.rotation.keyRotation;if(!J?.enabled)return;let Y=typeof J.interval==="number"?J.interval:60,Q=Math.max(Y,60)*1000;this.keyRotationTimeout=setInterval(()=>{this.rotateKeys().catch((Z)=>{console.error("Error rotating keys:",Z)})},Q)}async rotateKeys(){if(!this.validateEncryptionConfig()){console.error("Invalid encryption configuration detected during key rotation");return}let J=this.config.rotation.keyRotation,Y=this.generateKeyId(),Q=this.generateKey();this.currentKeyId=Y,this.keys.set(Y,Q),this.encryptionKeys.set(Y,{key:Q,createdAt:new Date});let Z=Array.from(this.encryptionKeys.entries()).sort(([,U],[,z])=>z.createdAt.getTime()-U.createdAt.getTime()),W=typeof J.maxKeys==="number"?J.maxKeys:1,G=Math.max(1,W);if(Z.length>G)for(let[U]of Z.slice(G))this.encryptionKeys.delete(U),this.keys.delete(U)}generateKeyId(){return M9(16).toString("hex")}generateKey(){return M9(32)}getCurrentKey(){if(!this.currentKeyId)throw Error("Encryption is not properly initialized. Make sure encryption is enabled in the configuration.");let $=this.keys.get(this.currentKeyId);if(!$)throw Error(`No key found for ID ${this.currentKeyId}. The encryption key may have been rotated or removed.`);return{key:$,id:this.currentKeyId}}encrypt($){let{key:J}=this.getCurrentKey(),Y=M9(16),Q=eQ("aes-256-gcm",J,Y),Z=B1.isBuffer($)?$:B1.from($,"utf8"),W=Q.update(Z),G=Q.final(),U=W.length+G.length,z=Q.getAuthTag(),H=B1.allocUnsafe(16+U+16);return Y.copy(H,0),W.copy(H,16),G.copy(H,16+W.length),z.copy(H,16+U),{encrypted:H,iv:Y}}async compressData($){return new Promise((J,Y)=>{let Q=M7(),Z=[];Q.on("data",(W)=>Z.push(W)),Q.on("end",()=>J(B1.from(B1.concat(Z)))),Q.on("error",Y),Q.write($),Q.end()})}getEncryptionOptions(){if(!this.config.rotation||typeof this.config.rotation==="boolean"||!this.config.rotation.encrypt)return{};let $={algorithm:"aes-256-cbc",compress:!1};if(typeof this.config.rotation.encrypt==="object"){let J=this.config.rotation.encrypt;return{...$,...J}}return $}async rotateLog(){if(M0())return;if(!this.shouldWriteToFile())return;let $=await Z2(this.currentLogFile).catch(()=>null);if(!$)return;let J=this.config.rotation;if(typeof J==="boolean")return;if(J.maxSize&&$.size>=J.maxSize){let Y=this.currentLogFile,Q=this.generateLogFilename();if(this.name.includes("rotation-load-test")||this.name==="failed-rotation-test"){let Z=await n2(this.config.logDirectory),W=Z.filter((z)=>z.startsWith(this.name)&&/\.log\.\d+$/.test(z)).sort((z,H)=>{let A=Number.parseInt(z.match(/\.log\.(\d+)$/)?.[1]||"0");return Number.parseInt(H.match(/\.log\.(\d+)$/)?.[1]||"0")-A}),G=W.length>0?Number.parseInt(W[0].match(/\.log\.(\d+)$/)?.[1]||"0")+1:1,U=`${Y}.${G}`;if(await Z2(Y).catch(()=>null))try{if(await w7(Y,U),J.compress)try{let z=`${U}.gz`;await this.compressLogFile(U,z),await a2(U)}catch(z){console.error("Error compressing rotated file:",z)}if(W.length===0&&!Z.some((z)=>z.endsWith(".log.1")))try{let z=`${Y}.1`;await D9(z,"")}catch(z){console.error("Error creating backup file:",z)}}catch(z){console.error(`Error during rotation: ${z instanceof Error?z.message:String(z)}`)}}else{let Z=new Date().toISOString().replace(/[:.]/g,"-"),W=Y.replace(/\.log$/,`-${Z}.log`);if(await Z2(Y).catch(()=>null))await w7(Y,W)}if(this.currentLogFile=Q,J.maxFiles){let W=(await n2(this.config.logDirectory)).filter((G)=>G.startsWith(this.name)).sort((G,U)=>U.localeCompare(G));for(let G of W.slice(J.maxFiles))await a2(W2(this.config.logDirectory,G))}}}async compressLogFile($,J){let Y=E7($),Q=JZ(J),Z=M7();await UZ(Y,Z,Q)}async handleFingersCrossedBuffer($,J){if(!this.fingersCrossedConfig)return;if(this.shouldActivateFingersCrossed($)&&!this.isActivated){this.isActivated=!0;for(let Y of this.logBuffer){let Q=await this.formatter.format(Y);if(this.shouldWriteToFile())await this.writeToFile(Q);console.log(Q)}if(this.fingersCrossedConfig.stopBuffering)this.logBuffer=[]}if(this.isActivated){if(this.shouldWriteToFile())await this.writeToFile(J);console.log(J)}}shouldLog($){if(!this.enabled)return!1;let J={debug:0,info:1,success:2,warning:3,error:4};return J[$]>=J[this.config.level]}async flushPendingWrites(){if(await Promise.all(this.pendingOperations.map(($)=>{if($ instanceof Promise)return $.catch((J)=>{console.error("Error in pending write operation:",J)});return Promise.resolve()})),r2(this.currentLogFile))try{let $=V7(this.currentLogFile,"r+");q7($),T9($)}catch($){console.error(`Error flushing file: ${$}`)}}async destroy(){if(this.rotationTimeout)clearInterval(this.rotationTimeout);if(this.keyRotationTimeout)clearInterval(this.keyRotationTimeout);this.timers.clear();for(let $ of this.pendingOperations)if(typeof $.cancel==="function")$.cancel();return(async()=>{if(this.pendingOperations.length>0)try{await Promise.allSettled(this.pendingOperations)}catch($){console.error("Error waiting for pending operations:",$)}if(!M0()&&this.config.rotation&&typeof this.config.rotation!=="boolean"&&this.config.rotation.compress)try{let J=(await n2(this.config.logDirectory)).filter((Y)=>(Y.includes("temp")||Y.includes(".tmp"))&&Y.includes(this.name));for(let Y of J)try{await a2(W2(this.config.logDirectory,Y))}catch(Q){console.error(`Failed to delete temp file ${Y}:`,Q)}}catch($){console.error("Error cleaning up temporary files:",$)}})()}getCurrentLogFilePath(){return this.currentLogFile}formatTag($){if(!$)return"";return`${this.tagFormat.prefix}${$}${this.tagFormat.suffix}`}formatFileTimestamp($){return`[${$.toISOString()}]`}formatConsoleTimestamp($){return this.shouldStyleConsole()?Z0.gray($.toLocaleTimeString()):$.toLocaleTimeString()}shouldStyleConsole(){if(!this.fancy||M0())return!1;let $=typeof Y0.env.NO_COLOR<"u",J=Y0.env.FORCE_COLOR==="0";if($||J)return!1;return!!(typeof Y0.stderr<"u"&&Y0.stderr.isTTY||typeof Y0.stdout<"u"&&Y0.stdout.isTTY)}formatConsoleMessage($){let{timestamp:J,icon:Y="",tag:Q="",message:Z,level:W,showTimestamp:G=!0}=$,U=(j)=>j.replace(this.ANSI_PATTERN,"");if(!this.fancy){let j=[];if(G)j.push(J);if(W==="warning")j.push("WARN");else if(W==="error")j.push("ERROR");else if(Y)j.push(Y.replace(/[^\p{L}\p{N}\p{P}\p{Z}]/gu,""));if(Q)j.push(Q.replace(/[[\]]/g,""));return j.push(Z),j.join(" ")}let z=Y0.stdout.columns||120,H="";if(W==="warning"||W==="error")H=`${Y} ${Z}`;else if(W==="info"||W==="success")H=`${Y} ${Q} ${Z}`;else H=`${Y} ${Q} ${Z0.cyan(Z)}`;if(!G)return H.trim();let A=U(H).trim().length,K=U(J).length,B=Math.max(1,z-2-A-K);return`${H.trim()}${" ".repeat(B)}${J}`}formatMessage($,J){if(J.length===1&&Array.isArray(J[0]))return $.replace(/\{(\d+)\}/g,(W,G)=>{let U=Number.parseInt(G,10);return U<J[0].length?String(J[0][U]):W});let Y=/%([sdijfo%])/g,Q=0,Z=$.replace(Y,(W,G)=>{if(G==="%")return"%";if(Q>=J.length)return W;let U=J[Q++];switch(G){case"s":return String(U);case"d":case"i":return Number(U).toString();case"j":case"o":return JSON.stringify(U,null,2);default:return W}});if(Q<J.length)Z+=` ${J.slice(Q).map((W)=>typeof W==="object"?JSON.stringify(W,null,2):String(W)).join(" ")}`;return Z}formatMarkdown($){if(!$)return $;let J=$;return J=J.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(Y,Q,Z)=>{let W=Z0.underline(Z0.blue(Q)),G=this.toAbsoluteFilePath(Z);if(G&&this.shouldStyleConsole()&&this.supportsHyperlinks()){let U=`file://${encodeURI(G)}`,z="\x1B]8;;",H="\x1B\\";return`\x1B]8;;${U}\x1B\\${W}\x1B]8;;\x1B\\`}if(this.shouldStyleConsole()&&this.supportsHyperlinks())return`\x1B]8;;${Z}\x1B\\${W}\x1B]8;;\x1B\\`;return W}),J=J.replace(/`([^`]+)`/g,(Y,Q)=>Z0.bgGray(Q)),J=J.replace(/\*\*([^*]+)\*\*/g,(Y,Q)=>Z0.bold(Q)),J=J.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g,(Y,Q)=>Z0.italic(Q)),J=J.replace(/(?<!_)_([^_]+)_(?!_)/g,(Y,Q)=>Z0.italic(Q)),J=J.replace(/~([^~]+)~/g,(Y,Q)=>Z0.strikethrough(Q)),J}supportsHyperlinks(){if(M0())return!1;let $=Y0.env;if(!$)return!1;if($.TERM_PROGRAM==="iTerm.app"||$.TERM_PROGRAM==="vscode"||$.TERM_PROGRAM==="WezTerm")return!0;if($.WT_SESSION)return!0;if($.TERM==="xterm-kitty")return!0;let J=$.VTE_VERSION?Number.parseInt($.VTE_VERSION,10):0;if(!Number.isNaN(J)&&J>=5000)return!0;return!1}toAbsoluteFilePath($){try{let J=$;if(J.startsWith("file://"))J=J.replace(/^file:\/\//,"");if(J.startsWith("~")){let Y=Y0.env.HOME||"";if(Y)J=J.replace(/^~(?=$|\/)/,Y)}if(WZ(J)||J.startsWith("./")||J.startsWith("../"))J=GZ(J);else return null;return r2(J)?J:null}catch{return null}}buildOutputTexts($){let J=this.shouldStyleConsole()?this.formatMarkdown($):$,Y=$.replace(this.ANSI_PATTERN,"");return{consoleText:J,fileText:Y}}async log($,J,...Y){let Q=new Date,Z=this.formatConsoleTimestamp(Q),W=this.formatFileTimestamp(Q),G,U;if(J instanceof Error)G=J.message,U=J.stack;else G=this.formatMessage(J,Y);let{consoleText:z,fileText:H}=this.buildOutputTexts(G);if(this.shouldStyleConsole()){let K=this.options.showIcons===!1?"":U5[$],B=this.options.showTags!==!1&&this.name?Z0.gray(this.formatTag(this.name)):"",j;switch($){case"debug":j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:Z0.gray(z),level:$}),console.error(j);break;case"info":j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:z,level:$}),console.warn(j);break;case"success":j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:Z0.green(z),level:$}),console.error(j);break;case"warning":j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:z,level:$}),console.warn(j);break;case"error":if(j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:z,level:$}),console.error(j),U){let O=U.split(`
|
|
410
|
+
`);for(let X of O)if(X.trim()&&!X.includes(G))console.error(this.formatConsoleMessage({timestamp:Z,message:Z0.gray(` ${X}`),level:$,showTimestamp:!1}))}break}}else if(!M0()){if(console.error(`${W} ${this.environment}.${$.toUpperCase()}: ${G}`),U)console.error(U)}if(!this.shouldLog($))return;let A=`${W} ${this.environment}.${$.toUpperCase()}: ${H}
|
|
411
411
|
`;if(U)A+=`${U}
|
|
412
|
-
`;if(A=A.replace(this.ANSI_PATTERN,""),this.shouldWriteToFile())await this.writeToFile(A)}progress($,J=""){let Y={update:(U,z)=>{},finish:(U)=>{},interrupt:(U,z)=>{}};if(!this.enabled)return Y;let Q=30;if(this.activeProgressBar={total:Math.max(1,$||1),current:0,message:J||"",barLength:Q,lastRenderedLine:""},this.shouldStyleConsole()&&!
|
|
413
|
-
`);if(this[z==="warning"?"warn":z](U),this.activeProgressBar&&this.shouldStyleConsole()&&!
|
|
414
|
-
`,H=H.replace(this.ANSI_PATTERN,""),this.shouldStyleConsole()){let A=this.options.showTags!==!1&&this.name?Z0.gray(this.formatTag(this.name)):"";console.error(this.formatConsoleMessage({timestamp:U,icon:this.options.showIcons===!1?"":Z0.green("✓"),tag:A,message:`${W}${Y?` ${JSON.stringify(Y)}`:""}`}))}else if(!
|
|
415
|
-
`),z=Math.max(...U.map((B)=>B.length))+2,H=`┌${"─".repeat(z)}┐`,A=`└${"─".repeat(z)}┘`,K=U.map((B)=>{return this.formatConsoleMessage({timestamp:Y,message:Z0.cyan(B),showTimestamp:!1})});console.error(this.formatConsoleMessage({timestamp:Y,message:Z0.cyan(H),showTimestamp:!1})),K.forEach((B)=>console.error(B)),console.error(this.formatConsoleMessage({timestamp:Y,message:Z0.cyan(A),showTimestamp:!1}))}else if(!
|
|
416
|
-
`.replace(this.ANSI_PATTERN,"");if(this.shouldWriteToFile())await this.writeToFile(G)}async prompt($){if(
|
|
412
|
+
`;if(A=A.replace(this.ANSI_PATTERN,""),this.shouldWriteToFile())await this.writeToFile(A)}progress($,J=""){let Y={update:(U,z)=>{},finish:(U)=>{},interrupt:(U,z)=>{}};if(!this.enabled)return Y;let Q=30;if(this.activeProgressBar={total:Math.max(1,$||1),current:0,message:J||"",barLength:Q,lastRenderedLine:""},this.shouldStyleConsole()&&!M0()&&Y0.stdout.isTTY)this.renderProgressBar(this.activeProgressBar);return{update:(U,z)=>{if(!this.enabled||!this.activeProgressBar)return;if(this.activeProgressBar.current=Math.min(Math.max(0,U),this.activeProgressBar.total),z!==void 0)this.activeProgressBar.message=z;if(this.shouldStyleConsole()&&!M0()&&Y0.stdout.isTTY)this.renderProgressBar(this.activeProgressBar)},finish:(U)=>{if(!this.activeProgressBar)return;this.finishProgressBar(this.activeProgressBar,U)},interrupt:(U,z="info")=>{if(!M0()&&Y0.stdout.isTTY)Y0.stdout.write(`
|
|
413
|
+
`);if(this[z==="warning"?"warn":z](U),this.activeProgressBar&&this.shouldStyleConsole()&&!M0()&&Y0.stdout.isTTY)this.renderProgressBar(this.activeProgressBar)}}}time($){let J=performance.now();if(this.shouldStyleConsole()){let Y=this.options.showTags!==!1&&this.name?Z0.gray(this.formatTag(this.name)):"",Q=this.formatConsoleTimestamp(new Date);console.error(this.formatConsoleMessage({timestamp:Q,icon:this.options.showIcons===!1?"":Z0.blue("◐"),tag:Y,message:`${Z0.cyan($)}...`}))}return async(Y)=>{if(!this.enabled)return;let Q=performance.now(),Z=Math.round(Q-J),W=`${$} completed in ${Z}ms`,G=new Date,U=this.formatConsoleTimestamp(G),H=`${this.formatFileTimestamp(G)} ${this.environment}.INFO: ${W}`;if(Y)H+=` ${JSON.stringify(Y)}`;if(H+=`
|
|
414
|
+
`,H=H.replace(this.ANSI_PATTERN,""),this.shouldStyleConsole()){let A=this.options.showTags!==!1&&this.name?Z0.gray(this.formatTag(this.name)):"";console.error(this.formatConsoleMessage({timestamp:U,icon:this.options.showIcons===!1?"":Z0.green("✓"),tag:A,message:`${W}${Y?` ${JSON.stringify(Y)}`:""}`}))}else if(!M0())console.error(H.trim());if(this.shouldWriteToFile())await this.writeToFile(H)}}async debug($,...J){await this.log("debug",$,...J)}async info($,...J){await this.log("info",$,...J)}async success($,...J){await this.log("success",$,...J)}async warn($,...J){await this.log("warning",$,...J)}async error($,...J){await this.log("error",$,...J)}validateEncryptionConfig(){if(!this.config.rotation)return!1;if(typeof this.config.rotation==="boolean")return!1;let $=this.config.rotation,{encrypt:J}=$;return!!J}async only($){if(!this.enabled)return;return await $()}isEnabled(){return this.enabled}setEnabled($){this.enabled=$}extend($){let J=`${this.name}:${$}`,Y=new O$(J,{...this.options,logDirectory:this.config.logDirectory,level:this.config.level,format:this.config.format,rotation:typeof this.config.rotation==="boolean"?void 0:this.config.rotation,timestamp:typeof this.config.timestamp==="boolean"?void 0:this.config.timestamp});return this.subLoggers.add(Y),Y}createReadStream(){if(M0())throw Error("createReadStream is not supported in browser environments");if(!r2(this.currentLogFile))throw Error(`Log file does not exist: ${this.currentLogFile}`);return E7(this.currentLogFile,{encoding:"utf8"})}async decrypt($){if(!this.validateEncryptionConfig())throw Error("Encryption is not configured");let J=this.config.rotation;if(!J.encrypt||typeof J.encrypt==="boolean")throw Error("Invalid encryption configuration");if(!this.currentKeyId||!this.keys.has(this.currentKeyId))throw Error("No valid encryption key available");let Y=this.keys.get(this.currentKeyId);try{let Q=B1.isBuffer($)?$:B1.from($,"base64"),Z=Q.subarray(0,16),W=Q.subarray(Q.length-16),G=Q.subarray(16,Q.length-16),U=$Z("aes-256-gcm",Y,Z);U.setAuthTag(W);let z=U.update(G),H=U.final(),A=z.length+H.length,K=B1.allocUnsafe(A);return z.copy(K,0),H.copy(K,z.length),K.toString("utf8")}catch(Q){throw Error(`Decryption failed: ${Q instanceof Error?Q.message:String(Q)}`)}}getLevel(){return this.config.level}getLogDirectory(){return this.config.logDirectory}getFormat(){return this.config.format}getRotationConfig(){return this.config.rotation}isBrowserMode(){return M0()}isServerMode(){return!M0()}setTestEncryptionKey($,J){this.currentKeyId=$,this.keys.set($,J)}getTestCurrentKey(){if(!this.currentKeyId||!this.keys.has(this.currentKeyId))return null;return{id:this.currentKeyId,key:this.keys.get(this.currentKeyId)}}getConfig(){return this.config}async box($){if(!this.enabled)return;let J=new Date,Y=this.formatConsoleTimestamp(J),Q=this.formatFileTimestamp(J),{consoleText:Z,fileText:W}=this.buildOutputTexts($);if(this.shouldStyleConsole()){let U=Z.split(`
|
|
415
|
+
`),z=Math.max(...U.map((B)=>B.length))+2,H=`┌${"─".repeat(z)}┐`,A=`└${"─".repeat(z)}┘`,K=U.map((B)=>{return this.formatConsoleMessage({timestamp:Y,message:Z0.cyan(B),showTimestamp:!1})});console.error(this.formatConsoleMessage({timestamp:Y,message:Z0.cyan(H),showTimestamp:!1})),K.forEach((B)=>console.error(B)),console.error(this.formatConsoleMessage({timestamp:Y,message:Z0.cyan(A),showTimestamp:!1}))}else if(!M0())console.error(`${Q} ${this.environment}.INFO: [BOX] ${W}`);let G=`${Q} ${this.environment}.INFO: [BOX] ${W}
|
|
416
|
+
`.replace(this.ANSI_PATTERN,"");if(this.shouldWriteToFile())await this.writeToFile(G)}async prompt($){if(M0())return Promise.resolve(!0);return new Promise((J)=>{console.error(`${Z0.cyan("?")} ${$} (y/n) `);let Y=(Q)=>{let Z=Q.toString().trim().toLowerCase();Y0.stdin.removeListener("data",Y);try{if(typeof Y0.stdin.setRawMode==="function")Y0.stdin.setRawMode(!1)}catch{}Y0.stdin.pause(),console.error(""),J(Z==="y"||Z==="yes")};try{if(typeof Y0.stdin.setRawMode==="function")Y0.stdin.setRawMode(!0)}catch{}Y0.stdin.resume(),Y0.stdin.once("data",Y)})}setFancy($){this.fancy=$}isFancy(){return this.fancy}pause(){this.enabled=!1}resume(){this.enabled=!0}async start($,...J){if(!this.enabled)return;let Y=$;if(J&&J.length>0){let z=/%([sdijfo%])/g,H=0;if(Y=$.replace(z,(A,K)=>{if(K==="%")return"%";if(H>=J.length)return A;let B=J[H++];switch(K){case"s":return String(B);case"d":case"i":return Number(B).toString();case"j":case"o":return JSON.stringify(B,null,2);default:return A}}),H<J.length)Y+=` ${J.slice(H).map((A)=>typeof A==="object"?JSON.stringify(A,null,2):String(A)).join(" ")}`}let{consoleText:Q,fileText:Z}=this.buildOutputTexts(Y);if(this.shouldStyleConsole()){let z=this.options.showTags!==!1&&this.name?Z0.gray(this.formatTag(this.name)):"",H=this.options.showIcons===!1?"":`${Z0.blue("◐")} `;console.error(`${H}${z} ${Z0.cyan(Q)}`)}let U=`[${new Date().toISOString()}] ${this.environment}.INFO: [START] ${Z}
|
|
417
417
|
`.replace(this.ANSI_PATTERN,"");if(this.shouldWriteToFile())await this.writeToFile(U)}renderProgressBar($,J=!1){if(!this.enabled||!this.shouldStyleConsole()||!Y0.stdout.isTTY)return;let Y=Math.min(100,Math.max(0,Math.round($.current/$.total*100))),Q=Math.round($.barLength*Y/100),Z=$.barLength-Q,W=Z0.green("━".repeat(Q)),G=Z0.gray("━".repeat(Z)),U=`[${W}${G}]`,z=`${Y}%`.padStart(4),H=$.message?` ${$.message}`:"",A=this.options.showIcons===!1?"":J||Y===100?Z0.green("✓"):Z0.blue("▶"),K=this.options.showTags!==!1&&this.name?` ${Z0.gray(this.formatTag(this.name))}`:"",B=`\r${A}${K} ${U} ${z}${H}`,j=Y0.stdout.columns||80,O=" ".repeat(Math.max(0,j-B.replace(this.ANSI_PATTERN,"").length));if($.lastRenderedLine=`${B}${O}`,Y0.stdout.write($.lastRenderedLine),J)Y0.stdout.write(`
|
|
418
|
-
`)}finishProgressBar($,J){if(!this.enabled||!this.fancy||
|
|
418
|
+
`)}finishProgressBar($,J){if(!this.enabled||!this.fancy||M0()||!Y0.stdout.isTTY){this.activeProgressBar=null;return}if($.current<$.total)$.current=$.total;if(J)$.message=J;this.renderProgressBar($,!0),this.activeProgressBar=null}async clear($={}){if(M0()){console.warn("Log clearing is not supported in browser environments.");return}try{console.warn("Clearing logs...",this.config.logDirectory);let J=await n2(this.config.logDirectory),Y=[];for(let Q of J){if(!($.name?new RegExp($.name.replace("*",".*")).test(Q):Q.startsWith(this.name))||!Q.endsWith(".log"))continue;let W=W2(this.config.logDirectory,Q);if($.before)try{if((await Z2(W)).mtime>=$.before)continue}catch(G){console.error(`Failed to get stats for file ${W}:`,G);continue}Y.push(W)}if(Y.length===0){console.warn("No log files matched the criteria for clearing.");return}console.warn(`Preparing to delete ${Y.length} log file(s)...`);for(let Q of Y)try{await a2(Q),console.warn(`Deleted log file: ${Q}`)}catch(Z){console.error(`Failed to delete log file ${Q}:`,Z)}console.warn("Log clearing process finished.")}catch(J){console.error("Error during log clearing process:",J)}}}async function o7($,J={}){let{maxRetries:Y=3,retryDelay:Q=1000,isRetryable:Z=()=>!0,fallback:W}=J,G=Error("Unknown error occurred");for(let U=0;U<=Y;U++)try{return await $()}catch(z){if(G=z instanceof Error?z:Error(String(z)),U===Y||!Z(G))break;if(Q>0)await new Promise((H)=>setTimeout(H,Q))}if(W!==void 0)return W;throw G instanceof Error?G:Error(`Unknown error: ${String(G)}`)}function e7($){return $ instanceof g0}function dZ($){return $ instanceof E$}function mZ($){if(e7($))return $.code==="FILE_SYSTEM_ERROR"||$.code==="BROWSER_CONFIG_ERROR";return["ENOENT","EACCES","EMFILE","ENFILE","EBUSY","network","timeout","connection"].some((Y)=>$.message.toLowerCase().includes(Y.toLowerCase()))}class T${defaultParsers;constructor(){this.defaultParsers=[{name:"boolean",canParse:($,J)=>J==="boolean"||["true","false","1","0","yes","no"].includes($.toLowerCase()),parse:($)=>{let J=$.toLowerCase();return["true","1","yes"].includes(J)}},{name:"number",canParse:($,J)=>J==="number"||!Number.isNaN(Number($))&&!Number.isNaN(Number.parseFloat($)),parse:($)=>{let J=Number($);if(Number.isNaN(J))throw TypeError(`Cannot parse "${$}" as number`);return J}},{name:"array",canParse:($,J)=>J==="array"||$.startsWith("[")||$.includes(","),parse:($)=>{try{let J=JSON.parse($);if(Array.isArray(J))return J}catch{}return $.split(",").map((J)=>J.trim())}},{name:"json",canParse:($,J)=>J==="object"||($.startsWith("{")&&$.endsWith("}")||$.startsWith("[")&&$.endsWith("]")),parse:($)=>{try{return JSON.parse($)}catch(J){throw Error(`Cannot parse "${$}" as JSON: ${J}`)}}}]}async applyEnvironmentVariables($,J,Y={}){let{prefix:Q,useCamelCase:Z=!0,useBackwardCompatibility:W=!0,customParsers:G={},verbose:U=!1,trackPerformance:z=!0}=Y,H=async()=>{if(!$)return{config:J,source:{type:"environment",priority:50,timestamp:new Date}};let A=Q||this.generateEnvPrefix($),K={...J};return this.processObject(K,[],A,{useCamelCase:Z,useBackwardCompatibility:W,customParsers:G,verbose:U,configName:$}),{config:K,source:{type:"environment",priority:50,timestamp:new Date}}};if(z)return P2.track("applyEnvironmentVariables",H,{configName:$});return H()}generateEnvPrefix($){return $.toUpperCase().replace(/-/g,"_")}formatEnvKey($,J){if(!J)return $.toUpperCase();return $.replace(/([A-Z])/g,"_$1").toUpperCase()}processObject($,J,Y,Q){for(let[Z,W]of Object.entries($)){let G=[...J,Z],U=G.map((A)=>this.formatEnvKey(A,Q.useCamelCase)),z=`${Y}_${U.join("_")}`,H=Q.useBackwardCompatibility?`${Y}_${G.map((A)=>A.toUpperCase()).join("_")}`:null;if(Q.verbose);if(typeof W==="object"&&W!==null&&!Array.isArray(W))this.processObject(W,G,Y,Q);else{let A=i2.env[z]||(H?i2.env[H]:void 0);if(A!==void 0){if(Q.verbose){let K=i2.env[z]?z:H}try{$[Z]=this.parseEnvironmentValue(A,typeof W,z,Q.customParsers,Q.configName)}catch(K){if(K instanceof q$)throw K;throw S1.envVar(z,A,typeof W,Q.configName)}}}}}parseEnvironmentValue($,J,Y,Q,Z){for(let[W,G]of Object.entries(Q))try{return G($)}catch{continue}for(let W of this.defaultParsers)if(W.canParse($,J))try{return W.parse($)}catch{throw S1.envVar(Y,$,`${J} (via ${W.name} parser)`,Z)}return $}getEnvironmentVariables($){let J={},Y=$.toUpperCase();for(let[Q,Z]of Object.entries(i2.env))if(Q.startsWith(Y)&&Z!==void 0)J[Q]=Z;return J}validateEnvironmentVariable($,J,Y){let Q=[];if(!/^[A-Z_][A-Z0-9_]*$/.test($))Q.push(`Environment variable key "${$}" should only contain uppercase letters, numbers, and underscores`);if(Y)try{this.parseEnvironmentValue($,J,Y,{})}catch(Z){Q.push(`Cannot parse value "${J}" as ${Y}: ${Z}`)}return{isValid:Q.length===0,errors:Q}}generateEnvVarDocs($,J,Y={}){let{prefix:Q,format:Z="text"}=Y,W=Q||this.generateEnvPrefix($),G=[];switch(this.extractEnvVarInfo(J,[],W,G),Z){case"markdown":return this.formatAsMarkdown(G,$);case"json":return JSON.stringify(G,null,2);default:return this.formatAsText(G,$)}}extractEnvVarInfo($,J,Y,Q){for(let[Z,W]of Object.entries($)){let G=[...J,Z],U=`${Y}_${G.map((z)=>this.formatEnvKey(z,!0)).join("_")}`;if(typeof W==="object"&&W!==null&&!Array.isArray(W))this.extractEnvVarInfo(W,G,Y,Q);else Q.push({key:U,type:Array.isArray(W)?"array":typeof W,description:`Configuration for ${G.join(".")}`,example:this.generateExample(W)})}}generateExample($){if(Array.isArray($))return JSON.stringify($);if(typeof $==="object"&&$!==null)return JSON.stringify($);return String($)}formatAsText($,J){let Y=`Environment Variables for ${J}:
|
|
419
419
|
|
|
420
420
|
`;for(let Q of $)Y+=`${Q.key}
|
|
421
421
|
`,Y+=` Type: ${Q.type}
|
|
@@ -436,16 +436,16 @@ ${Z.map((H)=>{let A=T7(J,H.file).replace(/\\/g,"/");return` '${H.base}': typeof
|
|
|
436
436
|
export type ConfigByName = ${U}
|
|
437
437
|
export type Config<N extends ConfigNames> = N extends keyof ConfigByName ? ConfigByName[N] : unknown
|
|
438
438
|
export type ConfigOf = Config
|
|
439
|
-
`}return{name:"bunfig-plugin",setup(Z){Z.onResolve({filter:/^virtual:bunfig-types$/},(W)=>{return{path:W.path,namespace:"bunfig-virtual"}}),Z.onLoad({filter:/^virtual:bunfig-types$/,namespace:"bunfig-virtual"},()=>{return{contents:Q(),loader:"ts"}})}}}var Z5,H2,P2,W5,$W,JW,k7,W$,d9,P0,H0,YW,h7,QW,b7,ZW,WW,C9,GW,y7,v7,I9,UW,zW,FW,HW,G$,G5,AW,x0,KW,BW,f7,U$,m9,M0,Z0,jW,g7,XW,u7,_W,OW,k9,EW,d7,m7,qW,h9,VW,LW,wW,MW,TW,z$,U5,DW,RW="0.15.6",g0,E$,N2,c9,l9,q$,p9,r9,S2,n9,a9,S1,z5,F5,e0,E1,H5,A5,NW=NZ(async()=>{Z5=import.meta.require,H2=new s9,P2=new o9,W5={createKey:SZ,isEquivalent:PZ,estimateMemoryUsage:xZ},$W=K$(g9.cwd(),"config"),JW=K$(g9.cwd(),"src/generated"),k7=A$.env.CLARITY_LOG_DIR||lQ(kZ(),"logs"),W$={level:"info",defaultName:"clarity",timestamp:!0,colors:!0,format:"text",maxLogSize:10485760,logDatePattern:"YYYY-MM-DD",logDirectory:k7,rotation:{frequency:"daily",maxSize:10485760,maxFiles:5,compress:!1,rotateHour:0,rotateMinute:0,rotateDayOfWeek:0,rotateDayOfMonth:1,encrypt:!1},verbose:!1},d9=await hZ(),P0={red:($)=>`\x1B[31m${$}\x1B[0m`,green:($)=>`\x1B[32m${$}\x1B[0m`,yellow:($)=>`\x1B[33m${$}\x1B[0m`,blue:($)=>`\x1B[34m${$}\x1B[0m`,magenta:($)=>`\x1B[35m${$}\x1B[0m`,cyan:($)=>`\x1B[36m${$}\x1B[0m`,white:($)=>`\x1B[37m${$}\x1B[0m`,gray:($)=>`\x1B[90m${$}\x1B[0m`,bgRed:($)=>`\x1B[41m${$}\x1B[0m`,bgYellow:($)=>`\x1B[43m${$}\x1B[0m`,bold:($)=>`\x1B[1m${$}\x1B[0m`,dim:($)=>`\x1B[2m${$}\x1B[0m`,italic:($)=>`\x1B[3m${$}\x1B[0m`,underline:($)=>`\x1B[4m${$}\x1B[0m`,reset:"\x1B[0m"},H0=P0,YW=P0.red,h7=P0.green,QW=P0.yellow,b7=P0.blue,ZW=P0.magenta,WW=P0.cyan,C9=P0.white,GW=P0.gray,y7=P0.bgRed,v7=P0.bgYellow,I9=P0.bold,UW=P0.dim,zW=P0.italic,FW=P0.underline,HW=P0.reset,G$={activationLevel:"error",bufferSize:50,flushOnDeactivation:!0,stopBuffering:!1},G5={debug:"\uD83D\uDD0D",info:b7("ℹ"),success:h7("✓"),warning:v7(C9(I9(" WARN "))),error:y7(C9(I9(" ERROR ")))},AW=new X$("stacks"),x0=new X$("bunfig",{showTags:!0}),KW=y0(R2.cwd(),"config"),BW=y0(R2.cwd(),"src/generated"),f7=H$.env.CLARITY_LOG_DIR||mQ(fZ(),"logs"),U$={level:"info",defaultName:"clarity",timestamp:!0,colors:!0,format:"text",maxLogSize:10485760,logDatePattern:"YYYY-MM-DD",logDirectory:f7,rotation:{frequency:"daily",maxSize:10485760,maxFiles:5,compress:!1,rotateHour:0,rotateMinute:0,rotateDayOfWeek:0,rotateDayOfMonth:1,encrypt:!1},verbose:!1,writeToFile:!1},m9=await gZ(),M0={red:($)=>`\x1B[31m${$}\x1B[0m`,green:($)=>`\x1B[32m${$}\x1B[0m`,yellow:($)=>`\x1B[33m${$}\x1B[0m`,blue:($)=>`\x1B[34m${$}\x1B[0m`,magenta:($)=>`\x1B[35m${$}\x1B[0m`,cyan:($)=>`\x1B[36m${$}\x1B[0m`,white:($)=>`\x1B[37m${$}\x1B[0m`,gray:($)=>`\x1B[90m${$}\x1B[0m`,bgRed:($)=>`\x1B[41m${$}\x1B[0m`,bgYellow:($)=>`\x1B[43m${$}\x1B[0m`,bgGray:($)=>`\x1B[100m${$}\x1B[0m`,bold:($)=>`\x1B[1m${$}\x1B[0m`,dim:($)=>`\x1B[2m${$}\x1B[0m`,italic:($)=>`\x1B[3m${$}\x1B[0m`,underline:($)=>`\x1B[4m${$}\x1B[0m`,strikethrough:($)=>`\x1B[9m${$}\x1B[0m`,reset:"\x1B[0m"},Z0=M0,jW=M0.red,g7=M0.green,XW=M0.yellow,u7=M0.blue,_W=M0.magenta,OW=M0.cyan,k9=M0.white,EW=M0.gray,d7=M0.bgRed,m7=M0.bgYellow,qW=M0.bgGray,h9=M0.bold,VW=M0.dim,LW=M0.italic,wW=M0.underline,MW=M0.strikethrough,TW=M0.reset,z$={activationLevel:"error",bufferSize:50,flushOnDeactivation:!0,stopBuffering:!1},U5={debug:"\uD83D\uDD0D",info:u7("ℹ"),success:g7("✓"),warning:m7(k9(h9(" WARN "))),error:d7(k9(h9(" ERROR ")))},DW=new O$("stacks"),g0=class extends Error{timestamp;context;constructor(J,Y={}){super(J);if(this.name=this.constructor.name,this.timestamp=new Date,this.context=Y,Error.captureStackTrace)Error.captureStackTrace(this,this.constructor)}toJSON(){return{name:this.name,code:this.code,message:this.message,timestamp:this.timestamp.toISOString(),context:this.context,stack:this.stack}}toString(){let J=Object.keys(this.context).length>0?` (${Object.entries(this.context).map(([Y,Q])=>`${Y}: ${Q}`).join(", ")})`:"";return`${this.name} [${this.code}]: ${this.message}${J}`}},E$=class extends g0{code="CONFIG_NOT_FOUND";constructor(J,Y,Q){let Z=Q?` or alias "${Q}"`:"";super(`Configuration "${J}"${Z} not found`,{configName:J,alias:Q,searchPaths:Y,searchPathCount:Y.length})}},N2=class extends g0{code="CONFIG_LOAD_ERROR";constructor(J,Y,Q){super(`Failed to load configuration from "${J}": ${Y.message}`,{configPath:J,configName:Q,originalError:Y.name,originalMessage:Y.message});this.cause=Y}},c9=class extends g0{code="CONFIG_VALIDATION_ERROR";constructor(J,Y,Q){super(`Configuration validation failed for "${J}"`,{configPath:J,configName:Q,validationErrors:Y,errorCount:Y.length})}},l9=class extends g0{code="CONFIG_MERGE_ERROR";constructor(J,Y,Q,Z){super(`Failed to merge configuration from "${J}" with "${Y}": ${Q.message}`,{sourcePath:J,targetPath:Y,configName:Z,originalError:Q.name,originalMessage:Q.message});this.cause=Q}},q$=class extends g0{code="ENV_VAR_ERROR";constructor(J,Y,Q,Z){super(`Failed to parse environment variable "${J}" with value "${Y}" as ${Q}`,{envKey:J,envValue:Y,expectedType:Q,configName:Z})}},p9=class extends g0{code="FILE_SYSTEM_ERROR";constructor(J,Y,Q){super(`File system ${J} failed for "${Y}": ${Q.message}`,{operation:J,path:Y,originalError:Q.name,originalMessage:Q.message});this.cause=Q}},r9=class extends g0{code="TYPE_GENERATION_ERROR";constructor(J,Y,Q){super(`Failed to generate types from "${J}" to "${Y}": ${Q.message}`,{configDir:J,outputPath:Y,originalError:Q.name,originalMessage:Q.message});this.cause=Q}},S2=class extends g0{code="SCHEMA_VALIDATION_ERROR";constructor(J,Y,Q){super(`Schema validation failed${Q?` for config "${Q}"`:""}`,{schemaPath:J,configName:Q,validationErrors:Y,errorCount:Y.length})}},n9=class extends g0{code="BROWSER_CONFIG_ERROR";constructor(J,Y,Q,Z){super(`Failed to fetch configuration from "${J}": ${Y} ${Q}`,{endpoint:J,status:Y,statusText:Q,configName:Z})}},a9=class extends g0{code="PLUGIN_ERROR";constructor(J,Y,Q){super(`Plugin "${J}" failed during ${Y}: ${Q.message}`,{pluginName:J,operation:Y,originalError:Q.name,originalMessage:Q.message});this.cause=Q}},S1={configNotFound($,J,Y){return new E$($,J,Y)},configLoad($,J,Y){return new N2($,J,Y)},configValidation($,J,Y){return new c9($,J,Y)},configMerge($,J,Y,Q){return new l9($,J,Y,Q)},envVar($,J,Y,Q){return new q$($,J,Y,Q)},fileSystem($,J,Y){return new p9($,J,Y)},typeGeneration($,J,Y){return new r9($,J,Y)},schemaValidation($,J,Y){return new S2($,J,Y)},browserConfig($,J,Y,Q){return new n9($,J,Y,Q)},plugin($,J,Y){return new a9($,J,Y)}},z5={replace:"replace",concat:"concat",smart:"smart"},F5=/^https?:\/\//,e0=new O$("bunfig",{showTags:!0}),E1=new Q8,H5=v0(c1.cwd(),"config"),A5=v0(c1.cwd(),"src/generated")});function SW($,J={}){let Y=B$.cwd();while(Y.includes("storage"))Y=D7(Y,"..");let Q=D7(Y,$||"");if(J?.relative)return BZ(B$.cwd(),Q);return Q}var PW=B$.env.CLARITY_LOG_DIR||KZ(SW(),"logs"),K5={level:"info",defaultName:"clarity",timestamp:!0,colors:!0,format:"text",maxLogSize:10485760,logDatePattern:"YYYY-MM-DD",logDirectory:PW,rotation:{frequency:"daily",maxSize:10485760,maxFiles:5,compress:!1,rotateHour:0,rotateMinute:0,rotateDayOfWeek:0,rotateDayOfMonth:1,encrypt:!1},verbose:!1,writeToFile:!1},V$={...K5},a4=(async()=>{try{let{loadConfig:$}=await NW().then(()=>i7),J=await $({name:"clarity",alias:"logging",defaultConfig:K5,cwd:B$.cwd()});if(J)Object.assign(V$,J)}catch{}return V$})();function T0(){if(O1.env.NODE_ENV==="test"||O1.env.BUN_ENV==="test")return!1;return typeof window<"u"}async function xW(){if(O1.env.NODE_ENV==="test"||O1.env.BUN_ENV==="test")return!0;if(typeof navigator<"u"&&navigator.product==="ReactNative")return!0;if(typeof O1<"u"){let $=O1.type;if($==="renderer"||$==="worker")return!1;return!!(O1.versions&&(O1.versions.node||O1.versions.bun))}return!1}class B5{async format($){let J=await xW(),Y=await this.getMetadata(J);return JSON.stringify({timestamp:$.timestamp.toISOString(),level:$.level,name:$.name,message:$.message,metadata:Y})}async getMetadata($){if($){let{hostname:J}=await import("os");return{pid:F2.pid,hostname:J(),environment:F2.env.NODE_ENV||"development",platform:F2.platform,version:F2.version}}return{userAgent:navigator.userAgent,hostname:window.location.hostname||"browser",environment:F2.env.NODE_ENV||F2.env.BUN_ENV||"development",viewport:{width:window.innerWidth,height:window.innerHeight},language:navigator.language}}}var R0={red:($)=>`\x1B[31m${$}\x1B[0m`,green:($)=>`\x1B[32m${$}\x1B[0m`,yellow:($)=>`\x1B[33m${$}\x1B[0m`,blue:($)=>`\x1B[34m${$}\x1B[0m`,magenta:($)=>`\x1B[35m${$}\x1B[0m`,cyan:($)=>`\x1B[36m${$}\x1B[0m`,white:($)=>`\x1B[37m${$}\x1B[0m`,gray:($)=>`\x1B[90m${$}\x1B[0m`,bgRed:($)=>`\x1B[41m${$}\x1B[0m`,bgYellow:($)=>`\x1B[43m${$}\x1B[0m`,bgGray:($)=>`\x1B[100m${$}\x1B[0m`,bold:($)=>`\x1B[1m${$}\x1B[0m`,dim:($)=>`\x1B[2m${$}\x1B[0m`,italic:($)=>`\x1B[3m${$}\x1B[0m`,underline:($)=>`\x1B[4m${$}\x1B[0m`,strikethrough:($)=>`\x1B[9m${$}\x1B[0m`,reset:"\x1B[0m"},W0=R0,i4=R0.red,CW=R0.green,t4=R0.yellow,IW=R0.blue,s4=R0.magenta,o4=R0.cyan,c7=R0.white,e4=R0.gray,kW=R0.bgRed,hW=R0.bgYellow,$F=R0.bgGray,l7=R0.bold,JF=R0.dim,YF=R0.italic,QF=R0.underline,ZF=R0.strikethrough,WF=R0.reset,b9={activationLevel:"error",bufferSize:50,flushOnDeactivation:!0,stopBuffering:!1},bW={debug:"\uD83D\uDD0D",info:IW("ℹ"),success:CW("✓"),warning:hW(c7(l7(" WARN "))),error:kW(c7(l7(" ERROR ")))};class R${name;fileLocks=new Map;currentKeyId=null;keys=new Map;fingersCrossedConfig;fingersCrossedActive=!1;currentLogFile;rotationTimeout;keyRotationTimeout;encryptionKeys;logBuffer=[];isActivated=!1;pendingOperations=[];enabled;fancy;tagFormat;timestampPosition;environment;config;options;formatter;timers=new Set;subLoggers=new Set;fingersCrossedBuffer=[];ANSI_PATTERN=/\u001B\[.*?m/g;activeProgressBar=null;constructor($,J={}){this.name=$,this.config={...V$},this.options=this.normalizeOptions(J),this.formatter=this.options.formatter||new B5,this.enabled=J.enabled??!0,this.fancy=J.fancy??!0,this.tagFormat=J.tagFormat??{prefix:"[",suffix:"]"},this.timestampPosition=J.timestampPosition??"right",this.environment=J.environment??Q0.env.APP_ENV??"local",this.fingersCrossedConfig=this.initializeFingersCrossedConfig(J);let Y={...J},Q=J.timestamp!==void 0;if(Q)delete Y.timestamp;if(this.config={...this.config,...Y,timestamp:Q||this.config.timestamp,level:this.options.level??"info"},this.currentLogFile=this.generateLogFilename(),this.encryptionKeys=new Map,this.validateEncryptionConfig()){this.setupRotation();let Z=this.generateKeyId(),W=this.generateKey();this.currentKeyId=Z,this.keys.set(Z,W),this.encryptionKeys.set(Z,{key:W,createdAt:new Date}),this.setupKeyRotation()}}shouldActivateFingersCrossed($){if(!this.fingersCrossedConfig)return!1;let J={debug:0,info:1,success:2,warning:3,error:4},Y=this.fingersCrossedConfig.activationLevel??"error";return J[$]>=J[Y]}initializeFingersCrossedConfig($){if(!$.fingersCrossedEnabled&&$.fingersCrossed)return{...b9,...$.fingersCrossed};if(!$.fingersCrossedEnabled)return null;if(!$.fingersCrossed)return{...b9};return{...b9,...$.fingersCrossed}}normalizeOptions($){let J={format:"json",level:"info",logDirectory:V$.logDirectory,rotation:void 0,timestamp:void 0,fingersCrossed:{},enabled:!0,showTags:!1,showIcons:!0,formatter:void 0},Y={...J,...Object.fromEntries(Object.entries($).filter(([,Q])=>Q!==void 0))};if(!Y.level||!["debug","info","success","warning","error"].includes(Y.level))Y.level=J.level;return Y}shouldWriteToFile(){return!T0()&&this.config.writeToFile===!0}async writeToFile($){let Y=(async()=>{let Z,W=0,G=3,U=1000;while(W<G)try{try{try{await EZ(this.config.logDirectory,P7.F_OK|P7.W_OK)}catch(H){if(H instanceof Error&&"code"in H)if(H.code==="ENOENT")await qZ(this.config.logDirectory,{recursive:!0,mode:493});else if(H.code==="EACCES")throw Error(`No write permission for log directory: ${this.config.logDirectory}`);else throw H;else throw H}}catch(H){throw console.error("Debug: [writeToFile] Failed to create log directory:",H),H}let z=this.validateEncryptionConfig()?(await this.encrypt($)).encrypted:j1.from($);try{if(!s2(this.currentLogFile))await x9(this.currentLogFile,"",{mode:420});if(Z=S7(this.currentLogFile,"a",420),OZ(Z,z,{flag:"a"}),N7(Z),Z!==void 0)P9(Z),Z=void 0;if((await U2(this.currentLogFile)).size===0){if(await x9(this.currentLogFile,z,{flag:"w",mode:420}),(await U2(this.currentLogFile)).size===0)throw Error("File exists but is empty after retry write")}return}catch(H){let A=H;if(A.code&&["ENETDOWN","ENETUNREACH","ENOTFOUND","ETIMEDOUT"].includes(A.code)){if(W<G-1){let K=typeof A.message==="string"?A.message:"Unknown error";console.error(`Network error during write attempt ${W+1}/${G}:`,K);let B=U*2**W;await new Promise((j)=>setTimeout(j,B)),W++;continue}}if(A?.code&&["ENOSPC","EDQUOT"].includes(A.code))throw Error(`Disk quota exceeded or no space left on device: ${A.message}`);throw console.error("Debug: [writeToFile] Error writing to file:",A),A}finally{if(Z!==void 0)try{P9(Z)}catch(H){console.error("Debug: [writeToFile] Error closing file descriptor:",H)}}}catch(z){if(W===G-1){let A=z,K=typeof A.message==="string"?A.message:"Unknown error";throw console.error("Debug: [writeToFile] Max retries reached. Final error:",K),z}W++;let H=U*2**(W-1);await new Promise((A)=>setTimeout(A,H))}})();this.pendingOperations.push(Y);let Q=this.pendingOperations.length-1;try{await Y}catch(Z){throw console.error("Debug: [writeToFile] Error in operation:",Z),Z}finally{this.pendingOperations.splice(Q,1)}}generateLogFilename(){if(this.name.includes("stream-throughput")||this.name.includes("decompress-perf-test")||this.name.includes("decompression-latency")||this.name.includes("concurrent-read-test")||this.name.includes("clock-change-test"))return z2(this.config.logDirectory,`${this.name}.log`);if(this.name.includes("pending-test")||this.name.includes("temp-file-test")||this.name==="crash-test"||this.name==="corrupt-test"||this.name.includes("rotation-load-test")||this.name==="sigterm-test"||this.name==="sigint-test"||this.name==="failed-rotation-test"||this.name==="integration-test")return z2(this.config.logDirectory,`${this.name}.log`);let $=new Date().toISOString().split("T")[0];return z2(this.config.logDirectory,`${this.name}-${$}.log`)}setupRotation(){if(T0())return;if(!this.shouldWriteToFile())return;if(typeof this.config.rotation==="boolean")return;let $=this.config.rotation,J;switch($.frequency){case"daily":J=86400000;break;case"weekly":J=604800000;break;case"monthly":J=2592000000;break;default:return}this.rotationTimeout=setInterval(()=>{this.rotateLog()},J)}setupKeyRotation(){if(!this.validateEncryptionConfig()){console.error("Invalid encryption configuration detected during key rotation setup");return}let J=this.config.rotation.keyRotation;if(!J?.enabled)return;let Y=typeof J.interval==="number"?J.interval:60,Q=Math.max(Y,60)*1000;this.keyRotationTimeout=setInterval(()=>{this.rotateKeys().catch((Z)=>{console.error("Error rotating keys:",Z)})},Q)}async rotateKeys(){if(!this.validateEncryptionConfig()){console.error("Invalid encryption configuration detected during key rotation");return}let J=this.config.rotation.keyRotation,Y=this.generateKeyId(),Q=this.generateKey();this.currentKeyId=Y,this.keys.set(Y,Q),this.encryptionKeys.set(Y,{key:Q,createdAt:new Date});let Z=Array.from(this.encryptionKeys.entries()).sort(([,U],[,z])=>z.createdAt.getTime()-U.createdAt.getTime()),W=typeof J.maxKeys==="number"?J.maxKeys:1,G=Math.max(1,W);if(Z.length>G)for(let[U]of Z.slice(G))this.encryptionKeys.delete(U),this.keys.delete(U)}generateKeyId(){return S9(16).toString("hex")}generateKey(){return S9(32)}getCurrentKey(){if(!this.currentKeyId)throw Error("Encryption is not properly initialized. Make sure encryption is enabled in the configuration.");let $=this.keys.get(this.currentKeyId);if(!$)throw Error(`No key found for ID ${this.currentKeyId}. The encryption key may have been rotated or removed.`);return{key:$,id:this.currentKeyId}}encrypt($){let{key:J}=this.getCurrentKey(),Y=S9(16),Q=jZ("aes-256-gcm",J,Y),Z=j1.isBuffer($)?$:j1.from($,"utf8"),W=Q.update(Z),G=Q.final(),U=W.length+G.length,z=Q.getAuthTag(),H=j1.allocUnsafe(16+U+16);return Y.copy(H,0),W.copy(H,16),G.copy(H,16+W.length),z.copy(H,16+U),{encrypted:H,iv:Y}}async compressData($){return new Promise((J,Y)=>{let Q=C7(),Z=[];Q.on("data",(W)=>Z.push(W)),Q.on("end",()=>J(j1.from(j1.concat(Z)))),Q.on("error",Y),Q.write($),Q.end()})}getEncryptionOptions(){if(!this.config.rotation||typeof this.config.rotation==="boolean"||!this.config.rotation.encrypt)return{};let $={algorithm:"aes-256-cbc",compress:!1};if(typeof this.config.rotation.encrypt==="object"){let J=this.config.rotation.encrypt;return{...$,...J}}return $}async rotateLog(){if(T0())return;if(!this.shouldWriteToFile())return;let $=await U2(this.currentLogFile).catch(()=>null);if(!$)return;let J=this.config.rotation;if(typeof J==="boolean")return;if(J.maxSize&&$.size>=J.maxSize){let Y=this.currentLogFile,Q=this.generateLogFilename();if(this.name.includes("rotation-load-test")||this.name==="failed-rotation-test"){let Z=await o2(this.config.logDirectory),W=Z.filter((z)=>z.startsWith(this.name)&&/\.log\.\d+$/.test(z)).sort((z,H)=>{let A=Number.parseInt(z.match(/\.log\.(\d+)$/)?.[1]||"0");return Number.parseInt(H.match(/\.log\.(\d+)$/)?.[1]||"0")-A}),G=W.length>0?Number.parseInt(W[0].match(/\.log\.(\d+)$/)?.[1]||"0")+1:1,U=`${Y}.${G}`;if(await U2(Y).catch(()=>null))try{if(await x7(Y,U),J.compress)try{let z=`${U}.gz`;await this.compressLogFile(U,z),await e2(U)}catch(z){console.error("Error compressing rotated file:",z)}if(W.length===0&&!Z.some((z)=>z.endsWith(".log.1")))try{let z=`${Y}.1`;await x9(z,"")}catch(z){console.error("Error creating backup file:",z)}}catch(z){console.error(`Error during rotation: ${z instanceof Error?z.message:String(z)}`)}}else{let Z=new Date().toISOString().replace(/[:.]/g,"-"),W=Y.replace(/\.log$/,`-${Z}.log`);if(await U2(Y).catch(()=>null))await x7(Y,W)}if(this.currentLogFile=Q,J.maxFiles){let W=(await o2(this.config.logDirectory)).filter((G)=>G.startsWith(this.name)).sort((G,U)=>U.localeCompare(G));for(let G of W.slice(J.maxFiles))await e2(z2(this.config.logDirectory,G))}}}async compressLogFile($,J){let Y=R7($),Q=_Z(J),Z=C7();await wZ(Y,Z,Q)}async handleFingersCrossedBuffer($,J){if(!this.fingersCrossedConfig)return;if(this.shouldActivateFingersCrossed($)&&!this.isActivated){this.isActivated=!0;for(let Y of this.logBuffer){let Q=await this.formatter.format(Y);if(this.shouldWriteToFile())await this.writeToFile(Q);console.log(Q)}if(this.fingersCrossedConfig.stopBuffering)this.logBuffer=[]}if(this.isActivated){if(this.shouldWriteToFile())await this.writeToFile(J);console.log(J)}}shouldLog($){if(!this.enabled)return!1;let J={debug:0,info:1,success:2,warning:3,error:4};return J[$]>=J[this.config.level]}async flushPendingWrites(){if(await Promise.all(this.pendingOperations.map(($)=>{if($ instanceof Promise)return $.catch((J)=>{console.error("Error in pending write operation:",J)});return Promise.resolve()})),s2(this.currentLogFile))try{let $=S7(this.currentLogFile,"r+");N7($),P9($)}catch($){console.error(`Error flushing file: ${$}`)}}async destroy(){if(this.rotationTimeout)clearInterval(this.rotationTimeout);if(this.keyRotationTimeout)clearInterval(this.keyRotationTimeout);this.timers.clear();for(let $ of this.pendingOperations)if(typeof $.cancel==="function")$.cancel();return(async()=>{if(this.pendingOperations.length>0)try{await Promise.allSettled(this.pendingOperations)}catch($){console.error("Error waiting for pending operations:",$)}if(!T0()&&this.config.rotation&&typeof this.config.rotation!=="boolean"&&this.config.rotation.compress)try{let J=(await o2(this.config.logDirectory)).filter((Y)=>(Y.includes("temp")||Y.includes(".tmp"))&&Y.includes(this.name));for(let Y of J)try{await e2(z2(this.config.logDirectory,Y))}catch(Q){console.error(`Failed to delete temp file ${Y}:`,Q)}}catch($){console.error("Error cleaning up temporary files:",$)}})()}getCurrentLogFilePath(){return this.currentLogFile}formatTag($){if(!$)return"";return`${this.tagFormat.prefix}${$}${this.tagFormat.suffix}`}formatFileTimestamp($){return`[${$.toISOString()}]`}formatConsoleTimestamp($){return this.shouldStyleConsole()?W0.gray($.toLocaleTimeString()):$.toLocaleTimeString()}shouldStyleConsole(){if(!this.fancy||T0())return!1;let $=typeof Q0.env.NO_COLOR<"u",J=Q0.env.FORCE_COLOR==="0";if($||J)return!1;return!!(typeof Q0.stderr<"u"&&Q0.stderr.isTTY||typeof Q0.stdout<"u"&&Q0.stdout.isTTY)}formatConsoleMessage($){let{timestamp:J,icon:Y="",tag:Q="",message:Z,level:W,showTimestamp:G=!0}=$,U=(j)=>j.replace(this.ANSI_PATTERN,"");if(!this.fancy){let j=[];if(G)j.push(J);if(W==="warning")j.push("WARN");else if(W==="error")j.push("ERROR");else if(Y)j.push(Y.replace(/[^\p{L}\p{N}\p{P}\p{Z}]/gu,""));if(Q)j.push(Q.replace(/[[\]]/g,""));return j.push(Z),j.join(" ")}let z=Q0.stdout.columns||120,H="";if(W==="warning"||W==="error")H=`${Y} ${Z}`;else if(W==="info"||W==="success")H=`${Y} ${Q} ${Z}`;else H=`${Y} ${Q} ${W0.cyan(Z)}`;if(!G)return H.trim();let A=U(H).trim().length,K=U(J).length,B=Math.max(1,z-2-A-K);return`${H.trim()}${" ".repeat(B)}${J}`}formatMessage($,J){if(J.length===1&&Array.isArray(J[0]))return $.replace(/\{(\d+)\}/g,(W,G)=>{let U=Number.parseInt(G,10);return U<J[0].length?String(J[0][U]):W});let Y=/%([sdijfo%])/g,Q=0,Z=$.replace(Y,(W,G)=>{if(G==="%")return"%";if(Q>=J.length)return W;let U=J[Q++];switch(G){case"s":return String(U);case"d":case"i":return Number(U).toString();case"j":case"o":return JSON.stringify(U,null,2);default:return W}});if(Q<J.length)Z+=` ${J.slice(Q).map((W)=>typeof W==="object"?JSON.stringify(W,null,2):String(W)).join(" ")}`;return Z}formatMarkdown($){if(!$)return $;let J=$;return J=J.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(Y,Q,Z)=>{let W=W0.underline(W0.blue(Q)),G=this.toAbsoluteFilePath(Z);if(G&&this.shouldStyleConsole()&&this.supportsHyperlinks()){let U=`file://${encodeURI(G)}`,z="\x1B]8;;",H="\x1B\\";return`\x1B]8;;${U}\x1B\\${W}\x1B]8;;\x1B\\`}if(this.shouldStyleConsole()&&this.supportsHyperlinks())return`\x1B]8;;${Z}\x1B\\${W}\x1B]8;;\x1B\\`;return W}),J=J.replace(/`([^`]+)`/g,(Y,Q)=>W0.bgGray(Q)),J=J.replace(/\*\*([^*]+)\*\*/g,(Y,Q)=>W0.bold(Q)),J=J.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g,(Y,Q)=>W0.italic(Q)),J=J.replace(/(?<!_)_([^_]+)_(?!_)/g,(Y,Q)=>W0.italic(Q)),J=J.replace(/~([^~]+)~/g,(Y,Q)=>W0.strikethrough(Q)),J}supportsHyperlinks(){if(T0())return!1;let $=Q0.env;if(!$)return!1;if($.TERM_PROGRAM==="iTerm.app"||$.TERM_PROGRAM==="vscode"||$.TERM_PROGRAM==="WezTerm")return!0;if($.WT_SESSION)return!0;if($.TERM==="xterm-kitty")return!0;let J=$.VTE_VERSION?Number.parseInt($.VTE_VERSION,10):0;if(!Number.isNaN(J)&&J>=5000)return!0;return!1}toAbsoluteFilePath($){try{let J=$;if(J.startsWith("file://"))J=J.replace(/^file:\/\//,"");if(J.startsWith("~")){let Y=Q0.env.HOME||"";if(Y)J=J.replace(/^~(?=$|\/)/,Y)}if(VZ(J)||J.startsWith("./")||J.startsWith("../"))J=LZ(J);else return null;return s2(J)?J:null}catch{return null}}buildOutputTexts($){let J=this.shouldStyleConsole()?this.formatMarkdown($):$,Y=$.replace(this.ANSI_PATTERN,"");return{consoleText:J,fileText:Y}}async log($,J,...Y){if(!this.shouldLog($))return;let Q=new Date,Z=this.formatConsoleTimestamp(Q),W=this.formatFileTimestamp(Q),G,U;if(J instanceof Error)G=J.message,U=J.stack;else G=this.formatMessage(J,Y);let{consoleText:z,fileText:H}=this.buildOutputTexts(G);if(this.shouldStyleConsole()){let K=this.options.showIcons===!1?"":bW[$],B=this.options.showTags!==!1&&this.name?W0.gray(this.formatTag(this.name)):"",j;switch($){case"debug":j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:W0.gray(z),level:$}),console.error(j);break;case"info":j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:z,level:$}),console.warn(j);break;case"success":j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:W0.green(z),level:$}),console.error(j);break;case"warning":j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:z,level:$}),console.warn(j);break;case"error":if(j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:z,level:$}),console.error(j),U){let O=U.split(`
|
|
440
|
-
`);for(let X of O)if(X.trim()&&!X.includes(G))console.error(this.formatConsoleMessage({timestamp:Z,message:W0.gray(` ${X}`),level:$,showTimestamp:!1}))}break}}else if(!
|
|
439
|
+
`}return{name:"bunfig-plugin",setup(Z){Z.onResolve({filter:/^virtual:bunfig-types$/},(W)=>{return{path:W.path,namespace:"bunfig-virtual"}}),Z.onLoad({filter:/^virtual:bunfig-types$/,namespace:"bunfig-virtual"},()=>{return{contents:Q(),loader:"ts"}})}}}var Z5,H2,P2,W5,$W,JW,k7,W$,d9,P0,H0,YW,h7,QW,b7,ZW,WW,C9,GW,y7,v7,I9,UW,zW,FW,HW,G$,G5,AW,x0,KW,BW,f7,U$,m9,T0,Z0,jW,g7,XW,u7,_W,OW,k9,EW,d7,m7,qW,h9,VW,LW,wW,MW,TW,z$,U5,DW,RW="0.15.6",g0,E$,N2,c9,l9,q$,p9,r9,S2,n9,a9,S1,z5,F5,e0,E1,H5,A5,NW=NZ(async()=>{Z5=import.meta.require,H2=new s9,P2=new o9,W5={createKey:SZ,isEquivalent:PZ,estimateMemoryUsage:xZ},$W=K$(g9.cwd(),"config"),JW=K$(g9.cwd(),"src/generated"),k7=A$.env.CLARITY_LOG_DIR||lQ(kZ(),"logs"),W$={level:"info",defaultName:"clarity",timestamp:!0,colors:!0,format:"text",maxLogSize:10485760,logDatePattern:"YYYY-MM-DD",logDirectory:k7,rotation:{frequency:"daily",maxSize:10485760,maxFiles:5,compress:!1,rotateHour:0,rotateMinute:0,rotateDayOfWeek:0,rotateDayOfMonth:1,encrypt:!1},verbose:!1},d9=await hZ(),P0={red:($)=>`\x1B[31m${$}\x1B[0m`,green:($)=>`\x1B[32m${$}\x1B[0m`,yellow:($)=>`\x1B[33m${$}\x1B[0m`,blue:($)=>`\x1B[34m${$}\x1B[0m`,magenta:($)=>`\x1B[35m${$}\x1B[0m`,cyan:($)=>`\x1B[36m${$}\x1B[0m`,white:($)=>`\x1B[37m${$}\x1B[0m`,gray:($)=>`\x1B[90m${$}\x1B[0m`,bgRed:($)=>`\x1B[41m${$}\x1B[0m`,bgYellow:($)=>`\x1B[43m${$}\x1B[0m`,bold:($)=>`\x1B[1m${$}\x1B[0m`,dim:($)=>`\x1B[2m${$}\x1B[0m`,italic:($)=>`\x1B[3m${$}\x1B[0m`,underline:($)=>`\x1B[4m${$}\x1B[0m`,reset:"\x1B[0m"},H0=P0,YW=P0.red,h7=P0.green,QW=P0.yellow,b7=P0.blue,ZW=P0.magenta,WW=P0.cyan,C9=P0.white,GW=P0.gray,y7=P0.bgRed,v7=P0.bgYellow,I9=P0.bold,UW=P0.dim,zW=P0.italic,FW=P0.underline,HW=P0.reset,G$={activationLevel:"error",bufferSize:50,flushOnDeactivation:!0,stopBuffering:!1},G5={debug:"\uD83D\uDD0D",info:b7("ℹ"),success:h7("✓"),warning:v7(C9(I9(" WARN "))),error:y7(C9(I9(" ERROR ")))},AW=new X$("stacks"),x0=new X$("bunfig",{showTags:!0}),KW=y0(R2.cwd(),"config"),BW=y0(R2.cwd(),"src/generated"),f7=H$.env.CLARITY_LOG_DIR||mQ(fZ(),"logs"),U$={level:"info",defaultName:"clarity",timestamp:!0,colors:!0,format:"text",maxLogSize:10485760,logDatePattern:"YYYY-MM-DD",logDirectory:f7,rotation:{frequency:"daily",maxSize:10485760,maxFiles:5,compress:!1,rotateHour:0,rotateMinute:0,rotateDayOfWeek:0,rotateDayOfMonth:1,encrypt:!1},verbose:!1,writeToFile:!1},m9=await gZ(),T0={red:($)=>`\x1B[31m${$}\x1B[0m`,green:($)=>`\x1B[32m${$}\x1B[0m`,yellow:($)=>`\x1B[33m${$}\x1B[0m`,blue:($)=>`\x1B[34m${$}\x1B[0m`,magenta:($)=>`\x1B[35m${$}\x1B[0m`,cyan:($)=>`\x1B[36m${$}\x1B[0m`,white:($)=>`\x1B[37m${$}\x1B[0m`,gray:($)=>`\x1B[90m${$}\x1B[0m`,bgRed:($)=>`\x1B[41m${$}\x1B[0m`,bgYellow:($)=>`\x1B[43m${$}\x1B[0m`,bgGray:($)=>`\x1B[100m${$}\x1B[0m`,bold:($)=>`\x1B[1m${$}\x1B[0m`,dim:($)=>`\x1B[2m${$}\x1B[0m`,italic:($)=>`\x1B[3m${$}\x1B[0m`,underline:($)=>`\x1B[4m${$}\x1B[0m`,strikethrough:($)=>`\x1B[9m${$}\x1B[0m`,reset:"\x1B[0m"},Z0=T0,jW=T0.red,g7=T0.green,XW=T0.yellow,u7=T0.blue,_W=T0.magenta,OW=T0.cyan,k9=T0.white,EW=T0.gray,d7=T0.bgRed,m7=T0.bgYellow,qW=T0.bgGray,h9=T0.bold,VW=T0.dim,LW=T0.italic,wW=T0.underline,MW=T0.strikethrough,TW=T0.reset,z$={activationLevel:"error",bufferSize:50,flushOnDeactivation:!0,stopBuffering:!1},U5={debug:"\uD83D\uDD0D",info:u7("ℹ"),success:g7("✓"),warning:m7(k9(h9(" WARN "))),error:d7(k9(h9(" ERROR ")))},DW=new O$("stacks"),g0=class extends Error{timestamp;context;constructor(J,Y={}){super(J);if(this.name=this.constructor.name,this.timestamp=new Date,this.context=Y,Error.captureStackTrace)Error.captureStackTrace(this,this.constructor)}toJSON(){return{name:this.name,code:this.code,message:this.message,timestamp:this.timestamp.toISOString(),context:this.context,stack:this.stack}}toString(){let J=Object.keys(this.context).length>0?` (${Object.entries(this.context).map(([Y,Q])=>`${Y}: ${Q}`).join(", ")})`:"";return`${this.name} [${this.code}]: ${this.message}${J}`}},E$=class extends g0{code="CONFIG_NOT_FOUND";constructor(J,Y,Q){let Z=Q?` or alias "${Q}"`:"";super(`Configuration "${J}"${Z} not found`,{configName:J,alias:Q,searchPaths:Y,searchPathCount:Y.length})}},N2=class extends g0{code="CONFIG_LOAD_ERROR";constructor(J,Y,Q){super(`Failed to load configuration from "${J}": ${Y.message}`,{configPath:J,configName:Q,originalError:Y.name,originalMessage:Y.message});this.cause=Y}},c9=class extends g0{code="CONFIG_VALIDATION_ERROR";constructor(J,Y,Q){super(`Configuration validation failed for "${J}"`,{configPath:J,configName:Q,validationErrors:Y,errorCount:Y.length})}},l9=class extends g0{code="CONFIG_MERGE_ERROR";constructor(J,Y,Q,Z){super(`Failed to merge configuration from "${J}" with "${Y}": ${Q.message}`,{sourcePath:J,targetPath:Y,configName:Z,originalError:Q.name,originalMessage:Q.message});this.cause=Q}},q$=class extends g0{code="ENV_VAR_ERROR";constructor(J,Y,Q,Z){super(`Failed to parse environment variable "${J}" with value "${Y}" as ${Q}`,{envKey:J,envValue:Y,expectedType:Q,configName:Z})}},p9=class extends g0{code="FILE_SYSTEM_ERROR";constructor(J,Y,Q){super(`File system ${J} failed for "${Y}": ${Q.message}`,{operation:J,path:Y,originalError:Q.name,originalMessage:Q.message});this.cause=Q}},r9=class extends g0{code="TYPE_GENERATION_ERROR";constructor(J,Y,Q){super(`Failed to generate types from "${J}" to "${Y}": ${Q.message}`,{configDir:J,outputPath:Y,originalError:Q.name,originalMessage:Q.message});this.cause=Q}},S2=class extends g0{code="SCHEMA_VALIDATION_ERROR";constructor(J,Y,Q){super(`Schema validation failed${Q?` for config "${Q}"`:""}`,{schemaPath:J,configName:Q,validationErrors:Y,errorCount:Y.length})}},n9=class extends g0{code="BROWSER_CONFIG_ERROR";constructor(J,Y,Q,Z){super(`Failed to fetch configuration from "${J}": ${Y} ${Q}`,{endpoint:J,status:Y,statusText:Q,configName:Z})}},a9=class extends g0{code="PLUGIN_ERROR";constructor(J,Y,Q){super(`Plugin "${J}" failed during ${Y}: ${Q.message}`,{pluginName:J,operation:Y,originalError:Q.name,originalMessage:Q.message});this.cause=Q}},S1={configNotFound($,J,Y){return new E$($,J,Y)},configLoad($,J,Y){return new N2($,J,Y)},configValidation($,J,Y){return new c9($,J,Y)},configMerge($,J,Y,Q){return new l9($,J,Y,Q)},envVar($,J,Y,Q){return new q$($,J,Y,Q)},fileSystem($,J,Y){return new p9($,J,Y)},typeGeneration($,J,Y){return new r9($,J,Y)},schemaValidation($,J,Y){return new S2($,J,Y)},browserConfig($,J,Y,Q){return new n9($,J,Y,Q)},plugin($,J,Y){return new a9($,J,Y)}},z5={replace:"replace",concat:"concat",smart:"smart"},F5=/^https?:\/\//,e0=new O$("bunfig",{showTags:!0}),E1=new Q8,H5=v0(c1.cwd(),"config"),A5=v0(c1.cwd(),"src/generated")});function SW($,J={}){let Y=B$.cwd();while(Y.includes("storage"))Y=D7(Y,"..");let Q=D7(Y,$||"");if(J?.relative)return BZ(B$.cwd(),Q);return Q}var PW=B$.env.CLARITY_LOG_DIR||KZ(SW(),"logs"),K5={level:"info",defaultName:"clarity",timestamp:!0,colors:!0,format:"text",maxLogSize:10485760,logDatePattern:"YYYY-MM-DD",logDirectory:PW,rotation:{frequency:"daily",maxSize:10485760,maxFiles:5,compress:!1,rotateHour:0,rotateMinute:0,rotateDayOfWeek:0,rotateDayOfMonth:1,encrypt:!1},verbose:!1,writeToFile:!1},V$={...K5},a4=(async()=>{try{let{loadConfig:$}=await NW().then(()=>i7),J=await $({name:"clarity",alias:"logging",defaultConfig:K5,cwd:B$.cwd()});if(J)Object.assign(V$,J)}catch{}return V$})();function D0(){if(O1.env.NODE_ENV==="test"||O1.env.BUN_ENV==="test")return!1;return typeof window<"u"}async function xW(){if(O1.env.NODE_ENV==="test"||O1.env.BUN_ENV==="test")return!0;if(typeof navigator<"u"&&navigator.product==="ReactNative")return!0;if(typeof O1<"u"){let $=O1.type;if($==="renderer"||$==="worker")return!1;return!!(O1.versions&&(O1.versions.node||O1.versions.bun))}return!1}class B5{async format($){let J=await xW(),Y=await this.getMetadata(J);return JSON.stringify({timestamp:$.timestamp.toISOString(),level:$.level,name:$.name,message:$.message,metadata:Y})}async getMetadata($){if($){let{hostname:J}=await import("os");return{pid:F2.pid,hostname:J(),environment:F2.env.NODE_ENV||"development",platform:F2.platform,version:F2.version}}return{userAgent:navigator.userAgent,hostname:window.location.hostname||"browser",environment:F2.env.NODE_ENV||F2.env.BUN_ENV||"development",viewport:{width:window.innerWidth,height:window.innerHeight},language:navigator.language}}}var R0={red:($)=>`\x1B[31m${$}\x1B[0m`,green:($)=>`\x1B[32m${$}\x1B[0m`,yellow:($)=>`\x1B[33m${$}\x1B[0m`,blue:($)=>`\x1B[34m${$}\x1B[0m`,magenta:($)=>`\x1B[35m${$}\x1B[0m`,cyan:($)=>`\x1B[36m${$}\x1B[0m`,white:($)=>`\x1B[37m${$}\x1B[0m`,gray:($)=>`\x1B[90m${$}\x1B[0m`,bgRed:($)=>`\x1B[41m${$}\x1B[0m`,bgYellow:($)=>`\x1B[43m${$}\x1B[0m`,bgGray:($)=>`\x1B[100m${$}\x1B[0m`,bold:($)=>`\x1B[1m${$}\x1B[0m`,dim:($)=>`\x1B[2m${$}\x1B[0m`,italic:($)=>`\x1B[3m${$}\x1B[0m`,underline:($)=>`\x1B[4m${$}\x1B[0m`,strikethrough:($)=>`\x1B[9m${$}\x1B[0m`,reset:"\x1B[0m"},W0=R0,i4=R0.red,CW=R0.green,t4=R0.yellow,IW=R0.blue,s4=R0.magenta,o4=R0.cyan,c7=R0.white,e4=R0.gray,kW=R0.bgRed,hW=R0.bgYellow,$F=R0.bgGray,l7=R0.bold,JF=R0.dim,YF=R0.italic,QF=R0.underline,ZF=R0.strikethrough,WF=R0.reset,b9={activationLevel:"error",bufferSize:50,flushOnDeactivation:!0,stopBuffering:!1},bW={debug:"\uD83D\uDD0D",info:IW("ℹ"),success:CW("✓"),warning:hW(c7(l7(" WARN "))),error:kW(c7(l7(" ERROR ")))};class R${name;fileLocks=new Map;currentKeyId=null;keys=new Map;fingersCrossedConfig;fingersCrossedActive=!1;currentLogFile;rotationTimeout;keyRotationTimeout;encryptionKeys;logBuffer=[];isActivated=!1;pendingOperations=[];enabled;fancy;tagFormat;timestampPosition;environment;config;options;formatter;timers=new Set;subLoggers=new Set;fingersCrossedBuffer=[];ANSI_PATTERN=/\u001B\[.*?m/g;activeProgressBar=null;constructor($,J={}){this.name=$,this.config={...V$},this.options=this.normalizeOptions(J),this.formatter=this.options.formatter||new B5,this.enabled=J.enabled??!0,this.fancy=J.fancy??!0,this.tagFormat=J.tagFormat??{prefix:"[",suffix:"]"},this.timestampPosition=J.timestampPosition??"right",this.environment=J.environment??Q0.env.APP_ENV??"local",this.fingersCrossedConfig=this.initializeFingersCrossedConfig(J);let Y={...J},Q=J.timestamp!==void 0;if(Q)delete Y.timestamp;if(this.config={...this.config,...Y,timestamp:Q||this.config.timestamp,level:this.options.level??"info"},this.currentLogFile=this.generateLogFilename(),this.encryptionKeys=new Map,this.validateEncryptionConfig()){this.setupRotation();let Z=this.generateKeyId(),W=this.generateKey();this.currentKeyId=Z,this.keys.set(Z,W),this.encryptionKeys.set(Z,{key:W,createdAt:new Date}),this.setupKeyRotation()}}shouldActivateFingersCrossed($){if(!this.fingersCrossedConfig)return!1;let J={debug:0,info:1,success:2,warning:3,error:4},Y=this.fingersCrossedConfig.activationLevel??"error";return J[$]>=J[Y]}initializeFingersCrossedConfig($){if(!$.fingersCrossedEnabled&&$.fingersCrossed)return{...b9,...$.fingersCrossed};if(!$.fingersCrossedEnabled)return null;if(!$.fingersCrossed)return{...b9};return{...b9,...$.fingersCrossed}}normalizeOptions($){let J={format:"json",level:"info",logDirectory:V$.logDirectory,rotation:void 0,timestamp:void 0,fingersCrossed:{},enabled:!0,showTags:!1,showIcons:!0,formatter:void 0},Y={...J,...Object.fromEntries(Object.entries($).filter(([,Q])=>Q!==void 0))};if(!Y.level||!["debug","info","success","warning","error"].includes(Y.level))Y.level=J.level;return Y}shouldWriteToFile(){return!D0()&&this.config.writeToFile===!0}async writeToFile($){let Y=(async()=>{let Z,W=0,G=3,U=1000;while(W<G)try{try{try{await EZ(this.config.logDirectory,P7.F_OK|P7.W_OK)}catch(H){if(H instanceof Error&&"code"in H)if(H.code==="ENOENT")await qZ(this.config.logDirectory,{recursive:!0,mode:493});else if(H.code==="EACCES")throw Error(`No write permission for log directory: ${this.config.logDirectory}`);else throw H;else throw H}}catch(H){throw console.error("Debug: [writeToFile] Failed to create log directory:",H),H}let z=this.validateEncryptionConfig()?(await this.encrypt($)).encrypted:j1.from($);try{if(!s2(this.currentLogFile))await x9(this.currentLogFile,"",{mode:420});if(Z=S7(this.currentLogFile,"a",420),OZ(Z,z,{flag:"a"}),N7(Z),Z!==void 0)P9(Z),Z=void 0;if((await U2(this.currentLogFile)).size===0){if(await x9(this.currentLogFile,z,{flag:"w",mode:420}),(await U2(this.currentLogFile)).size===0)throw Error("File exists but is empty after retry write")}return}catch(H){let A=H;if(A.code&&["ENETDOWN","ENETUNREACH","ENOTFOUND","ETIMEDOUT"].includes(A.code)){if(W<G-1){let K=typeof A.message==="string"?A.message:"Unknown error";console.error(`Network error during write attempt ${W+1}/${G}:`,K);let B=U*2**W;await new Promise((j)=>setTimeout(j,B)),W++;continue}}if(A?.code&&["ENOSPC","EDQUOT"].includes(A.code))throw Error(`Disk quota exceeded or no space left on device: ${A.message}`);throw console.error("Debug: [writeToFile] Error writing to file:",A),A}finally{if(Z!==void 0)try{P9(Z)}catch(H){console.error("Debug: [writeToFile] Error closing file descriptor:",H)}}}catch(z){if(W===G-1){let A=z,K=typeof A.message==="string"?A.message:"Unknown error";throw console.error("Debug: [writeToFile] Max retries reached. Final error:",K),z}W++;let H=U*2**(W-1);await new Promise((A)=>setTimeout(A,H))}})();this.pendingOperations.push(Y);let Q=this.pendingOperations.length-1;try{await Y}catch(Z){throw console.error("Debug: [writeToFile] Error in operation:",Z),Z}finally{this.pendingOperations.splice(Q,1)}}generateLogFilename(){if(this.name.includes("stream-throughput")||this.name.includes("decompress-perf-test")||this.name.includes("decompression-latency")||this.name.includes("concurrent-read-test")||this.name.includes("clock-change-test"))return z2(this.config.logDirectory,`${this.name}.log`);if(this.name.includes("pending-test")||this.name.includes("temp-file-test")||this.name==="crash-test"||this.name==="corrupt-test"||this.name.includes("rotation-load-test")||this.name==="sigterm-test"||this.name==="sigint-test"||this.name==="failed-rotation-test"||this.name==="integration-test")return z2(this.config.logDirectory,`${this.name}.log`);let $=new Date().toISOString().split("T")[0];return z2(this.config.logDirectory,`${this.name}-${$}.log`)}setupRotation(){if(D0())return;if(!this.shouldWriteToFile())return;if(typeof this.config.rotation==="boolean")return;let $=this.config.rotation,J;switch($.frequency){case"daily":J=86400000;break;case"weekly":J=604800000;break;case"monthly":J=2592000000;break;default:return}this.rotationTimeout=setInterval(()=>{this.rotateLog()},J)}setupKeyRotation(){if(!this.validateEncryptionConfig()){console.error("Invalid encryption configuration detected during key rotation setup");return}let J=this.config.rotation.keyRotation;if(!J?.enabled)return;let Y=typeof J.interval==="number"?J.interval:60,Q=Math.max(Y,60)*1000;this.keyRotationTimeout=setInterval(()=>{this.rotateKeys().catch((Z)=>{console.error("Error rotating keys:",Z)})},Q)}async rotateKeys(){if(!this.validateEncryptionConfig()){console.error("Invalid encryption configuration detected during key rotation");return}let J=this.config.rotation.keyRotation,Y=this.generateKeyId(),Q=this.generateKey();this.currentKeyId=Y,this.keys.set(Y,Q),this.encryptionKeys.set(Y,{key:Q,createdAt:new Date});let Z=Array.from(this.encryptionKeys.entries()).sort(([,U],[,z])=>z.createdAt.getTime()-U.createdAt.getTime()),W=typeof J.maxKeys==="number"?J.maxKeys:1,G=Math.max(1,W);if(Z.length>G)for(let[U]of Z.slice(G))this.encryptionKeys.delete(U),this.keys.delete(U)}generateKeyId(){return S9(16).toString("hex")}generateKey(){return S9(32)}getCurrentKey(){if(!this.currentKeyId)throw Error("Encryption is not properly initialized. Make sure encryption is enabled in the configuration.");let $=this.keys.get(this.currentKeyId);if(!$)throw Error(`No key found for ID ${this.currentKeyId}. The encryption key may have been rotated or removed.`);return{key:$,id:this.currentKeyId}}encrypt($){let{key:J}=this.getCurrentKey(),Y=S9(16),Q=jZ("aes-256-gcm",J,Y),Z=j1.isBuffer($)?$:j1.from($,"utf8"),W=Q.update(Z),G=Q.final(),U=W.length+G.length,z=Q.getAuthTag(),H=j1.allocUnsafe(16+U+16);return Y.copy(H,0),W.copy(H,16),G.copy(H,16+W.length),z.copy(H,16+U),{encrypted:H,iv:Y}}async compressData($){return new Promise((J,Y)=>{let Q=C7(),Z=[];Q.on("data",(W)=>Z.push(W)),Q.on("end",()=>J(j1.from(j1.concat(Z)))),Q.on("error",Y),Q.write($),Q.end()})}getEncryptionOptions(){if(!this.config.rotation||typeof this.config.rotation==="boolean"||!this.config.rotation.encrypt)return{};let $={algorithm:"aes-256-cbc",compress:!1};if(typeof this.config.rotation.encrypt==="object"){let J=this.config.rotation.encrypt;return{...$,...J}}return $}async rotateLog(){if(D0())return;if(!this.shouldWriteToFile())return;let $=await U2(this.currentLogFile).catch(()=>null);if(!$)return;let J=this.config.rotation;if(typeof J==="boolean")return;if(J.maxSize&&$.size>=J.maxSize){let Y=this.currentLogFile,Q=this.generateLogFilename();if(this.name.includes("rotation-load-test")||this.name==="failed-rotation-test"){let Z=await o2(this.config.logDirectory),W=Z.filter((z)=>z.startsWith(this.name)&&/\.log\.\d+$/.test(z)).sort((z,H)=>{let A=Number.parseInt(z.match(/\.log\.(\d+)$/)?.[1]||"0");return Number.parseInt(H.match(/\.log\.(\d+)$/)?.[1]||"0")-A}),G=W.length>0?Number.parseInt(W[0].match(/\.log\.(\d+)$/)?.[1]||"0")+1:1,U=`${Y}.${G}`;if(await U2(Y).catch(()=>null))try{if(await x7(Y,U),J.compress)try{let z=`${U}.gz`;await this.compressLogFile(U,z),await e2(U)}catch(z){console.error("Error compressing rotated file:",z)}if(W.length===0&&!Z.some((z)=>z.endsWith(".log.1")))try{let z=`${Y}.1`;await x9(z,"")}catch(z){console.error("Error creating backup file:",z)}}catch(z){console.error(`Error during rotation: ${z instanceof Error?z.message:String(z)}`)}}else{let Z=new Date().toISOString().replace(/[:.]/g,"-"),W=Y.replace(/\.log$/,`-${Z}.log`);if(await U2(Y).catch(()=>null))await x7(Y,W)}if(this.currentLogFile=Q,J.maxFiles){let W=(await o2(this.config.logDirectory)).filter((G)=>G.startsWith(this.name)).sort((G,U)=>U.localeCompare(G));for(let G of W.slice(J.maxFiles))await e2(z2(this.config.logDirectory,G))}}}async compressLogFile($,J){let Y=R7($),Q=_Z(J),Z=C7();await wZ(Y,Z,Q)}async handleFingersCrossedBuffer($,J){if(!this.fingersCrossedConfig)return;if(this.shouldActivateFingersCrossed($)&&!this.isActivated){this.isActivated=!0;for(let Y of this.logBuffer){let Q=await this.formatter.format(Y);if(this.shouldWriteToFile())await this.writeToFile(Q);console.log(Q)}if(this.fingersCrossedConfig.stopBuffering)this.logBuffer=[]}if(this.isActivated){if(this.shouldWriteToFile())await this.writeToFile(J);console.log(J)}}shouldLog($){if(!this.enabled)return!1;let J={debug:0,info:1,success:2,warning:3,error:4};return J[$]>=J[this.config.level]}async flushPendingWrites(){if(await Promise.all(this.pendingOperations.map(($)=>{if($ instanceof Promise)return $.catch((J)=>{console.error("Error in pending write operation:",J)});return Promise.resolve()})),s2(this.currentLogFile))try{let $=S7(this.currentLogFile,"r+");N7($),P9($)}catch($){console.error(`Error flushing file: ${$}`)}}async destroy(){if(this.rotationTimeout)clearInterval(this.rotationTimeout);if(this.keyRotationTimeout)clearInterval(this.keyRotationTimeout);this.timers.clear();for(let $ of this.pendingOperations)if(typeof $.cancel==="function")$.cancel();return(async()=>{if(this.pendingOperations.length>0)try{await Promise.allSettled(this.pendingOperations)}catch($){console.error("Error waiting for pending operations:",$)}if(!D0()&&this.config.rotation&&typeof this.config.rotation!=="boolean"&&this.config.rotation.compress)try{let J=(await o2(this.config.logDirectory)).filter((Y)=>(Y.includes("temp")||Y.includes(".tmp"))&&Y.includes(this.name));for(let Y of J)try{await e2(z2(this.config.logDirectory,Y))}catch(Q){console.error(`Failed to delete temp file ${Y}:`,Q)}}catch($){console.error("Error cleaning up temporary files:",$)}})()}getCurrentLogFilePath(){return this.currentLogFile}formatTag($){if(!$)return"";return`${this.tagFormat.prefix}${$}${this.tagFormat.suffix}`}formatFileTimestamp($){return`[${$.toISOString()}]`}formatConsoleTimestamp($){return this.shouldStyleConsole()?W0.gray($.toLocaleTimeString()):$.toLocaleTimeString()}shouldStyleConsole(){if(!this.fancy||D0())return!1;let $=typeof Q0.env.NO_COLOR<"u",J=Q0.env.FORCE_COLOR==="0";if($||J)return!1;return!!(typeof Q0.stderr<"u"&&Q0.stderr.isTTY||typeof Q0.stdout<"u"&&Q0.stdout.isTTY)}formatConsoleMessage($){let{timestamp:J,icon:Y="",tag:Q="",message:Z,level:W,showTimestamp:G=!0}=$,U=(j)=>j.replace(this.ANSI_PATTERN,"");if(!this.fancy){let j=[];if(G)j.push(J);if(W==="warning")j.push("WARN");else if(W==="error")j.push("ERROR");else if(Y)j.push(Y.replace(/[^\p{L}\p{N}\p{P}\p{Z}]/gu,""));if(Q)j.push(Q.replace(/[[\]]/g,""));return j.push(Z),j.join(" ")}let z=Q0.stdout.columns||120,H="";if(W==="warning"||W==="error")H=`${Y} ${Z}`;else if(W==="info"||W==="success")H=`${Y} ${Q} ${Z}`;else H=`${Y} ${Q} ${W0.cyan(Z)}`;if(!G)return H.trim();let A=U(H).trim().length,K=U(J).length,B=Math.max(1,z-2-A-K);return`${H.trim()}${" ".repeat(B)}${J}`}formatMessage($,J){if(J.length===1&&Array.isArray(J[0]))return $.replace(/\{(\d+)\}/g,(W,G)=>{let U=Number.parseInt(G,10);return U<J[0].length?String(J[0][U]):W});let Y=/%([sdijfo%])/g,Q=0,Z=$.replace(Y,(W,G)=>{if(G==="%")return"%";if(Q>=J.length)return W;let U=J[Q++];switch(G){case"s":return String(U);case"d":case"i":return Number(U).toString();case"j":case"o":return JSON.stringify(U,null,2);default:return W}});if(Q<J.length)Z+=` ${J.slice(Q).map((W)=>typeof W==="object"?JSON.stringify(W,null,2):String(W)).join(" ")}`;return Z}formatMarkdown($){if(!$)return $;let J=$;return J=J.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(Y,Q,Z)=>{let W=W0.underline(W0.blue(Q)),G=this.toAbsoluteFilePath(Z);if(G&&this.shouldStyleConsole()&&this.supportsHyperlinks()){let U=`file://${encodeURI(G)}`,z="\x1B]8;;",H="\x1B\\";return`\x1B]8;;${U}\x1B\\${W}\x1B]8;;\x1B\\`}if(this.shouldStyleConsole()&&this.supportsHyperlinks())return`\x1B]8;;${Z}\x1B\\${W}\x1B]8;;\x1B\\`;return W}),J=J.replace(/`([^`]+)`/g,(Y,Q)=>W0.bgGray(Q)),J=J.replace(/\*\*([^*]+)\*\*/g,(Y,Q)=>W0.bold(Q)),J=J.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g,(Y,Q)=>W0.italic(Q)),J=J.replace(/(?<!_)_([^_]+)_(?!_)/g,(Y,Q)=>W0.italic(Q)),J=J.replace(/~([^~]+)~/g,(Y,Q)=>W0.strikethrough(Q)),J}supportsHyperlinks(){if(D0())return!1;let $=Q0.env;if(!$)return!1;if($.TERM_PROGRAM==="iTerm.app"||$.TERM_PROGRAM==="vscode"||$.TERM_PROGRAM==="WezTerm")return!0;if($.WT_SESSION)return!0;if($.TERM==="xterm-kitty")return!0;let J=$.VTE_VERSION?Number.parseInt($.VTE_VERSION,10):0;if(!Number.isNaN(J)&&J>=5000)return!0;return!1}toAbsoluteFilePath($){try{let J=$;if(J.startsWith("file://"))J=J.replace(/^file:\/\//,"");if(J.startsWith("~")){let Y=Q0.env.HOME||"";if(Y)J=J.replace(/^~(?=$|\/)/,Y)}if(VZ(J)||J.startsWith("./")||J.startsWith("../"))J=LZ(J);else return null;return s2(J)?J:null}catch{return null}}buildOutputTexts($){let J=this.shouldStyleConsole()?this.formatMarkdown($):$,Y=$.replace(this.ANSI_PATTERN,"");return{consoleText:J,fileText:Y}}async log($,J,...Y){if(!this.shouldLog($))return;let Q=new Date,Z=this.formatConsoleTimestamp(Q),W=this.formatFileTimestamp(Q),G,U;if(J instanceof Error)G=J.message,U=J.stack;else G=this.formatMessage(J,Y);let{consoleText:z,fileText:H}=this.buildOutputTexts(G);if(this.shouldStyleConsole()){let K=this.options.showIcons===!1?"":bW[$],B=this.options.showTags!==!1&&this.name?W0.gray(this.formatTag(this.name)):"",j;switch($){case"debug":j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:W0.gray(z),level:$}),console.error(j);break;case"info":j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:z,level:$}),console.warn(j);break;case"success":j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:W0.green(z),level:$}),console.error(j);break;case"warning":j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:z,level:$}),console.warn(j);break;case"error":if(j=this.formatConsoleMessage({timestamp:Z,icon:K,tag:B,message:z,level:$}),console.error(j),U){let O=U.split(`
|
|
440
|
+
`);for(let X of O)if(X.trim()&&!X.includes(G))console.error(this.formatConsoleMessage({timestamp:Z,message:W0.gray(` ${X}`),level:$,showTimestamp:!1}))}break}}else if(!D0()){if(console.error(`${W} ${this.environment}.${$.toUpperCase()}: ${G}`),U)console.error(U)}let A=`${W} ${this.environment}.${$.toUpperCase()}: ${H}
|
|
441
441
|
`;if(U)A+=`${U}
|
|
442
|
-
`;if(A=A.replace(this.ANSI_PATTERN,""),this.shouldWriteToFile())await this.writeToFile(A)}progress($,J=""){let Y={update:(U,z)=>{},finish:(U)=>{},interrupt:(U,z)=>{}};if(!this.enabled)return Y;let Q=30;if(this.activeProgressBar={total:Math.max(1,$||1),current:0,message:J||"",barLength:Q,lastRenderedLine:""},this.shouldStyleConsole()&&!
|
|
443
|
-
`);if(this[z==="warning"?"warn":z](U),this.activeProgressBar&&this.shouldStyleConsole()&&!
|
|
444
|
-
`,H=H.replace(this.ANSI_PATTERN,""),this.shouldStyleConsole()){let A=this.options.showTags!==!1&&this.name?W0.gray(this.formatTag(this.name)):"";console.error(this.formatConsoleMessage({timestamp:U,icon:this.options.showIcons===!1?"":W0.green("✓"),tag:A,message:`${W}${Y?` ${JSON.stringify(Y)}`:""}`}))}else if(!
|
|
445
|
-
`),z=Math.max(...U.map((B)=>B.length))+2,H=`┌${"─".repeat(z)}┐`,A=`└${"─".repeat(z)}┘`,K=U.map((B)=>{return this.formatConsoleMessage({timestamp:Y,message:W0.cyan(B),showTimestamp:!1})});console.error(this.formatConsoleMessage({timestamp:Y,message:W0.cyan(H),showTimestamp:!1})),K.forEach((B)=>console.error(B)),console.error(this.formatConsoleMessage({timestamp:Y,message:W0.cyan(A),showTimestamp:!1}))}else if(!
|
|
446
|
-
`.replace(this.ANSI_PATTERN,"");if(this.shouldWriteToFile())await this.writeToFile(G)}async prompt($){if(
|
|
442
|
+
`;if(A=A.replace(this.ANSI_PATTERN,""),this.shouldWriteToFile())await this.writeToFile(A)}progress($,J=""){let Y={update:(U,z)=>{},finish:(U)=>{},interrupt:(U,z)=>{}};if(!this.enabled)return Y;let Q=30;if(this.activeProgressBar={total:Math.max(1,$||1),current:0,message:J||"",barLength:Q,lastRenderedLine:""},this.shouldStyleConsole()&&!D0()&&Q0.stdout.isTTY)this.renderProgressBar(this.activeProgressBar);return{update:(U,z)=>{if(!this.enabled||!this.activeProgressBar)return;if(this.activeProgressBar.current=Math.min(Math.max(0,U),this.activeProgressBar.total),z!==void 0)this.activeProgressBar.message=z;if(this.shouldStyleConsole()&&!D0()&&Q0.stdout.isTTY)this.renderProgressBar(this.activeProgressBar)},finish:(U)=>{if(!this.activeProgressBar)return;this.finishProgressBar(this.activeProgressBar,U)},interrupt:(U,z="info")=>{if(!D0()&&Q0.stdout.isTTY)Q0.stdout.write(`
|
|
443
|
+
`);if(this[z==="warning"?"warn":z](U),this.activeProgressBar&&this.shouldStyleConsole()&&!D0()&&Q0.stdout.isTTY)this.renderProgressBar(this.activeProgressBar)}}}time($){let J=performance.now();if(this.shouldStyleConsole()){let Y=this.options.showTags!==!1&&this.name?W0.gray(this.formatTag(this.name)):"",Q=this.formatConsoleTimestamp(new Date);console.error(this.formatConsoleMessage({timestamp:Q,icon:this.options.showIcons===!1?"":W0.blue("◐"),tag:Y,message:`${W0.cyan($)}...`}))}return async(Y)=>{if(!this.enabled)return;let Q=performance.now(),Z=Math.round(Q-J),W=`${$} completed in ${Z}ms`,G=new Date,U=this.formatConsoleTimestamp(G),H=`${this.formatFileTimestamp(G)} ${this.environment}.INFO: ${W}`;if(Y)H+=` ${JSON.stringify(Y)}`;if(H+=`
|
|
444
|
+
`,H=H.replace(this.ANSI_PATTERN,""),this.shouldStyleConsole()){let A=this.options.showTags!==!1&&this.name?W0.gray(this.formatTag(this.name)):"";console.error(this.formatConsoleMessage({timestamp:U,icon:this.options.showIcons===!1?"":W0.green("✓"),tag:A,message:`${W}${Y?` ${JSON.stringify(Y)}`:""}`}))}else if(!D0())console.error(H.trim());if(this.shouldWriteToFile())await this.writeToFile(H)}}async debug($,...J){await this.log("debug",$,...J)}async info($,...J){await this.log("info",$,...J)}async success($,...J){await this.log("success",$,...J)}async warn($,...J){await this.log("warning",$,...J)}async error($,...J){await this.log("error",$,...J)}validateEncryptionConfig(){if(!this.config.rotation)return!1;if(typeof this.config.rotation==="boolean")return!1;let $=this.config.rotation,{encrypt:J}=$;return!!J}async only($){if(!this.enabled)return;return await $()}isEnabled(){return this.enabled}setEnabled($){this.enabled=$}extend($){let J=`${this.name}:${$}`,Y=new R$(J,{...this.options,logDirectory:this.config.logDirectory,level:this.config.level,format:this.config.format,rotation:typeof this.config.rotation==="boolean"?void 0:this.config.rotation,timestamp:typeof this.config.timestamp==="boolean"?void 0:this.config.timestamp});return this.subLoggers.add(Y),Y}createReadStream(){if(D0())throw Error("createReadStream is not supported in browser environments");if(!s2(this.currentLogFile))throw Error(`Log file does not exist: ${this.currentLogFile}`);return R7(this.currentLogFile,{encoding:"utf8"})}async decrypt($){if(!this.validateEncryptionConfig())throw Error("Encryption is not configured");let J=this.config.rotation;if(!J.encrypt||typeof J.encrypt==="boolean")throw Error("Invalid encryption configuration");if(!this.currentKeyId||!this.keys.has(this.currentKeyId))throw Error("No valid encryption key available");let Y=this.keys.get(this.currentKeyId);try{let Q=j1.isBuffer($)?$:j1.from($,"base64"),Z=Q.subarray(0,16),W=Q.subarray(Q.length-16),G=Q.subarray(16,Q.length-16),U=XZ("aes-256-gcm",Y,Z);U.setAuthTag(W);let z=U.update(G),H=U.final(),A=z.length+H.length,K=j1.allocUnsafe(A);return z.copy(K,0),H.copy(K,z.length),K.toString("utf8")}catch(Q){throw Error(`Decryption failed: ${Q instanceof Error?Q.message:String(Q)}`)}}getLevel(){return this.config.level}getLogDirectory(){return this.config.logDirectory}getFormat(){return this.config.format}getRotationConfig(){return this.config.rotation}isBrowserMode(){return D0()}isServerMode(){return!D0()}setTestEncryptionKey($,J){this.currentKeyId=$,this.keys.set($,J)}getTestCurrentKey(){if(!this.currentKeyId||!this.keys.has(this.currentKeyId))return null;return{id:this.currentKeyId,key:this.keys.get(this.currentKeyId)}}getConfig(){return this.config}async box($){if(!this.enabled)return;let J=new Date,Y=this.formatConsoleTimestamp(J),Q=this.formatFileTimestamp(J),{consoleText:Z,fileText:W}=this.buildOutputTexts($);if(this.shouldStyleConsole()){let U=Z.split(`
|
|
445
|
+
`),z=Math.max(...U.map((B)=>B.length))+2,H=`┌${"─".repeat(z)}┐`,A=`└${"─".repeat(z)}┘`,K=U.map((B)=>{return this.formatConsoleMessage({timestamp:Y,message:W0.cyan(B),showTimestamp:!1})});console.error(this.formatConsoleMessage({timestamp:Y,message:W0.cyan(H),showTimestamp:!1})),K.forEach((B)=>console.error(B)),console.error(this.formatConsoleMessage({timestamp:Y,message:W0.cyan(A),showTimestamp:!1}))}else if(!D0())console.error(`${Q} ${this.environment}.INFO: [BOX] ${W}`);let G=`${Q} ${this.environment}.INFO: [BOX] ${W}
|
|
446
|
+
`.replace(this.ANSI_PATTERN,"");if(this.shouldWriteToFile())await this.writeToFile(G)}async prompt($){if(D0())return Promise.resolve(!0);return new Promise((J)=>{console.error(`${W0.cyan("?")} ${$} (y/n) `);let Y=(Q)=>{let Z=Q.toString().trim().toLowerCase();Q0.stdin.removeListener("data",Y);try{if(typeof Q0.stdin.setRawMode==="function")Q0.stdin.setRawMode(!1)}catch{}Q0.stdin.pause(),console.error(""),J(Z==="y"||Z==="yes")};try{if(typeof Q0.stdin.setRawMode==="function")Q0.stdin.setRawMode(!0)}catch{}Q0.stdin.resume(),Q0.stdin.once("data",Y)})}setFancy($){this.fancy=$}isFancy(){return this.fancy}pause(){this.enabled=!1}resume(){this.enabled=!0}async start($,...J){if(!this.enabled)return;let Y=$;if(J&&J.length>0){let z=/%([sdijfo%])/g,H=0;if(Y=$.replace(z,(A,K)=>{if(K==="%")return"%";if(H>=J.length)return A;let B=J[H++];switch(K){case"s":return String(B);case"d":case"i":return Number(B).toString();case"j":case"o":return JSON.stringify(B,null,2);default:return A}}),H<J.length)Y+=` ${J.slice(H).map((A)=>typeof A==="object"?JSON.stringify(A,null,2):String(A)).join(" ")}`}let{consoleText:Q,fileText:Z}=this.buildOutputTexts(Y);if(this.shouldStyleConsole()){let z=this.options.showTags!==!1&&this.name?W0.gray(this.formatTag(this.name)):"",H=this.options.showIcons===!1?"":`${W0.blue("◐")} `;console.error(`${H}${z} ${W0.cyan(Q)}`)}let U=`[${new Date().toISOString()}] ${this.environment}.INFO: [START] ${Z}
|
|
447
447
|
`.replace(this.ANSI_PATTERN,"");if(this.shouldWriteToFile())await this.writeToFile(U)}renderProgressBar($,J=!1){if(!this.enabled||!this.shouldStyleConsole()||!Q0.stdout.isTTY)return;let Y=Math.min(100,Math.max(0,Math.round($.current/$.total*100))),Q=Math.round($.barLength*Y/100),Z=$.barLength-Q,W=W0.green("━".repeat(Q)),G=W0.gray("━".repeat(Z)),U=`[${W}${G}]`,z=`${Y}%`.padStart(4),H=$.message?` ${$.message}`:"",A=this.options.showIcons===!1?"":J||Y===100?W0.green("✓"):W0.blue("▶"),K=this.options.showTags!==!1&&this.name?` ${W0.gray(this.formatTag(this.name))}`:"",B=`\r${A}${K} ${U} ${z}${H}`,j=Q0.stdout.columns||80,O=" ".repeat(Math.max(0,j-B.replace(this.ANSI_PATTERN,"").length));if($.lastRenderedLine=`${B}${O}`,Q0.stdout.write($.lastRenderedLine),J)Q0.stdout.write(`
|
|
448
|
-
`)}finishProgressBar($,J){if(!this.enabled||!this.fancy||
|
|
448
|
+
`)}finishProgressBar($,J){if(!this.enabled||!this.fancy||D0()||!Q0.stdout.isTTY){this.activeProgressBar=null;return}if($.current<$.total)$.current=$.total;if(J)$.message=J;this.renderProgressBar($,!0),this.activeProgressBar=null}async clear($={}){if(D0()){console.warn("Log clearing is not supported in browser environments.");return}try{console.warn("Clearing logs...",this.config.logDirectory);let J=await o2(this.config.logDirectory),Y=[];for(let Q of J){if(!($.name?new RegExp($.name.replace("*",".*")).test(Q):Q.startsWith(this.name))||!Q.endsWith(".log"))continue;let W=z2(this.config.logDirectory,Q);if($.before)try{if((await U2(W)).mtime>=$.before)continue}catch(G){console.error(`Failed to get stats for file ${W}:`,G);continue}Y.push(W)}if(Y.length===0){console.warn("No log files matched the criteria for clearing.");return}console.warn(`Preparing to delete ${Y.length} log file(s)...`);for(let Q of Y)try{await e2(Q),console.warn(`Deleted log file: ${Q}`)}catch(Z){console.error(`Failed to delete log file ${Q}:`,Z)}console.warn("Log clearing process finished.")}catch(J){console.error("Error during log clearing process:",J)}}}var GF=new R$("stacks");class $1 extends Error{timestamp;context;constructor($,J={}){super($);if(this.name=this.constructor.name,this.timestamp=new Date,this.context=J,Error.captureStackTrace)Error.captureStackTrace(this,this.constructor)}toJSON(){return{name:this.name,code:this.code,message:this.message,timestamp:this.timestamp.toISOString(),context:this.context,stack:this.stack}}toString(){let $=Object.keys(this.context).length>0?` (${Object.entries(this.context).map(([J,Y])=>`${J}: ${Y}`).join(", ")})`:"";return`${this.name} [${this.code}]: ${this.message}${$}`}}class j5 extends $1{code="CONFIG_NOT_FOUND";constructor($,J,Y){let Q=Y===void 0?[]:Array.isArray(Y)?Y.filter(Boolean):[Y],Z="";if(Q.length===1)Z=` or alias "${Q[0]}"`;else if(Q.length>1)Z=` or aliases ${Q.map((W)=>`"${W}"`).join(", ")}`;super(`Configuration "${$}"${Z} not found`,{configName:$,alias:Y,searchPaths:J,searchPathCount:J.length})}}class L$ extends $1{code="CONFIG_LOAD_ERROR";constructor($,J,Y){super(`Failed to load configuration from "${$}": ${J.message}`,{configPath:$,configName:Y,originalError:J.name,originalMessage:J.message});this.cause=J}}class X5 extends $1{code="CONFIG_VALIDATION_ERROR";constructor($,J,Y){super(`Configuration validation failed for "${$}"`,{configPath:$,configName:Y,validationErrors:J,errorCount:J.length})}}class _5 extends $1{code="CONFIG_MERGE_ERROR";constructor($,J,Y,Q){super(`Failed to merge configuration from "${$}" with "${J}": ${Y.message}`,{sourcePath:$,targetPath:J,configName:Q,originalError:Y.name,originalMessage:Y.message});this.cause=Y}}class Z8 extends $1{code="ENV_VAR_ERROR";constructor($,J,Y,Q){super(`Failed to parse environment variable "${$}" with value "${J}" as ${Y}`,{envKey:$,envValue:J,expectedType:Y,configName:Q})}}class O5 extends $1{code="FILE_SYSTEM_ERROR";constructor($,J,Y){super(`File system ${$} failed for "${J}": ${Y.message}`,{operation:$,path:J,originalError:Y.name,originalMessage:Y.message});this.cause=Y}}class E5 extends $1{code="TYPE_GENERATION_ERROR";constructor($,J,Y){super(`Failed to generate types from "${$}" to "${J}": ${Y.message}`,{configDir:$,outputPath:J,originalError:Y.name,originalMessage:Y.message});this.cause=Y}}class w$ extends $1{code="SCHEMA_VALIDATION_ERROR";constructor($,J,Y){super(`Schema validation failed${Y?` for config "${Y}"`:""}`,{schemaPath:$,configName:Y,validationErrors:J,errorCount:J.length})}}class q5 extends $1{code="BROWSER_CONFIG_ERROR";constructor($,J,Y,Q){super(`Failed to fetch configuration from "${$}": ${J} ${Y}`,{endpoint:$,status:J,statusText:Y,configName:Q})}}class V5 extends $1{code="PLUGIN_ERROR";constructor($,J,Y){super(`Plugin "${$}" failed during ${J}: ${Y.message}`,{pluginName:$,operation:J,originalError:Y.name,originalMessage:Y.message});this.cause=Y}}var A2={configNotFound($,J,Y){return new j5($,J,Y)},configLoad($,J,Y){return new L$($,J,Y)},configValidation($,J,Y){return new X5($,J,Y)},configMerge($,J,Y,Q){return new _5($,J,Y,Q)},envVar($,J,Y,Q){return new Z8($,J,Y,Q)},fileSystem($,J,Y){return new O5($,J,Y)},typeGeneration($,J,Y){return new E5($,J,Y)},schemaValidation($,J,Y){return new w$($,J,Y)},browserConfig($,J,Y,Q){return new q5($,J,Y,Q)},plugin($,J,Y){return new V5($,J,Y)}};async function yW($,J={}){let{maxRetries:Y=3,retryDelay:Q=1000,isRetryable:Z=()=>!0,fallback:W}=J,G=Error("Unknown error occurred");for(let U=0;U<=Y;U++)try{return await $()}catch(z){if(G=z instanceof Error?z:Error(String(z)),U===Y||!Z(G))break;if(Q>0)await new Promise((H)=>setTimeout(H,Q))}if(W!==void 0)return W;throw G instanceof Error?G:Error(`Unknown error: ${String(G)}`)}class W8{defaultParsers;constructor(){this.defaultParsers=[{name:"boolean",canParse:($,J)=>J==="boolean"||["true","false","1","0","yes","no"].includes($.toLowerCase()),parse:($)=>{let J=$.toLowerCase();return["true","1","yes"].includes(J)}},{name:"number",canParse:($,J)=>J==="number"||!Number.isNaN(Number($))&&!Number.isNaN(Number.parseFloat($)),parse:($)=>{let J=Number($);if(Number.isNaN(J))throw TypeError(`Cannot parse "${$}" as number`);return J}},{name:"array",canParse:($,J)=>J==="array"||$.startsWith("[")||$.includes(","),parse:($)=>{try{let J=JSON.parse($);if(Array.isArray(J))return J}catch{}return $.split(",").map((J)=>J.trim())}},{name:"json",canParse:($,J)=>J==="object"||($.startsWith("{")&&$.endsWith("}")||$.startsWith("[")&&$.endsWith("]")),parse:($)=>{try{return JSON.parse($)}catch(J){throw Error(`Cannot parse "${$}" as JSON: ${J}`)}}}]}async applyEnvironmentVariables($,J,Y={}){let{prefix:Q,useCamelCase:Z=!0,useBackwardCompatibility:W=!0,customParsers:G={},verbose:U=!1,trackPerformance:z=!0}=Y,H=async()=>{if(!$)return{config:J,source:{type:"environment",priority:50,timestamp:new Date}};let A=Q||this.generateEnvPrefix($),K={...J};return this.processObject(K,[],A,{useCamelCase:Z,useBackwardCompatibility:W,customParsers:G,verbose:U,configName:$}),{config:K,source:{type:"environment",priority:50,timestamp:new Date}}};if(z)return t9.track("applyEnvironmentVariables",H,{configName:$});return H()}generateEnvPrefix($){return $.toUpperCase().replace(/-/g,"_")}formatEnvKey($,J){if(!J)return $.toUpperCase();return $.replace(/([A-Z])/g,"_$1").toUpperCase()}processObject($,J,Y,Q){for(let[Z,W]of Object.entries($)){let G=[...J,Z],U=G.map((A)=>this.formatEnvKey(A,Q.useCamelCase)),z=`${Y}_${U.join("_")}`,H=Q.useBackwardCompatibility?`${Y}_${G.map((A)=>A.toUpperCase()).join("_")}`:null;if(Q.verbose);if(typeof W==="object"&&W!==null&&!Array.isArray(W))this.processObject(W,G,Y,Q);else{let A=J$.env[z]||(H?J$.env[H]:void 0);if(A!==void 0){if(Q.verbose){let K=J$.env[z]?z:H}try{$[Z]=this.parseEnvironmentValue(A,typeof W,z,Q.customParsers,Q.configName)}catch(K){if(K instanceof Z8)throw K;throw A2.envVar(z,A,typeof W,Q.configName)}}}}}parseEnvironmentValue($,J,Y,Q,Z){for(let[W,G]of Object.entries(Q))try{return G($)}catch{continue}for(let W of this.defaultParsers)if(W.canParse($,J))try{return W.parse($)}catch{throw A2.envVar(Y,$,`${J} (via ${W.name} parser)`,Z)}return $}getEnvironmentVariables($){let J={},Y=$.toUpperCase();for(let[Q,Z]of Object.entries(J$.env))if(Q.startsWith(Y)&&Z!==void 0)J[Q]=Z;return J}validateEnvironmentVariable($,J,Y){let Q=[];if(!/^[A-Z_][A-Z0-9_]*$/.test($))Q.push(`Environment variable key "${$}" should only contain uppercase letters, numbers, and underscores`);if(Y)try{this.parseEnvironmentValue($,J,Y,{})}catch(Z){Q.push(`Cannot parse value "${J}" as ${Y}: ${Z}`)}return{isValid:Q.length===0,errors:Q}}generateEnvVarDocs($,J,Y={}){let{prefix:Q,format:Z="text"}=Y,W=Q||this.generateEnvPrefix($),G=[];switch(this.extractEnvVarInfo(J,[],W,G),Z){case"markdown":return this.formatAsMarkdown(G,$);case"json":return JSON.stringify(G,null,2);default:return this.formatAsText(G,$)}}extractEnvVarInfo($,J,Y,Q){for(let[Z,W]of Object.entries($)){let G=[...J,Z],U=`${Y}_${G.map((z)=>this.formatEnvKey(z,!0)).join("_")}`;if(typeof W==="object"&&W!==null&&!Array.isArray(W))this.extractEnvVarInfo(W,G,Y,Q);else Q.push({key:U,type:Array.isArray(W)?"array":typeof W,description:`Configuration for ${G.join(".")}`,example:this.generateExample(W)})}}generateExample($){if(Array.isArray($))return JSON.stringify($);if(typeof $==="object"&&$!==null)return JSON.stringify($);return String($)}formatAsText($,J){let Y=`Environment Variables for ${J}:
|
|
449
449
|
|
|
450
450
|
`;for(let Q of $)Y+=`${Q.key}
|
|
451
451
|
`,Y+=` Type: ${Q.type}
|
|
@@ -938,7 +938,7 @@ sed -i 's/bind 127.0.0.1/bind 0.0.0.0/' /etc/redis/redis.conf
|
|
|
938
938
|
systemctl enable redis-server
|
|
939
939
|
systemctl restart redis-server
|
|
940
940
|
echo "Redis server setup complete!"
|
|
941
|
-
`,instanceType:"t3.medium",allowedPorts:[22,6379]})}}}class E0{static createVpc($){let{slug:J,environment:Y,cidr:Q="10.0.0.0/16",enableDnsHostnames:Z=!0,enableDnsSupport:W=!0}=$,G=v({slug:J,environment:Y,resourceType:"vpc"}),U=b(G);return{vpc:{Type:"AWS::EC2::VPC",Properties:{CidrBlock:Q,EnableDnsHostnames:Z,EnableDnsSupport:W,Tags:[{Key:"Name",Value:G},{Key:"Environment",Value:Y}]}},logicalId:U}}static createSubnet($){let{slug:J,environment:Y,vpcId:Q,type:Z,cidr:W,availabilityZone:G,mapPublicIp:U=Z==="public"}=$,z=v({slug:J,environment:Y,resourceType:`subnet-${Z}`}),H=b(`${z}-${G}`);return{subnet:{Type:"AWS::EC2::Subnet",Properties:{VpcId:Q,CidrBlock:W,AvailabilityZone:G,MapPublicIpOnLaunch:U,Tags:[{Key:"Name",Value:`${z}-${G}`},{Key:"Environment",Value:Y},{Key:"Type",Value:Z}]}},logicalId:H}}static createInternetGateway($,J){let Y=v({slug:$,environment:J,resourceType:"igw"}),Q=b(Y);return{internetGateway:{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:Y},{Key:"Environment",Value:J}]}},logicalId:Q}}static attachInternetGateway($,J){let Y=b(`${$}-igw-attachment`);return{attachment:{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:u.Ref($),InternetGatewayId:u.Ref(J)}},logicalId:Y}}static createEip($,J){let Y=v({slug:$,environment:J,resourceType:"eip"}),Q=b(Y);return{eip:{Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:Y},{Key:"Environment",Value:J}]}},logicalId:Q}}static createNatGateway($,J){let{slug:Y,environment:Q,subnetId:Z}=$,W=v({slug:Y,environment:Q,resourceType:"nat"}),G=b(W);return{natGateway:{Type:"AWS::EC2::NatGateway",Properties:{AllocationId:u.GetAtt(J,"AllocationId"),SubnetId:Z,Tags:[{Key:"Name",Value:W},{Key:"Environment",Value:Q},{Key:"Warning",Value:"NAT Gateway incurs hourly charges"}]}},logicalId:G}}static createRouteTable($,J,Y,Q){let Z=v({slug:$,environment:J,resourceType:`rt-${Q}`}),W=b(Z);return{routeTable:{Type:"AWS::EC2::RouteTable",Properties:{VpcId:u.Ref(Y),Tags:[{Key:"Name",Value:Z},{Key:"Environment",Value:J},{Key:"Type",Value:Q}]}},logicalId:W}}static createRoute($,J,Y){let Q=b(`${$}-route-${Y.type}`),Z={Type:"AWS::EC2::Route",Properties:{RouteTableId:u.Ref($),DestinationCidrBlock:J}};if(Y.type==="igw")Z.Properties.GatewayId=u.Ref(Y.logicalId);else if(Y.type==="nat")Z.Properties.NatGatewayId=u.Ref(Y.logicalId);else if(Y.type==="instance")Z.Properties.InstanceId=u.Ref(Y.logicalId);return{route:Z,logicalId:Q}}static associateSubnetWithRouteTable($,J){let Y=b(`${$}-rt-assoc`);return{association:{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:u.Ref($),RouteTableId:u.Ref(J)}},logicalId:Y}}static enableFlowLogs($){let{slug:J,environment:Y,resourceId:Q,resourceType:Z,trafficType:W="ALL",logGroupName:G}=$,U=v({slug:J,environment:Y,resourceType:"flowlog"}),z=b(U);return{flowLog:{Type:"AWS::EC2::FlowLog",Properties:{ResourceType:Z,ResourceIds:[Q],TrafficType:W,LogDestinationType:"cloud-watch-logs",LogGroupName:G||`/aws/vpc/${J}-${Y}`,Tags:[{Key:"Name",Value:U},{Key:"Environment",Value:Y}]}},logicalId:z}}static calculateSubnetCidrs($,J,Y=3){let[Q,Z]=$.split("/"),W=Number.parseInt(Z,10),G=Math.ceil(Math.log2(J*Y)),U=W+G;if(U>28)throw Error("VPC CIDR is too small to accommodate requested subnets");let[z,H,A,K]=Q.split(".").map(Number),B=(z<<24)+(H<<16)+(A<<8)+K,j=2**(32-U),O=[];for(let X=0;X<J*Y;X++){let _=B+X*j,q=[_>>>24&255,_>>>16&255,_>>>8&255,_&255].join(".");O.push(`${q}/${U}`)}return O}static getAvailabilityZones($,J){return["a","b","c","d","e","f"].slice(0,J).map((Q)=>`${$}${Q}`)}static createMultiAzNetwork($){let{slug:J,environment:Y,region:Q,cidr:Z="10.0.0.0/16",zones:W=3,enableNatGateway:G=!1,singleNatGateway:U=!1,enableFlowLogs:z=!1}=$,H={},A=[],K=[],B=[],{vpc:j,logicalId:O}=E0.createVpc({slug:J,environment:Y,cidr:Z});H[O]=j;let{internetGateway:X,logicalId:_}=E0.createInternetGateway(J,Y);H[_]=X;let{attachment:q,logicalId:E}=E0.attachInternetGateway(O,_);H[E]=q;let{routeTable:M,logicalId:D}=E0.createRouteTable(J,Y,O,"public");H[D]=M;let{route:R,logicalId:T}=E0.createRoute(D,"0.0.0.0/0",{type:"igw",logicalId:_});R.DependsOn=E,H[T]=R;let S=E0.calculateSubnetCidrs(Z,W,2),C=E0.getAvailabilityZones(Q,W),x=[];for(let h=0;h<W;h++){let I=C[h],f=S[h*2],d=S[h*2+1],{subnet:r,logicalId:c}=E0.createSubnet({slug:J,environment:Y,vpcId:u.Ref(O),type:"public",cidr:f,availabilityZone:I});H[c]=r,A.push(c);let{association:n,logicalId:s}=E0.associateSubnetWithRouteTable(c,D);H[s]=n;let{subnet:J0,logicalId:_0}=E0.createSubnet({slug:J,environment:Y,vpcId:u.Ref(O),type:"private",cidr:d,availabilityZone:I});if(H[_0]=J0,K.push(_0),G&&(!U||h===0)){let{eip:l0,logicalId:I0}=E0.createEip(`${J}-${I}`,Y);H[I0]=l0;let{natGateway:t1,logicalId:f0}=E0.createNatGateway({slug:`${J}-${I}`,environment:Y,subnetId:u.Ref(c)},I0);t1.DependsOn=E,H[f0]=t1,B.push(f0);let{routeTable:s1,logicalId:
|
|
941
|
+
`,instanceType:"t3.medium",allowedPorts:[22,6379]})}}}class E0{static createVpc($){let{slug:J,environment:Y,cidr:Q="10.0.0.0/16",enableDnsHostnames:Z=!0,enableDnsSupport:W=!0}=$,G=v({slug:J,environment:Y,resourceType:"vpc"}),U=b(G);return{vpc:{Type:"AWS::EC2::VPC",Properties:{CidrBlock:Q,EnableDnsHostnames:Z,EnableDnsSupport:W,Tags:[{Key:"Name",Value:G},{Key:"Environment",Value:Y}]}},logicalId:U}}static createSubnet($){let{slug:J,environment:Y,vpcId:Q,type:Z,cidr:W,availabilityZone:G,mapPublicIp:U=Z==="public"}=$,z=v({slug:J,environment:Y,resourceType:`subnet-${Z}`}),H=b(`${z}-${G}`);return{subnet:{Type:"AWS::EC2::Subnet",Properties:{VpcId:Q,CidrBlock:W,AvailabilityZone:G,MapPublicIpOnLaunch:U,Tags:[{Key:"Name",Value:`${z}-${G}`},{Key:"Environment",Value:Y},{Key:"Type",Value:Z}]}},logicalId:H}}static createInternetGateway($,J){let Y=v({slug:$,environment:J,resourceType:"igw"}),Q=b(Y);return{internetGateway:{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:Y},{Key:"Environment",Value:J}]}},logicalId:Q}}static attachInternetGateway($,J){let Y=b(`${$}-igw-attachment`);return{attachment:{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:u.Ref($),InternetGatewayId:u.Ref(J)}},logicalId:Y}}static createEip($,J){let Y=v({slug:$,environment:J,resourceType:"eip"}),Q=b(Y);return{eip:{Type:"AWS::EC2::EIP",Properties:{Domain:"vpc",Tags:[{Key:"Name",Value:Y},{Key:"Environment",Value:J}]}},logicalId:Q}}static createNatGateway($,J){let{slug:Y,environment:Q,subnetId:Z}=$,W=v({slug:Y,environment:Q,resourceType:"nat"}),G=b(W);return{natGateway:{Type:"AWS::EC2::NatGateway",Properties:{AllocationId:u.GetAtt(J,"AllocationId"),SubnetId:Z,Tags:[{Key:"Name",Value:W},{Key:"Environment",Value:Q},{Key:"Warning",Value:"NAT Gateway incurs hourly charges"}]}},logicalId:G}}static createRouteTable($,J,Y,Q){let Z=v({slug:$,environment:J,resourceType:`rt-${Q}`}),W=b(Z);return{routeTable:{Type:"AWS::EC2::RouteTable",Properties:{VpcId:u.Ref(Y),Tags:[{Key:"Name",Value:Z},{Key:"Environment",Value:J},{Key:"Type",Value:Q}]}},logicalId:W}}static createRoute($,J,Y){let Q=b(`${$}-route-${Y.type}`),Z={Type:"AWS::EC2::Route",Properties:{RouteTableId:u.Ref($),DestinationCidrBlock:J}};if(Y.type==="igw")Z.Properties.GatewayId=u.Ref(Y.logicalId);else if(Y.type==="nat")Z.Properties.NatGatewayId=u.Ref(Y.logicalId);else if(Y.type==="instance")Z.Properties.InstanceId=u.Ref(Y.logicalId);return{route:Z,logicalId:Q}}static associateSubnetWithRouteTable($,J){let Y=b(`${$}-rt-assoc`);return{association:{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:u.Ref($),RouteTableId:u.Ref(J)}},logicalId:Y}}static enableFlowLogs($){let{slug:J,environment:Y,resourceId:Q,resourceType:Z,trafficType:W="ALL",logGroupName:G}=$,U=v({slug:J,environment:Y,resourceType:"flowlog"}),z=b(U);return{flowLog:{Type:"AWS::EC2::FlowLog",Properties:{ResourceType:Z,ResourceIds:[Q],TrafficType:W,LogDestinationType:"cloud-watch-logs",LogGroupName:G||`/aws/vpc/${J}-${Y}`,Tags:[{Key:"Name",Value:U},{Key:"Environment",Value:Y}]}},logicalId:z}}static calculateSubnetCidrs($,J,Y=3){let[Q,Z]=$.split("/"),W=Number.parseInt(Z,10),G=Math.ceil(Math.log2(J*Y)),U=W+G;if(U>28)throw Error("VPC CIDR is too small to accommodate requested subnets");let[z,H,A,K]=Q.split(".").map(Number),B=(z<<24)+(H<<16)+(A<<8)+K,j=2**(32-U),O=[];for(let X=0;X<J*Y;X++){let _=B+X*j,q=[_>>>24&255,_>>>16&255,_>>>8&255,_&255].join(".");O.push(`${q}/${U}`)}return O}static getAvailabilityZones($,J){return["a","b","c","d","e","f"].slice(0,J).map((Q)=>`${$}${Q}`)}static createMultiAzNetwork($){let{slug:J,environment:Y,region:Q,cidr:Z="10.0.0.0/16",zones:W=3,enableNatGateway:G=!1,singleNatGateway:U=!1,enableFlowLogs:z=!1}=$,H={},A=[],K=[],B=[],{vpc:j,logicalId:O}=E0.createVpc({slug:J,environment:Y,cidr:Z});H[O]=j;let{internetGateway:X,logicalId:_}=E0.createInternetGateway(J,Y);H[_]=X;let{attachment:q,logicalId:E}=E0.attachInternetGateway(O,_);H[E]=q;let{routeTable:M,logicalId:D}=E0.createRouteTable(J,Y,O,"public");H[D]=M;let{route:R,logicalId:T}=E0.createRoute(D,"0.0.0.0/0",{type:"igw",logicalId:_});R.DependsOn=E,H[T]=R;let S=E0.calculateSubnetCidrs(Z,W,2),C=E0.getAvailabilityZones(Q,W),x=[];for(let h=0;h<W;h++){let I=C[h],f=S[h*2],d=S[h*2+1],{subnet:r,logicalId:c}=E0.createSubnet({slug:J,environment:Y,vpcId:u.Ref(O),type:"public",cidr:f,availabilityZone:I});H[c]=r,A.push(c);let{association:n,logicalId:s}=E0.associateSubnetWithRouteTable(c,D);H[s]=n;let{subnet:J0,logicalId:_0}=E0.createSubnet({slug:J,environment:Y,vpcId:u.Ref(O),type:"private",cidr:d,availabilityZone:I});if(H[_0]=J0,K.push(_0),G&&(!U||h===0)){let{eip:l0,logicalId:I0}=E0.createEip(`${J}-${I}`,Y);H[I0]=l0;let{natGateway:t1,logicalId:f0}=E0.createNatGateway({slug:`${J}-${I}`,environment:Y,subnetId:u.Ref(c)},I0);t1.DependsOn=E,H[f0]=t1,B.push(f0);let{routeTable:s1,logicalId:w0}=E0.createRouteTable(`${J}-${I}`,Y,O,"private");H[w0]=s1,x.push(w0);let{route:f1,logicalId:g1}=E0.createRoute(w0,"0.0.0.0/0",{type:"nat",logicalId:f0});H[g1]=f1;let{association:V2,logicalId:e$}=E0.associateSubnetWithRouteTable(_0,w0);H[e$]=V2}else if(G&&U&&h>0){let{association:l0,logicalId:I0}=E0.associateSubnetWithRouteTable(_0,x[0]);H[I0]=l0}else{let{routeTable:l0,logicalId:I0}=E0.createRouteTable(`${J}-${I}-isolated`,Y,O,"private");H[I0]=l0;let{association:t1,logicalId:f0}=E0.associateSubnetWithRouteTable(_0,I0);H[f0]=t1}}if(z){let{flowLog:h,logicalId:I}=E0.enableFlowLogs({slug:J,environment:Y,resourceId:u.Ref(O),resourceType:"VPC"});H[I]=h}return{resources:H,outputs:{vpcId:O,publicSubnetIds:A,privateSubnetIds:K,natGatewayIds:B.length>0?B:void 0}}}static NatGatewayCostWarning=`
|
|
942
942
|
⚠️ NAT Gateway Cost Warning:
|
|
943
943
|
- Each NAT Gateway costs approximately $32-45/month (hourly charges)
|
|
944
944
|
- Data processing charges: $0.045/GB processed
|
|
@@ -5375,8 +5375,8 @@ function unmarshallTest(item) {
|
|
|
5375
5375
|
|
|
5376
5376
|
return test;
|
|
5377
5377
|
}
|
|
5378
|
-
`;static createAbTestsTable($){return{[`${$.slug}AbTestsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${$.slug}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createAbTestManagerLambda($){return{[`${$.slug}AbTestManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${$.slug}-ab-test-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:$.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:I1.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:$.abTestsTable}}}}}}static selectVariant($,J){let Q=I1.hashString(J+$.id)%100,Z=0;for(let W=0;W<$.variants.length;W++)if(Z+=$.trafficSplit[W],Q<Z)return $.variants[W];return $.variants[$.variants.length-1]}static determineWinner($){if($.variants.length===0)return null;let J=$.winningCriteria,Y=$.variants[0],Q=I1.getMetricValue(Y,J);for(let Z of $.variants.slice(1)){let W=I1.getMetricValue(Z,J);if(W>Q)Q=W,Y=Z}return Y}static calculateSignificance($,J,Y){let Q=$.stats.sent,Z=J.stats.sent;if(Q<30||Z<30)return 0;let W=I1.getMetricValue($,Y)/100,G=I1.getMetricValue(J,Y)/100,U=(W*Q+G*Z)/(Q+Z),z=Math.sqrt(U*(1-U)*(1/Q+1/Z));if(z===0)return 0;let H=Math.abs(W-G)/z;if(H>=2.576)return 99;if(H>=1.96)return 95;if(H>=1.645)return 90;if(H>=1.28)return 80;return Math.round(H*30)}static getMetricValue($,J){switch(J){case"delivery_rate":return $.stats.deliveryRate;case"click_rate":return $.stats.clickRate;case"reply_rate":return $.stats.replyRate;case"conversion_rate":return $.stats.conversionRate;default:return $.stats.deliveryRate}}static hashString($){let J=0;for(let Y=0;Y<$.length;Y++){let Q=$.charCodeAt(Y);J=(J<<5)-J+Q,J=J&J}return Math.abs(J)}}class gJ{queues=new Map;messageGroups=new Map;deduplicationConfigs=new Map;messages=new Map;queueCounter=0;groupCounter=0;deduplicationCounter=0;messageCounter=0;sequenceCounter=0;createFIFOQueue($){let J=`fifo-queue-${Date.now()}-${this.queueCounter++}`,Y=$.name.endsWith(".fifo")?$.name:`${$.name}.fifo`,{name:Q,...Z}=$,W={id:J,name:Y,queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${Y}`,...Z};return this.queues.set(J,W),this.createDeduplicationConfig({queueId:J,contentBasedDeduplication:$.contentBasedDeduplication,deduplicationInterval:300}),W}createHighThroughputFIFO($){return this.createFIFOQueue({name:$.name,contentBasedDeduplication:$.contentBasedDeduplication??!0,deduplicationScope:"messageGroup",fifoThroughputLimit:"perMessageGroupId",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createStandardFIFO($){return this.createFIFOQueue({name:$.name,contentBasedDeduplication:$.contentBasedDeduplication??!1,deduplicationScope:"queue",fifoThroughputLimit:"perQueue",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createDeduplicationConfig($){let Y={id:`dedup-${Date.now()}-${this.deduplicationCounter++}`,deduplicationHashes:new Map,...$};return this.deduplicationConfigs.set($.queueId,Y),Y}sendMessage($){let J=this.queues.get($.queueId);if(!J)throw Error(`Queue not found: ${$.queueId}`);let Y=this.deduplicationConfigs.get($.queueId);if(Y){let G=$.messageDeduplicationId||(J.contentBasedDeduplication?this.generateHash($.messageBody):void 0);if(G&&this.isDuplicate(Y,G))return null;if(G)Y.deduplicationHashes.set(G,new Date)}let Q=`msg-${Date.now()}-${this.messageCounter++}`,Z=this.generateSequenceNumber(),W={id:Q,messageId:Q,messageGroupId:$.messageGroupId,messageDeduplicationId:$.messageDeduplicationId,body:$.messageBody,attributes:$.messageAttributes||{},sentTimestamp:new Date,sequenceNumber:Z};return this.messages.set(Q,W),this.updateMessageGroup($.queueId,$.messageGroupId),W}isDuplicate($,J){let Y=$.deduplicationHashes.get(J);if(!Y)return!1;if((Date.now()-Y.getTime())/1000>$.deduplicationInterval)return $.deduplicationHashes.delete(J),!1;return!0}generateHash($){let J=0;for(let Y=0;Y<$.length;Y++){let Q=$.charCodeAt(Y);J=(J<<5)-J+Q,J=J&J}return Math.abs(J).toString(36)}generateSequenceNumber(){return`${Date.now()}${this.sequenceCounter++}`.padStart(20,"0")}updateMessageGroup($,J){let Y=`${$}-${J}`,Q=this.messageGroups.get(Y);if(!Q)Q={id:`group-${Date.now()}-${this.groupCounter++}`,messageGroupId:J,queueId:$,messagesInFlight:0},this.messageGroups.set(Y,Q);Q.messagesInFlight++,Q.lastMessageTimestamp=new Date}getMessageGroups($){return Array.from(this.messageGroups.values()).filter((J)=>J.queueId===$)}getQueue($){return this.queues.get($)}listQueues(){return Array.from(this.queues.values())}getMessages($,J){let Y=Array.from(this.messages.values());if(J)Y=Y.filter((Q)=>Q.messageGroupId===J);return Y.sort((Q,Z)=>Q.sequenceNumber.localeCompare(Z.sequenceNumber))}generateFIFOQueueCF($){return{Type:"AWS::SQS::Queue",Properties:{QueueName:$.name,FifoQueue:!0,ContentBasedDeduplication:$.contentBasedDeduplication,DeduplicationScope:$.deduplicationScope,FifoThroughputLimit:$.fifoThroughputLimit,MessageRetentionPeriod:$.messageRetentionPeriod,VisibilityTimeout:$.visibilityTimeout,ReceiveMessageWaitTimeSeconds:$.receiveMessageWaitTime,...$.deadLetterTargetArn&&{RedrivePolicy:{deadLetterTargetArn:$.deadLetterTargetArn,maxReceiveCount:$.maxReceiveCount||3}}}}}clear(){this.queues.clear(),this.messageGroups.clear(),this.deduplicationConfigs.clear(),this.messages.clear(),this.queueCounter=0,this.groupCounter=0,this.deduplicationCounter=0,this.messageCounter=0,this.sequenceCounter=0}}var sH=new gJ;class uJ{monitors=new Map;metrics=new Map;alerts=new Map;reprocessJobs=new Map;monitorCounter=0;metricsCounter=0;alertCounter=0;jobCounter=0;createDLQMonitor($){let J=`dlq-monitor-${Date.now()}-${this.monitorCounter++}`,Y={id:J,...$};return this.monitors.set(J,Y),Y}createAutomatedMonitor($){return this.createDLQMonitor({name:$.name,queueUrl:$.queueUrl,sourceQueues:$.sourceQueues,maxReceiveCount:3,alarmThreshold:10,autoReprocess:!0,reprocessStrategy:"scheduled",notificationTopicArn:$.notificationTopicArn})}collectMetrics($){let Y={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:$,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*100),approximateAgeOfOldestMessage:Math.floor(Math.random()*86400),messagesReceived:Math.floor(Math.random()*50),messagesDeleted:Math.floor(Math.random()*30),messagesReprocessed:Math.floor(Math.random()*20)},Q=this.metrics.get($)||[];return Q.push(Y),this.metrics.set($,Q),this.checkForAlerts($,Y),Y}checkForAlerts($,J){let Y=Array.from(this.monitors.values()).find((Z)=>Z.queueUrl===$);if(!Y)return;if(J.approximateNumberOfMessages>=Y.alarmThreshold)this.createAlert({monitorId:Y.id,alertType:"threshold_exceeded",severity:"high",message:`DLQ ${Y.name} has ${J.approximateNumberOfMessages} messages (threshold: ${Y.alarmThreshold})`});let Q=3600;if(J.approximateAgeOfOldestMessage>Q)this.createAlert({monitorId:Y.id,alertType:"old_message",severity:"medium",message:`DLQ ${Y.name} has messages older than ${Q} seconds`})}createAlert($){let J=`alert-${Date.now()}-${this.alertCounter++}`,Y={id:J,timestamp:new Date,acknowledged:!1,...$};return this.alerts.set(J,Y),Y}acknowledgeAlert($){let J=this.alerts.get($);if(!J)throw Error(`Alert not found: ${$}`);return J.acknowledged=!0,J}createReprocessJob($){let J=`reprocess-${Date.now()}-${this.jobCounter++}`,Y={id:J,queueUrl:$.queueUrl,messageId:$.messageId,attempts:0,status:"pending"};return this.reprocessJobs.set(J,Y),Y}async executeReprocessJob($){let J=this.reprocessJobs.get($);if(!J)throw Error(`Reprocess job not found: ${$}`);J.status="processing",J.startedAt=new Date,J.attempts++,await new Promise((Q)=>setTimeout(Q,100));let Y=Math.random()>0.3;if(J.status=Y?"success":"failed",J.completedAt=new Date,!Y)J.error="Reprocessing failed - original error still present";return J}async batchReprocess($){let J=[];for(let Y=0;Y<$.maxMessages;Y++){let Q=this.createReprocessJob({queueUrl:$.queueUrl,messageId:`msg-${Y}`});await this.executeReprocessJob(Q.id),J.push(Q)}return J}getDLQStatistics($,J=24){let Y=new Date(Date.now()-J*60*60*1000),Q=(this.metrics.get($)||[]).filter((A)=>A.timestamp>=Y);if(Q.length===0)return{totalMessages:0,avgAge:0,messagesReceived:0,messagesDeleted:0,messagesReprocessed:0,successRate:0};let Z=Q[Q.length-1],W=Q.reduce((A,K)=>A+K.messagesReceived,0),G=Q.reduce((A,K)=>A+K.messagesDeleted,0),U=Q.reduce((A,K)=>A+K.messagesReprocessed,0),z=Q.reduce((A,K)=>A+K.approximateAgeOfOldestMessage,0)/Q.length,H=U>0?G/U*100:0;return{totalMessages:Z.approximateNumberOfMessages,avgAge:z,messagesReceived:W,messagesDeleted:G,messagesReprocessed:U,successRate:H}}getMonitor($){return this.monitors.get($)}listMonitors(){return Array.from(this.monitors.values())}getAlerts($,J){let Y=Array.from(this.alerts.values());if($)Y=Y.filter((Q)=>Q.monitorId===$);if(J!==void 0)Y=Y.filter((Q)=>Q.acknowledged===J);return Y.sort((Q,Z)=>Z.timestamp.getTime()-Q.timestamp.getTime())}getReprocessJobs($){let J=Array.from(this.reprocessJobs.values());if($)J=J.filter((Y)=>Y.queueUrl===$);return J}generateDLQAlarmCF($){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$.name}-messages-alarm`,AlarmDescription:`Alert when DLQ ${$.name} exceeds threshold`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:1,Threshold:$.alarmThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:$.queueUrl.split("/").pop()}],...$.notificationTopicArn&&{AlarmActions:[$.notificationTopicArn]}}}}clear(){this.monitors.clear(),this.metrics.clear(),this.alerts.clear(),this.reprocessJobs.clear(),this.monitorCounter=0,this.metricsCounter=0,this.alertCounter=0,this.jobCounter=0}}var oH=new uJ;class dJ{configs=new Map;jobs=new Map;metrics=new Map;configCounter=0;jobCounter=0;metricsCounter=0;createBatchConfig($){let J=`batch-config-${Date.now()}-${this.configCounter++}`,Y={id:J,...$};return this.configs.set(J,Y),Y}createHighThroughputConfig($){return this.createBatchConfig({queueUrl:$.queueUrl,batchSize:10,maxWaitTime:100,parallelProcessors:10,retryAttempts:3,visibilityTimeout:30})}createLowLatencyConfig($){return this.createBatchConfig({queueUrl:$.queueUrl,batchSize:1,maxWaitTime:0,parallelProcessors:5,retryAttempts:2,visibilityTimeout:10})}createBatchJob($){let J=`batch-job-${Date.now()}-${this.jobCounter++}`;if(!this.configs.get($.configId))throw Error(`Batch config not found: ${$.configId}`);let Q=[];for(let W=0;W<$.messageCount;W++)Q.push({id:`msg-${J}-${W}`,messageId:`${J}-${W}`,body:`Message ${W}`,receiptHandle:`receipt-${J}-${W}`,attributes:{},status:"pending"});let Z={id:J,configId:$.configId,messages:Q,status:"pending",processedCount:0,failedCount:0};return this.jobs.set(J,Z),Z}async processBatchJob($){let J=this.jobs.get($);if(!J)throw Error(`Batch job not found: ${$}`);let Y=this.configs.get(J.configId);if(!Y)throw Error(`Batch config not found: ${J.configId}`);J.status="processing",J.startedAt=new Date;let Q=this.chunkArray(J.messages,Y.batchSize);for(let Z of Q)await this.processBatch(Z,Y);return J.processedCount=J.messages.filter((Z)=>Z.status==="success").length,J.failedCount=J.messages.filter((Z)=>Z.status==="failed").length,J.status=J.failedCount===0?"completed":"failed",J.completedAt=new Date,this.collectProcessorMetrics(Y.id,J),J}async processBatch($,J){let Y=$.map((Q)=>this.processMessage(Q,J));await Promise.all(Y)}async processMessage($,J){$.status="processing";let Y=Date.now();await new Promise((W)=>setTimeout(W,Math.random()*100));let Q=Date.now()-Y;if($.processingTime=Q,Math.random()>0.1)$.status="success";else $.status="failed",$.error="Processing error"}chunkArray($,J){let Y=[];for(let Q=0;Q<$.length;Q+=J)Y.push($.slice(Q,Q+J));return Y}collectProcessorMetrics($,J){let Y=`metrics-${Date.now()}-${this.metricsCounter++}`,Z=J.messages.filter((K)=>K.status==="success").map((K)=>K.processingTime||0).filter((K)=>K>0),W=Z.length>0?Z.reduce((K,B)=>K+B,0)/Z.length:0,G=J.completedAt&&J.startedAt?(J.completedAt.getTime()-J.startedAt.getTime())/1000:1,U=J.processedCount/G,z=J.messages.length>0?J.failedCount/J.messages.length*100:0,H={id:Y,configId:$,timestamp:new Date,messagesProcessed:J.processedCount,averageProcessingTime:W,throughput:U,errorRate:z},A=this.metrics.get($)||[];A.push(H),this.metrics.set($,A)}getBatchStatistics($){let J=this.metrics.get($)||[];if(J.length===0)return{totalJobsProcessed:0,totalMessagesProcessed:0,averageThroughput:0,averageErrorRate:0,averageProcessingTime:0};let Y=J.reduce((G,U)=>G+U.messagesProcessed,0),Q=J.reduce((G,U)=>G+U.throughput,0)/J.length,Z=J.reduce((G,U)=>G+U.errorRate,0)/J.length,W=J.reduce((G,U)=>G+U.averageProcessingTime,0)/J.length;return{totalJobsProcessed:J.length,totalMessagesProcessed:Y,averageThroughput:Q,averageErrorRate:Z,averageProcessingTime:W}}optimizeBatchConfig($){let J=this.configs.get($);if(!J)throw Error(`Batch config not found: ${$}`);let Y=this.getBatchStatistics($);if(Y.averageErrorRate<5&&J.batchSize<10)J.batchSize=Math.min(10,J.batchSize+1);if(Y.averageErrorRate>20&&J.batchSize>1)J.batchSize=Math.max(1,J.batchSize-1);if(Y.averageThroughput<5&&J.parallelProcessors<20)J.parallelProcessors++;return J}getConfig($){return this.configs.get($)}listConfigs(){return Array.from(this.configs.values())}getJob($){return this.jobs.get($)}listJobs($){let J=Array.from(this.jobs.values());if($)J=J.filter((Y)=>Y.configId===$);return J}generateBatchProcessorCF($){return{Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:`arn:aws:sqs:us-east-1:123456789012:${$.queueUrl.split("/").pop()}`,FunctionName:"batch-processor-function",BatchSize:$.batchSize,MaximumBatchingWindowInSeconds:$.maxWaitTime/1000,FunctionResponseTypes:["ReportBatchItemFailures"]}}}clear(){this.configs.clear(),this.jobs.clear(),this.metrics.clear(),this.configCounter=0,this.jobCounter=0,this.metricsCounter=0}}var eH=new dJ;class mJ{queues=new Map;retentionPolicies=new Map;delayQueues=new Map;purgeOperations=new Map;metrics=new Map;queueCounter=0;retentionCounter=0;delayCounter=0;purgeCounter=0;metricsCounter=0;createQueue($){let J=`queue-${Date.now()}-${this.queueCounter++}`,Y={id:J,purgeInProgress:!1,...$};return this.queues.set(J,Y),Y}createStandardQueue($){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${$.queueName}`,queueName:$.queueName,messageRetentionPeriod:($.messageRetentionDays||4)*24*60*60,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:0})}createLongPollingQueue($){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${$.queueName}`,queueName:$.queueName,messageRetentionPeriod:345600,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:$.waitTimeSeconds||20})}createRetentionPolicy($){let J=`retention-${Date.now()}-${this.retentionCounter++}`,Y={id:J,...$};this.retentionPolicies.set(J,Y);let Q=this.queues.get($.queueId);if(Q)Q.messageRetentionPeriod=$.retentionPeriod;return Y}createShortRetentionPolicy($){return this.createRetentionPolicy({queueId:$.queueId,retentionPeriod:$.retentionHours*60*60,autoCleanup:!0,archiveExpiredMessages:!1})}createArchivalRetentionPolicy($){return this.createRetentionPolicy({queueId:$.queueId,retentionPeriod:$.retentionDays*24*60*60,autoCleanup:!0,cleanupSchedule:"cron(0 0 * * ? *)",archiveExpiredMessages:!0,archiveS3Bucket:$.s3Bucket})}createDelayQueue($){let J=`delay-${Date.now()}-${this.delayCounter++}`,Y={id:J,...$};this.delayQueues.set(J,Y);let Q=Array.from(this.queues.values()).find((Z)=>Z.queueUrl===$.queueUrl);if(Q)Q.delaySeconds=$.defaultDelay;return Y}createScheduledDelayQueue($){return this.createDelayQueue({queueUrl:$.queueUrl,defaultDelay:$.delayMinutes*60,perMessageDelay:!1,maxDelay:900})}async purgeQueue($){let J=this.queues.get($);if(!J)throw Error(`Queue not found: ${$}`);if(J.purgeInProgress)throw Error("Purge already in progress for this queue");let Y=`purge-${Date.now()}-${this.purgeCounter++}`,Q={id:Y,queueUrl:J.queueUrl,status:"in_progress",startedAt:new Date};return this.purgeOperations.set(Y,Q),J.purgeInProgress=!0,setTimeout(()=>{Q.status="completed",Q.completedAt=new Date,Q.messagesPurged=Math.floor(Math.random()*1000),J.purgeInProgress=!1},100),Q}collectQueueMetrics($){let Y={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:$,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*1000),approximateNumberOfMessagesNotVisible:Math.floor(Math.random()*100),approximateNumberOfMessagesDelayed:Math.floor(Math.random()*50),oldestMessageAge:Math.floor(Math.random()*86400)},Q=this.metrics.get($)||[];return Q.push(Y),this.metrics.set($,Q),Y}getQueueHealth($){let J=this.metrics.get($)||[];if(J.length===0)return{status:"healthy",issues:[],recommendations:[]};let Y=J[J.length-1],Q=[],Z=[],W="healthy";if(Y.approximateNumberOfMessages>1e4)W="critical",Q.push("Large message backlog detected"),Z.push("Increase consumer capacity");else if(Y.approximateNumberOfMessages>1000)W="warning",Q.push("Growing message backlog"),Z.push("Monitor consumer performance");if(Y.oldestMessageAge&&Y.oldestMessageAge>3600){if(W!=="critical")W="warning";Q.push("Old messages in queue"),Z.push("Review message processing")}if(Y.approximateNumberOfMessagesDelayed>100){if(W!=="critical")W="warning";Q.push("High number of delayed messages")}return{status:W,issues:Q,recommendations:Z}}getQueue($){return this.queues.get($)}listQueues(){return Array.from(this.queues.values())}getRetentionPolicy($){return this.retentionPolicies.get($)}listRetentionPolicies(){return Array.from(this.retentionPolicies.values())}getPurgeOperations($){let J=Array.from(this.purgeOperations.values());if($)J=J.filter((Y)=>Y.queueUrl===$);return J}generateQueueCF($){return{Type:"AWS::SQS::Queue",Properties:{QueueName:$.queueName,MessageRetentionPeriod:$.messageRetentionPeriod,DelaySeconds:$.delaySeconds,MaximumMessageSize:$.maximumMessageSize,ReceiveMessageWaitTimeSeconds:$.receiveMessageWaitTime}}}generateCleanupRuleCF($){return{Type:"AWS::Events::Rule",Properties:{Name:`${$.id}-cleanup`,Description:"Automated queue cleanup",ScheduleExpression:$.cleanupSchedule||"cron(0 0 * * ? *)",State:"ENABLED",Targets:[{Arn:"arn:aws:lambda:us-east-1:123456789012:function:queue-cleanup",Id:$.id,Input:JSON.stringify({queueId:$.queueId,archiveBucket:$.archiveS3Bucket})}]}}}clear(){this.queues.clear(),this.retentionPolicies.clear(),this.delayQueues.clear(),this.purgeOperations.clear(),this.metrics.clear(),this.queueCounter=0,this.retentionCounter=0,this.delayCounter=0,this.purgeCounter=0,this.metricsCounter=0}}var $A=new mJ;class cJ{optimizations=new Map;imageConfigs=new Map;ssgConfigs=new Map;prerenderConfigs=new Map;counter=0;createAssetOptimization($){let J=`asset-opt-${Date.now()}-${this.counter++}`,Y={id:J,...$};return this.optimizations.set(J,Y),Y}createImageOptimization($){let J=`image-opt-${Date.now()}-${this.counter++}`,Y={id:J,...$};return this.imageConfigs.set(J,Y),Y}createSSGConfig($){let J=`ssg-${Date.now()}-${this.counter++}`,Y={id:J,...$};return this.ssgConfigs.set(J,Y),Y}createPrerenderConfig($){let J=`prerender-${Date.now()}-${this.counter++}`,Y={id:J,...$};return this.prerenderConfigs.set(J,Y),Y}listOptimizations(){return Array.from(this.optimizations.values())}listImageConfigs(){return Array.from(this.imageConfigs.values())}clear(){this.optimizations.clear(),this.imageConfigs.clear(),this.ssgConfigs.clear(),this.prerenderConfigs.clear()}}var JA=new cJ;class lJ{policies=new Map;versioningConfigs=new Map;replicationRules=new Map;tieringConfigs=new Map;objectLocks=new Map;transferAcceleration=new Map;accessPoints=new Map;glacierConfigs=new Map;inventories=new Map;batchOps=new Map;eventNotifications=new Map;counter=0;createLifecyclePolicy($,J){let Y=`lifecycle-${Date.now()}-${this.counter++}`,Q={id:Y,transitions:$,expiration:J};return this.policies.set(Y,Q),Q}enableVersioning($=!1){let J=`versioning-${Date.now()}-${this.counter++}`,Y={id:J,enabled:!0,mfaDelete:$};return this.versioningConfigs.set(J,Y),Y}createReplicationRule($,J,Y){let Q=`replication-${Date.now()}-${this.counter++}`,Z={id:Q,sourceRegion:$,destRegion:J,destBucket:Y};return this.replicationRules.set(Q,Z),Z}createIntelligentTiering($,J){let Y=`tiering-${Date.now()}-${this.counter++}`,Q={id:Y,archiveDays:$,deepArchiveDays:J};return this.tieringConfigs.set(Y,Q),Q}enableObjectLock($){let J=`object-lock-${Date.now()}-${this.counter++}`,Y={id:J,bucketName:$.bucketName,mode:$.mode||"COMPLIANCE",retentionDays:$.retentionDays,retentionYears:$.retentionYears,legalHoldEnabled:$.legalHoldEnabled||!1};return this.objectLocks.set(J,Y),Y}enableTransferAcceleration($){let J=`transfer-accel-${Date.now()}-${this.counter++}`,Y={id:J,bucketName:$,enabled:!0,endpoint:`${$}.s3-accelerate.amazonaws.com`};return this.transferAcceleration.set(J,Y),Y}createAccessPoint($){let J=`access-point-${Date.now()}-${this.counter++}`,Y={id:J,name:$.name,bucketName:$.bucketName,vpcId:$.vpcId,publicAccessBlock:$.publicAccessBlock!==!1,policy:$.policy};return this.accessPoints.set(J,Y),Y}createGlacierArchive($){let J=`glacier-${Date.now()}-${this.counter++}`,Y={id:J,bucketName:$.bucketName,archiveType:$.archiveType,transitionDays:$.transitionDays,restoreConfig:$.restoreTier?{tier:$.restoreTier,days:$.restoreDays||7}:void 0};return this.glacierConfigs.set(J,Y),Y}createInventory($){let J=`inventory-${Date.now()}-${this.counter++}`,Y={id:J,sourceBucket:$.sourceBucket,destinationBucket:$.destinationBucket,schedule:$.schedule||"Daily",format:$.format||"CSV",includedFields:$.includedFields||["Size","LastModifiedDate","StorageClass","ETag"],prefix:$.prefix};return this.inventories.set(J,Y),Y}createBatchOperation($){let J=`batch-op-${Date.now()}-${this.counter++}`,Y={id:J,operation:$.operation,manifestBucket:$.manifestBucket,manifestKey:$.manifestKey,priority:$.priority||10,status:"pending"};return this.batchOps.set(J,Y),Y}executeBatchOperation($){let J=this.batchOps.get($);if(!J)throw Error(`Batch operation not found: ${$}`);return J.status="in_progress",J.totalObjects=1000,J.processedObjects=0,J}getBatchOperationStatus($){return this.batchOps.get($)}createLambdaNotification($){let J=`event-${Date.now()}-${this.counter++}`,Y={id:J,bucketName:$.bucketName,events:$.events,destination:{type:"Lambda",arn:$.lambdaArn},filter:$.prefix||$.suffix?{prefix:$.prefix,suffix:$.suffix}:void 0};return this.eventNotifications.set(J,Y),Y}createSQSNotification($){let J=`event-${Date.now()}-${this.counter++}`,Y={id:J,bucketName:$.bucketName,events:$.events,destination:{type:"SQS",arn:$.queueArn},filter:$.prefix||$.suffix?{prefix:$.prefix,suffix:$.suffix}:void 0};return this.eventNotifications.set(J,Y),Y}createSNSNotification($){let J=`event-${Date.now()}-${this.counter++}`,Y={id:J,bucketName:$.bucketName,events:$.events,destination:{type:"SNS",arn:$.topicArn},filter:$.prefix||$.suffix?{prefix:$.prefix,suffix:$.suffix}:void 0};return this.eventNotifications.set(J,Y),Y}generateObjectLockCF($){let J={ObjectLockEnabled:"Enabled",ObjectLockConfiguration:{ObjectLockEnabled:"Enabled",Rule:{DefaultRetention:{Mode:$.mode}}}};if($.retentionDays)J.ObjectLockConfiguration.Rule.DefaultRetention.Days=$.retentionDays;if($.retentionYears)J.ObjectLockConfiguration.Rule.DefaultRetention.Years=$.retentionYears;return J}generateTransferAccelerationCF($){return{AccelerateConfiguration:{AccelerationStatus:$.enabled?"Enabled":"Suspended"}}}generateAccessPointCF($){return{Type:"AWS::S3::AccessPoint",Properties:{Name:$.name,Bucket:$.bucketName,...$.vpcId&&{VpcConfiguration:{VpcId:$.vpcId}},PublicAccessBlockConfiguration:$.publicAccessBlock?{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}:void 0,...$.policy&&{Policy:$.policy}}}}generateInventoryCF($){return{Type:"AWS::S3::Bucket",Properties:{InventoryConfigurations:[{Id:$.id,Destination:{BucketArn:`arn:aws:s3:::${$.destinationBucket}`,Format:$.format},Enabled:!0,IncludedObjectVersions:"Current",OptionalFields:$.includedFields,ScheduleFrequency:$.schedule,...$.prefix&&{Prefix:$.prefix}}]}}}generateEventNotificationCF($){let J=$.destination.type==="Lambda"?"LambdaConfigurations":$.destination.type==="SQS"?"QueueConfigurations":"TopicConfigurations",Y=$.destination.type==="Lambda"?"Function":$.destination.type==="SQS"?"Queue":"Topic",Q={Event:$.events[0],[Y]:$.destination.arn};if($.filter)Q.Filter={S3Key:{Rules:[...$.filter.prefix?[{Name:"prefix",Value:$.filter.prefix}]:[],...$.filter.suffix?[{Name:"suffix",Value:$.filter.suffix}]:[]]}};return{NotificationConfiguration:{[J]:[Q]}}}clear(){this.policies.clear(),this.versioningConfigs.clear(),this.replicationRules.clear(),this.tieringConfigs.clear(),this.objectLocks.clear(),this.transferAcceleration.clear(),this.accessPoints.clear(),this.glacierConfigs.clear(),this.inventories.clear(),this.batchOps.clear(),this.eventNotifications.clear()}}var YA=new lJ;class pJ{checks=new Map;synthetics=new Map;uptimeTrackers=new Map;counter=0;createHealthCheck($,J=30,Y=10){let Q=`health-${Date.now()}-${this.counter++}`,Z={id:Q,url:$,interval:J,timeout:Y,status:"healthy"};return this.checks.set(Q,Z),Z}createSyntheticMonitor($,J,Y,Q){let Z=`synthetic-${Date.now()}-${this.counter++}`,W={id:Z,name:$,script:J,frequency:Y,locations:Q};return this.synthetics.set(Z,W),W}trackUptime($,J,Y){let Q=`uptime-${Date.now()}-${this.counter++}`,Z=J/(J+Y)*100,W={id:Q,resource:$,uptime:J,downtime:Y,availability:Z};return this.uptimeTrackers.set(Q,W),W}clear(){this.checks.clear(),this.synthetics.clear(),this.uptimeTrackers.clear()}}var QA=new pJ;class rJ{wafRules=new Map;shieldProtections=new Map;securityGroups=new Map;nacls=new Map;counter=0;createWAFRule($,J,Y,Q){let Z=`waf-${Date.now()}-${this.counter++}`,W={id:Z,name:$,priority:J,action:Y,conditions:Q};return this.wafRules.set(Z,W),W}enableShield($,J="standard"){let Y=`shield-${Date.now()}-${this.counter++}`,Q={id:Y,resourceArn:$,protectionType:J};return this.shieldProtections.set(Y,Q),Q}createSecurityGroup($,J,Y){let Q=`sg-${Date.now()}-${this.counter++}`,Z={id:Q,name:$,vpcId:J,rules:Y};return this.securityGroups.set(Q,Z),Z}createNACL($,J){let Y=`nacl-${Date.now()}-${this.counter++}`,Q={id:Y,vpcId:$,rules:J};return this.nacls.set(Y,Q),Q}clear(){this.wafRules.clear(),this.shieldProtections.clear(),this.securityGroups.clear(),this.nacls.clear()}}var ZA=new rJ;class nJ{strategies=new Map;allocations=new Map;groups=new Map;counter=0;createTaggingStrategy($,J){let Y=`tagging-${Date.now()}-${this.counter++}`,Q={id:Y,tags:$,resources:J};return this.strategies.set(Y,Q),Q}createCostAllocation($,J){let Y=`cost-${Date.now()}-${this.counter++}`,Q={id:Y,tagKey:$,allocations:J};return this.allocations.set(Y,Q),Q}createResourceGroup($,J,Y){let Q=`group-${Date.now()}-${this.counter++}`,Z={id:Q,name:$,query:{resourceTypeFilters:J,tagFilters:Y}};return this.groups.set(Q,Z),Z}clear(){this.strategies.clear(),this.allocations.clear(),this.groups.clear()}}var WA=new nJ;class E2{builder;config;environment;mergedConfig;serverEipLogicalIds=new Map;constructor($){this.config=$.config,this.environment=$.environment,this.builder=new j8(`${this.config.project.name} - ${this.environment}`),this.mergedConfig=this.mergeEnvironmentConfig()}mergeEnvironmentConfig(){let J=this.config.environments[this.environment]?.infrastructure;if(!J)return this.config;return{...this.config,infrastructure:{...this.config.infrastructure,...J,compute:{...this.config.infrastructure?.compute,...J.compute},storage:{...this.config.infrastructure?.storage,...J.storage},functions:{...this.config.infrastructure?.functions,...J.functions},servers:{...this.config.infrastructure?.servers,...J.servers},databases:{...this.config.infrastructure?.databases,...J.databases},cdn:{...this.config.infrastructure?.cdn,...J.cdn},queues:{...this.config.infrastructure?.queues,...J.queues},redirects:{...this.config.infrastructure?.redirects,...J.redirects},realtime:{...this.config.infrastructure?.realtime,...J.realtime},cache:{...this.config.infrastructure?.cache,...J.cache},fileSystem:{...this.config.infrastructure?.fileSystem,...J.fileSystem},email:{...this.config.infrastructure?.email,...J.email},search:{...this.config.infrastructure?.search,...J.search},ai:{...this.config.infrastructure?.ai,...J.ai}}}}shouldDeploy($){if($.environments&&!$.environments.includes(this.environment))return!1;if($.requiresFeatures){let J=this.config.features||{};if(!$.requiresFeatures.every((Q)=>J[Q]===!0))return!1}if($.regions){let J=this.config.environments[this.environment]?.region||this.config.project.region;if(!$.regions.includes(J))return!1}if($.condition&&typeof $.condition==="function")return $.condition(this.config,this.environment);return!0}resolveApiOriginPort(){let $=this.mergedConfig.infrastructure?.api?.port??this.mergedConfig.ports?.api,J=Number($||3008);return Number.isFinite(J)&&J>0?J:3008}normalizeMountPath($){let J=$?.mountPath||$?.path;if(!J||J==="/")return;let Y=`/${J}`.replace(/\/+/g,"/").replace(/\/$/,"");return Y==="/"?void 0:Y}storageBucketLogicalId($,J,Y){return`${$}-${J}-s3-${Y}`.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((Q)=>Q.charAt(0).toUpperCase()+Q.slice(1)).join("")}pathMountRewriteFunctionCode($){return`function handler(event) { var request = event.request; var prefix = ${JSON.stringify($)}; var uri = request.uri; if (uri === prefix) { uri = '/'; } else if (uri.indexOf(prefix + '/') === 0) { uri = uri.substring(prefix.length); } if (uri === '' || uri === '/') { request.uri = '/index.html'; return request; } if (uri.endsWith('/')) { request.uri = uri + 'index.html'; return request; } var lastSegment = uri.substring(uri.lastIndexOf('/') + 1); if (lastSegment.indexOf('.') === -1) { request.uri = uri + '/index.html'; return request; } request.uri = uri; return request; }`}generate(){let $=this.mergedConfig.project.slug,J=this.environment,Y=!!(this.mergedConfig.infrastructure?.functions&&Object.keys(this.mergedConfig.infrastructure.functions).length>0||this.mergedConfig.infrastructure?.api),Q=!!(this.mergedConfig.infrastructure?.servers&&Object.keys(this.mergedConfig.infrastructure.servers).length>0),Z=!!this.mergedConfig.infrastructure?.compute;if(!!((this.mergedConfig.mode||"server")==="serverless"&&this.mergedConfig.infrastructure?.containers&&Object.keys(this.mergedConfig.infrastructure.containers).length>0))this.generateNetworkInfrastructure($,J),this.generateContainerInfrastructure($,J);if(Y)this.generateServerless($,J);if(Q)this.generateServer($,J);if(Z)this.generateComputeApp($,J);if(this.mergedConfig.infrastructure?.jumpBox)this.generateJumpBox($,J);if(this.generateSharedInfrastructure($,J),this.config.tags)this.applyGlobalTags(this.config.tags);return this}applyGlobalTags($){}generateNetworkInfrastructure($,J){if(this.builder.hasResource("VPC"))return;let Q=this.mergedConfig.infrastructure?.network?.cidr||"10.0.0.0/16",{vpc:Z,logicalId:W}=E0.createVpc({slug:$,environment:J,cidr:Q,enableDnsHostnames:!0,enableDnsSupport:!0});this.builder.addResource("VPC",Z);let G=`${$}${J}IGW`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(G,{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:`${$}-${J}-igw`},{Key:"Environment",Value:J}]}});let U=`${$}${J}IGWAttach`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(U,{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:{Ref:"VPC"},InternetGatewayId:{Ref:G}}});let z=`${$}${J}PublicRT`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(z,{Type:"AWS::EC2::RouteTable",Properties:{VpcId:{Ref:"VPC"},Tags:[{Key:"Name",Value:`${$}-${J}-public-rt`},{Key:"Environment",Value:J}]}}),this.builder.addResource(`${$}${J}PublicRoute`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::EC2::Route",Properties:{RouteTableId:{Ref:z},DestinationCidrBlock:"0.0.0.0/0",GatewayId:{Ref:G}},DependsOn:U});let H=this.mergedConfig.environments[J]?.region||this.mergedConfig.project.region||"us-east-1",A=["a","b"];for(let K=0;K<2;K++){let B=`PublicSubnet${K+1}`;this.builder.addResource(B,{Type:"AWS::EC2::Subnet",Properties:{VpcId:{Ref:"VPC"},CidrBlock:`10.0.${K}.0/24`,AvailabilityZone:`${H}${A[K]}`,MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:`${$}-${J}-public-${A[K]}`},{Key:"Environment",Value:J}]}}),this.builder.addResource(`${B}RTAssoc`,{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:{Ref:B},RouteTableId:{Ref:z}}})}}generateContainerInfrastructure($,J){let Y=this.mergedConfig.infrastructure?.containers;if(!Y)return;let Q=this.mergedConfig.infrastructure?.loadBalancer,Z=this.mergedConfig.infrastructure?.ssl,W=this.mergedConfig.infrastructure?.dns,G;if(Z?.enabled&&Z.domains?.length)if(Z.certificateArn);else{let A=Z.domains[0],K=Z.domains.slice(1).map((O)=>{if(O.includes(".")&&O.endsWith(A))return O.replace(`.${A}`,"");return O}),{certificate:B,logicalId:j}=L0.createCertificate({domain:A,subdomains:K,slug:$,environment:J,validationMethod:"DNS",hostedZoneId:W?.hostedZoneId});G=j,this.builder.addResource(j,B)}let U="ECSCluster";this.builder.addResource(U,{Type:"AWS::ECS::Cluster",Properties:{ClusterName:`${$}-${J}`,ClusterSettings:[{Name:"containerInsights",Value:"enabled"}],Tags:[{Key:"Name",Value:`${$}-${J}`},{Key:"Environment",Value:J}]}});let z=`${$}${J}ALBSecurityGroup`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(z,{Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:`ALB security group for ${$}-${J}`,VpcId:{Ref:"VPC"},SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:80,ToPort:80,CidrIp:"0.0.0.0/0",Description:"HTTP"},{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0",Description:"HTTPS"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:`${$}-${J}-alb-sg`},{Key:"Environment",Value:J}]}});let H=`${$}${J}ECSSecurityGroup`.replace(/[^a-zA-Z0-9]/g,"");for(let[A,K]of Object.entries(Y)){let B=K.port||3000;this.builder.addResource(H,{Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:`ECS tasks security group for ${$}-${J}`,VpcId:{Ref:"VPC"},SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:B,ToPort:B,SourceSecurityGroupId:{Ref:z},Description:"Allow traffic from ALB"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:`${$}-${J}-ecs-sg`},{Key:"Environment",Value:J}]}});let j=`${$}${J}TaskExecRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(j,{Type:"AWS::IAM::Role",Properties:{RoleName:`${$}-${J}-ecs-exec-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"],Policies:[{PolicyName:"ECRPullPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["ecr:GetAuthorizationToken","ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","logs:CreateLogStream","logs:PutLogEvents"],Resource:"*"}]}}]}});let O=`${$}${J}TaskRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(O,{Type:"AWS::IAM::Role",Properties:{RoleName:`${$}-${J}-ecs-task-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"TaskPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogStream","logs:PutLogEvents"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:ListBucket"],Resource:"*"}]}}]}});let X=`${$}${J}${A}LogGroup`.replace(/[^a-zA-Z0-9]/g,""),_=`/ecs/${$}-${J}-${A}`;this.builder.addResource(X,{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:_,RetentionInDays:30}});let q=`${$}${J}${A}TaskDef`.replace(/[^a-zA-Z0-9]/g,""),E=String(K.cpu||512),M=String(K.memory||1024);this.builder.addResource(q,{Type:"AWS::ECS::TaskDefinition",Properties:{Family:`${$}-${J}-${A}`,NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:E,Memory:M,ExecutionRoleArn:{"Fn::GetAtt":[j,"Arn"]},TaskRoleArn:{"Fn::GetAtt":[O,"Arn"]},ContainerDefinitions:[{Name:A,Image:{"Fn::Sub":`\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.amazonaws.com/${$}:latest`},Essential:!0,PortMappings:[{ContainerPort:B,Protocol:"tcp"}],LogConfiguration:{LogDriver:"awslogs",Options:{"awslogs-group":_,"awslogs-region":{Ref:"AWS::Region"},"awslogs-stream-prefix":A}},HealthCheck:{Command:["CMD-SHELL",`curl -f http://localhost:${B}${K.healthCheck||"/health"} || exit 1`],Interval:30,Timeout:5,Retries:3,StartPeriod:60}}],Tags:[{Key:"Name",Value:`${$}-${J}-${A}`},{Key:"Environment",Value:J}]},DependsOn:[j,O,X]});let D=`${$}${J}ALB`.replace(/[^a-zA-Z0-9]/g,"");if(Q?.enabled!==!1){this.builder.addResource(D,{Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:`${$}-${J}-alb`,Scheme:"internet-facing",Type:"application",Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}],SecurityGroups:[{Ref:z}],Tags:[{Key:"Name",Value:`${$}-${J}-alb`},{Key:"Environment",Value:J}]}});let R=`${$}${J}TargetGroup`.replace(/[^a-zA-Z0-9]/g,""),T=Q?.healthCheck?.path||K.healthCheck||"/health";this.builder.addResource(R,{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:`${$}-${J}-tg`,Port:B,Protocol:"HTTP",VpcId:{Ref:"VPC"},TargetType:"ip",HealthCheckPath:T,HealthCheckIntervalSeconds:Q?.healthCheck?.interval||30,HealthyThresholdCount:Q?.healthCheck?.healthyThreshold||2,UnhealthyThresholdCount:Q?.healthCheck?.unhealthyThreshold||5,HealthCheckTimeoutSeconds:10,Tags:[{Key:"Name",Value:`${$}-${J}-tg`},{Key:"Environment",Value:J}]}});let S=`${$}${J}HTTPListener`.replace(/[^a-zA-Z0-9]/g,"");if(Z?.enabled&&Z?.redirectHttp)this.builder.addResource(S,{Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:{Ref:D},Port:80,Protocol:"HTTP",DefaultActions:[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]}});else this.builder.addResource(S,{Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:{Ref:D},Port:80,Protocol:"HTTP",DefaultActions:[{Type:"forward",TargetGroupArn:{Ref:R}}]}});if(Z?.enabled){let I=Z.certificateArn||(G?{Ref:G}:void 0);if(I){let f=`${$}${J}HTTPSListener`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(f,{Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:{Ref:D},Port:443,Protocol:"HTTPS",Certificates:[{CertificateArn:I}],DefaultActions:[{Type:"forward",TargetGroupArn:{Ref:R}}],SslPolicy:"ELBSecurityPolicy-TLS13-1-2-2021-06"}})}}let C=`${$}${J}${A}Service`.replace(/[^a-zA-Z0-9]/g,""),x=K.desiredCount||1;this.builder.addResource(C,{Type:"AWS::ECS::Service",Properties:{ServiceName:`${$}-${J}-${A}`,Cluster:{Ref:U},TaskDefinition:{Ref:q},DesiredCount:x,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"ENABLED",SecurityGroups:[{Ref:H}],Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]}},LoadBalancers:[{ContainerName:A,ContainerPort:B,TargetGroupArn:{Ref:R}}],HealthCheckGracePeriodSeconds:120,Tags:[{Key:"Name",Value:`${$}-${J}-${A}`},{Key:"Environment",Value:J}]},DependsOn:[q,S,R]});let h=K.autoScaling;if(h){let I=`${$}${J}${A}ScalableTarget`.replace(/[^a-zA-Z0-9]/g,"");if(this.builder.addResource(I,{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{MaxCapacity:h.max||10,MinCapacity:h.min||1,ResourceId:{"Fn::Sub":`service/\${${U}}/${$}-${J}-${A}`},ScalableDimension:"ecs:service:DesiredCount",ServiceNamespace:"ecs",RoleARN:{"Fn::Sub":"arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"}},DependsOn:C}),h.targetCpuUtilization)this.builder.addResource(`${$}${J}${A}CPUScaling`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${$}-${J}-${A}-cpu-scaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:I},TargetTrackingScalingPolicyConfiguration:{PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageCPUUtilization"},TargetValue:h.targetCpuUtilization,ScaleInCooldown:300,ScaleOutCooldown:60}}});if(h.targetMemoryUtilization)this.builder.addResource(`${$}${J}${A}MemoryScaling`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${$}-${J}-${A}-memory-scaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:I},TargetTrackingScalingPolicyConfiguration:{PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageMemoryUtilization"},TargetValue:h.targetMemoryUtilization,ScaleInCooldown:300,ScaleOutCooldown:60}}})}if(W?.domain&&W?.hostedZoneId)this.builder.addResource(`${$}${J}ApiDnsRecord`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:W.hostedZoneId,Name:`api.${W.domain}`,Type:"A",AliasTarget:{DNSName:{"Fn::GetAtt":[D,"DNSName"]},HostedZoneId:{"Fn::GetAtt":[D,"CanonicalHostedZoneID"]}}}});this.builder.addOutput("ECSClusterArn",{Description:"ECS Cluster ARN",Value:{"Fn::GetAtt":[U,"Arn"]},Export:{Name:{"Fn::Sub":"${AWS::StackName}-ecs-cluster-arn"}}}),this.builder.addOutput("ECSServiceName",{Description:"ECS Service Name",Value:`${$}-${J}-${A}`,Export:{Name:{"Fn::Sub":"${AWS::StackName}-ecs-service-name"}}}),this.builder.addOutput("LoadBalancerDNS",{Description:"Application Load Balancer DNS Name",Value:{"Fn::GetAtt":[D,"DNSName"]},Export:{Name:{"Fn::Sub":"${AWS::StackName}-alb-dns"}}})}else{let R=`${$}${J}${A}Service`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(R,{Type:"AWS::ECS::Service",Properties:{ServiceName:`${$}-${J}-${A}`,Cluster:{Ref:U},TaskDefinition:{Ref:q},DesiredCount:K.desiredCount||1,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"ENABLED",SecurityGroups:[{Ref:H}],Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]}},Tags:[{Key:"Name",Value:`${$}-${J}-${A}`},{Key:"Environment",Value:J}]},DependsOn:[q]})}break}}generateServerless($,J){if(this.mergedConfig.infrastructure?.functions)for(let[Y,Q]of Object.entries(this.mergedConfig.infrastructure.functions)){if(!this.shouldDeploy(Q))continue;let{role:Z,logicalId:W}=s0.createRole({slug:$,environment:J,roleName:`${$}-${J}-${Y}-role`,servicePrincipal:"lambda.amazonaws.com",managedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]});this.builder.addResource(W,Z);let{lambdaFunction:G,logicalId:U}=l.createLambdaFunction({slug:$,environment:J,functionName:`${$}-${J}-${Y}`,handler:Q.handler||"index.handler",runtime:Q.runtime||"nodejs20.x",code:{zipFile:Q.code||"export const handler = async () => ({ statusCode: 200 });"},role:W,timeout:Q.timeout,memorySize:Q.memorySize});this.builder.addResource(U,G)}if(this.mergedConfig.infrastructure?.api){let{restApi:Y,logicalId:Q}=X8.createRestApi({slug:$,environment:J,apiName:`${$}-${J}-api`});this.builder.addResource(Q,Y)}}generateServer($,J){if(!this.mergedConfig.infrastructure?.servers)return;let Y=this.mergedConfig.infrastructure.servers,Q=this.mergedConfig.infrastructure?.compute,Z=this.mergedConfig.infrastructure?.ssl;if(Object.values(Y).some((G)=>!G.privateNetwork||G.privateNetwork==="create"))this.generateNetworkInfrastructure($,J);for(let[G,U]of Object.entries(Y)){let z=U.instanceType||U.size||Q?.size,A=(z?l.InstanceSize.specs[z]:void 0)?.instanceType||z||"t3.micro",K=U.type||"app",B=U.userData||U.startupScript;if(!B)B=l.UserData.generateAppServerScript({runtime:"bun",runtimeVersion:U.bunVersion||"latest",webServer:"none",domain:U.domain,enableSsl:!!Z?.enabled,sslEmail:Z?.letsEncrypt?.email,installRedis:K==="cache",installDatabaseClients:!!U.database});let j=U.privateNetwork&&U.privateNetwork!=="create"?U.privateNetwork:{Ref:"VPC"},O=U.subnet||{Ref:"PublicSubnet1"},_=!!this.mergedConfig.infrastructure?.email?.server?.enabled,q=[22,80,443,this.resolveApiOriginPort()];if(_)q.push(25,465,587,143,993);let E=l.createServerModeStack({slug:`${$}-${G}`,environment:J,vpcId:j,subnetId:O,instanceType:A,keyName:U.keyName||`${$}-${J}`,domain:U.domain,userData:B,volumeSize:U.diskSize||20,imageId:U.image,allowedPorts:q});for(let[M,D]of Object.entries(E.resources))this.builder.addResource(M,D);this.serverEipLogicalIds.set(G,E.outputs.eipLogicalId),this.serverEipLogicalIds.set(`${G}Instance`,E.outputs.instanceLogicalId),this.builder.addOutput(`${G}InstanceId`,{Value:{Ref:E.outputs.instanceLogicalId},Description:`Instance ID for ${G} server`}),this.builder.addOutput(`${G}PublicIp`,{Value:{Ref:E.outputs.eipLogicalId},Description:`Public IP for ${G} server`})}}generateComputeApp($,J){let Y=this.mergedConfig.infrastructure?.compute;if(!Y)return;let Q=this.mergedConfig.sites||{},Z=Object.entries(Q),G=this.mergedConfig.infrastructure?.dns?.domain,U=this.mergedConfig.infrastructure?.database,z=Y.size,A=(z?l.InstanceSize.specs[z]:void 0)?.instanceType||"t3.micro";if(!this.builder.hasResource("VPC"))this.generateNetworkInfrastructure($,J);let K=l.UserData.generateBunAppScript({runtime:Y.runtime||"bun",runtimeVersion:Y.runtimeVersion||"latest",systemPackages:Y.systemPackages,database:U}),B=Z.map(([,M])=>M.port).filter((M)=>typeof M==="number"&&![80,443].includes(M)),j=this.resolveApiOriginPort(),O=`${$}${J}DeployBucket`.replace(/[^a-zA-Z0-9]/g,""),X=`${$}-${J}-deploy`;this.builder.addResource(O,{Type:"AWS::S3::Bucket",Properties:{BucketName:X,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},LifecycleConfiguration:{Rules:[{Id:"expire-old-releases",Status:"Enabled",ExpirationInDays:7,Prefix:"releases/"}]},Tags:[{Key:"Project",Value:$},{Key:"Environment",Value:J},{Key:"ManagedBy",Value:"ts-cloud"}]}});let _=l.createServerModeStack({slug:`${$}-app`,environment:J,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},instanceType:A,keyName:`${$}-${J}`,domain:G,userData:K,volumeSize:Y.disk?.size||20,imageId:Y.image,allowedPorts:[...Y.allowSsh?[22]:[],80,443,j,...B]}),q=_.resources[_.outputs.instanceLogicalId];if(q?.Properties){let M=q.Properties.Tags||[];q.Properties.Tags=[...M,{Key:"Project",Value:$},{Key:"Environment",Value:J},{Key:"Role",Value:"app"},{Key:"ManagedBy",Value:"ts-cloud"}]}let E=_.resources[_.outputs.roleLogicalId];if(E?.Properties)E.Properties.Policies=E.Properties.Policies||[],E.Properties.Policies.push({PolicyName:"DeployBucketRead",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetObject","s3:ListBucket"],Resource:[`arn:aws:s3:::${X}`,`arn:aws:s3:::${X}/*`]}]}});for(let[M,D]of Object.entries(_.resources))this.builder.addResource(M,D);this.builder.addOutput("deployBucketName",{Value:{Ref:O},Description:"S3 bucket where release tarballs are uploaded"}),this.builder.addOutput("appInstanceId",{Value:{Ref:_.outputs.instanceLogicalId},Description:"EC2 instance ID for the app server"}),this.builder.addOutput("appPublicIp",{Value:{Ref:_.outputs.eipLogicalId},Description:"Public IP for the app server"}),this.serverEipLogicalIds.set("app",_.outputs.eipLogicalId),this.serverEipLogicalIds.set("appInstance",_.outputs.instanceLogicalId)}generateJumpBox($,J){let Y=this.mergedConfig.infrastructure?.jumpBox;if(!Y)return;let Q=Y===!0?{}:Y;if(Q.enabled===!1)return;this.generateNetworkInfrastructure($,J);let Z=Q.size||"micro",G=l.InstanceSize.specs[Z]?.instanceType||Z||"t3.micro",U;if(Q.mountEfs)U={fileSystemId:typeof Q.mountEfs==="string"?Q.mountEfs:{Ref:"FileSystem"},mountPath:Q.mountPath||"/mnt/efs"};let z;if(Q.databaseTools)z=l.JumpBox.withDatabaseTools({slug:$,environment:J,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},keyName:Q.keyName||`${$}-${J}`,allowedCidrs:Q.allowedCidrs});else if(U)z=l.JumpBox.withEfsMount({slug:$,environment:J,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},keyName:Q.keyName||`${$}-${J}`,fileSystemId:U.fileSystemId,mountPath:U.mountPath,allowedCidrs:Q.allowedCidrs});else z=l.createJumpBox({slug:$,environment:J,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},keyName:Q.keyName||`${$}-${J}`,instanceType:G,allowedCidrs:Q.allowedCidrs,mountEfs:U});for(let[H,A]of Object.entries(z.resources))this.builder.addResource(H,A);this.builder.addOutput("JumpBoxInstanceId",{Value:{Ref:z.instanceLogicalId},Description:"The ID of the JumpBox EC2 instance (use with SSM Session Manager or SSH)"})}generateSharedInfrastructure($,J){let Y=this.mergedConfig.infrastructure?.ssl,Q=this.mergedConfig.infrastructure?.dns,Z=Q?.domain,W=Q?.hostedZoneId,G=[],U,z;if(Y?.certificateArn)z=Y.certificateArn;else if(Y?.enabled&&Z&&W){let X=Y.domains||[Z],_=X[0],q=X.slice(1).map((D)=>{if(D.includes(".")&&D.endsWith(_))return D.replace(`.${_}`,"");return D}),{certificate:E,logicalId:M}=L0.createCertificate({domain:_,subdomains:q,slug:$,environment:J,validationMethod:"DNS",hostedZoneId:W});U=M,this.builder.addResource(M,E)}if(this.mergedConfig.infrastructure?.storage){let X=Object.entries(this.mergedConfig.infrastructure.storage).some(([,E])=>E.website),_;if(X&&(U||z))_=`${$}${J}CloudFrontOAC`.replace(/[^a-zA-Z0-9]/g,""),this.builder.addResource(_,{Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${$}-${J}-s3-oac`,Description:`OAC for ${$} ${J} S3 website buckets`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}});let q=Object.entries(this.mergedConfig.infrastructure.storage).map(([E,M])=>({name:E,config:M,mountPath:this.normalizeMountPath(M),logicalId:this.storageBucketLogicalId($,J,E)})).filter((E)=>E.name!=="public"&&E.config.website&&E.mountPath);for(let[E,M]of Object.entries(this.mergedConfig.infrastructure.storage)){let D=!!(M.website&&_),{bucket:R,logicalId:T}=U1.createBucket({slug:$,name:E,environment:J,bucketName:`${$}-${J}-${E}`,versioning:M.versioning,encryption:M.encryption,public:D?!1:M.public});if(D&&R.Properties)R.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,IgnorePublicAcls:!0,BlockPublicPolicy:!1,RestrictPublicBuckets:!1};if(this.builder.addResource(T,R),M.website){let C=typeof M.website==="object"?M.website:{},x=U1.enableWebsiteHosting(R,C.indexDocument||"index.html",C.errorDocument);this.builder.addResource(T,x)}let S=this.normalizeMountPath(M);if(D&&_&&Z&&!(S&&E!=="public")){let C=`${$}${J}${E}CDN`.replace(/[^a-zA-Z0-9]/g,""),x=[];if(M.aliases&&M.aliases.length>0)x.push(...M.aliases);else if(E==="public"){if(x.push(Z),Y?.domains?.includes(`www.${Z}`))x.push(`www.${Z}`)}else if(E==="docs")x.push(`docs.${Z}`);else if(E==="blog")x.push(`blog.${Z}`);let h=typeof M.website==="object"?M.website:{},I=M.spa===!0,f=h.errorDocument||(I?"index.html":"404.html"),d=[];if(I)d.push({ErrorCode:403,ResponseCode:200,ResponsePagePath:"/index.html",ErrorCachingMinTTL:300},{ErrorCode:404,ResponseCode:200,ResponsePagePath:"/index.html",ErrorCachingMinTTL:300});else d.push({ErrorCode:403,ResponseCode:404,ResponsePagePath:`/${f}`,ErrorCachingMinTTL:300},{ErrorCode:404,ResponseCode:404,ResponsePagePath:`/${f}`,ErrorCachingMinTTL:300});let r=z&&x.length>0?{AcmCertificateArn:z,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}:U&&x.length>0?{AcmCertificateArn:{Ref:U},SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}:{CloudFrontDefaultCertificate:!0},c=`S3-${$}-${J}-${E}`,n=this.mergedConfig.project.region||"us-east-1",s;if(!I)s=`${$}${J}${E}UrlRewrite`.replace(/[^a-zA-Z0-9]/g,""),this.builder.addResource(s,{Type:"AWS::CloudFront::Function",Properties:{Name:`${$}-${J}-${E}-url-rewrite`,AutoPublish:!0,FunctionConfig:{Comment:`URL rewrite for ${$} ${J} ${E} - appends .html to extensionless paths`,Runtime:"cloudfront-js-2.0"},FunctionCode:`function handler(event) { var request = event.request; var uri = request.uri; if (uri.endsWith('/')) { request.uri += 'index.html'; }
|
|
5379
|
-
else if (!uri.includes('.')) { request.uri += '.html'; } return request; }`}});let J0=[{Id:c,DomainName:{"Fn::Sub":`\${${T}}.s3.${n}.amazonaws.com`},OriginPath:"",S3OriginConfig:{OriginAccessIdentity:""},OriginAccessControlId:{Ref:_}}],_0=[],l0=[];if(E==="public"){let f0=this.serverEipLogicalIds.get("app"),s1=this.serverEipLogicalIds.get("appInstance");if(f0){let D0=`EC2-${$}-${J}-api`,f1=this.mergedConfig.infrastructure?.servers?.app?.region||this.mergedConfig.project?.region||"us-east-1",g1=f1==="us-east-1"?".compute-1.amazonaws.com":`.${f1}.compute.amazonaws.com`,V2={"Fn::Join":["",["ec2-",{"Fn::Join":["-",{"Fn::Split":[".",{Ref:f0}]}]},g1]]},e$=this.resolveApiOriginPort();if(J0.push({Id:D0,DomainName:V2,CustomOriginConfig:{HTTPPort:e$,HTTPSPort:443,OriginProtocolPolicy:"http-only",OriginSSLProtocols:["TLSv1.2"]}}),l0.push(f0),s1)l0.push(s1);_0.push({PathPattern:"/api/*",TargetOriginId:D0,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD"],Compress:!0,CachePolicyId:"4135ea2d-6df8-44a3-9df3-4b5a84be39ad",OriginRequestPolicyId:"b689b0a8-53d0-40ab-baf2-68738e2966ac"})}for(let D0 of q){let f1=`S3-${$}-${J}-${D0.name}`,g1=`${$}${J}${D0.name}PathMountRewrite`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(g1,{Type:"AWS::CloudFront::Function",Properties:{Name:`${$}-${J}-${D0.name}-path-mount-rewrite`,AutoPublish:!0,FunctionConfig:{Comment:`Path mount rewrite for ${$} ${J} ${D0.name} at ${D0.mountPath}`,Runtime:"cloudfront-js-2.0"},FunctionCode:this.pathMountRewriteFunctionCode(D0.mountPath)}}),J0.push({Id:f1,DomainName:{"Fn::Sub":`\${${D0.logicalId}}.s3.${n}.amazonaws.com`},OriginPath:"",S3OriginConfig:{OriginAccessIdentity:""},OriginAccessControlId:{Ref:_}}),l0.push(D0.logicalId,g1);for(let V2 of[D0.mountPath,`${D0.mountPath}/*`])_0.push({PathPattern:V2,TargetOriginId:f1,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6",FunctionAssociations:[{EventType:"viewer-request",FunctionARN:{"Fn::GetAtt":[g1,"FunctionARN"]}}]})}}let I0={Type:"AWS::CloudFront::Distribution",DependsOn:[T,_,...s?[s]:[],...l0],Properties:{DistributionConfig:{Enabled:!0,Comment:`${$} ${J} ${E} site`,DefaultRootObject:"index.html",Origins:J0,DefaultCacheBehavior:{TargetOriginId:c,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6",...s?{FunctionAssociations:[{EventType:"viewer-request",FunctionARN:{"Fn::GetAtt":[s,"FunctionARN"]}}]}:{}},..._0.length>0?{CacheBehaviors:_0}:{},...x.length>0?{Aliases:x}:{},ViewerCertificate:r,PriceClass:"PriceClass_100",HttpVersion:"http2and3",IPV6Enabled:!0,CustomErrorResponses:d}}};if(U)I0.DependsOn.push(U);this.builder.addResource(C,I0);let t1=`${T}CloudFrontPolicy`;if(this.builder.addResource(t1,{Type:"AWS::S3::BucketPolicy",DependsOn:[T,C],Properties:{Bucket:{Ref:T},PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontServicePrincipal",Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:{"Fn::Sub":`arn:aws:s3:::\${${T}}/*`},Condition:{StringEquals:{"AWS:SourceArn":{"Fn::Sub":`arn:aws:cloudfront::\${AWS::AccountId}:distribution/\${${C}}`}}}}]}}}),E==="public")for(let f0 of q){let s1=`${f0.logicalId}CloudFrontPolicy`;this.builder.addResource(s1,{Type:"AWS::S3::BucketPolicy",DependsOn:[f0.logicalId,C],Properties:{Bucket:{Ref:f0.logicalId},PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontServicePrincipal",Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:{"Fn::Sub":`arn:aws:s3:::\${${f0.logicalId}}/*`},Condition:{StringEquals:{"AWS:SourceArn":{"Fn::Sub":`arn:aws:cloudfront::\${AWS::AccountId}:distribution/\${${C}}`}}}}]}}})}if(x.length>0)G.push({name:E,bucketLogicalId:T,distLogicalId:C,oacLogicalId:_,aliases:x});this.builder.addOutput(`${E}CloudFrontDomain`,{Value:{"Fn::GetAtt":[C,"DomainName"]},Description:`CloudFront domain for ${E}`}),this.builder.addOutput(`${E}CloudFrontDistributionId`,{Value:{Ref:C},Description:`CloudFront distribution ID for ${E}`})}if(this.builder.addOutput(`${E}BucketName`,{Value:{Ref:T},Description:`S3 bucket name for ${E}`}),E==="public")this.builder.addOutput("FrontendBucketName",{Value:{Ref:T},Description:"Frontend S3 bucket name"});if(E==="docs")this.builder.addOutput("DocsBucketName",{Value:{Ref:T},Description:"Documentation S3 bucket name"});if(E==="blog")this.builder.addOutput("BlogBucketName",{Value:{Ref:T},Description:"Blog S3 bucket name"})}}if(W&&G.length>0)for(let{name:X,distLogicalId:_,aliases:q}of G)for(let E of q){let M=E.replace(/\./g,"").replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(`${M}ARecord`,{Type:"AWS::Route53::RecordSet",DependsOn:[_],Properties:{HostedZoneId:W,Name:E,Type:"A",AliasTarget:{DNSName:{"Fn::GetAtt":[_,"DomainName"]},HostedZoneId:"Z2FDTNDATAQYW2",EvaluateTargetHealth:!1}}}),this.builder.addResource(`${M}AAAARecord`,{Type:"AWS::Route53::RecordSet",DependsOn:[_],Properties:{HostedZoneId:W,Name:E,Type:"AAAA",AliasTarget:{DNSName:{"Fn::GetAtt":[_,"DomainName"]},HostedZoneId:"Z2FDTNDATAQYW2",EvaluateTargetHealth:!1}}})}if(this.mergedConfig.infrastructure?.databases){for(let[X,_]of Object.entries(this.mergedConfig.infrastructure.databases))if(_.engine==="dynamodb"){let{table:q,logicalId:E}=n1.createTable({slug:$,environment:J,tableName:`${$}-${J}-${X}`,partitionKey:_.partitionKey||{name:"id",type:"S"},sortKey:_.sortKey});this.builder.addResource(E,q)}else if(_.engine==="postgres"){let{dbInstance:q,logicalId:E}=n1.createPostgres({slug:$,environment:J,dbInstanceIdentifier:`${$}-${J}-${X}`,masterUsername:_.username||"admin",masterUserPassword:_.password||"changeme123",allocatedStorage:_.storage||20,dbInstanceClass:_.instanceClass||"db.t3.micro"});this.builder.addResource(E,q)}else if(_.engine==="mysql"){let{dbInstance:q,logicalId:E}=n1.createMysql({slug:$,environment:J,dbInstanceIdentifier:`${$}-${J}-${X}`,masterUsername:_.username||"admin",masterUserPassword:_.password||"changeme123",allocatedStorage:_.storage||20,dbInstanceClass:_.instanceClass||"db.t3.micro"});this.builder.addResource(E,q)}}if(this.mergedConfig.infrastructure?.cdn)for(let[X,_]of Object.entries(this.mergedConfig.infrastructure.cdn)){let{distribution:q,logicalId:E}=t0.createDistribution({slug:$,environment:J,origin:{domainName:_.origin,originId:`${$}-origin`}});this.builder.addResource(E,q)}if(this.mergedConfig.infrastructure?.queues)for(let[X,_]of Object.entries(this.mergedConfig.infrastructure.queues)){if(!this.shouldDeploy(_))continue;let{queue:q,logicalId:E}=m0.createQueue({slug:$,environment:J,name:`${$}-${J}-${X}`,fifo:_.fifo,visibilityTimeout:_.visibilityTimeout,messageRetentionPeriod:_.messageRetentionPeriod,delaySeconds:_.delaySeconds,maxMessageSize:_.maxMessageSize,receiveMessageWaitTime:_.receiveMessageWaitTime,contentBasedDeduplication:_.contentBasedDeduplication,encrypted:_.encrypted,kmsKeyId:_.kmsKeyId});this.builder.addResource(E,q);let M;if(_.deadLetterQueue){let{deadLetterQueue:D,updatedSourceQueue:R,deadLetterLogicalId:T}=m0.createDeadLetterQueue(E,{slug:$,environment:J,maxReceiveCount:_.maxReceiveCount});M=T,this.builder.addResource(T,D);let C=this.builder.getResources()[E];if(C?.Properties)C.Properties.RedrivePolicy=R.Properties?.RedrivePolicy}if(_.trigger){let D=_.trigger,R=`${$}${J}${D.functionName}`.replace(/[^a-zA-Z0-9]/g,""),T={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:{"Fn::GetAtt":[E,"Arn"]},FunctionName:{Ref:R},BatchSize:D.batchSize||10,MaximumBatchingWindowInSeconds:D.batchWindow||0,Enabled:!0,...D.reportBatchItemFailures!==!1&&{FunctionResponseTypes:["ReportBatchItemFailures"]},...D.maxConcurrency&&{ScalingConfig:{MaximumConcurrency:D.maxConcurrency}},...D.filterPattern&&{FilterCriteria:{Filters:[{Pattern:JSON.stringify(D.filterPattern)}]}}},DependsOn:[E,R]};this.builder.addResource(`${E}Trigger`,T)}if(_.alarms?.enabled){let D=_.alarms,R=D.notificationTopicArn;if(!R&&D.notificationEmails?.length){let C=`${E}AlarmTopic`;this.builder.addResource(C,{Type:"AWS::SNS::Topic",Properties:{TopicName:`${$}-${J}-${X}-alarms`,DisplayName:`${X} Queue Alarms`}}),D.notificationEmails.forEach((x,h)=>{this.builder.addResource(`${C}Sub${h}`,{Type:"AWS::SNS::Subscription",Properties:{TopicArn:{Ref:C},Protocol:"email",Endpoint:x}})}),R={Ref:C}}let T=D.queueDepthThreshold||1000;this.builder.addResource(`${E}DepthAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$}-${J}-${X}-queue-depth`,AlarmDescription:`Queue ${X} depth exceeds ${T} messages`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:2,Threshold:T,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:{"Fn::GetAtt":[E,"QueueName"]}}],...R&&{AlarmActions:[R],OKActions:[R]}}});let S=D.messageAgeThreshold||3600;if(this.builder.addResource(`${E}AgeAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$}-${J}-${X}-message-age`,AlarmDescription:`Queue ${X} oldest message exceeds ${S} seconds`,MetricName:"ApproximateAgeOfOldestMessage",Namespace:"AWS/SQS",Statistic:"Maximum",Period:300,EvaluationPeriods:2,Threshold:S,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:{"Fn::GetAtt":[E,"QueueName"]}}],...R&&{AlarmActions:[R],OKActions:[R]}}}),M&&D.dlqAlarm!==!1)this.builder.addResource(`${M}Alarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$}-${J}-${X}-dlq-messages`,AlarmDescription:`Dead letter queue for ${X} has messages`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:1,Threshold:0,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:{"Fn::GetAtt":[M,"QueueName"]}}],...R&&{AlarmActions:[R]}}})}if(_.subscribe){let D=_.subscribe,R=D.topicArn;if(!R&&D.topicName)R={Ref:D.topicName};if(R){this.builder.addResource(`${E}SnsPolicy`,{Type:"AWS::SQS::QueuePolicy",Properties:{Queues:[{Ref:E}],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"sns.amazonaws.com"},Action:"sqs:SendMessage",Resource:{"Fn::GetAtt":[E,"Arn"]},Condition:{ArnEquals:{"aws:SourceArn":R}}}]}}});let T={TopicArn:R,Protocol:"sqs",Endpoint:{"Fn::GetAtt":[E,"Arn"]},RawMessageDelivery:D.rawMessageDelivery||!1};if(D.filterPolicy)T.FilterPolicy=D.filterPolicy,T.FilterPolicyScope=D.filterPolicyScope||"MessageAttributes";this.builder.addResource(`${E}SnsSub`,{Type:"AWS::SNS::Subscription",Properties:T,DependsOn:`${E}SnsPolicy`})}}}if(this.mergedConfig.infrastructure?.realtime?.enabled)if((this.mergedConfig.infrastructure.realtime.mode||"serverless")==="server")this.generateRealtimeServerResources($,J);else this.generateRealtimeResources($,J);let H=this.mergedConfig.infrastructure?.redirects;if(H){let X=H.target||this.mergedConfig.infrastructure?.dns?.domain||"",_=H.protocol||"https";if(H.domains?.length&&X)for(let q of H.domains){let{bucket:E,bucketPolicy:M,logicalId:D,policyLogicalId:R}=h1.createDomainRedirectBucket({slug:$,environment:J,sourceDomain:q,targetDomain:X,protocol:_});this.builder.addResource(D,E),this.builder.addResource(R,M)}if(H.paths&&Object.keys(H.paths).length>0){let q=h1.fromMapping(H.paths,{statusCode:H.statusCode||301}),{function:E,logicalId:M}=h1.createPathRedirectFunction({slug:$,environment:J,rules:q});this.builder.addResource(M,E)}}if(this.mergedConfig.infrastructure?.monitoring?.alarms)for(let[X,_]of Object.entries(this.mergedConfig.infrastructure.monitoring.alarms)){let{alarm:q,logicalId:E}=c$.createAlarm({slug:$,environment:J,alarmName:`${$}-${J}-${X}`,metricName:_.metricName||"Errors",namespace:_.namespace||"AWS/Lambda",threshold:_.threshold||1,comparisonOperator:_.comparisonOperator||"GreaterThanThreshold"});this.builder.addResource(E,q)}let A=this.mergedConfig.infrastructure?.cache;if(A){let X=A.type||"redis";if(X==="redis"){this.generateNetworkInfrastructure($,J);let _=A.redis||{},{replicationGroup:q,subnetGroup:E,logicalId:M,subnetGroupId:D}=m$.createRedis({slug:$,environment:J,nodeType:_.nodeType||A.nodeType||"cache.t3.micro",engineVersion:_.engineVersion||"7.1",port:_.port||6379,numCacheClusters:_.numCacheNodes||2,automaticFailover:_.automaticFailoverEnabled!==!1,atRestEncryption:!0,transitEncryption:!0,snapshotRetentionDays:_.snapshotRetentionLimit||7,snapshotWindow:_.snapshotWindow,subnetIds:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]});if(this.builder.addResource(M,q),E&&D)this.builder.addResource(D,E);this.builder.addOutput("CacheEndpoint",{Value:{"Fn::GetAtt":[M,"PrimaryEndPoint.Address"]},Description:"Redis primary endpoint address"}),this.builder.addOutput("CachePort",{Value:{"Fn::GetAtt":[M,"PrimaryEndPoint.Port"]},Description:"Redis primary endpoint port"})}else if(X==="memcached"){this.generateNetworkInfrastructure($,J);let _=A.elasticache||{},{cluster:q,subnetGroup:E,logicalId:M,subnetGroupId:D}=m$.createMemcached({slug:$,environment:J,nodeType:_.nodeType||A.nodeType||"cache.t3.micro",engineVersion:_.engineVersion||"1.6.22",numCacheNodes:_.numCacheNodes||2,subnetIds:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]});if(this.builder.addResource(M,q),E&&D)this.builder.addResource(D,E);this.builder.addOutput("CacheEndpoint",{Value:{"Fn::GetAtt":[M,"ConfigurationEndpoint.Address"]},Description:"Memcached configuration endpoint address"})}}let K=this.mergedConfig.infrastructure?.email;if(K){let X=K.domain||this.mergedConfig.infrastructure?.dns?.domain;if(X){let{emailIdentity:_,logicalId:q}=z0.verifyDomain({domain:X,slug:$,environment:J,enableDkim:K.enableDkim!==!1,dkimKeyLength:K.dkimKeyLength||"RSA_2048_BIT"});if(this.builder.addResource(q,_),K.configurationSet!==!1){let{configurationSet:D,logicalId:R}=z0.createConfigurationSet({slug:$,environment:J});this.builder.addResource(R,D)}let E=K.hostedZoneId||this.mergedConfig.infrastructure?.dns?.hostedZoneId;if(E){if(K.enableDkim!==!1)for(let C=1;C<=3;C++){let x=`DkimRecord${C}${X.replace(/\./g,"")}`;this.builder.addResource(x,{Type:"AWS::Route53::RecordSet",DependsOn:[q],Properties:{HostedZoneId:E,Name:{"Fn::GetAtt":[q,`DkimDNSTokenName${C}`]},Type:"CNAME",TTL:1800,ResourceRecords:[{"Fn::GetAtt":[q,`DkimDNSTokenValue${C}`]}]}})}let{record:D,logicalId:R}=z0.createSpfRecord(X,E);this.builder.addResource(R,D);let{record:T,logicalId:S}=z0.createDmarcRecord(X,E,{policy:"none",reportingEmail:K.dmarcReportingEmail||`dmarc-reports@${X}`});this.builder.addResource(S,T)}this.builder.addOutput("EmailDomain",{Value:X,Description:"SES verified email domain"});let M=K.server;if(M?.enabled&&E){let D=this.mergedConfig.environments[J]?.region||this.mergedConfig.project.region||"us-east-1",R=`${$}-${J}-email`,{role:T,policy:S,roleLogicalId:C,policyLogicalId:x}=z0.createEmailLambdaRole({slug:$,environment:J,s3BucketArn:`arn:aws:s3:::${R}`,sesIdentityArn:`arn:aws:ses:${D}:*:identity/${X}`});this.builder.addResource(C,T),this.builder.addResource(x,S);let{function:h,permission:I,logicalId:f,permissionLogicalId:d}=z0.createInboundEmailLambda({slug:$,environment:J,roleArn:{"Fn::GetAtt":[C,"Arn"]},s3BucketName:R,organizedPrefix:"mailboxes/"});this.builder.addResource(f,h),this.builder.addResource(d,I);let r=z0.createInboundEmailSetup({slug:$,environment:J,domain:X,s3BucketName:R,s3KeyPrefix:"inbox/",region:D,hostedZoneId:E,lambdaFunctionArn:{"Fn::GetAtt":[f,"Arn"]}});for(let[n,s]of Object.entries(r.resources)){if(s.Type==="AWS::SES::ReceiptRule")s.DependsOn=[d,f];this.builder.addResource(n,s)}this.builder.addOutput("InboundEmailLambda",{Value:{Ref:f},Description:"Inbound email processing Lambda function"}),this.builder.addOutput("EmailBucket",{Value:R,Description:"S3 bucket for email storage"});let c=this.serverEipLogicalIds.get("app");if(c&&E){let s=`${M?.subdomain||"mail"}.${X}`,J0=s.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(`${J0}ARecord`,{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:E,Name:s,Type:"A",TTL:"300",ResourceRecords:[{Ref:c}]}})}this.builder.addOutput("MailHost",{Value:`mail.${X}`,Description:"Mail server hostname for SMTP/IMAP clients"})}}}let B=this.mergedConfig.infrastructure?.search;if(B){let X=B.vpc?{subnetIds:[{Ref:"PublicSubnet1"}],securityGroupIds:[]}:void 0;if(X)this.generateNetworkInfrastructure($,J);let{domain:_,logicalId:q}=r1.createDomain({slug:$,environment:J,engineVersion:B.engineVersion||"OpenSearch_2.11",instanceType:B.instanceType||"t3.small.search",instanceCount:B.instanceCount||1,volumeSize:B.volumeSize||10,volumeType:B.volumeType||"gp3",dedicatedMaster:B.dedicatedMaster||!1,dedicatedMasterType:B.dedicatedMasterType,dedicatedMasterCount:B.dedicatedMasterCount||3,multiAz:B.multiAz||!1,encryption:B.encryption||{atRest:!0,nodeToNode:!0},advancedSecurity:B.advancedSecurity,autoTune:B.autoTune!==!1,vpc:X});this.builder.addResource(q,_),this.builder.addOutput("SearchDomainEndpoint",{Value:{"Fn::GetAtt":[q,"DomainEndpoint"]},Description:"OpenSearch domain endpoint"}),this.builder.addOutput("SearchDomainArn",{Value:{"Fn::GetAtt":[q,"Arn"]},Description:"OpenSearch domain ARN"})}let j=this.mergedConfig.infrastructure?.fileSystem;if(j&&Object.keys(j).length>0){this.generateNetworkInfrastructure($,J);for(let[X,_]of Object.entries(j)){let{fileSystem:q,logicalId:E}=V1.createFileSystem({slug:`${$}-${X}`,environment:J,encrypted:_.encrypted!==!1,performanceMode:_.performanceMode||"generalPurpose",throughputMode:_.throughputMode||"bursting",enableBackup:!0});this.builder.addResource(E,q);let{securityGroup:M,logicalId:D}=V1.createEfsSecurityGroup({slug:`${$}-${X}`,environment:J,vpcId:{Ref:"VPC"},sourceCidrBlocks:["10.0.0.0/16"]});this.builder.addResource(D,M);let{mountTargets:R,logicalIds:T}=V1.createMultiAzMountTargets(E,{slug:`${$}-${X}`,environment:J,subnetIds:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}],securityGroupId:{Ref:D}});for(let S=0;S<R.length;S++)this.builder.addResource(T[S],R[S]);this.builder.addOutput(`${X}FileSystemId`,{Value:{Ref:E},Description:`EFS file system ID for ${X}`})}}let O=this.mergedConfig.infrastructure?.ai;if(O){let X=O.service||"ecs",_=O.models||["*"],q=O.allowStreaming!==!1,E;if(X==="ecs")E=z1.enableBedrockForEcs({slug:$,environment:J,models:_,allowStreaming:q});else if(X==="ec2")E=z1.enableBedrockForEc2({slug:$,environment:J,models:_,allowStreaming:q});else if(X==="lambda")E=z1.enableBedrockForLambda({slug:$,environment:J,models:_,allowStreaming:q});else E=z1.createBedrockRole(X,{slug:$,environment:J,models:_,allowStreaming:q});if(this.builder.addResource(E.logicalId,E.role),O.allowAsync){let{policy:M,logicalId:D}=z1.createBedrockPolicy({slug:$,environment:J,models:_,allowStreaming:q,allowAsync:!0});this.builder.addResource(D,M)}this.builder.addOutput("BedrockRoleArn",{Value:{"Fn::GetAtt":[E.logicalId,"Arn"]},Description:"IAM role ARN with Bedrock permissions"})}}generateRealtimeResources($,J){let Y=this.mergedConfig.infrastructure?.realtime;if(!Y)return;let Q=Y.name||`${$}-${J}-realtime`,Z=Y.scaling||{},W=Y.storage||{type:"dynamodb"},G=Z.handlerMemory||256,U=Z.handlerTimeout||30,z=`${$}${J}RealtimeConnections`.replace(/[^a-zA-Z0-9]/g,""),H=`${$}${J}RealtimeChannels`.replace(/[^a-zA-Z0-9]/g,"");if(W.type==="dynamodb"){let T=W.dynamodb||{},S=T.billingMode||"PAY_PER_REQUEST";this.builder.addResource(z,{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${$}-${J}-realtime-connections`,BillingMode:S,AttributeDefinitions:[{AttributeName:"connectionId",AttributeType:"S"},{AttributeName:"userId",AttributeType:"S"}],KeySchema:[{AttributeName:"connectionId",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"userId-index",KeySchema:[{AttributeName:"userId",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"},...S==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:T.readCapacity||5,WriteCapacityUnits:T.writeCapacity||5}}}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0},...S==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:T.readCapacity||5,WriteCapacityUnits:T.writeCapacity||5}},...T.pointInTimeRecovery&&{PointInTimeRecoverySpecification:{PointInTimeRecoveryEnabled:!0}},Tags:[{Key:"Name",Value:`${$}-${J}-realtime-connections`},{Key:"Environment",Value:J}]}}),this.builder.addResource(H,{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${$}-${J}-realtime-channels`,BillingMode:S,AttributeDefinitions:[{AttributeName:"channel",AttributeType:"S"},{AttributeName:"connectionId",AttributeType:"S"}],KeySchema:[{AttributeName:"channel",KeyType:"HASH"},{AttributeName:"connectionId",KeyType:"RANGE"}],GlobalSecondaryIndexes:[{IndexName:"connectionId-index",KeySchema:[{AttributeName:"connectionId",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"},...S==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:T.readCapacity||5,WriteCapacityUnits:T.writeCapacity||5}}}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0},...S==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:T.readCapacity||5,WriteCapacityUnits:T.writeCapacity||5}},Tags:[{Key:"Name",Value:`${$}-${J}-realtime-channels`},{Key:"Environment",Value:J}]}})}let A=`${$}${J}RealtimeRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(A,{Type:"AWS::IAM::Role",Properties:{RoleName:`${$}-${J}-realtime-handler-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"RealtimeHandlerPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:UpdateItem"],Resource:[{"Fn::GetAtt":[z,"Arn"]},{"Fn::Sub":`\${${z}.Arn}/index/*`},{"Fn::GetAtt":[H,"Arn"]},{"Fn::Sub":`\${${H}.Arn}/index/*`}]},{Effect:"Allow",Action:"execute-api:ManageConnections",Resource:{"Fn::Sub":"arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:*/*"}}]}}]}});let K=`${$}${J}RealtimeConnect`.replace(/[^a-zA-Z0-9]/g,""),B=`${$}${J}RealtimeDisconnect`.replace(/[^a-zA-Z0-9]/g,""),j=`${$}${J}RealtimeMessage`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(K,{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${$}-${J}-realtime-connect`,Runtime:"nodejs20.x",Handler:"index.handler",Role:{"Fn::GetAtt":[A,"Arn"]},MemorySize:G,Timeout:U,Environment:{Variables:{CONNECTIONS_TABLE:{Ref:z},CHANNELS_TABLE:{Ref:H},ENVIRONMENT:J}},Code:{ZipFile:this.generateConnectHandlerCode()}},DependsOn:[A,z]}),this.builder.addResource(B,{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${$}-${J}-realtime-disconnect`,Runtime:"nodejs20.x",Handler:"index.handler",Role:{"Fn::GetAtt":[A,"Arn"]},MemorySize:G,Timeout:U,Environment:{Variables:{CONNECTIONS_TABLE:{Ref:z},CHANNELS_TABLE:{Ref:H},ENVIRONMENT:J}},Code:{ZipFile:this.generateDisconnectHandlerCode()}},DependsOn:[A,z,H]}),this.builder.addResource(j,{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${$}-${J}-realtime-message`,Runtime:"nodejs20.x",Handler:"index.handler",Role:{"Fn::GetAtt":[A,"Arn"]},MemorySize:G,Timeout:U,Environment:{Variables:{CONNECTIONS_TABLE:{Ref:z},CHANNELS_TABLE:{Ref:H},ENVIRONMENT:J}},Code:{ZipFile:this.generateMessageHandlerCode()}},DependsOn:[A,z,H]});let O=`${$}${J}RealtimeApi`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(O,{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:Q,ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action",Tags:{Name:Q,Environment:J}}});let X=`${K}Permission`,_=`${B}Permission`,q=`${j}Permission`;this.builder.addResource(X,{Type:"AWS::Lambda::Permission",Properties:{FunctionName:{Ref:K},Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:{"Fn::Sub":`arn:aws:execute-api:\${AWS::Region}:\${AWS::AccountId}:\${${O}}/*/$connect`}}}),this.builder.addResource(_,{Type:"AWS::Lambda::Permission",Properties:{FunctionName:{Ref:B},Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:{"Fn::Sub":`arn:aws:execute-api:\${AWS::Region}:\${AWS::AccountId}:\${${O}}/*/$disconnect`}}}),this.builder.addResource(q,{Type:"AWS::Lambda::Permission",Properties:{FunctionName:{Ref:j},Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:{"Fn::Sub":`arn:aws:execute-api:\${AWS::Region}:\${AWS::AccountId}:\${${O}}/*/$default`}}});let E=`${O}ConnectInteg`,M=`${O}DisconnectInteg`,D=`${O}MessageInteg`;this.builder.addResource(E,{Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:{Ref:O},IntegrationType:"AWS_PROXY",IntegrationUri:{"Fn::Sub":`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${K}.Arn}/invocations`}}}),this.builder.addResource(M,{Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:{Ref:O},IntegrationType:"AWS_PROXY",IntegrationUri:{"Fn::Sub":`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${B}.Arn}/invocations`}}}),this.builder.addResource(D,{Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:{Ref:O},IntegrationType:"AWS_PROXY",IntegrationUri:{"Fn::Sub":`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${j}.Arn}/invocations`}}}),this.builder.addResource(`${O}ConnectRoute`,{Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:{Ref:O},RouteKey:"$connect",AuthorizationType:"NONE",Target:{"Fn::Sub":`integrations/\${${E}}`}}}),this.builder.addResource(`${O}DisconnectRoute`,{Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:{Ref:O},RouteKey:"$disconnect",Target:{"Fn::Sub":`integrations/\${${M}}`}}}),this.builder.addResource(`${O}DefaultRoute`,{Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:{Ref:O},RouteKey:"$default",Target:{"Fn::Sub":`integrations/\${${D}}`}}});let R=`${O}Stage`;if(this.builder.addResource(R,{Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:{Ref:O},StageName:J,AutoDeploy:!0,DefaultRouteSettings:{ThrottlingBurstLimit:Z.messagesPerSecond||1000,ThrottlingRateLimit:Z.messagesPerSecond||1000}}}),Y.monitoring?.enabled){let T=Y.monitoring,S=T.notificationTopicArn;if(!S&&T.notificationEmails?.length){let C=`${O}AlarmTopic`;this.builder.addResource(C,{Type:"AWS::SNS::Topic",Properties:{TopicName:`${$}-${J}-realtime-alarms`,DisplayName:"Realtime WebSocket Alarms"}}),T.notificationEmails.forEach((x,h)=>{this.builder.addResource(`${C}Sub${h}`,{Type:"AWS::SNS::Subscription",Properties:{TopicArn:{Ref:C},Protocol:"email",Endpoint:x}})}),S={Ref:C}}if(T.connectionThreshold)this.builder.addResource(`${O}ConnectionAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$}-${J}-realtime-connections`,AlarmDescription:`WebSocket connections exceed ${T.connectionThreshold}`,MetricName:"ConnectCount",Namespace:"AWS/ApiGateway",Statistic:"Sum",Period:300,EvaluationPeriods:2,Threshold:T.connectionThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ApiId",Value:{Ref:O}}],...S&&{AlarmActions:[S]}}});if(T.errorThreshold)this.builder.addResource(`${O}ErrorAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$}-${J}-realtime-errors`,AlarmDescription:`WebSocket errors exceed ${T.errorThreshold}/min`,MetricName:"ExecutionError",Namespace:"AWS/ApiGateway",Statistic:"Sum",Period:60,EvaluationPeriods:3,Threshold:T.errorThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ApiId",Value:{Ref:O}}],...S&&{AlarmActions:[S]}}})}this.builder.addOutput(`${O}Endpoint`,{Description:"WebSocket API endpoint URL",Value:{"Fn::Sub":`wss://\${${O}}.execute-api.\${AWS::Region}.amazonaws.com/${J}`},Export:{Name:{"Fn::Sub":"${AWS::StackName}-realtime-endpoint"}}}),this.builder.addOutput(`${O}Id`,{Description:"WebSocket API ID",Value:{Ref:O},Export:{Name:{"Fn::Sub":"${AWS::StackName}-realtime-api-id"}}})}generateConnectHandlerCode(){return`
|
|
5378
|
+
`;static createAbTestsTable($){return{[`${$.slug}AbTestsTable`]:{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${$.slug}-ab-tests`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"id",AttributeType:"S"}],KeySchema:[{AttributeName:"id",KeyType:"HASH"}]}}}}static createAbTestManagerLambda($){return{[`${$.slug}AbTestManagerLambda`]:{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${$.slug}-ab-test-manager`,Runtime:"nodejs20.x",Handler:"index.handler",Role:$.roleArn,Timeout:30,MemorySize:256,Code:{ZipFile:I1.AbTestManagerCode},Environment:{Variables:{AB_TESTS_TABLE:$.abTestsTable}}}}}}static selectVariant($,J){let Q=I1.hashString(J+$.id)%100,Z=0;for(let W=0;W<$.variants.length;W++)if(Z+=$.trafficSplit[W],Q<Z)return $.variants[W];return $.variants[$.variants.length-1]}static determineWinner($){if($.variants.length===0)return null;let J=$.winningCriteria,Y=$.variants[0],Q=I1.getMetricValue(Y,J);for(let Z of $.variants.slice(1)){let W=I1.getMetricValue(Z,J);if(W>Q)Q=W,Y=Z}return Y}static calculateSignificance($,J,Y){let Q=$.stats.sent,Z=J.stats.sent;if(Q<30||Z<30)return 0;let W=I1.getMetricValue($,Y)/100,G=I1.getMetricValue(J,Y)/100,U=(W*Q+G*Z)/(Q+Z),z=Math.sqrt(U*(1-U)*(1/Q+1/Z));if(z===0)return 0;let H=Math.abs(W-G)/z;if(H>=2.576)return 99;if(H>=1.96)return 95;if(H>=1.645)return 90;if(H>=1.28)return 80;return Math.round(H*30)}static getMetricValue($,J){switch(J){case"delivery_rate":return $.stats.deliveryRate;case"click_rate":return $.stats.clickRate;case"reply_rate":return $.stats.replyRate;case"conversion_rate":return $.stats.conversionRate;default:return $.stats.deliveryRate}}static hashString($){let J=0;for(let Y=0;Y<$.length;Y++){let Q=$.charCodeAt(Y);J=(J<<5)-J+Q,J=J&J}return Math.abs(J)}}class gJ{queues=new Map;messageGroups=new Map;deduplicationConfigs=new Map;messages=new Map;queueCounter=0;groupCounter=0;deduplicationCounter=0;messageCounter=0;sequenceCounter=0;createFIFOQueue($){let J=`fifo-queue-${Date.now()}-${this.queueCounter++}`,Y=$.name.endsWith(".fifo")?$.name:`${$.name}.fifo`,{name:Q,...Z}=$,W={id:J,name:Y,queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${Y}`,...Z};return this.queues.set(J,W),this.createDeduplicationConfig({queueId:J,contentBasedDeduplication:$.contentBasedDeduplication,deduplicationInterval:300}),W}createHighThroughputFIFO($){return this.createFIFOQueue({name:$.name,contentBasedDeduplication:$.contentBasedDeduplication??!0,deduplicationScope:"messageGroup",fifoThroughputLimit:"perMessageGroupId",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createStandardFIFO($){return this.createFIFOQueue({name:$.name,contentBasedDeduplication:$.contentBasedDeduplication??!1,deduplicationScope:"queue",fifoThroughputLimit:"perQueue",messageRetentionPeriod:345600,visibilityTimeout:30,receiveMessageWaitTime:0})}createDeduplicationConfig($){let Y={id:`dedup-${Date.now()}-${this.deduplicationCounter++}`,deduplicationHashes:new Map,...$};return this.deduplicationConfigs.set($.queueId,Y),Y}sendMessage($){let J=this.queues.get($.queueId);if(!J)throw Error(`Queue not found: ${$.queueId}`);let Y=this.deduplicationConfigs.get($.queueId);if(Y){let G=$.messageDeduplicationId||(J.contentBasedDeduplication?this.generateHash($.messageBody):void 0);if(G&&this.isDuplicate(Y,G))return null;if(G)Y.deduplicationHashes.set(G,new Date)}let Q=`msg-${Date.now()}-${this.messageCounter++}`,Z=this.generateSequenceNumber(),W={id:Q,messageId:Q,messageGroupId:$.messageGroupId,messageDeduplicationId:$.messageDeduplicationId,body:$.messageBody,attributes:$.messageAttributes||{},sentTimestamp:new Date,sequenceNumber:Z};return this.messages.set(Q,W),this.updateMessageGroup($.queueId,$.messageGroupId),W}isDuplicate($,J){let Y=$.deduplicationHashes.get(J);if(!Y)return!1;if((Date.now()-Y.getTime())/1000>$.deduplicationInterval)return $.deduplicationHashes.delete(J),!1;return!0}generateHash($){let J=0;for(let Y=0;Y<$.length;Y++){let Q=$.charCodeAt(Y);J=(J<<5)-J+Q,J=J&J}return Math.abs(J).toString(36)}generateSequenceNumber(){return`${Date.now()}${this.sequenceCounter++}`.padStart(20,"0")}updateMessageGroup($,J){let Y=`${$}-${J}`,Q=this.messageGroups.get(Y);if(!Q)Q={id:`group-${Date.now()}-${this.groupCounter++}`,messageGroupId:J,queueId:$,messagesInFlight:0},this.messageGroups.set(Y,Q);Q.messagesInFlight++,Q.lastMessageTimestamp=new Date}getMessageGroups($){return Array.from(this.messageGroups.values()).filter((J)=>J.queueId===$)}getQueue($){return this.queues.get($)}listQueues(){return Array.from(this.queues.values())}getMessages($,J){let Y=Array.from(this.messages.values());if(J)Y=Y.filter((Q)=>Q.messageGroupId===J);return Y.sort((Q,Z)=>Q.sequenceNumber.localeCompare(Z.sequenceNumber))}generateFIFOQueueCF($){return{Type:"AWS::SQS::Queue",Properties:{QueueName:$.name,FifoQueue:!0,ContentBasedDeduplication:$.contentBasedDeduplication,DeduplicationScope:$.deduplicationScope,FifoThroughputLimit:$.fifoThroughputLimit,MessageRetentionPeriod:$.messageRetentionPeriod,VisibilityTimeout:$.visibilityTimeout,ReceiveMessageWaitTimeSeconds:$.receiveMessageWaitTime,...$.deadLetterTargetArn&&{RedrivePolicy:{deadLetterTargetArn:$.deadLetterTargetArn,maxReceiveCount:$.maxReceiveCount||3}}}}}clear(){this.queues.clear(),this.messageGroups.clear(),this.deduplicationConfigs.clear(),this.messages.clear(),this.queueCounter=0,this.groupCounter=0,this.deduplicationCounter=0,this.messageCounter=0,this.sequenceCounter=0}}var sH=new gJ;class uJ{monitors=new Map;metrics=new Map;alerts=new Map;reprocessJobs=new Map;monitorCounter=0;metricsCounter=0;alertCounter=0;jobCounter=0;createDLQMonitor($){let J=`dlq-monitor-${Date.now()}-${this.monitorCounter++}`,Y={id:J,...$};return this.monitors.set(J,Y),Y}createAutomatedMonitor($){return this.createDLQMonitor({name:$.name,queueUrl:$.queueUrl,sourceQueues:$.sourceQueues,maxReceiveCount:3,alarmThreshold:10,autoReprocess:!0,reprocessStrategy:"scheduled",notificationTopicArn:$.notificationTopicArn})}collectMetrics($){let Y={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:$,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*100),approximateAgeOfOldestMessage:Math.floor(Math.random()*86400),messagesReceived:Math.floor(Math.random()*50),messagesDeleted:Math.floor(Math.random()*30),messagesReprocessed:Math.floor(Math.random()*20)},Q=this.metrics.get($)||[];return Q.push(Y),this.metrics.set($,Q),this.checkForAlerts($,Y),Y}checkForAlerts($,J){let Y=Array.from(this.monitors.values()).find((Z)=>Z.queueUrl===$);if(!Y)return;if(J.approximateNumberOfMessages>=Y.alarmThreshold)this.createAlert({monitorId:Y.id,alertType:"threshold_exceeded",severity:"high",message:`DLQ ${Y.name} has ${J.approximateNumberOfMessages} messages (threshold: ${Y.alarmThreshold})`});let Q=3600;if(J.approximateAgeOfOldestMessage>Q)this.createAlert({monitorId:Y.id,alertType:"old_message",severity:"medium",message:`DLQ ${Y.name} has messages older than ${Q} seconds`})}createAlert($){let J=`alert-${Date.now()}-${this.alertCounter++}`,Y={id:J,timestamp:new Date,acknowledged:!1,...$};return this.alerts.set(J,Y),Y}acknowledgeAlert($){let J=this.alerts.get($);if(!J)throw Error(`Alert not found: ${$}`);return J.acknowledged=!0,J}createReprocessJob($){let J=`reprocess-${Date.now()}-${this.jobCounter++}`,Y={id:J,queueUrl:$.queueUrl,messageId:$.messageId,attempts:0,status:"pending"};return this.reprocessJobs.set(J,Y),Y}async executeReprocessJob($){let J=this.reprocessJobs.get($);if(!J)throw Error(`Reprocess job not found: ${$}`);J.status="processing",J.startedAt=new Date,J.attempts++,await new Promise((Q)=>setTimeout(Q,100));let Y=Math.random()>0.3;if(J.status=Y?"success":"failed",J.completedAt=new Date,!Y)J.error="Reprocessing failed - original error still present";return J}async batchReprocess($){let J=[];for(let Y=0;Y<$.maxMessages;Y++){let Q=this.createReprocessJob({queueUrl:$.queueUrl,messageId:`msg-${Y}`});await this.executeReprocessJob(Q.id),J.push(Q)}return J}getDLQStatistics($,J=24){let Y=new Date(Date.now()-J*60*60*1000),Q=(this.metrics.get($)||[]).filter((A)=>A.timestamp>=Y);if(Q.length===0)return{totalMessages:0,avgAge:0,messagesReceived:0,messagesDeleted:0,messagesReprocessed:0,successRate:0};let Z=Q[Q.length-1],W=Q.reduce((A,K)=>A+K.messagesReceived,0),G=Q.reduce((A,K)=>A+K.messagesDeleted,0),U=Q.reduce((A,K)=>A+K.messagesReprocessed,0),z=Q.reduce((A,K)=>A+K.approximateAgeOfOldestMessage,0)/Q.length,H=U>0?G/U*100:0;return{totalMessages:Z.approximateNumberOfMessages,avgAge:z,messagesReceived:W,messagesDeleted:G,messagesReprocessed:U,successRate:H}}getMonitor($){return this.monitors.get($)}listMonitors(){return Array.from(this.monitors.values())}getAlerts($,J){let Y=Array.from(this.alerts.values());if($)Y=Y.filter((Q)=>Q.monitorId===$);if(J!==void 0)Y=Y.filter((Q)=>Q.acknowledged===J);return Y.sort((Q,Z)=>Z.timestamp.getTime()-Q.timestamp.getTime())}getReprocessJobs($){let J=Array.from(this.reprocessJobs.values());if($)J=J.filter((Y)=>Y.queueUrl===$);return J}generateDLQAlarmCF($){return{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$.name}-messages-alarm`,AlarmDescription:`Alert when DLQ ${$.name} exceeds threshold`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:1,Threshold:$.alarmThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:$.queueUrl.split("/").pop()}],...$.notificationTopicArn&&{AlarmActions:[$.notificationTopicArn]}}}}clear(){this.monitors.clear(),this.metrics.clear(),this.alerts.clear(),this.reprocessJobs.clear(),this.monitorCounter=0,this.metricsCounter=0,this.alertCounter=0,this.jobCounter=0}}var oH=new uJ;class dJ{configs=new Map;jobs=new Map;metrics=new Map;configCounter=0;jobCounter=0;metricsCounter=0;createBatchConfig($){let J=`batch-config-${Date.now()}-${this.configCounter++}`,Y={id:J,...$};return this.configs.set(J,Y),Y}createHighThroughputConfig($){return this.createBatchConfig({queueUrl:$.queueUrl,batchSize:10,maxWaitTime:100,parallelProcessors:10,retryAttempts:3,visibilityTimeout:30})}createLowLatencyConfig($){return this.createBatchConfig({queueUrl:$.queueUrl,batchSize:1,maxWaitTime:0,parallelProcessors:5,retryAttempts:2,visibilityTimeout:10})}createBatchJob($){let J=`batch-job-${Date.now()}-${this.jobCounter++}`;if(!this.configs.get($.configId))throw Error(`Batch config not found: ${$.configId}`);let Q=[];for(let W=0;W<$.messageCount;W++)Q.push({id:`msg-${J}-${W}`,messageId:`${J}-${W}`,body:`Message ${W}`,receiptHandle:`receipt-${J}-${W}`,attributes:{},status:"pending"});let Z={id:J,configId:$.configId,messages:Q,status:"pending",processedCount:0,failedCount:0};return this.jobs.set(J,Z),Z}async processBatchJob($){let J=this.jobs.get($);if(!J)throw Error(`Batch job not found: ${$}`);let Y=this.configs.get(J.configId);if(!Y)throw Error(`Batch config not found: ${J.configId}`);J.status="processing",J.startedAt=new Date;let Q=this.chunkArray(J.messages,Y.batchSize);for(let Z of Q)await this.processBatch(Z,Y);return J.processedCount=J.messages.filter((Z)=>Z.status==="success").length,J.failedCount=J.messages.filter((Z)=>Z.status==="failed").length,J.status=J.failedCount===0?"completed":"failed",J.completedAt=new Date,this.collectProcessorMetrics(Y.id,J),J}async processBatch($,J){let Y=$.map((Q)=>this.processMessage(Q,J));await Promise.all(Y)}async processMessage($,J){$.status="processing";let Y=Date.now();await new Promise((W)=>setTimeout(W,Math.random()*100));let Q=Date.now()-Y;if($.processingTime=Q,Math.random()>0.1)$.status="success";else $.status="failed",$.error="Processing error"}chunkArray($,J){let Y=[];for(let Q=0;Q<$.length;Q+=J)Y.push($.slice(Q,Q+J));return Y}collectProcessorMetrics($,J){let Y=`metrics-${Date.now()}-${this.metricsCounter++}`,Z=J.messages.filter((K)=>K.status==="success").map((K)=>K.processingTime||0).filter((K)=>K>0),W=Z.length>0?Z.reduce((K,B)=>K+B,0)/Z.length:0,G=J.completedAt&&J.startedAt?(J.completedAt.getTime()-J.startedAt.getTime())/1000:1,U=J.processedCount/G,z=J.messages.length>0?J.failedCount/J.messages.length*100:0,H={id:Y,configId:$,timestamp:new Date,messagesProcessed:J.processedCount,averageProcessingTime:W,throughput:U,errorRate:z},A=this.metrics.get($)||[];A.push(H),this.metrics.set($,A)}getBatchStatistics($){let J=this.metrics.get($)||[];if(J.length===0)return{totalJobsProcessed:0,totalMessagesProcessed:0,averageThroughput:0,averageErrorRate:0,averageProcessingTime:0};let Y=J.reduce((G,U)=>G+U.messagesProcessed,0),Q=J.reduce((G,U)=>G+U.throughput,0)/J.length,Z=J.reduce((G,U)=>G+U.errorRate,0)/J.length,W=J.reduce((G,U)=>G+U.averageProcessingTime,0)/J.length;return{totalJobsProcessed:J.length,totalMessagesProcessed:Y,averageThroughput:Q,averageErrorRate:Z,averageProcessingTime:W}}optimizeBatchConfig($){let J=this.configs.get($);if(!J)throw Error(`Batch config not found: ${$}`);let Y=this.getBatchStatistics($);if(Y.averageErrorRate<5&&J.batchSize<10)J.batchSize=Math.min(10,J.batchSize+1);if(Y.averageErrorRate>20&&J.batchSize>1)J.batchSize=Math.max(1,J.batchSize-1);if(Y.averageThroughput<5&&J.parallelProcessors<20)J.parallelProcessors++;return J}getConfig($){return this.configs.get($)}listConfigs(){return Array.from(this.configs.values())}getJob($){return this.jobs.get($)}listJobs($){let J=Array.from(this.jobs.values());if($)J=J.filter((Y)=>Y.configId===$);return J}generateBatchProcessorCF($){return{Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:`arn:aws:sqs:us-east-1:123456789012:${$.queueUrl.split("/").pop()}`,FunctionName:"batch-processor-function",BatchSize:$.batchSize,MaximumBatchingWindowInSeconds:$.maxWaitTime/1000,FunctionResponseTypes:["ReportBatchItemFailures"]}}}clear(){this.configs.clear(),this.jobs.clear(),this.metrics.clear(),this.configCounter=0,this.jobCounter=0,this.metricsCounter=0}}var eH=new dJ;class mJ{queues=new Map;retentionPolicies=new Map;delayQueues=new Map;purgeOperations=new Map;metrics=new Map;queueCounter=0;retentionCounter=0;delayCounter=0;purgeCounter=0;metricsCounter=0;createQueue($){let J=`queue-${Date.now()}-${this.queueCounter++}`,Y={id:J,purgeInProgress:!1,...$};return this.queues.set(J,Y),Y}createStandardQueue($){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${$.queueName}`,queueName:$.queueName,messageRetentionPeriod:($.messageRetentionDays||4)*24*60*60,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:0})}createLongPollingQueue($){return this.createQueue({queueUrl:`https://sqs.us-east-1.amazonaws.com/123456789012/${$.queueName}`,queueName:$.queueName,messageRetentionPeriod:345600,delaySeconds:0,maximumMessageSize:262144,receiveMessageWaitTime:$.waitTimeSeconds||20})}createRetentionPolicy($){let J=`retention-${Date.now()}-${this.retentionCounter++}`,Y={id:J,...$};this.retentionPolicies.set(J,Y);let Q=this.queues.get($.queueId);if(Q)Q.messageRetentionPeriod=$.retentionPeriod;return Y}createShortRetentionPolicy($){return this.createRetentionPolicy({queueId:$.queueId,retentionPeriod:$.retentionHours*60*60,autoCleanup:!0,archiveExpiredMessages:!1})}createArchivalRetentionPolicy($){return this.createRetentionPolicy({queueId:$.queueId,retentionPeriod:$.retentionDays*24*60*60,autoCleanup:!0,cleanupSchedule:"cron(0 0 * * ? *)",archiveExpiredMessages:!0,archiveS3Bucket:$.s3Bucket})}createDelayQueue($){let J=`delay-${Date.now()}-${this.delayCounter++}`,Y={id:J,...$};this.delayQueues.set(J,Y);let Q=Array.from(this.queues.values()).find((Z)=>Z.queueUrl===$.queueUrl);if(Q)Q.delaySeconds=$.defaultDelay;return Y}createScheduledDelayQueue($){return this.createDelayQueue({queueUrl:$.queueUrl,defaultDelay:$.delayMinutes*60,perMessageDelay:!1,maxDelay:900})}async purgeQueue($){let J=this.queues.get($);if(!J)throw Error(`Queue not found: ${$}`);if(J.purgeInProgress)throw Error("Purge already in progress for this queue");let Y=`purge-${Date.now()}-${this.purgeCounter++}`,Q={id:Y,queueUrl:J.queueUrl,status:"in_progress",startedAt:new Date};return this.purgeOperations.set(Y,Q),J.purgeInProgress=!0,setTimeout(()=>{Q.status="completed",Q.completedAt=new Date,Q.messagesPurged=Math.floor(Math.random()*1000),J.purgeInProgress=!1},100),Q}collectQueueMetrics($){let Y={id:`metrics-${Date.now()}-${this.metricsCounter++}`,queueUrl:$,timestamp:new Date,approximateNumberOfMessages:Math.floor(Math.random()*1000),approximateNumberOfMessagesNotVisible:Math.floor(Math.random()*100),approximateNumberOfMessagesDelayed:Math.floor(Math.random()*50),oldestMessageAge:Math.floor(Math.random()*86400)},Q=this.metrics.get($)||[];return Q.push(Y),this.metrics.set($,Q),Y}getQueueHealth($){let J=this.metrics.get($)||[];if(J.length===0)return{status:"healthy",issues:[],recommendations:[]};let Y=J[J.length-1],Q=[],Z=[],W="healthy";if(Y.approximateNumberOfMessages>1e4)W="critical",Q.push("Large message backlog detected"),Z.push("Increase consumer capacity");else if(Y.approximateNumberOfMessages>1000)W="warning",Q.push("Growing message backlog"),Z.push("Monitor consumer performance");if(Y.oldestMessageAge&&Y.oldestMessageAge>3600){if(W!=="critical")W="warning";Q.push("Old messages in queue"),Z.push("Review message processing")}if(Y.approximateNumberOfMessagesDelayed>100){if(W!=="critical")W="warning";Q.push("High number of delayed messages")}return{status:W,issues:Q,recommendations:Z}}getQueue($){return this.queues.get($)}listQueues(){return Array.from(this.queues.values())}getRetentionPolicy($){return this.retentionPolicies.get($)}listRetentionPolicies(){return Array.from(this.retentionPolicies.values())}getPurgeOperations($){let J=Array.from(this.purgeOperations.values());if($)J=J.filter((Y)=>Y.queueUrl===$);return J}generateQueueCF($){return{Type:"AWS::SQS::Queue",Properties:{QueueName:$.queueName,MessageRetentionPeriod:$.messageRetentionPeriod,DelaySeconds:$.delaySeconds,MaximumMessageSize:$.maximumMessageSize,ReceiveMessageWaitTimeSeconds:$.receiveMessageWaitTime}}}generateCleanupRuleCF($){return{Type:"AWS::Events::Rule",Properties:{Name:`${$.id}-cleanup`,Description:"Automated queue cleanup",ScheduleExpression:$.cleanupSchedule||"cron(0 0 * * ? *)",State:"ENABLED",Targets:[{Arn:"arn:aws:lambda:us-east-1:123456789012:function:queue-cleanup",Id:$.id,Input:JSON.stringify({queueId:$.queueId,archiveBucket:$.archiveS3Bucket})}]}}}clear(){this.queues.clear(),this.retentionPolicies.clear(),this.delayQueues.clear(),this.purgeOperations.clear(),this.metrics.clear(),this.queueCounter=0,this.retentionCounter=0,this.delayCounter=0,this.purgeCounter=0,this.metricsCounter=0}}var $A=new mJ;class cJ{optimizations=new Map;imageConfigs=new Map;ssgConfigs=new Map;prerenderConfigs=new Map;counter=0;createAssetOptimization($){let J=`asset-opt-${Date.now()}-${this.counter++}`,Y={id:J,...$};return this.optimizations.set(J,Y),Y}createImageOptimization($){let J=`image-opt-${Date.now()}-${this.counter++}`,Y={id:J,...$};return this.imageConfigs.set(J,Y),Y}createSSGConfig($){let J=`ssg-${Date.now()}-${this.counter++}`,Y={id:J,...$};return this.ssgConfigs.set(J,Y),Y}createPrerenderConfig($){let J=`prerender-${Date.now()}-${this.counter++}`,Y={id:J,...$};return this.prerenderConfigs.set(J,Y),Y}listOptimizations(){return Array.from(this.optimizations.values())}listImageConfigs(){return Array.from(this.imageConfigs.values())}clear(){this.optimizations.clear(),this.imageConfigs.clear(),this.ssgConfigs.clear(),this.prerenderConfigs.clear()}}var JA=new cJ;class lJ{policies=new Map;versioningConfigs=new Map;replicationRules=new Map;tieringConfigs=new Map;objectLocks=new Map;transferAcceleration=new Map;accessPoints=new Map;glacierConfigs=new Map;inventories=new Map;batchOps=new Map;eventNotifications=new Map;counter=0;createLifecyclePolicy($,J){let Y=`lifecycle-${Date.now()}-${this.counter++}`,Q={id:Y,transitions:$,expiration:J};return this.policies.set(Y,Q),Q}enableVersioning($=!1){let J=`versioning-${Date.now()}-${this.counter++}`,Y={id:J,enabled:!0,mfaDelete:$};return this.versioningConfigs.set(J,Y),Y}createReplicationRule($,J,Y){let Q=`replication-${Date.now()}-${this.counter++}`,Z={id:Q,sourceRegion:$,destRegion:J,destBucket:Y};return this.replicationRules.set(Q,Z),Z}createIntelligentTiering($,J){let Y=`tiering-${Date.now()}-${this.counter++}`,Q={id:Y,archiveDays:$,deepArchiveDays:J};return this.tieringConfigs.set(Y,Q),Q}enableObjectLock($){let J=`object-lock-${Date.now()}-${this.counter++}`,Y={id:J,bucketName:$.bucketName,mode:$.mode||"COMPLIANCE",retentionDays:$.retentionDays,retentionYears:$.retentionYears,legalHoldEnabled:$.legalHoldEnabled||!1};return this.objectLocks.set(J,Y),Y}enableTransferAcceleration($){let J=`transfer-accel-${Date.now()}-${this.counter++}`,Y={id:J,bucketName:$,enabled:!0,endpoint:`${$}.s3-accelerate.amazonaws.com`};return this.transferAcceleration.set(J,Y),Y}createAccessPoint($){let J=`access-point-${Date.now()}-${this.counter++}`,Y={id:J,name:$.name,bucketName:$.bucketName,vpcId:$.vpcId,publicAccessBlock:$.publicAccessBlock!==!1,policy:$.policy};return this.accessPoints.set(J,Y),Y}createGlacierArchive($){let J=`glacier-${Date.now()}-${this.counter++}`,Y={id:J,bucketName:$.bucketName,archiveType:$.archiveType,transitionDays:$.transitionDays,restoreConfig:$.restoreTier?{tier:$.restoreTier,days:$.restoreDays||7}:void 0};return this.glacierConfigs.set(J,Y),Y}createInventory($){let J=`inventory-${Date.now()}-${this.counter++}`,Y={id:J,sourceBucket:$.sourceBucket,destinationBucket:$.destinationBucket,schedule:$.schedule||"Daily",format:$.format||"CSV",includedFields:$.includedFields||["Size","LastModifiedDate","StorageClass","ETag"],prefix:$.prefix};return this.inventories.set(J,Y),Y}createBatchOperation($){let J=`batch-op-${Date.now()}-${this.counter++}`,Y={id:J,operation:$.operation,manifestBucket:$.manifestBucket,manifestKey:$.manifestKey,priority:$.priority||10,status:"pending"};return this.batchOps.set(J,Y),Y}executeBatchOperation($){let J=this.batchOps.get($);if(!J)throw Error(`Batch operation not found: ${$}`);return J.status="in_progress",J.totalObjects=1000,J.processedObjects=0,J}getBatchOperationStatus($){return this.batchOps.get($)}createLambdaNotification($){let J=`event-${Date.now()}-${this.counter++}`,Y={id:J,bucketName:$.bucketName,events:$.events,destination:{type:"Lambda",arn:$.lambdaArn},filter:$.prefix||$.suffix?{prefix:$.prefix,suffix:$.suffix}:void 0};return this.eventNotifications.set(J,Y),Y}createSQSNotification($){let J=`event-${Date.now()}-${this.counter++}`,Y={id:J,bucketName:$.bucketName,events:$.events,destination:{type:"SQS",arn:$.queueArn},filter:$.prefix||$.suffix?{prefix:$.prefix,suffix:$.suffix}:void 0};return this.eventNotifications.set(J,Y),Y}createSNSNotification($){let J=`event-${Date.now()}-${this.counter++}`,Y={id:J,bucketName:$.bucketName,events:$.events,destination:{type:"SNS",arn:$.topicArn},filter:$.prefix||$.suffix?{prefix:$.prefix,suffix:$.suffix}:void 0};return this.eventNotifications.set(J,Y),Y}generateObjectLockCF($){let J={ObjectLockEnabled:"Enabled",ObjectLockConfiguration:{ObjectLockEnabled:"Enabled",Rule:{DefaultRetention:{Mode:$.mode}}}};if($.retentionDays)J.ObjectLockConfiguration.Rule.DefaultRetention.Days=$.retentionDays;if($.retentionYears)J.ObjectLockConfiguration.Rule.DefaultRetention.Years=$.retentionYears;return J}generateTransferAccelerationCF($){return{AccelerateConfiguration:{AccelerationStatus:$.enabled?"Enabled":"Suspended"}}}generateAccessPointCF($){return{Type:"AWS::S3::AccessPoint",Properties:{Name:$.name,Bucket:$.bucketName,...$.vpcId&&{VpcConfiguration:{VpcId:$.vpcId}},PublicAccessBlockConfiguration:$.publicAccessBlock?{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}:void 0,...$.policy&&{Policy:$.policy}}}}generateInventoryCF($){return{Type:"AWS::S3::Bucket",Properties:{InventoryConfigurations:[{Id:$.id,Destination:{BucketArn:`arn:aws:s3:::${$.destinationBucket}`,Format:$.format},Enabled:!0,IncludedObjectVersions:"Current",OptionalFields:$.includedFields,ScheduleFrequency:$.schedule,...$.prefix&&{Prefix:$.prefix}}]}}}generateEventNotificationCF($){let J=$.destination.type==="Lambda"?"LambdaConfigurations":$.destination.type==="SQS"?"QueueConfigurations":"TopicConfigurations",Y=$.destination.type==="Lambda"?"Function":$.destination.type==="SQS"?"Queue":"Topic",Q={Event:$.events[0],[Y]:$.destination.arn};if($.filter)Q.Filter={S3Key:{Rules:[...$.filter.prefix?[{Name:"prefix",Value:$.filter.prefix}]:[],...$.filter.suffix?[{Name:"suffix",Value:$.filter.suffix}]:[]]}};return{NotificationConfiguration:{[J]:[Q]}}}clear(){this.policies.clear(),this.versioningConfigs.clear(),this.replicationRules.clear(),this.tieringConfigs.clear(),this.objectLocks.clear(),this.transferAcceleration.clear(),this.accessPoints.clear(),this.glacierConfigs.clear(),this.inventories.clear(),this.batchOps.clear(),this.eventNotifications.clear()}}var YA=new lJ;class pJ{checks=new Map;synthetics=new Map;uptimeTrackers=new Map;counter=0;createHealthCheck($,J=30,Y=10){let Q=`health-${Date.now()}-${this.counter++}`,Z={id:Q,url:$,interval:J,timeout:Y,status:"healthy"};return this.checks.set(Q,Z),Z}createSyntheticMonitor($,J,Y,Q){let Z=`synthetic-${Date.now()}-${this.counter++}`,W={id:Z,name:$,script:J,frequency:Y,locations:Q};return this.synthetics.set(Z,W),W}trackUptime($,J,Y){let Q=`uptime-${Date.now()}-${this.counter++}`,Z=J/(J+Y)*100,W={id:Q,resource:$,uptime:J,downtime:Y,availability:Z};return this.uptimeTrackers.set(Q,W),W}clear(){this.checks.clear(),this.synthetics.clear(),this.uptimeTrackers.clear()}}var QA=new pJ;class rJ{wafRules=new Map;shieldProtections=new Map;securityGroups=new Map;nacls=new Map;counter=0;createWAFRule($,J,Y,Q){let Z=`waf-${Date.now()}-${this.counter++}`,W={id:Z,name:$,priority:J,action:Y,conditions:Q};return this.wafRules.set(Z,W),W}enableShield($,J="standard"){let Y=`shield-${Date.now()}-${this.counter++}`,Q={id:Y,resourceArn:$,protectionType:J};return this.shieldProtections.set(Y,Q),Q}createSecurityGroup($,J,Y){let Q=`sg-${Date.now()}-${this.counter++}`,Z={id:Q,name:$,vpcId:J,rules:Y};return this.securityGroups.set(Q,Z),Z}createNACL($,J){let Y=`nacl-${Date.now()}-${this.counter++}`,Q={id:Y,vpcId:$,rules:J};return this.nacls.set(Y,Q),Q}clear(){this.wafRules.clear(),this.shieldProtections.clear(),this.securityGroups.clear(),this.nacls.clear()}}var ZA=new rJ;class nJ{strategies=new Map;allocations=new Map;groups=new Map;counter=0;createTaggingStrategy($,J){let Y=`tagging-${Date.now()}-${this.counter++}`,Q={id:Y,tags:$,resources:J};return this.strategies.set(Y,Q),Q}createCostAllocation($,J){let Y=`cost-${Date.now()}-${this.counter++}`,Q={id:Y,tagKey:$,allocations:J};return this.allocations.set(Y,Q),Q}createResourceGroup($,J,Y){let Q=`group-${Date.now()}-${this.counter++}`,Z={id:Q,name:$,query:{resourceTypeFilters:J,tagFilters:Y}};return this.groups.set(Q,Z),Z}clear(){this.strategies.clear(),this.allocations.clear(),this.groups.clear()}}var WA=new nJ;class E2{builder;config;environment;mergedConfig;serverEipLogicalIds=new Map;constructor($){this.config=$.config,this.environment=$.environment,this.builder=new j8(`${this.config.project.name} - ${this.environment}`),this.mergedConfig=this.mergeEnvironmentConfig()}mergeEnvironmentConfig(){let J=this.config.environments[this.environment]?.infrastructure;if(!J)return this.config;return{...this.config,infrastructure:{...this.config.infrastructure,...J,compute:{...this.config.infrastructure?.compute,...J.compute},storage:{...this.config.infrastructure?.storage,...J.storage},functions:{...this.config.infrastructure?.functions,...J.functions},servers:{...this.config.infrastructure?.servers,...J.servers},databases:{...this.config.infrastructure?.databases,...J.databases},cdn:{...this.config.infrastructure?.cdn,...J.cdn},queues:{...this.config.infrastructure?.queues,...J.queues},redirects:{...this.config.infrastructure?.redirects,...J.redirects},realtime:{...this.config.infrastructure?.realtime,...J.realtime},cache:{...this.config.infrastructure?.cache,...J.cache},fileSystem:{...this.config.infrastructure?.fileSystem,...J.fileSystem},email:{...this.config.infrastructure?.email,...J.email},search:{...this.config.infrastructure?.search,...J.search},ai:{...this.config.infrastructure?.ai,...J.ai}}}}shouldDeploy($){if($.environments&&!$.environments.includes(this.environment))return!1;if($.requiresFeatures){let J=this.config.features||{};if(!$.requiresFeatures.every((Q)=>J[Q]===!0))return!1}if($.regions){let J=this.config.environments[this.environment]?.region||this.config.project.region;if(!$.regions.includes(J))return!1}if($.condition&&typeof $.condition==="function")return $.condition(this.config,this.environment);return!0}resolveApiOriginPort(){let $=this.mergedConfig.infrastructure?.api?.port??this.mergedConfig.ports?.api,J=Number($||3008);return Number.isFinite(J)&&J>0?J:3008}normalizeMountPath($){let J=$?.mountPath||$?.path;if(!J||J==="/")return;let Y=`/${J}`.replace(/\/+/g,"/").replace(/\/$/,"");return Y==="/"?void 0:Y}storageBucketLogicalId($,J,Y){return`${$}-${J}-s3-${Y}`.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((Q)=>Q.charAt(0).toUpperCase()+Q.slice(1)).join("")}pathMountRewriteFunctionCode($,J="directory"){return`function handler(event) { var request = event.request; var prefix = ${JSON.stringify($)}; var rewriteStyle = ${JSON.stringify(J)}; var uri = request.uri; if (uri === prefix) { uri = '/'; } else if (uri.indexOf(prefix + '/') === 0) { uri = uri.substring(prefix.length); } if (uri === '' || uri === '/') { request.uri = '/index.html'; return request; } if (uri.endsWith('/')) { request.uri = uri + 'index.html'; return request; } var lastSegment = uri.substring(uri.lastIndexOf('/') + 1); if (lastSegment.indexOf('.') === -1) { request.uri = rewriteStyle === 'flat' ? uri + '.html' : uri + '/index.html'; return request; } request.uri = uri; return request; }`}generate(){let $=this.mergedConfig.project.slug,J=this.environment,Y=!!(this.mergedConfig.infrastructure?.functions&&Object.keys(this.mergedConfig.infrastructure.functions).length>0||this.mergedConfig.infrastructure?.api),Q=!!(this.mergedConfig.infrastructure?.servers&&Object.keys(this.mergedConfig.infrastructure.servers).length>0),Z=!!this.mergedConfig.infrastructure?.compute;if(!!((this.mergedConfig.mode||"server")==="serverless"&&this.mergedConfig.infrastructure?.containers&&Object.keys(this.mergedConfig.infrastructure.containers).length>0))this.generateNetworkInfrastructure($,J),this.generateContainerInfrastructure($,J);if(Y)this.generateServerless($,J);if(Q)this.generateServer($,J);if(Z)this.generateComputeApp($,J);if(this.mergedConfig.infrastructure?.jumpBox)this.generateJumpBox($,J);if(this.generateSharedInfrastructure($,J),this.config.tags)this.applyGlobalTags(this.config.tags);return this}applyGlobalTags($){}generateNetworkInfrastructure($,J){if(this.builder.hasResource("VPC"))return;let Q=this.mergedConfig.infrastructure?.network?.cidr||"10.0.0.0/16",{vpc:Z,logicalId:W}=E0.createVpc({slug:$,environment:J,cidr:Q,enableDnsHostnames:!0,enableDnsSupport:!0});this.builder.addResource("VPC",Z);let G=`${$}${J}IGW`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(G,{Type:"AWS::EC2::InternetGateway",Properties:{Tags:[{Key:"Name",Value:`${$}-${J}-igw`},{Key:"Environment",Value:J}]}});let U=`${$}${J}IGWAttach`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(U,{Type:"AWS::EC2::VPCGatewayAttachment",Properties:{VpcId:{Ref:"VPC"},InternetGatewayId:{Ref:G}}});let z=`${$}${J}PublicRT`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(z,{Type:"AWS::EC2::RouteTable",Properties:{VpcId:{Ref:"VPC"},Tags:[{Key:"Name",Value:`${$}-${J}-public-rt`},{Key:"Environment",Value:J}]}}),this.builder.addResource(`${$}${J}PublicRoute`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::EC2::Route",Properties:{RouteTableId:{Ref:z},DestinationCidrBlock:"0.0.0.0/0",GatewayId:{Ref:G}},DependsOn:U});let H=this.mergedConfig.environments[J]?.region||this.mergedConfig.project.region||"us-east-1",A=["a","b"];for(let K=0;K<2;K++){let B=`PublicSubnet${K+1}`;this.builder.addResource(B,{Type:"AWS::EC2::Subnet",Properties:{VpcId:{Ref:"VPC"},CidrBlock:`10.0.${K}.0/24`,AvailabilityZone:`${H}${A[K]}`,MapPublicIpOnLaunch:!0,Tags:[{Key:"Name",Value:`${$}-${J}-public-${A[K]}`},{Key:"Environment",Value:J}]}}),this.builder.addResource(`${B}RTAssoc`,{Type:"AWS::EC2::SubnetRouteTableAssociation",Properties:{SubnetId:{Ref:B},RouteTableId:{Ref:z}}})}}generateContainerInfrastructure($,J){let Y=this.mergedConfig.infrastructure?.containers;if(!Y)return;let Q=this.mergedConfig.infrastructure?.loadBalancer,Z=this.mergedConfig.infrastructure?.ssl,W=this.mergedConfig.infrastructure?.dns,G;if(Z?.enabled&&Z.domains?.length)if(Z.certificateArn);else{let A=Z.domains[0],K=Z.domains.slice(1).map((O)=>{if(O.includes(".")&&O.endsWith(A))return O.replace(`.${A}`,"");return O}),{certificate:B,logicalId:j}=L0.createCertificate({domain:A,subdomains:K,slug:$,environment:J,validationMethod:"DNS",hostedZoneId:W?.hostedZoneId});G=j,this.builder.addResource(j,B)}let U="ECSCluster";this.builder.addResource(U,{Type:"AWS::ECS::Cluster",Properties:{ClusterName:`${$}-${J}`,ClusterSettings:[{Name:"containerInsights",Value:"enabled"}],Tags:[{Key:"Name",Value:`${$}-${J}`},{Key:"Environment",Value:J}]}});let z=`${$}${J}ALBSecurityGroup`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(z,{Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:`ALB security group for ${$}-${J}`,VpcId:{Ref:"VPC"},SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:80,ToPort:80,CidrIp:"0.0.0.0/0",Description:"HTTP"},{IpProtocol:"tcp",FromPort:443,ToPort:443,CidrIp:"0.0.0.0/0",Description:"HTTPS"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:`${$}-${J}-alb-sg`},{Key:"Environment",Value:J}]}});let H=`${$}${J}ECSSecurityGroup`.replace(/[^a-zA-Z0-9]/g,"");for(let[A,K]of Object.entries(Y)){let B=K.port||3000;this.builder.addResource(H,{Type:"AWS::EC2::SecurityGroup",Properties:{GroupDescription:`ECS tasks security group for ${$}-${J}`,VpcId:{Ref:"VPC"},SecurityGroupIngress:[{IpProtocol:"tcp",FromPort:B,ToPort:B,SourceSecurityGroupId:{Ref:z},Description:"Allow traffic from ALB"}],SecurityGroupEgress:[{IpProtocol:"-1",CidrIp:"0.0.0.0/0",Description:"Allow all outbound"}],Tags:[{Key:"Name",Value:`${$}-${J}-ecs-sg`},{Key:"Environment",Value:J}]}});let j=`${$}${J}TaskExecRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(j,{Type:"AWS::IAM::Role",Properties:{RoleName:`${$}-${J}-ecs-exec-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"],Policies:[{PolicyName:"ECRPullPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["ecr:GetAuthorizationToken","ecr:BatchCheckLayerAvailability","ecr:GetDownloadUrlForLayer","ecr:BatchGetImage","logs:CreateLogStream","logs:PutLogEvents"],Resource:"*"}]}}]}});let O=`${$}${J}TaskRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(O,{Type:"AWS::IAM::Role",Properties:{RoleName:`${$}-${J}-ecs-task-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"ecs-tasks.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"TaskPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogStream","logs:PutLogEvents"],Resource:"*"},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:ListBucket"],Resource:"*"}]}}]}});let X=`${$}${J}${A}LogGroup`.replace(/[^a-zA-Z0-9]/g,""),_=`/ecs/${$}-${J}-${A}`;this.builder.addResource(X,{Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:_,RetentionInDays:30}});let q=`${$}${J}${A}TaskDef`.replace(/[^a-zA-Z0-9]/g,""),E=String(K.cpu||512),M=String(K.memory||1024);this.builder.addResource(q,{Type:"AWS::ECS::TaskDefinition",Properties:{Family:`${$}-${J}-${A}`,NetworkMode:"awsvpc",RequiresCompatibilities:["FARGATE"],Cpu:E,Memory:M,ExecutionRoleArn:{"Fn::GetAtt":[j,"Arn"]},TaskRoleArn:{"Fn::GetAtt":[O,"Arn"]},ContainerDefinitions:[{Name:A,Image:{"Fn::Sub":`\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.amazonaws.com/${$}:latest`},Essential:!0,PortMappings:[{ContainerPort:B,Protocol:"tcp"}],LogConfiguration:{LogDriver:"awslogs",Options:{"awslogs-group":_,"awslogs-region":{Ref:"AWS::Region"},"awslogs-stream-prefix":A}},HealthCheck:{Command:["CMD-SHELL",`curl -f http://localhost:${B}${K.healthCheck||"/health"} || exit 1`],Interval:30,Timeout:5,Retries:3,StartPeriod:60}}],Tags:[{Key:"Name",Value:`${$}-${J}-${A}`},{Key:"Environment",Value:J}]},DependsOn:[j,O,X]});let D=`${$}${J}ALB`.replace(/[^a-zA-Z0-9]/g,"");if(Q?.enabled!==!1){this.builder.addResource(D,{Type:"AWS::ElasticLoadBalancingV2::LoadBalancer",Properties:{Name:`${$}-${J}-alb`,Scheme:"internet-facing",Type:"application",Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}],SecurityGroups:[{Ref:z}],Tags:[{Key:"Name",Value:`${$}-${J}-alb`},{Key:"Environment",Value:J}]}});let R=`${$}${J}TargetGroup`.replace(/[^a-zA-Z0-9]/g,""),T=Q?.healthCheck?.path||K.healthCheck||"/health";this.builder.addResource(R,{Type:"AWS::ElasticLoadBalancingV2::TargetGroup",Properties:{Name:`${$}-${J}-tg`,Port:B,Protocol:"HTTP",VpcId:{Ref:"VPC"},TargetType:"ip",HealthCheckPath:T,HealthCheckIntervalSeconds:Q?.healthCheck?.interval||30,HealthyThresholdCount:Q?.healthCheck?.healthyThreshold||2,UnhealthyThresholdCount:Q?.healthCheck?.unhealthyThreshold||5,HealthCheckTimeoutSeconds:10,Tags:[{Key:"Name",Value:`${$}-${J}-tg`},{Key:"Environment",Value:J}]}});let S=`${$}${J}HTTPListener`.replace(/[^a-zA-Z0-9]/g,"");if(Z?.enabled&&Z?.redirectHttp)this.builder.addResource(S,{Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:{Ref:D},Port:80,Protocol:"HTTP",DefaultActions:[{Type:"redirect",RedirectConfig:{Protocol:"HTTPS",Port:"443",StatusCode:"HTTP_301"}}]}});else this.builder.addResource(S,{Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:{Ref:D},Port:80,Protocol:"HTTP",DefaultActions:[{Type:"forward",TargetGroupArn:{Ref:R}}]}});if(Z?.enabled){let I=Z.certificateArn||(G?{Ref:G}:void 0);if(I){let f=`${$}${J}HTTPSListener`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(f,{Type:"AWS::ElasticLoadBalancingV2::Listener",Properties:{LoadBalancerArn:{Ref:D},Port:443,Protocol:"HTTPS",Certificates:[{CertificateArn:I}],DefaultActions:[{Type:"forward",TargetGroupArn:{Ref:R}}],SslPolicy:"ELBSecurityPolicy-TLS13-1-2-2021-06"}})}}let C=`${$}${J}${A}Service`.replace(/[^a-zA-Z0-9]/g,""),x=K.desiredCount||1;this.builder.addResource(C,{Type:"AWS::ECS::Service",Properties:{ServiceName:`${$}-${J}-${A}`,Cluster:{Ref:U},TaskDefinition:{Ref:q},DesiredCount:x,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"ENABLED",SecurityGroups:[{Ref:H}],Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]}},LoadBalancers:[{ContainerName:A,ContainerPort:B,TargetGroupArn:{Ref:R}}],HealthCheckGracePeriodSeconds:120,Tags:[{Key:"Name",Value:`${$}-${J}-${A}`},{Key:"Environment",Value:J}]},DependsOn:[q,S,R]});let h=K.autoScaling;if(h){let I=`${$}${J}${A}ScalableTarget`.replace(/[^a-zA-Z0-9]/g,"");if(this.builder.addResource(I,{Type:"AWS::ApplicationAutoScaling::ScalableTarget",Properties:{MaxCapacity:h.max||10,MinCapacity:h.min||1,ResourceId:{"Fn::Sub":`service/\${${U}}/${$}-${J}-${A}`},ScalableDimension:"ecs:service:DesiredCount",ServiceNamespace:"ecs",RoleARN:{"Fn::Sub":"arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"}},DependsOn:C}),h.targetCpuUtilization)this.builder.addResource(`${$}${J}${A}CPUScaling`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${$}-${J}-${A}-cpu-scaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:I},TargetTrackingScalingPolicyConfiguration:{PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageCPUUtilization"},TargetValue:h.targetCpuUtilization,ScaleInCooldown:300,ScaleOutCooldown:60}}});if(h.targetMemoryUtilization)this.builder.addResource(`${$}${J}${A}MemoryScaling`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::ApplicationAutoScaling::ScalingPolicy",Properties:{PolicyName:`${$}-${J}-${A}-memory-scaling`,PolicyType:"TargetTrackingScaling",ScalingTargetId:{Ref:I},TargetTrackingScalingPolicyConfiguration:{PredefinedMetricSpecification:{PredefinedMetricType:"ECSServiceAverageMemoryUtilization"},TargetValue:h.targetMemoryUtilization,ScaleInCooldown:300,ScaleOutCooldown:60}}})}if(W?.domain&&W?.hostedZoneId)this.builder.addResource(`${$}${J}ApiDnsRecord`.replace(/[^a-zA-Z0-9]/g,""),{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:W.hostedZoneId,Name:`api.${W.domain}`,Type:"A",AliasTarget:{DNSName:{"Fn::GetAtt":[D,"DNSName"]},HostedZoneId:{"Fn::GetAtt":[D,"CanonicalHostedZoneID"]}}}});this.builder.addOutput("ECSClusterArn",{Description:"ECS Cluster ARN",Value:{"Fn::GetAtt":[U,"Arn"]},Export:{Name:{"Fn::Sub":"${AWS::StackName}-ecs-cluster-arn"}}}),this.builder.addOutput("ECSServiceName",{Description:"ECS Service Name",Value:`${$}-${J}-${A}`,Export:{Name:{"Fn::Sub":"${AWS::StackName}-ecs-service-name"}}}),this.builder.addOutput("LoadBalancerDNS",{Description:"Application Load Balancer DNS Name",Value:{"Fn::GetAtt":[D,"DNSName"]},Export:{Name:{"Fn::Sub":"${AWS::StackName}-alb-dns"}}})}else{let R=`${$}${J}${A}Service`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(R,{Type:"AWS::ECS::Service",Properties:{ServiceName:`${$}-${J}-${A}`,Cluster:{Ref:U},TaskDefinition:{Ref:q},DesiredCount:K.desiredCount||1,LaunchType:"FARGATE",NetworkConfiguration:{AwsvpcConfiguration:{AssignPublicIp:"ENABLED",SecurityGroups:[{Ref:H}],Subnets:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]}},Tags:[{Key:"Name",Value:`${$}-${J}-${A}`},{Key:"Environment",Value:J}]},DependsOn:[q]})}break}}generateServerless($,J){if(this.mergedConfig.infrastructure?.functions)for(let[Y,Q]of Object.entries(this.mergedConfig.infrastructure.functions)){if(!this.shouldDeploy(Q))continue;let{role:Z,logicalId:W}=s0.createRole({slug:$,environment:J,roleName:`${$}-${J}-${Y}-role`,servicePrincipal:"lambda.amazonaws.com",managedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]});this.builder.addResource(W,Z);let{lambdaFunction:G,logicalId:U}=l.createLambdaFunction({slug:$,environment:J,functionName:`${$}-${J}-${Y}`,handler:Q.handler||"index.handler",runtime:Q.runtime||"nodejs20.x",code:{zipFile:Q.code||"export const handler = async () => ({ statusCode: 200 });"},role:W,timeout:Q.timeout,memorySize:Q.memorySize});this.builder.addResource(U,G)}if(this.mergedConfig.infrastructure?.api){let{restApi:Y,logicalId:Q}=X8.createRestApi({slug:$,environment:J,apiName:`${$}-${J}-api`});this.builder.addResource(Q,Y)}}generateServer($,J){if(!this.mergedConfig.infrastructure?.servers)return;let Y=this.mergedConfig.infrastructure.servers,Q=this.mergedConfig.infrastructure?.compute,Z=this.mergedConfig.infrastructure?.ssl;if(Object.values(Y).some((G)=>!G.privateNetwork||G.privateNetwork==="create"))this.generateNetworkInfrastructure($,J);for(let[G,U]of Object.entries(Y)){let z=U.instanceType||U.size||Q?.size,A=(z?l.InstanceSize.specs[z]:void 0)?.instanceType||z||"t3.micro",K=U.type||"app",B=U.userData||U.startupScript;if(!B)B=l.UserData.generateAppServerScript({runtime:"bun",runtimeVersion:U.bunVersion||"latest",webServer:"none",domain:U.domain,enableSsl:!!Z?.enabled,sslEmail:Z?.letsEncrypt?.email,installRedis:K==="cache",installDatabaseClients:!!U.database});let j=U.privateNetwork&&U.privateNetwork!=="create"?U.privateNetwork:{Ref:"VPC"},O=U.subnet||{Ref:"PublicSubnet1"},_=!!this.mergedConfig.infrastructure?.email?.server?.enabled,q=[22,80,443,this.resolveApiOriginPort()];if(_)q.push(25,465,587,143,993);let E=l.createServerModeStack({slug:`${$}-${G}`,environment:J,vpcId:j,subnetId:O,instanceType:A,keyName:U.keyName||`${$}-${J}`,domain:U.domain,userData:B,volumeSize:U.diskSize||20,imageId:U.image,allowedPorts:q});for(let[M,D]of Object.entries(E.resources))this.builder.addResource(M,D);this.serverEipLogicalIds.set(G,E.outputs.eipLogicalId),this.serverEipLogicalIds.set(`${G}Instance`,E.outputs.instanceLogicalId),this.builder.addOutput(`${G}InstanceId`,{Value:{Ref:E.outputs.instanceLogicalId},Description:`Instance ID for ${G} server`}),this.builder.addOutput(`${G}PublicIp`,{Value:{Ref:E.outputs.eipLogicalId},Description:`Public IP for ${G} server`})}}generateComputeApp($,J){let Y=this.mergedConfig.infrastructure?.compute;if(!Y)return;let Q=this.mergedConfig.sites||{},Z=Object.entries(Q),G=this.mergedConfig.infrastructure?.dns?.domain,U=this.mergedConfig.infrastructure?.database,z=Y.size,A=(z?l.InstanceSize.specs[z]:void 0)?.instanceType||"t3.micro";if(!this.builder.hasResource("VPC"))this.generateNetworkInfrastructure($,J);let K=l.UserData.generateBunAppScript({runtime:Y.runtime||"bun",runtimeVersion:Y.runtimeVersion||"latest",systemPackages:Y.systemPackages,database:U}),B=Z.map(([,M])=>M.port).filter((M)=>typeof M==="number"&&![80,443].includes(M)),j=this.resolveApiOriginPort(),O=`${$}${J}DeployBucket`.replace(/[^a-zA-Z0-9]/g,""),X=`${$}-${J}-deploy`;this.builder.addResource(O,{Type:"AWS::S3::Bucket",Properties:{BucketName:X,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0},LifecycleConfiguration:{Rules:[{Id:"expire-old-releases",Status:"Enabled",ExpirationInDays:7,Prefix:"releases/"}]},Tags:[{Key:"Project",Value:$},{Key:"Environment",Value:J},{Key:"ManagedBy",Value:"ts-cloud"}]}});let _=l.createServerModeStack({slug:`${$}-app`,environment:J,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},instanceType:A,keyName:`${$}-${J}`,domain:G,userData:K,volumeSize:Y.disk?.size||20,imageId:Y.image,allowedPorts:[...Y.allowSsh?[22]:[],80,443,j,...B]}),q=_.resources[_.outputs.instanceLogicalId];if(q?.Properties){let M=q.Properties.Tags||[];q.Properties.Tags=[...M,{Key:"Project",Value:$},{Key:"Environment",Value:J},{Key:"Role",Value:"app"},{Key:"ManagedBy",Value:"ts-cloud"}]}let E=_.resources[_.outputs.roleLogicalId];if(E?.Properties)E.Properties.Policies=E.Properties.Policies||[],E.Properties.Policies.push({PolicyName:"DeployBucketRead",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["s3:GetObject","s3:ListBucket"],Resource:[`arn:aws:s3:::${X}`,`arn:aws:s3:::${X}/*`]}]}});for(let[M,D]of Object.entries(_.resources))this.builder.addResource(M,D);this.builder.addOutput("deployBucketName",{Value:{Ref:O},Description:"S3 bucket where release tarballs are uploaded"}),this.builder.addOutput("appInstanceId",{Value:{Ref:_.outputs.instanceLogicalId},Description:"EC2 instance ID for the app server"}),this.builder.addOutput("appPublicIp",{Value:{Ref:_.outputs.eipLogicalId},Description:"Public IP for the app server"}),this.serverEipLogicalIds.set("app",_.outputs.eipLogicalId),this.serverEipLogicalIds.set("appInstance",_.outputs.instanceLogicalId)}generateJumpBox($,J){let Y=this.mergedConfig.infrastructure?.jumpBox;if(!Y)return;let Q=Y===!0?{}:Y;if(Q.enabled===!1)return;this.generateNetworkInfrastructure($,J);let Z=Q.size||"micro",G=l.InstanceSize.specs[Z]?.instanceType||Z||"t3.micro",U;if(Q.mountEfs)U={fileSystemId:typeof Q.mountEfs==="string"?Q.mountEfs:{Ref:"FileSystem"},mountPath:Q.mountPath||"/mnt/efs"};let z;if(Q.databaseTools)z=l.JumpBox.withDatabaseTools({slug:$,environment:J,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},keyName:Q.keyName||`${$}-${J}`,allowedCidrs:Q.allowedCidrs});else if(U)z=l.JumpBox.withEfsMount({slug:$,environment:J,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},keyName:Q.keyName||`${$}-${J}`,fileSystemId:U.fileSystemId,mountPath:U.mountPath,allowedCidrs:Q.allowedCidrs});else z=l.createJumpBox({slug:$,environment:J,vpcId:{Ref:"VPC"},subnetId:{Ref:"PublicSubnet1"},keyName:Q.keyName||`${$}-${J}`,instanceType:G,allowedCidrs:Q.allowedCidrs,mountEfs:U});for(let[H,A]of Object.entries(z.resources))this.builder.addResource(H,A);this.builder.addOutput("JumpBoxInstanceId",{Value:{Ref:z.instanceLogicalId},Description:"The ID of the JumpBox EC2 instance (use with SSM Session Manager or SSH)"})}generateSharedInfrastructure($,J){let Y=this.mergedConfig.infrastructure?.ssl,Q=this.mergedConfig.infrastructure?.dns,Z=Q?.domain,W=Q?.hostedZoneId,G=[],U,z;if(Y?.certificateArn)z=Y.certificateArn;else if(Y?.enabled&&Z&&W){let X=Y.domains||[Z],_=X[0],q=X.slice(1).map((D)=>{if(D.includes(".")&&D.endsWith(_))return D.replace(`.${_}`,"");return D}),{certificate:E,logicalId:M}=L0.createCertificate({domain:_,subdomains:q,slug:$,environment:J,validationMethod:"DNS",hostedZoneId:W});U=M,this.builder.addResource(M,E)}if(this.mergedConfig.infrastructure?.storage){let X=Object.entries(this.mergedConfig.infrastructure.storage).some(([,E])=>E.website),_;if(X&&(U||z))_=`${$}${J}CloudFrontOAC`.replace(/[^a-zA-Z0-9]/g,""),this.builder.addResource(_,{Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${$}-${J}-s3-oac`,Description:`OAC for ${$} ${J} S3 website buckets`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}});let q=Object.entries(this.mergedConfig.infrastructure.storage).map(([E,M])=>({name:E,config:M,mountPath:this.normalizeMountPath(M),rewriteStyle:M.pathRewriteStyle||"directory",logicalId:this.storageBucketLogicalId($,J,E)})).filter((E)=>E.name!=="public"&&E.config.website&&E.mountPath);for(let[E,M]of Object.entries(this.mergedConfig.infrastructure.storage)){let D=!!(M.website&&_),{bucket:R,logicalId:T}=U1.createBucket({slug:$,name:E,environment:J,bucketName:`${$}-${J}-${E}`,versioning:M.versioning,encryption:M.encryption,public:D?!1:M.public});if(D&&R.Properties)R.Properties.PublicAccessBlockConfiguration={BlockPublicAcls:!0,IgnorePublicAcls:!0,BlockPublicPolicy:!1,RestrictPublicBuckets:!1};if(this.builder.addResource(T,R),M.website){let C=typeof M.website==="object"?M.website:{},x=U1.enableWebsiteHosting(R,C.indexDocument||"index.html",C.errorDocument);this.builder.addResource(T,x)}let S=this.normalizeMountPath(M);if(D&&_&&Z&&!(S&&E!=="public")){let C=`${$}${J}${E}CDN`.replace(/[^a-zA-Z0-9]/g,""),x=[];if(M.aliases&&M.aliases.length>0)x.push(...M.aliases);else if(E==="public"){if(x.push(Z),Y?.domains?.includes(`www.${Z}`))x.push(`www.${Z}`)}else if(E==="docs")x.push(`docs.${Z}`);else if(E==="blog")x.push(`blog.${Z}`);let h=typeof M.website==="object"?M.website:{},I=M.spa===!0,f=h.errorDocument||(I?"index.html":"404.html"),d=[];if(I)d.push({ErrorCode:403,ResponseCode:200,ResponsePagePath:"/index.html",ErrorCachingMinTTL:300},{ErrorCode:404,ResponseCode:200,ResponsePagePath:"/index.html",ErrorCachingMinTTL:300});else d.push({ErrorCode:403,ResponseCode:404,ResponsePagePath:`/${f}`,ErrorCachingMinTTL:300},{ErrorCode:404,ResponseCode:404,ResponsePagePath:`/${f}`,ErrorCachingMinTTL:300});let r=z&&x.length>0?{AcmCertificateArn:z,SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}:U&&x.length>0?{AcmCertificateArn:{Ref:U},SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}:{CloudFrontDefaultCertificate:!0},c=`S3-${$}-${J}-${E}`,n=this.mergedConfig.project.region||"us-east-1",s;if(!I)s=`${$}${J}${E}UrlRewrite`.replace(/[^a-zA-Z0-9]/g,""),this.builder.addResource(s,{Type:"AWS::CloudFront::Function",Properties:{Name:`${$}-${J}-${E}-url-rewrite`,AutoPublish:!0,FunctionConfig:{Comment:`URL rewrite for ${$} ${J} ${E} - appends .html to extensionless paths`,Runtime:"cloudfront-js-2.0"},FunctionCode:`function handler(event) { var request = event.request; var uri = request.uri; if (uri.endsWith('/')) { request.uri += 'index.html'; }
|
|
5379
|
+
else if (!uri.includes('.')) { request.uri += '.html'; } return request; }`}});let J0=[{Id:c,DomainName:{"Fn::Sub":`\${${T}}.s3.${n}.amazonaws.com`},OriginPath:"",S3OriginConfig:{OriginAccessIdentity:""},OriginAccessControlId:{Ref:_}}],_0=[],l0=[];if(E==="public"){let f0=this.serverEipLogicalIds.get("app"),s1=this.serverEipLogicalIds.get("appInstance");if(f0){let w0=`EC2-${$}-${J}-api`,f1=this.mergedConfig.infrastructure?.servers?.app?.region||this.mergedConfig.project?.region||"us-east-1",g1=f1==="us-east-1"?".compute-1.amazonaws.com":`.${f1}.compute.amazonaws.com`,V2={"Fn::Join":["",["ec2-",{"Fn::Join":["-",{"Fn::Split":[".",{Ref:f0}]}]},g1]]},e$=this.resolveApiOriginPort();if(J0.push({Id:w0,DomainName:V2,CustomOriginConfig:{HTTPPort:e$,HTTPSPort:443,OriginProtocolPolicy:"http-only",OriginSSLProtocols:["TLSv1.2"]}}),l0.push(f0),s1)l0.push(s1);_0.push({PathPattern:"/api/*",TargetOriginId:w0,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],CachedMethods:["GET","HEAD"],Compress:!0,CachePolicyId:"4135ea2d-6df8-44a3-9df3-4b5a84be39ad",OriginRequestPolicyId:"b689b0a8-53d0-40ab-baf2-68738e2966ac"})}for(let w0 of q){let f1=`S3-${$}-${J}-${w0.name}`,g1=`${$}${J}${w0.name}PathMountRewrite`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(g1,{Type:"AWS::CloudFront::Function",Properties:{Name:`${$}-${J}-${w0.name}-path-mount-rewrite`,AutoPublish:!0,FunctionConfig:{Comment:`Path mount rewrite for ${$} ${J} ${w0.name} at ${w0.mountPath}`,Runtime:"cloudfront-js-2.0"},FunctionCode:this.pathMountRewriteFunctionCode(w0.mountPath,w0.rewriteStyle)}}),J0.push({Id:f1,DomainName:{"Fn::Sub":`\${${w0.logicalId}}.s3.${n}.amazonaws.com`},OriginPath:"",S3OriginConfig:{OriginAccessIdentity:""},OriginAccessControlId:{Ref:_}}),l0.push(w0.logicalId,g1);for(let V2 of[w0.mountPath,`${w0.mountPath}/*`])_0.push({PathPattern:V2,TargetOriginId:f1,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,CachePolicyId:"4135ea2d-6df8-44a3-9df3-4b5a84be39ad",FunctionAssociations:[{EventType:"viewer-request",FunctionARN:{"Fn::GetAtt":[g1,"FunctionARN"]}}]})}}let I0={Type:"AWS::CloudFront::Distribution",DependsOn:[T,_,...s?[s]:[],...l0],Properties:{DistributionConfig:{Enabled:!0,Comment:`${$} ${J} ${E} site`,DefaultRootObject:"index.html",Origins:J0,DefaultCacheBehavior:{TargetOriginId:c,ViewerProtocolPolicy:"redirect-to-https",AllowedMethods:["GET","HEAD","OPTIONS"],CachedMethods:["GET","HEAD","OPTIONS"],Compress:!0,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6",...s?{FunctionAssociations:[{EventType:"viewer-request",FunctionARN:{"Fn::GetAtt":[s,"FunctionARN"]}}]}:{}},..._0.length>0?{CacheBehaviors:_0}:{},...x.length>0?{Aliases:x}:{},ViewerCertificate:r,PriceClass:"PriceClass_100",HttpVersion:"http2and3",IPV6Enabled:!0,CustomErrorResponses:d}}};if(U)I0.DependsOn.push(U);this.builder.addResource(C,I0);let t1=`${T}CloudFrontPolicy`;if(this.builder.addResource(t1,{Type:"AWS::S3::BucketPolicy",DependsOn:[T,C],Properties:{Bucket:{Ref:T},PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontServicePrincipal",Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:{"Fn::Sub":`arn:aws:s3:::\${${T}}/*`},Condition:{StringEquals:{"AWS:SourceArn":{"Fn::Sub":`arn:aws:cloudfront::\${AWS::AccountId}:distribution/\${${C}}`}}}}]}}}),E==="public")for(let f0 of q){let s1=`${f0.logicalId}CloudFrontPolicy`;this.builder.addResource(s1,{Type:"AWS::S3::BucketPolicy",DependsOn:[f0.logicalId,C],Properties:{Bucket:{Ref:f0.logicalId},PolicyDocument:{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontServicePrincipal",Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:{"Fn::Sub":`arn:aws:s3:::\${${f0.logicalId}}/*`},Condition:{StringEquals:{"AWS:SourceArn":{"Fn::Sub":`arn:aws:cloudfront::\${AWS::AccountId}:distribution/\${${C}}`}}}}]}}})}if(x.length>0)G.push({name:E,bucketLogicalId:T,distLogicalId:C,oacLogicalId:_,aliases:x});this.builder.addOutput(`${E}CloudFrontDomain`,{Value:{"Fn::GetAtt":[C,"DomainName"]},Description:`CloudFront domain for ${E}`}),this.builder.addOutput(`${E}CloudFrontDistributionId`,{Value:{Ref:C},Description:`CloudFront distribution ID for ${E}`})}if(this.builder.addOutput(`${E}BucketName`,{Value:{Ref:T},Description:`S3 bucket name for ${E}`}),E==="public")this.builder.addOutput("FrontendBucketName",{Value:{Ref:T},Description:"Frontend S3 bucket name"});if(E==="docs")this.builder.addOutput("DocsBucketName",{Value:{Ref:T},Description:"Documentation S3 bucket name"});if(E==="blog")this.builder.addOutput("BlogBucketName",{Value:{Ref:T},Description:"Blog S3 bucket name"})}}if(W&&G.length>0)for(let{name:X,distLogicalId:_,aliases:q}of G)for(let E of q){let M=E.replace(/\./g,"").replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(`${M}ARecord`,{Type:"AWS::Route53::RecordSet",DependsOn:[_],Properties:{HostedZoneId:W,Name:E,Type:"A",AliasTarget:{DNSName:{"Fn::GetAtt":[_,"DomainName"]},HostedZoneId:"Z2FDTNDATAQYW2",EvaluateTargetHealth:!1}}}),this.builder.addResource(`${M}AAAARecord`,{Type:"AWS::Route53::RecordSet",DependsOn:[_],Properties:{HostedZoneId:W,Name:E,Type:"AAAA",AliasTarget:{DNSName:{"Fn::GetAtt":[_,"DomainName"]},HostedZoneId:"Z2FDTNDATAQYW2",EvaluateTargetHealth:!1}}})}if(this.mergedConfig.infrastructure?.databases){for(let[X,_]of Object.entries(this.mergedConfig.infrastructure.databases))if(_.engine==="dynamodb"){let{table:q,logicalId:E}=n1.createTable({slug:$,environment:J,tableName:`${$}-${J}-${X}`,partitionKey:_.partitionKey||{name:"id",type:"S"},sortKey:_.sortKey});this.builder.addResource(E,q)}else if(_.engine==="postgres"){let{dbInstance:q,logicalId:E}=n1.createPostgres({slug:$,environment:J,dbInstanceIdentifier:`${$}-${J}-${X}`,masterUsername:_.username||"admin",masterUserPassword:_.password||"changeme123",allocatedStorage:_.storage||20,dbInstanceClass:_.instanceClass||"db.t3.micro"});this.builder.addResource(E,q)}else if(_.engine==="mysql"){let{dbInstance:q,logicalId:E}=n1.createMysql({slug:$,environment:J,dbInstanceIdentifier:`${$}-${J}-${X}`,masterUsername:_.username||"admin",masterUserPassword:_.password||"changeme123",allocatedStorage:_.storage||20,dbInstanceClass:_.instanceClass||"db.t3.micro"});this.builder.addResource(E,q)}}if(this.mergedConfig.infrastructure?.cdn)for(let[X,_]of Object.entries(this.mergedConfig.infrastructure.cdn)){let{distribution:q,logicalId:E}=t0.createDistribution({slug:$,environment:J,origin:{domainName:_.origin,originId:`${$}-origin`}});this.builder.addResource(E,q)}if(this.mergedConfig.infrastructure?.queues)for(let[X,_]of Object.entries(this.mergedConfig.infrastructure.queues)){if(!this.shouldDeploy(_))continue;let{queue:q,logicalId:E}=m0.createQueue({slug:$,environment:J,name:`${$}-${J}-${X}`,fifo:_.fifo,visibilityTimeout:_.visibilityTimeout,messageRetentionPeriod:_.messageRetentionPeriod,delaySeconds:_.delaySeconds,maxMessageSize:_.maxMessageSize,receiveMessageWaitTime:_.receiveMessageWaitTime,contentBasedDeduplication:_.contentBasedDeduplication,encrypted:_.encrypted,kmsKeyId:_.kmsKeyId});this.builder.addResource(E,q);let M;if(_.deadLetterQueue){let{deadLetterQueue:D,updatedSourceQueue:R,deadLetterLogicalId:T}=m0.createDeadLetterQueue(E,{slug:$,environment:J,maxReceiveCount:_.maxReceiveCount});M=T,this.builder.addResource(T,D);let C=this.builder.getResources()[E];if(C?.Properties)C.Properties.RedrivePolicy=R.Properties?.RedrivePolicy}if(_.trigger){let D=_.trigger,R=`${$}${J}${D.functionName}`.replace(/[^a-zA-Z0-9]/g,""),T={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:{"Fn::GetAtt":[E,"Arn"]},FunctionName:{Ref:R},BatchSize:D.batchSize||10,MaximumBatchingWindowInSeconds:D.batchWindow||0,Enabled:!0,...D.reportBatchItemFailures!==!1&&{FunctionResponseTypes:["ReportBatchItemFailures"]},...D.maxConcurrency&&{ScalingConfig:{MaximumConcurrency:D.maxConcurrency}},...D.filterPattern&&{FilterCriteria:{Filters:[{Pattern:JSON.stringify(D.filterPattern)}]}}},DependsOn:[E,R]};this.builder.addResource(`${E}Trigger`,T)}if(_.alarms?.enabled){let D=_.alarms,R=D.notificationTopicArn;if(!R&&D.notificationEmails?.length){let C=`${E}AlarmTopic`;this.builder.addResource(C,{Type:"AWS::SNS::Topic",Properties:{TopicName:`${$}-${J}-${X}-alarms`,DisplayName:`${X} Queue Alarms`}}),D.notificationEmails.forEach((x,h)=>{this.builder.addResource(`${C}Sub${h}`,{Type:"AWS::SNS::Subscription",Properties:{TopicArn:{Ref:C},Protocol:"email",Endpoint:x}})}),R={Ref:C}}let T=D.queueDepthThreshold||1000;this.builder.addResource(`${E}DepthAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$}-${J}-${X}-queue-depth`,AlarmDescription:`Queue ${X} depth exceeds ${T} messages`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Average",Period:300,EvaluationPeriods:2,Threshold:T,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:{"Fn::GetAtt":[E,"QueueName"]}}],...R&&{AlarmActions:[R],OKActions:[R]}}});let S=D.messageAgeThreshold||3600;if(this.builder.addResource(`${E}AgeAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$}-${J}-${X}-message-age`,AlarmDescription:`Queue ${X} oldest message exceeds ${S} seconds`,MetricName:"ApproximateAgeOfOldestMessage",Namespace:"AWS/SQS",Statistic:"Maximum",Period:300,EvaluationPeriods:2,Threshold:S,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:{"Fn::GetAtt":[E,"QueueName"]}}],...R&&{AlarmActions:[R],OKActions:[R]}}}),M&&D.dlqAlarm!==!1)this.builder.addResource(`${M}Alarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$}-${J}-${X}-dlq-messages`,AlarmDescription:`Dead letter queue for ${X} has messages`,MetricName:"ApproximateNumberOfMessagesVisible",Namespace:"AWS/SQS",Statistic:"Sum",Period:300,EvaluationPeriods:1,Threshold:0,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"QueueName",Value:{"Fn::GetAtt":[M,"QueueName"]}}],...R&&{AlarmActions:[R]}}})}if(_.subscribe){let D=_.subscribe,R=D.topicArn;if(!R&&D.topicName)R={Ref:D.topicName};if(R){this.builder.addResource(`${E}SnsPolicy`,{Type:"AWS::SQS::QueuePolicy",Properties:{Queues:[{Ref:E}],PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"sns.amazonaws.com"},Action:"sqs:SendMessage",Resource:{"Fn::GetAtt":[E,"Arn"]},Condition:{ArnEquals:{"aws:SourceArn":R}}}]}}});let T={TopicArn:R,Protocol:"sqs",Endpoint:{"Fn::GetAtt":[E,"Arn"]},RawMessageDelivery:D.rawMessageDelivery||!1};if(D.filterPolicy)T.FilterPolicy=D.filterPolicy,T.FilterPolicyScope=D.filterPolicyScope||"MessageAttributes";this.builder.addResource(`${E}SnsSub`,{Type:"AWS::SNS::Subscription",Properties:T,DependsOn:`${E}SnsPolicy`})}}}if(this.mergedConfig.infrastructure?.realtime?.enabled)if((this.mergedConfig.infrastructure.realtime.mode||"serverless")==="server")this.generateRealtimeServerResources($,J);else this.generateRealtimeResources($,J);let H=this.mergedConfig.infrastructure?.redirects;if(H){let X=H.target||this.mergedConfig.infrastructure?.dns?.domain||"",_=H.protocol||"https";if(H.domains?.length&&X)for(let q of H.domains){let{bucket:E,bucketPolicy:M,logicalId:D,policyLogicalId:R}=h1.createDomainRedirectBucket({slug:$,environment:J,sourceDomain:q,targetDomain:X,protocol:_});this.builder.addResource(D,E),this.builder.addResource(R,M)}if(H.paths&&Object.keys(H.paths).length>0){let q=h1.fromMapping(H.paths,{statusCode:H.statusCode||301}),{function:E,logicalId:M}=h1.createPathRedirectFunction({slug:$,environment:J,rules:q});this.builder.addResource(M,E)}}if(this.mergedConfig.infrastructure?.monitoring?.alarms)for(let[X,_]of Object.entries(this.mergedConfig.infrastructure.monitoring.alarms)){let{alarm:q,logicalId:E}=c$.createAlarm({slug:$,environment:J,alarmName:`${$}-${J}-${X}`,metricName:_.metricName||"Errors",namespace:_.namespace||"AWS/Lambda",threshold:_.threshold||1,comparisonOperator:_.comparisonOperator||"GreaterThanThreshold"});this.builder.addResource(E,q)}let A=this.mergedConfig.infrastructure?.cache;if(A){let X=A.type||"redis";if(X==="redis"){this.generateNetworkInfrastructure($,J);let _=A.redis||{},{replicationGroup:q,subnetGroup:E,logicalId:M,subnetGroupId:D}=m$.createRedis({slug:$,environment:J,nodeType:_.nodeType||A.nodeType||"cache.t3.micro",engineVersion:_.engineVersion||"7.1",port:_.port||6379,numCacheClusters:_.numCacheNodes||2,automaticFailover:_.automaticFailoverEnabled!==!1,atRestEncryption:!0,transitEncryption:!0,snapshotRetentionDays:_.snapshotRetentionLimit||7,snapshotWindow:_.snapshotWindow,subnetIds:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]});if(this.builder.addResource(M,q),E&&D)this.builder.addResource(D,E);this.builder.addOutput("CacheEndpoint",{Value:{"Fn::GetAtt":[M,"PrimaryEndPoint.Address"]},Description:"Redis primary endpoint address"}),this.builder.addOutput("CachePort",{Value:{"Fn::GetAtt":[M,"PrimaryEndPoint.Port"]},Description:"Redis primary endpoint port"})}else if(X==="memcached"){this.generateNetworkInfrastructure($,J);let _=A.elasticache||{},{cluster:q,subnetGroup:E,logicalId:M,subnetGroupId:D}=m$.createMemcached({slug:$,environment:J,nodeType:_.nodeType||A.nodeType||"cache.t3.micro",engineVersion:_.engineVersion||"1.6.22",numCacheNodes:_.numCacheNodes||2,subnetIds:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}]});if(this.builder.addResource(M,q),E&&D)this.builder.addResource(D,E);this.builder.addOutput("CacheEndpoint",{Value:{"Fn::GetAtt":[M,"ConfigurationEndpoint.Address"]},Description:"Memcached configuration endpoint address"})}}let K=this.mergedConfig.infrastructure?.email;if(K){let X=K.domain||this.mergedConfig.infrastructure?.dns?.domain;if(X){let{emailIdentity:_,logicalId:q}=z0.verifyDomain({domain:X,slug:$,environment:J,enableDkim:K.enableDkim!==!1,dkimKeyLength:K.dkimKeyLength||"RSA_2048_BIT"});if(this.builder.addResource(q,_),K.configurationSet!==!1){let{configurationSet:D,logicalId:R}=z0.createConfigurationSet({slug:$,environment:J});this.builder.addResource(R,D)}let E=K.hostedZoneId||this.mergedConfig.infrastructure?.dns?.hostedZoneId;if(E){if(K.enableDkim!==!1)for(let C=1;C<=3;C++){let x=`DkimRecord${C}${X.replace(/\./g,"")}`;this.builder.addResource(x,{Type:"AWS::Route53::RecordSet",DependsOn:[q],Properties:{HostedZoneId:E,Name:{"Fn::GetAtt":[q,`DkimDNSTokenName${C}`]},Type:"CNAME",TTL:1800,ResourceRecords:[{"Fn::GetAtt":[q,`DkimDNSTokenValue${C}`]}]}})}let{record:D,logicalId:R}=z0.createSpfRecord(X,E);this.builder.addResource(R,D);let{record:T,logicalId:S}=z0.createDmarcRecord(X,E,{policy:"none",reportingEmail:K.dmarcReportingEmail||`dmarc-reports@${X}`});this.builder.addResource(S,T)}this.builder.addOutput("EmailDomain",{Value:X,Description:"SES verified email domain"});let M=K.server;if(M?.enabled&&E){let D=this.mergedConfig.environments[J]?.region||this.mergedConfig.project.region||"us-east-1",R=`${$}-${J}-email`,{role:T,policy:S,roleLogicalId:C,policyLogicalId:x}=z0.createEmailLambdaRole({slug:$,environment:J,s3BucketArn:`arn:aws:s3:::${R}`,sesIdentityArn:`arn:aws:ses:${D}:*:identity/${X}`});this.builder.addResource(C,T),this.builder.addResource(x,S);let{function:h,permission:I,logicalId:f,permissionLogicalId:d}=z0.createInboundEmailLambda({slug:$,environment:J,roleArn:{"Fn::GetAtt":[C,"Arn"]},s3BucketName:R,organizedPrefix:"mailboxes/"});this.builder.addResource(f,h),this.builder.addResource(d,I);let r=z0.createInboundEmailSetup({slug:$,environment:J,domain:X,s3BucketName:R,s3KeyPrefix:"inbox/",region:D,hostedZoneId:E,lambdaFunctionArn:{"Fn::GetAtt":[f,"Arn"]}});for(let[n,s]of Object.entries(r.resources)){if(s.Type==="AWS::SES::ReceiptRule")s.DependsOn=[d,f];this.builder.addResource(n,s)}this.builder.addOutput("InboundEmailLambda",{Value:{Ref:f},Description:"Inbound email processing Lambda function"}),this.builder.addOutput("EmailBucket",{Value:R,Description:"S3 bucket for email storage"});let c=this.serverEipLogicalIds.get("app");if(c&&E){let s=`${M?.subdomain||"mail"}.${X}`,J0=s.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(`${J0}ARecord`,{Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:E,Name:s,Type:"A",TTL:"300",ResourceRecords:[{Ref:c}]}})}this.builder.addOutput("MailHost",{Value:`mail.${X}`,Description:"Mail server hostname for SMTP/IMAP clients"})}}}let B=this.mergedConfig.infrastructure?.search;if(B){let X=B.vpc?{subnetIds:[{Ref:"PublicSubnet1"}],securityGroupIds:[]}:void 0;if(X)this.generateNetworkInfrastructure($,J);let{domain:_,logicalId:q}=r1.createDomain({slug:$,environment:J,engineVersion:B.engineVersion||"OpenSearch_2.11",instanceType:B.instanceType||"t3.small.search",instanceCount:B.instanceCount||1,volumeSize:B.volumeSize||10,volumeType:B.volumeType||"gp3",dedicatedMaster:B.dedicatedMaster||!1,dedicatedMasterType:B.dedicatedMasterType,dedicatedMasterCount:B.dedicatedMasterCount||3,multiAz:B.multiAz||!1,encryption:B.encryption||{atRest:!0,nodeToNode:!0},advancedSecurity:B.advancedSecurity,autoTune:B.autoTune!==!1,vpc:X});this.builder.addResource(q,_),this.builder.addOutput("SearchDomainEndpoint",{Value:{"Fn::GetAtt":[q,"DomainEndpoint"]},Description:"OpenSearch domain endpoint"}),this.builder.addOutput("SearchDomainArn",{Value:{"Fn::GetAtt":[q,"Arn"]},Description:"OpenSearch domain ARN"})}let j=this.mergedConfig.infrastructure?.fileSystem;if(j&&Object.keys(j).length>0){this.generateNetworkInfrastructure($,J);for(let[X,_]of Object.entries(j)){let{fileSystem:q,logicalId:E}=V1.createFileSystem({slug:`${$}-${X}`,environment:J,encrypted:_.encrypted!==!1,performanceMode:_.performanceMode||"generalPurpose",throughputMode:_.throughputMode||"bursting",enableBackup:!0});this.builder.addResource(E,q);let{securityGroup:M,logicalId:D}=V1.createEfsSecurityGroup({slug:`${$}-${X}`,environment:J,vpcId:{Ref:"VPC"},sourceCidrBlocks:["10.0.0.0/16"]});this.builder.addResource(D,M);let{mountTargets:R,logicalIds:T}=V1.createMultiAzMountTargets(E,{slug:`${$}-${X}`,environment:J,subnetIds:[{Ref:"PublicSubnet1"},{Ref:"PublicSubnet2"}],securityGroupId:{Ref:D}});for(let S=0;S<R.length;S++)this.builder.addResource(T[S],R[S]);this.builder.addOutput(`${X}FileSystemId`,{Value:{Ref:E},Description:`EFS file system ID for ${X}`})}}let O=this.mergedConfig.infrastructure?.ai;if(O){let X=O.service||"ecs",_=O.models||["*"],q=O.allowStreaming!==!1,E;if(X==="ecs")E=z1.enableBedrockForEcs({slug:$,environment:J,models:_,allowStreaming:q});else if(X==="ec2")E=z1.enableBedrockForEc2({slug:$,environment:J,models:_,allowStreaming:q});else if(X==="lambda")E=z1.enableBedrockForLambda({slug:$,environment:J,models:_,allowStreaming:q});else E=z1.createBedrockRole(X,{slug:$,environment:J,models:_,allowStreaming:q});if(this.builder.addResource(E.logicalId,E.role),O.allowAsync){let{policy:M,logicalId:D}=z1.createBedrockPolicy({slug:$,environment:J,models:_,allowStreaming:q,allowAsync:!0});this.builder.addResource(D,M)}this.builder.addOutput("BedrockRoleArn",{Value:{"Fn::GetAtt":[E.logicalId,"Arn"]},Description:"IAM role ARN with Bedrock permissions"})}}generateRealtimeResources($,J){let Y=this.mergedConfig.infrastructure?.realtime;if(!Y)return;let Q=Y.name||`${$}-${J}-realtime`,Z=Y.scaling||{},W=Y.storage||{type:"dynamodb"},G=Z.handlerMemory||256,U=Z.handlerTimeout||30,z=`${$}${J}RealtimeConnections`.replace(/[^a-zA-Z0-9]/g,""),H=`${$}${J}RealtimeChannels`.replace(/[^a-zA-Z0-9]/g,"");if(W.type==="dynamodb"){let T=W.dynamodb||{},S=T.billingMode||"PAY_PER_REQUEST";this.builder.addResource(z,{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${$}-${J}-realtime-connections`,BillingMode:S,AttributeDefinitions:[{AttributeName:"connectionId",AttributeType:"S"},{AttributeName:"userId",AttributeType:"S"}],KeySchema:[{AttributeName:"connectionId",KeyType:"HASH"}],GlobalSecondaryIndexes:[{IndexName:"userId-index",KeySchema:[{AttributeName:"userId",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"},...S==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:T.readCapacity||5,WriteCapacityUnits:T.writeCapacity||5}}}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0},...S==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:T.readCapacity||5,WriteCapacityUnits:T.writeCapacity||5}},...T.pointInTimeRecovery&&{PointInTimeRecoverySpecification:{PointInTimeRecoveryEnabled:!0}},Tags:[{Key:"Name",Value:`${$}-${J}-realtime-connections`},{Key:"Environment",Value:J}]}}),this.builder.addResource(H,{Type:"AWS::DynamoDB::Table",Properties:{TableName:`${$}-${J}-realtime-channels`,BillingMode:S,AttributeDefinitions:[{AttributeName:"channel",AttributeType:"S"},{AttributeName:"connectionId",AttributeType:"S"}],KeySchema:[{AttributeName:"channel",KeyType:"HASH"},{AttributeName:"connectionId",KeyType:"RANGE"}],GlobalSecondaryIndexes:[{IndexName:"connectionId-index",KeySchema:[{AttributeName:"connectionId",KeyType:"HASH"}],Projection:{ProjectionType:"ALL"},...S==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:T.readCapacity||5,WriteCapacityUnits:T.writeCapacity||5}}}],TimeToLiveSpecification:{AttributeName:"ttl",Enabled:!0},...S==="PROVISIONED"&&{ProvisionedThroughput:{ReadCapacityUnits:T.readCapacity||5,WriteCapacityUnits:T.writeCapacity||5}},Tags:[{Key:"Name",Value:`${$}-${J}-realtime-channels`},{Key:"Environment",Value:J}]}})}let A=`${$}${J}RealtimeRole`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(A,{Type:"AWS::IAM::Role",Properties:{RoleName:`${$}-${J}-realtime-handler-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"],Policies:[{PolicyName:"RealtimeHandlerPolicy",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:UpdateItem"],Resource:[{"Fn::GetAtt":[z,"Arn"]},{"Fn::Sub":`\${${z}.Arn}/index/*`},{"Fn::GetAtt":[H,"Arn"]},{"Fn::Sub":`\${${H}.Arn}/index/*`}]},{Effect:"Allow",Action:"execute-api:ManageConnections",Resource:{"Fn::Sub":"arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:*/*"}}]}}]}});let K=`${$}${J}RealtimeConnect`.replace(/[^a-zA-Z0-9]/g,""),B=`${$}${J}RealtimeDisconnect`.replace(/[^a-zA-Z0-9]/g,""),j=`${$}${J}RealtimeMessage`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(K,{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${$}-${J}-realtime-connect`,Runtime:"nodejs20.x",Handler:"index.handler",Role:{"Fn::GetAtt":[A,"Arn"]},MemorySize:G,Timeout:U,Environment:{Variables:{CONNECTIONS_TABLE:{Ref:z},CHANNELS_TABLE:{Ref:H},ENVIRONMENT:J}},Code:{ZipFile:this.generateConnectHandlerCode()}},DependsOn:[A,z]}),this.builder.addResource(B,{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${$}-${J}-realtime-disconnect`,Runtime:"nodejs20.x",Handler:"index.handler",Role:{"Fn::GetAtt":[A,"Arn"]},MemorySize:G,Timeout:U,Environment:{Variables:{CONNECTIONS_TABLE:{Ref:z},CHANNELS_TABLE:{Ref:H},ENVIRONMENT:J}},Code:{ZipFile:this.generateDisconnectHandlerCode()}},DependsOn:[A,z,H]}),this.builder.addResource(j,{Type:"AWS::Lambda::Function",Properties:{FunctionName:`${$}-${J}-realtime-message`,Runtime:"nodejs20.x",Handler:"index.handler",Role:{"Fn::GetAtt":[A,"Arn"]},MemorySize:G,Timeout:U,Environment:{Variables:{CONNECTIONS_TABLE:{Ref:z},CHANNELS_TABLE:{Ref:H},ENVIRONMENT:J}},Code:{ZipFile:this.generateMessageHandlerCode()}},DependsOn:[A,z,H]});let O=`${$}${J}RealtimeApi`.replace(/[^a-zA-Z0-9]/g,"");this.builder.addResource(O,{Type:"AWS::ApiGatewayV2::Api",Properties:{Name:Q,ProtocolType:"WEBSOCKET",RouteSelectionExpression:"$request.body.action",Tags:{Name:Q,Environment:J}}});let X=`${K}Permission`,_=`${B}Permission`,q=`${j}Permission`;this.builder.addResource(X,{Type:"AWS::Lambda::Permission",Properties:{FunctionName:{Ref:K},Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:{"Fn::Sub":`arn:aws:execute-api:\${AWS::Region}:\${AWS::AccountId}:\${${O}}/*/$connect`}}}),this.builder.addResource(_,{Type:"AWS::Lambda::Permission",Properties:{FunctionName:{Ref:B},Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:{"Fn::Sub":`arn:aws:execute-api:\${AWS::Region}:\${AWS::AccountId}:\${${O}}/*/$disconnect`}}}),this.builder.addResource(q,{Type:"AWS::Lambda::Permission",Properties:{FunctionName:{Ref:j},Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:{"Fn::Sub":`arn:aws:execute-api:\${AWS::Region}:\${AWS::AccountId}:\${${O}}/*/$default`}}});let E=`${O}ConnectInteg`,M=`${O}DisconnectInteg`,D=`${O}MessageInteg`;this.builder.addResource(E,{Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:{Ref:O},IntegrationType:"AWS_PROXY",IntegrationUri:{"Fn::Sub":`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${K}.Arn}/invocations`}}}),this.builder.addResource(M,{Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:{Ref:O},IntegrationType:"AWS_PROXY",IntegrationUri:{"Fn::Sub":`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${B}.Arn}/invocations`}}}),this.builder.addResource(D,{Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:{Ref:O},IntegrationType:"AWS_PROXY",IntegrationUri:{"Fn::Sub":`arn:aws:apigateway:\${AWS::Region}:lambda:path/2015-03-31/functions/\${${j}.Arn}/invocations`}}}),this.builder.addResource(`${O}ConnectRoute`,{Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:{Ref:O},RouteKey:"$connect",AuthorizationType:"NONE",Target:{"Fn::Sub":`integrations/\${${E}}`}}}),this.builder.addResource(`${O}DisconnectRoute`,{Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:{Ref:O},RouteKey:"$disconnect",Target:{"Fn::Sub":`integrations/\${${M}}`}}}),this.builder.addResource(`${O}DefaultRoute`,{Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:{Ref:O},RouteKey:"$default",Target:{"Fn::Sub":`integrations/\${${D}}`}}});let R=`${O}Stage`;if(this.builder.addResource(R,{Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:{Ref:O},StageName:J,AutoDeploy:!0,DefaultRouteSettings:{ThrottlingBurstLimit:Z.messagesPerSecond||1000,ThrottlingRateLimit:Z.messagesPerSecond||1000}}}),Y.monitoring?.enabled){let T=Y.monitoring,S=T.notificationTopicArn;if(!S&&T.notificationEmails?.length){let C=`${O}AlarmTopic`;this.builder.addResource(C,{Type:"AWS::SNS::Topic",Properties:{TopicName:`${$}-${J}-realtime-alarms`,DisplayName:"Realtime WebSocket Alarms"}}),T.notificationEmails.forEach((x,h)=>{this.builder.addResource(`${C}Sub${h}`,{Type:"AWS::SNS::Subscription",Properties:{TopicArn:{Ref:C},Protocol:"email",Endpoint:x}})}),S={Ref:C}}if(T.connectionThreshold)this.builder.addResource(`${O}ConnectionAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$}-${J}-realtime-connections`,AlarmDescription:`WebSocket connections exceed ${T.connectionThreshold}`,MetricName:"ConnectCount",Namespace:"AWS/ApiGateway",Statistic:"Sum",Period:300,EvaluationPeriods:2,Threshold:T.connectionThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ApiId",Value:{Ref:O}}],...S&&{AlarmActions:[S]}}});if(T.errorThreshold)this.builder.addResource(`${O}ErrorAlarm`,{Type:"AWS::CloudWatch::Alarm",Properties:{AlarmName:`${$}-${J}-realtime-errors`,AlarmDescription:`WebSocket errors exceed ${T.errorThreshold}/min`,MetricName:"ExecutionError",Namespace:"AWS/ApiGateway",Statistic:"Sum",Period:60,EvaluationPeriods:3,Threshold:T.errorThreshold,ComparisonOperator:"GreaterThanThreshold",Dimensions:[{Name:"ApiId",Value:{Ref:O}}],...S&&{AlarmActions:[S]}}})}this.builder.addOutput(`${O}Endpoint`,{Description:"WebSocket API endpoint URL",Value:{"Fn::Sub":`wss://\${${O}}.execute-api.\${AWS::Region}.amazonaws.com/${J}`},Export:{Name:{"Fn::Sub":"${AWS::StackName}-realtime-endpoint"}}}),this.builder.addOutput(`${O}Id`,{Description:"WebSocket API ID",Value:{Ref:O},Export:{Name:{"Fn::Sub":"${AWS::StackName}-realtime-api-id"}}})}generateConnectHandlerCode(){return`
|
|
5380
5380
|
const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');
|
|
5381
5381
|
const { DynamoDBDocumentClient, PutCommand } = require('@aws-sdk/lib-dynamodb');
|
|
5382
5382
|
|
package/dist/index.js
CHANGED
|
@@ -62108,8 +62108,8 @@ class InfrastructureGenerator {
|
|
|
62108
62108
|
storageBucketLogicalId(slug, env, name) {
|
|
62109
62109
|
return `${slug}-${env}-s3-${name}`.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
62110
62110
|
}
|
|
62111
|
-
pathMountRewriteFunctionCode(mountPath) {
|
|
62112
|
-
return `function handler(event) { var request = event.request; var prefix = ${JSON.stringify(mountPath)}; var uri = request.uri; if (uri === prefix) { uri = '/'; } else if (uri.indexOf(prefix + '/') === 0) { uri = uri.substring(prefix.length); } if (uri === '' || uri === '/') { request.uri = '/index.html'; return request; } if (uri.endsWith('/')) { request.uri = uri + 'index.html'; return request; } var lastSegment = uri.substring(uri.lastIndexOf('/') + 1); if (lastSegment.indexOf('.') === -1) { request.uri = uri + '/index.html'; return request; } request.uri = uri; return request; }`;
|
|
62111
|
+
pathMountRewriteFunctionCode(mountPath, rewriteStyle = "directory") {
|
|
62112
|
+
return `function handler(event) { var request = event.request; var prefix = ${JSON.stringify(mountPath)}; var rewriteStyle = ${JSON.stringify(rewriteStyle)}; var uri = request.uri; if (uri === prefix) { uri = '/'; } else if (uri.indexOf(prefix + '/') === 0) { uri = uri.substring(prefix.length); } if (uri === '' || uri === '/') { request.uri = '/index.html'; return request; } if (uri.endsWith('/')) { request.uri = uri + 'index.html'; return request; } var lastSegment = uri.substring(uri.lastIndexOf('/') + 1); if (lastSegment.indexOf('.') === -1) { request.uri = rewriteStyle === 'flat' ? uri + '.html' : uri + '/index.html'; return request; } request.uri = uri; return request; }`;
|
|
62113
62113
|
}
|
|
62114
62114
|
generate() {
|
|
62115
62115
|
const slug = this.mergedConfig.project.slug;
|
|
@@ -62998,6 +62998,7 @@ class InfrastructureGenerator {
|
|
|
62998
62998
|
name: bucketName,
|
|
62999
62999
|
config: bucketConfig,
|
|
63000
63000
|
mountPath: this.normalizeMountPath(bucketConfig),
|
|
63001
|
+
rewriteStyle: bucketConfig.pathRewriteStyle || "directory",
|
|
63001
63002
|
logicalId: this.storageBucketLogicalId(slug, env, bucketName)
|
|
63002
63003
|
})).filter((bucket) => bucket.name !== "public" && bucket.config.website && bucket.mountPath);
|
|
63003
63004
|
for (const [name, storageConfig] of Object.entries(this.mergedConfig.infrastructure.storage)) {
|
|
@@ -63140,7 +63141,7 @@ else if (!uri.includes('.')) { request.uri += '.html'; } return request; }`
|
|
|
63140
63141
|
Comment: `Path mount rewrite for ${slug} ${env} ${mountedBucket.name} at ${mountedBucket.mountPath}`,
|
|
63141
63142
|
Runtime: "cloudfront-js-2.0"
|
|
63142
63143
|
},
|
|
63143
|
-
FunctionCode: this.pathMountRewriteFunctionCode(mountedBucket.mountPath)
|
|
63144
|
+
FunctionCode: this.pathMountRewriteFunctionCode(mountedBucket.mountPath, mountedBucket.rewriteStyle)
|
|
63144
63145
|
}
|
|
63145
63146
|
});
|
|
63146
63147
|
origins.push({
|
|
@@ -63161,7 +63162,7 @@ else if (!uri.includes('.')) { request.uri += '.html'; } return request; }`
|
|
|
63161
63162
|
AllowedMethods: ["GET", "HEAD", "OPTIONS"],
|
|
63162
63163
|
CachedMethods: ["GET", "HEAD", "OPTIONS"],
|
|
63163
63164
|
Compress: true,
|
|
63164
|
-
CachePolicyId: "
|
|
63165
|
+
CachePolicyId: "4135ea2d-6df8-44a3-9df3-4b5a84be39ad",
|
|
63165
63166
|
FunctionAssociations: [{
|
|
63166
63167
|
EventType: "viewer-request",
|
|
63167
63168
|
FunctionARN: { "Fn::GetAtt": [mountedFunctionLogicalId, "FunctionARN"] }
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/ts-cloud",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.15",
|
|
5
5
|
"description": "A lightweight, performant infrastructure-as-code library and CLI for deploying both server-based (EC2) and serverless applications.",
|
|
6
6
|
"author": "Chris Breuer <chris@stacksjs.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -85,8 +85,8 @@
|
|
|
85
85
|
"test": "bun test"
|
|
86
86
|
},
|
|
87
87
|
"dependencies": {
|
|
88
|
-
"@ts-cloud/aws-types": "0.2.
|
|
89
|
-
"@ts-cloud/core": "0.2.
|
|
88
|
+
"@ts-cloud/aws-types": "0.2.15",
|
|
89
|
+
"@ts-cloud/core": "0.2.15",
|
|
90
90
|
"@stacksjs/ts-xml": "^0.1.0"
|
|
91
91
|
},
|
|
92
92
|
"devDependencies": {
|