balda 0.0.35 → 0.0.38

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/lib/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import Ct from'pino';import Ee from'path';import xe from'fs';import {execSync}from'child_process';import*as it from'readline';import {createRequire}from'module';import {Ajv}from'ajv';import Ot from'fast-json-stringify';import At from'crypto';var Qe=Object.defineProperty;var Ue=(l=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(l,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):l)(function(l){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+l+'" is not supported')});var x=(l,e,t,r)=>{for(var o=void 0,s=l.length-1,c;s>=0;s--)(c=l[s])&&(o=(c(e,t,o))||o);return o&&Qe(e,t,o),o};var ze=class{type;constructor(){this.type=this.getRunTime();}getRunTime(){if(typeof Bun<"u")return "bun";if(typeof Deno<"u")return "deno";if(typeof process<"u")return "node";throw new Error("No environment detected")}},O=new ze;var Be=class{getCliArgs(){switch(O.type){case "bun":return this.getBunArgs();case "node":return this.getNodeArgs();case "deno":return Deno.args;default:throw new Error("Unsupported runtime")}}getCliCaller(){switch(O.type){case "bun":return "bun";case "node":return process.argv[0];case "deno":return "deno";default:throw new Error("Unsupported runtime")}}getBunArgs(){let e=Bun.argv,t=this.findScriptIndex(e);return e.slice(t+1)}getNodeArgs(){let e=process.argv,t=this.findScriptIndex(e);return e.slice(t+1)}findScriptIndex(e){if(e.length>=3&&e[1].includes(".bin/"))return 1;for(let t=0;t<e.length;t++){let r=e[t],o=r.split("/").pop()||r;if(!r.startsWith("-")){if(o==="yarn"&&t+1<e.length&&e[t+1]==="run"||o==="npx"&&t+1<e.length)return t+1;if(o==="yarn"||o==="pnpm")return t;if(o==="npm"&&t+1<e.length&&e[t+1]==="run"||o==="bun"&&t+1<e.length&&e[t+1]==="run")return t+1;if(/\.(js|ts|mjs|cjs)$/.test(r))return t;if(/^(tsx|ts-node|node|bun)$/.test(o)){for(let s=t+1;s<e.length;s++)if(!e[s].startsWith("-")&&/\.(js|ts|mjs|cjs)$/.test(e[s]))return s;return t}}}for(let t=e.length-1;t>=0;t--)if(!e[t].startsWith("-"))return t;return 1}},fe=new Be;var tt=(l,e)=>{let t=Array(e.length+1).fill(null).map(()=>Array(l.length+1).fill(null));for(let r=0;r<=l.length;r++)t[0][r]=r;for(let r=0;r<=e.length;r++)t[r][0]=r;for(let r=1;r<=e.length;r++)for(let o=1;o<=l.length;o++){let s=l[o-1]===e[r-1]?0:1;t[r][o]=Math.min(t[r][o-1]+1,t[r-1][o]+1,t[r-1][o-1]+s);}return t[e.length][l.length]},qe=l=>l.toLowerCase().replace(/[-_.]/g,"_").replace(/([A-Z])/g,"_$1").replace(/^_+/,"").replace(/_+$/,"").toLowerCase(),Oe=l=>l.split(/[-_.]/g).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(""),rt=l=>l.split(/[-_.]/g).map(e=>e.toLowerCase()).join("-");var St=l=>{if(!l||l==="-"||l==="--")return null;let e=l.indexOf("=");if(e>0){let t=l.substring(0,e),r=l.substring(e+1);return {name:t,value:st(r)}}return {name:l,value:true}},st=l=>{if(l.toLowerCase()==="true")return true;if(l.toLowerCase()==="false")return false;let e=Number(l);return !Number.isNaN(e)&&Number.isFinite(e)?e:l},Y=()=>{let l=fe.getCliArgs(),e=[],t={};if(!l||!l.length)return {args:e,flags:t};for(let r=0;r<l.length;r++){let o=l[r];if(!(!o||typeof o!="string")){if(o.startsWith("-")){let s=St(o);if(s){if(s.value===true&&r+1<l.length){let c=l[r+1];c&&typeof c=="string"&&!c.startsWith("-")&&(s.value=st(c),r++);}if(s.name in t){let c=t[s.name];Array.isArray(c)?c.push(s.value):t[s.name]=[c,s.value];}else t[s.name]=s.value;}continue}e.push(o);}}return {args:e,flags:t}},ot=(l,e)=>{if(!l||typeof l!="string"||!e||!Array.isArray(e)||e.length===0)return "";let t=l.toLowerCase().trim(),r=e.filter(c=>{let a=c.toLowerCase();if(a===t||a.includes(t)||t.includes(a))return true;let d=tt(a,t),u=Math.max(t.length,a.length)*.4;return d<=u});if(r.length===0)return "";let s=r.slice(0,3).map(c=>`\x1B[36m${c}\x1B[0m`).join(", ");return `\x1B[31m\u2717\x1B[0m Command \x1B[33m${l}\x1B[0m not found
3
- \x1B[32m\u{1F4A1}\x1B[0m Did you mean: ${s}?`},$e=()=>fe.getCliArgs()[0]||null;var Pt=()=>Ct({level:"info",formatters:{level:e=>({level:e})}}),M=Pt();var Le=class{getCwd(){switch(O.type){case "node":case "bun":return process.cwd();case "deno":return Deno.cwd();default:throw new Error("Unsupported runtime")}}},N=new Le;var He=class{basename(e){switch(O.type){case "node":case "bun":case "deno":return Ee.basename(e);default:throw new Error("Unsupported runtime")}}join(...e){switch(O.type){case "node":case "bun":case "deno":return Ee.join(...e);default:throw new Error("Unsupported runtime")}}extName(e){switch(O.type){case "bun":case "node":case "deno":return Ee.extname(e);default:throw new Error("Unsupported runtime")}}resolve(...e){switch(O.type){case "bun":case "node":case "deno":return Ee.resolve(...e);default:throw new Error("Unsupported runtime")}}},w=new He;var _=class{static metadata=new WeakMap;static set(e,t,r){this.metadata.has(e)||this.metadata.set(e,new Map),this.metadata.get(e).set(t,r);}static get(e,t){return this.metadata.get(e)?.get(t)}static getAll(e){return this.metadata.get(e)}static getOrCreateAll(e){return this.metadata.has(e)||this.metadata.set(e,new Map),this.metadata.get(e)}static delete(e,t){this.metadata.get(e)?.delete(t);}static clear(e){this.metadata.delete(e);}};var ee="VALIDATION_ERROR";var nt=Y().args.slice(1),$=l=>(e,t)=>{let r=$e();if(!r||r!==e.commandName)return;let o=t;_.set(e,t,{type:"arg",name:o,description:l.description});let s=nt.length?nt.shift():l.defaultValue;if(l.required&&!s){let c=_.get(e,ee);_.set(e,ee,[...c||[],{type:"arg",name:o,message:"Required argument not provided"}]);return}l.parse&&s&&(s=l.parse(s)),Object.defineProperty(e,t,{value:s,enumerable:true,configurable:true,writable:true});};var Je=class{exit(e){switch(O.type){case "bun":case "node":process.exit(e);case "deno":Deno.exit(e);default:throw new Error(`Unsupported runtime: ${O.type}`)}}},L=new Je;var q=class{static flagsAndArgs={flags:Y().flags,args:Y().args.slice(1)};static commandName=this.name;static calledBy=this.name;static description="";static help=[];static options={keepAlive:false,loggerPath:"src/logger.ts",allowUnknownFlags:true};static args=this.flagsAndArgs.args;static flags=this.flagsAndArgs.flags;static logger=M.child({scope:this.constructor.name});static handle(){throw new Error(`Handle method not implemented in command class ${this.name}`)}static handleHelpFlag(e){let t=["-h","--help"];if(!Object.keys(e).some(u=>t.includes(u)))return;let o=this.commandName,s=this.description||"No description available",c=this.help||[],a=this.options,d=this.generateHelpOutput({name:o,description:s,helpText:c,options:a,args:this.args,flags:this.flags},this);console.log(d),L.exit(0);}static generateHelpOutput=(e,t)=>{let{name:r,description:o,helpText:s,options:c,args:a,flags:d}=e,u={title:"\x1B[1;36m",subtitle:"\x1B[1;33m",description:"\x1B[0;37m",code:"\x1B[0;32m",flag:"\x1B[0;35m",reset:"\x1B[0m",error:"\x1B[0;31m",success:"\x1B[0;32m",info:"\x1B[0;34m"},i=[`${u.title}${r}${u.reset}`,`${u.description}${o}${u.reset}`,"",`${u.subtitle}Usage:${u.reset}`,` ${u.code}${r}${u.reset} [options] [arguments]`,"",`${u.subtitle}Options:${u.reset}`,` ${u.flag}-h, --help${u.reset} Show this help message`,"",`${u.subtitle}Command Options:${u.reset}`,` ${u.flag}keepAlive${u.reset} ${c?.keepAlive??false?u.success+"Enabled"+u.reset:u.error+"Disabled"+u.reset}`,` ${u.flag}loggerPath${u.reset} ${c?.loggerPath??"src/logger.ts"}`,` ${u.flag}allowUnknownFlags${u.reset} ${c?.allowUnknownFlags??true?u.success+"Enabled"+u.reset:u.error+"Disabled"+u.reset}`,""];if(s){let h=Array.isArray(s)?s:[s];i.push(`${u.subtitle}Help:${u.reset}`),h.forEach(g=>{i.push(` ${u.description}${g}${u.reset}`);}),i.push("");}let n=_.getAll(t),p=n?Array.from(n.values()).filter(h=>h.type==="arg"):[],m=n?Array.from(n.values()).filter(h=>h.type==="flag"):[];return p.length&&(i.push(`${u.subtitle}Available Arguments:${u.reset}`),p.forEach(h=>{let g=h.required?` ${u.error}(required)${u.reset}`:"",y=h.description?` ${u.description}${h.description}${u.reset}`:"";i.push(` ${u.code}${h.name}${u.reset}${g}${y}`);}),i.push("")),m.length&&(i.push(`${u.subtitle}Available Flags:${u.reset}`),m.forEach(h=>{h.aliases&&!Array.isArray(h.aliases)&&(h.aliases=[h.aliases]);let g=h.aliases.length?` ${u.flag}(${h.aliases.join(", ")})${u.reset}`:"",y=h.required?` ${u.error}(required)${u.reset}`:"",b=h.description?` ${u.description}${h.description}${u.reset}`:"";i.push(` ${u.flag}--${h.name}${g}${u.reset}${y}${b}`);}),i.push("")),((a?.length??0)>0||d&&Object.keys(d).length>0)&&(i.push(`${u.subtitle}Current Context:${u.reset}`),a?.length&&i.push(` ${u.info}Provided Arguments:${u.reset} ${u.code}${a.join(" ")}${u.reset}`),d&&Object.keys(d).length>0&&(i.push(` ${u.info}Provided Flags:${u.reset}`),Object.keys(d).forEach(h=>{let g=d[h],y=g!=null?` = ${u.code}${g}${u.reset}`:"";i.push(` ${u.flag}${h}${u.reset}${y}`);})),i.push("")),s&&(Array.isArray(s)?s.some(h=>h.includes("example")):s.includes("example"))&&(i.push(`${u.subtitle}Examples:${u.reset}`),(Array.isArray(s)?s.filter(g=>g.includes("example")):[s.split("example")[1].trim()]).forEach(g=>{i.push(` ${u.code}${g}${u.reset}`);}),i.push("")),i.join(`
4
- `)};static validateUnknownFlags=e=>{if(e.options?.allowUnknownFlags!==false)return;let t=new Set(["-h","--help"]),r=new Set,o=_.getAll(e);if(o){for(let c of o.values())if(c.type==="flag"&&(r.add(`--${c.name}`),r.add(`-${c.name}`),r.add(c.name),c.aliases)){let a=Array.isArray(c.aliases)?c.aliases:[c.aliases];for(let d of a)r.add(`--${d}`),r.add(`-${d}`),r.add(d);}}let s=Object.keys(e.flags).filter(c=>!t.has(c)&&!r.has(c));if(s.length){let c={error:"\x1B[0;31m",title:"\x1B[1;31m",reset:"\x1B[0m",info:"\x1B[0;34m",flag:"\x1B[0;35m"};console.error(`${c.title}\u274C Unknown Flags:${c.reset}`),console.error(""),s.forEach(a=>{console.error(` ${c.error}\u2022${c.reset} ${c.flag}${a}${c.reset}`);}),console.error(""),console.error(`${c.info}\u{1F4A1} Tip: Use --help for available flags${c.reset}`),L.exit(1);}};static validateContext=e=>{let t=Array.from(_.get(e,ee)||[]);if(t.length){let r={error:"\x1B[0;31m",title:"\x1B[1;31m",reset:"\x1B[0m",info:"\x1B[0;34m",code:"\x1B[0;32m"};console.error(`${r.title}\u274C Validation Errors:${r.reset}`),console.error(""),t.forEach((o,s)=>{let c=`${r.info}${s+1}.${r.reset}`,a=`${r.error}${o.type.toUpperCase()}${r.reset}`,d=`${r.code}${o.name}${r.reset}`;console.error(` ${c} ${a} ${d}: ${r.error}${o.message}${r.reset}`);}),console.error(""),console.error(`${r.info}\u{1F4A1} Tip: Use --help for usage information${r.reset}`),L.exit(1);}}};var B=l=>(e,t)=>{let r=$e();if(!r||r!==e.commandName)return;let o=l.name||t,s=Y().flags,c=l.aliases?Array.isArray(l.aliases)?l.aliases:[l.aliases]:[],a=[o,...c],d=l.defaultValue;for(let u of a){let i=[u,`-${u}`,`--${u}`];for(let n of i)if(n in s){let p=s[n];l.type==="list"?d=(Array.isArray(p)?p:[p]).map(h=>{let g=String(h);return l.parse?l.parse(g):g}):(d=p,l.type==="boolean"?d=!!d:l.type==="number"?d=Number(d):l.type==="string"&&(d=String(d)),l.parse&&(d=l.parse(d)));break}if(d!==l.defaultValue)break}if(_.set(e,t,{type:"flag",name:o,aliases:c||[],description:l.description}),l.required&&(l.type==="list"?!d||Array.isArray(d)&&d.length===0:!d)){let i=_.get(e,ee);_.set(e,ee,[...i||[],{type:"flag",name:o,message:"Required flag not provided"}]);return}Object.defineProperty(e,t,{value:d,enumerable:true,configurable:true,writable:true});};B.boolean=l=>B({...l,type:"boolean"});B.string=l=>B({...l,type:"string"});B.number=l=>B({...l,type:"number"});B.list=l=>B({...l,type:"list"});B.array=l=>B({...l,type:"list"});var P=B;var We=class{async glob(...e){let t=await import('fs/promises'),r=N.getCwd(),o=w.resolve(r,e[1]?.cwd??""),s=[];for await(let c of t.glob(...e)){if(typeof c=="string"){s.push(w.resolve(o,c));continue}c.isFile()&&s.push(w.resolve(o,c.name));}return s}async mkdir(e,t){switch(O.type){case "bun":case "node":await(await import('fs/promises')).mkdir(e,{recursive:t?.recursive??false,mode:t?.mode});break;case "deno":typeof t?.mode=="string"&&(t.mode=Number.parseInt(t.mode)),await Deno.mkdir(e,{recursive:t?.recursive??false,mode:t?.mode});break}}async exists(e){switch(O.type){case "node":return (await import('fs')).existsSync(e);case "bun":return (await import('fs')).existsSync(e);case "deno":return Deno.stat(e).then(()=>true).catch(()=>false);default:throw new Error("Unsupported runtime")}}async readFile(e,t){switch(O.type){case "node":let o=await(await import('fs/promises')).readFile(e,{encoding:t?.encoding??null});return t?.encoding==="utf8"?o:new Uint8Array(o);case "bun":let s=Bun.file(e);return t?.encoding==="utf8"?s.text():new Uint8Array(await s.arrayBuffer());case "deno":let c=await Deno.readFile(e);return t?.encoding==="utf8"?new TextDecoder().decode(c):new Uint8Array(c)}}async writeFile(e,t){switch(O.type){case "node":await(await import('fs/promises')).writeFile(e,t);break;case "bun":await Bun.write(e,t);break;case "deno":await Deno.writeFile(e,t);break}}async stat(e){switch(O.type){case "node":let r=await(await import('fs/promises')).stat(e);return {isDirectory:r.isDirectory(),isFile:r.isFile(),isSymbolicLink:r.isSymbolicLink(),size:r.size};case "bun":let s=await(await import('fs/promises')).stat(e);return {isDirectory:s.isDirectory(),isFile:s.isFile(),isSymbolicLink:s.isSymbolicLink(),size:s.size};case "deno":let c=await Deno.stat(e);return {isDirectory:c.isDirectory,isFile:c.isFile,isSymbolicLink:false,size:c.size}}}async unlink(e){switch(O.type){case "node":await(await import('fs/promises')).unlink(e);break;case "bun":await Bun.file(e).delete();break;case "deno":await Deno.remove(e);break;default:throw new Error("Unsupported runtime")}}async streamFile(e){switch(O.type){case "node":let t=await import('fs'),{Readable:r}=await import('stream'),o=t.createReadStream(e);return r.toWeb(o);case "bun":return Bun.file(e).stream();case "deno":return (await Deno.open(e)).readable;default:throw new Error("Unsupported runtime")}}async readdir(e){switch(O.type){case "bun":case "node":return (await import('fs/promises')).readdir(e);case "deno":let r=[];for await(let o of Deno.readDir(e))r.push(o.name);return r;default:throw new Error("Unsupported runtime")}}},f=new We;var Me=typeof import.meta<"u"?createRequire(import.meta.url):Ue("module").createRequire?.(import.meta?.url??__filename)??Ue,V=async l=>{let e=w.join(process.cwd(),"node_modules");if(!await f.exists(e))return l;let r=[];for(let o of l){let s=w.join(e,o);await f.exists(s)||r.push(o);}return r},F=async()=>await f.exists(w.join(process.cwd(),"yarn.lock"))?["yarn","add","-D"]:await f.exists(w.join(process.cwd(),"pnpm-lock.yaml"))?["pnpm","add","-D"]:await f.exists(w.join(process.cwd(),"package-lock.json"))?["npm","install","-D"]:await f.exists(w.join(process.cwd(),"bun.lockb"))?["bun","add","-D"]:await f.exists(w.join(process.cwd(),"deno.lock"))?["deno","add","-D"]:["npm","install","-D"],A=async(l,e,t,r,o=true)=>{let s=it.createInterface({input:process.stdin,output:process.stdout}),c=t.join(", "),a=`Do you want to install the following ${o?"dev":""} dependencies using ${e}?
3
+ \x1B[32m\u{1F4A1}\x1B[0m Did you mean: ${s}?`},$e=()=>fe.getCliArgs()[0]||null;var Pt=()=>Ct({level:"info",formatters:{level:e=>({level:e})}}),M=Pt();var Le=class{getCwd(){switch(O.type){case "node":case "bun":return process.cwd();case "deno":return Deno.cwd();default:throw new Error("Unsupported runtime")}}},N=new Le;var He=class{basename(e){switch(O.type){case "node":case "bun":case "deno":return Ee.basename(e);default:throw new Error("Unsupported runtime")}}join(...e){switch(O.type){case "node":case "bun":case "deno":return Ee.join(...e);default:throw new Error("Unsupported runtime")}}extName(e){switch(O.type){case "bun":case "node":case "deno":return Ee.extname(e);default:throw new Error("Unsupported runtime")}}resolve(...e){switch(O.type){case "bun":case "node":case "deno":return Ee.resolve(...e);default:throw new Error("Unsupported runtime")}}},w=new He;var _=class{static metadata=new WeakMap;static set(e,t,r){this.metadata.has(e)||this.metadata.set(e,new Map),this.metadata.get(e).set(t,r);}static get(e,t){return this.metadata.get(e)?.get(t)}static getAll(e){return this.metadata.get(e)}static getOrCreateAll(e){return this.metadata.has(e)||this.metadata.set(e,new Map),this.metadata.get(e)}static delete(e,t){this.metadata.get(e)?.delete(t);}static clear(e){this.metadata.delete(e);}};var ee="VALIDATION_ERROR";var nt=Y().args.slice(1),$=l=>(e,t)=>{let r=$e();if(!r||r!==e.commandName)return;let o=t;_.set(e,t,{type:"arg",name:o,description:l.description});let s=nt.length?nt.shift():l.defaultValue;if(l.required&&!s){let c=_.get(e,ee);_.set(e,ee,[...c||[],{type:"arg",name:o,message:"Required argument not provided"}]);return}l.parse&&s&&(s=l.parse(s)),Object.defineProperty(e,t,{value:s,enumerable:true,configurable:true,writable:true});};var Je=class{exit(e){switch(O.type){case "bun":case "node":process.exit(e);case "deno":Deno.exit(e);default:throw new Error(`Unsupported runtime: ${O.type}`)}}},H=new Je;var q=class{static flagsAndArgs={flags:Y().flags,args:Y().args.slice(1)};static commandName=this.name;static calledBy=this.name;static description="";static help=[];static options={keepAlive:false,loggerPath:"src/logger.ts",allowUnknownFlags:true};static args=this.flagsAndArgs.args;static flags=this.flagsAndArgs.flags;static logger=M.child({scope:this.constructor.name});static handle(){throw new Error(`Handle method not implemented in command class ${this.name}`)}static handleHelpFlag(e){let t=["-h","--help"];if(!Object.keys(e).some(u=>t.includes(u)))return;let o=this.commandName,s=this.description||"No description available",c=this.help||[],a=this.options,d=this.generateHelpOutput({name:o,description:s,helpText:c,options:a,args:this.args,flags:this.flags},this);console.log(d),H.exit(0);}static generateHelpOutput=(e,t)=>{let{name:r,description:o,helpText:s,options:c,args:a,flags:d}=e,u={title:"\x1B[1;36m",subtitle:"\x1B[1;33m",description:"\x1B[0;37m",code:"\x1B[0;32m",flag:"\x1B[0;35m",reset:"\x1B[0m",error:"\x1B[0;31m",success:"\x1B[0;32m",info:"\x1B[0;34m"},i=[`${u.title}${r}${u.reset}`,`${u.description}${o}${u.reset}`,"",`${u.subtitle}Usage:${u.reset}`,` ${u.code}${r}${u.reset} [options] [arguments]`,"",`${u.subtitle}Options:${u.reset}`,` ${u.flag}-h, --help${u.reset} Show this help message`,"",`${u.subtitle}Command Options:${u.reset}`,` ${u.flag}keepAlive${u.reset} ${c?.keepAlive??false?u.success+"Enabled"+u.reset:u.error+"Disabled"+u.reset}`,` ${u.flag}loggerPath${u.reset} ${c?.loggerPath??"src/logger.ts"}`,` ${u.flag}allowUnknownFlags${u.reset} ${c?.allowUnknownFlags??true?u.success+"Enabled"+u.reset:u.error+"Disabled"+u.reset}`,""];if(s){let h=Array.isArray(s)?s:[s];i.push(`${u.subtitle}Help:${u.reset}`),h.forEach(g=>{i.push(` ${u.description}${g}${u.reset}`);}),i.push("");}let n=_.getAll(t),p=n?Array.from(n.values()).filter(h=>h.type==="arg"):[],m=n?Array.from(n.values()).filter(h=>h.type==="flag"):[];return p.length&&(i.push(`${u.subtitle}Available Arguments:${u.reset}`),p.forEach(h=>{let g=h.required?` ${u.error}(required)${u.reset}`:"",y=h.description?` ${u.description}${h.description}${u.reset}`:"";i.push(` ${u.code}${h.name}${u.reset}${g}${y}`);}),i.push("")),m.length&&(i.push(`${u.subtitle}Available Flags:${u.reset}`),m.forEach(h=>{h.aliases&&!Array.isArray(h.aliases)&&(h.aliases=[h.aliases]);let g=h.aliases.length?` ${u.flag}(${h.aliases.join(", ")})${u.reset}`:"",y=h.required?` ${u.error}(required)${u.reset}`:"",b=h.description?` ${u.description}${h.description}${u.reset}`:"";i.push(` ${u.flag}--${h.name}${g}${u.reset}${y}${b}`);}),i.push("")),((a?.length??0)>0||d&&Object.keys(d).length>0)&&(i.push(`${u.subtitle}Current Context:${u.reset}`),a?.length&&i.push(` ${u.info}Provided Arguments:${u.reset} ${u.code}${a.join(" ")}${u.reset}`),d&&Object.keys(d).length>0&&(i.push(` ${u.info}Provided Flags:${u.reset}`),Object.keys(d).forEach(h=>{let g=d[h],y=g!=null?` = ${u.code}${g}${u.reset}`:"";i.push(` ${u.flag}${h}${u.reset}${y}`);})),i.push("")),s&&(Array.isArray(s)?s.some(h=>h.includes("example")):s.includes("example"))&&(i.push(`${u.subtitle}Examples:${u.reset}`),(Array.isArray(s)?s.filter(g=>g.includes("example")):[s.split("example")[1].trim()]).forEach(g=>{i.push(` ${u.code}${g}${u.reset}`);}),i.push("")),i.join(`
4
+ `)};static validateUnknownFlags=e=>{if(e.options?.allowUnknownFlags!==false)return;let t=new Set(["-h","--help"]),r=new Set,o=_.getAll(e);if(o){for(let c of o.values())if(c.type==="flag"&&(r.add(`--${c.name}`),r.add(`-${c.name}`),r.add(c.name),c.aliases)){let a=Array.isArray(c.aliases)?c.aliases:[c.aliases];for(let d of a)r.add(`--${d}`),r.add(`-${d}`),r.add(d);}}let s=Object.keys(e.flags).filter(c=>!t.has(c)&&!r.has(c));if(s.length){let c={error:"\x1B[0;31m",title:"\x1B[1;31m",reset:"\x1B[0m",info:"\x1B[0;34m",flag:"\x1B[0;35m"};console.error(`${c.title}\u274C Unknown Flags:${c.reset}`),console.error(""),s.forEach(a=>{console.error(` ${c.error}\u2022${c.reset} ${c.flag}${a}${c.reset}`);}),console.error(""),console.error(`${c.info}\u{1F4A1} Tip: Use --help for available flags${c.reset}`),H.exit(1);}};static validateContext=e=>{let t=Array.from(_.get(e,ee)||[]);if(t.length){let r={error:"\x1B[0;31m",title:"\x1B[1;31m",reset:"\x1B[0m",info:"\x1B[0;34m",code:"\x1B[0;32m"};console.error(`${r.title}\u274C Validation Errors:${r.reset}`),console.error(""),t.forEach((o,s)=>{let c=`${r.info}${s+1}.${r.reset}`,a=`${r.error}${o.type.toUpperCase()}${r.reset}`,d=`${r.code}${o.name}${r.reset}`;console.error(` ${c} ${a} ${d}: ${r.error}${o.message}${r.reset}`);}),console.error(""),console.error(`${r.info}\u{1F4A1} Tip: Use --help for usage information${r.reset}`),H.exit(1);}}};var B=l=>(e,t)=>{let r=$e();if(!r||r!==e.commandName)return;let o=l.name||t,s=Y().flags,c=l.aliases?Array.isArray(l.aliases)?l.aliases:[l.aliases]:[],a=[o,...c],d=l.defaultValue;for(let u of a){let i=[u,`-${u}`,`--${u}`];for(let n of i)if(n in s){let p=s[n];l.type==="list"?d=(Array.isArray(p)?p:[p]).map(h=>{let g=String(h);return l.parse?l.parse(g):g}):(d=p,l.type==="boolean"?d=!!d:l.type==="number"?d=Number(d):l.type==="string"&&(d=String(d)),l.parse&&(d=l.parse(d)));break}if(d!==l.defaultValue)break}if(_.set(e,t,{type:"flag",name:o,aliases:c||[],description:l.description}),l.required&&(l.type==="list"?!d||Array.isArray(d)&&d.length===0:!d)){let i=_.get(e,ee);_.set(e,ee,[...i||[],{type:"flag",name:o,message:"Required flag not provided"}]);return}Object.defineProperty(e,t,{value:d,enumerable:true,configurable:true,writable:true});};B.boolean=l=>B({...l,type:"boolean"});B.string=l=>B({...l,type:"string"});B.number=l=>B({...l,type:"number"});B.list=l=>B({...l,type:"list"});B.array=l=>B({...l,type:"list"});var P=B;var We=class{async glob(...e){let t=await import('fs/promises'),r=N.getCwd(),o=w.resolve(r,e[1]?.cwd??""),s=[];for await(let c of t.glob(...e)){if(typeof c=="string"){s.push(w.resolve(o,c));continue}c.isFile()&&s.push(w.resolve(o,c.name));}return s}async mkdir(e,t){switch(O.type){case "bun":case "node":await(await import('fs/promises')).mkdir(e,{recursive:t?.recursive??false,mode:t?.mode});break;case "deno":typeof t?.mode=="string"&&(t.mode=Number.parseInt(t.mode)),await Deno.mkdir(e,{recursive:t?.recursive??false,mode:t?.mode});break}}async exists(e){switch(O.type){case "node":return (await import('fs')).existsSync(e);case "bun":return (await import('fs')).existsSync(e);case "deno":return Deno.stat(e).then(()=>true).catch(()=>false);default:throw new Error("Unsupported runtime")}}async readFile(e,t){switch(O.type){case "node":let o=await(await import('fs/promises')).readFile(e,{encoding:t?.encoding??null});return t?.encoding==="utf8"?o:new Uint8Array(o);case "bun":let s=Bun.file(e);return t?.encoding==="utf8"?s.text():new Uint8Array(await s.arrayBuffer());case "deno":let c=await Deno.readFile(e);return t?.encoding==="utf8"?new TextDecoder().decode(c):new Uint8Array(c)}}async writeFile(e,t){switch(O.type){case "node":await(await import('fs/promises')).writeFile(e,t);break;case "bun":await Bun.write(e,t);break;case "deno":await Deno.writeFile(e,t);break}}async stat(e){switch(O.type){case "node":let r=await(await import('fs/promises')).stat(e);return {isDirectory:r.isDirectory(),isFile:r.isFile(),isSymbolicLink:r.isSymbolicLink(),size:r.size};case "bun":let s=await(await import('fs/promises')).stat(e);return {isDirectory:s.isDirectory(),isFile:s.isFile(),isSymbolicLink:s.isSymbolicLink(),size:s.size};case "deno":let c=await Deno.stat(e);return {isDirectory:c.isDirectory,isFile:c.isFile,isSymbolicLink:false,size:c.size}}}async unlink(e){switch(O.type){case "node":await(await import('fs/promises')).unlink(e);break;case "bun":await Bun.file(e).delete();break;case "deno":await Deno.remove(e);break;default:throw new Error("Unsupported runtime")}}async streamFile(e){switch(O.type){case "node":let t=await import('fs'),{Readable:r}=await import('stream'),o=t.createReadStream(e);return r.toWeb(o);case "bun":return Bun.file(e).stream();case "deno":return (await Deno.open(e)).readable;default:throw new Error("Unsupported runtime")}}async readdir(e){switch(O.type){case "bun":case "node":return (await import('fs/promises')).readdir(e);case "deno":let r=[];for await(let o of Deno.readDir(e))r.push(o.name);return r;default:throw new Error("Unsupported runtime")}}},f=new We;var Me=typeof import.meta<"u"?createRequire(import.meta.url):Ue("module").createRequire?.(import.meta?.url??__filename)??Ue,V=async l=>{let e=w.join(process.cwd(),"node_modules");if(!await f.exists(e))return l;let r=[];for(let o of l){let s=w.join(e,o);await f.exists(s)||r.push(o);}return r},F=async()=>await f.exists(w.join(process.cwd(),"yarn.lock"))?["yarn","add","-D"]:await f.exists(w.join(process.cwd(),"pnpm-lock.yaml"))?["pnpm","add","-D"]:await f.exists(w.join(process.cwd(),"package-lock.json"))?["npm","install","-D"]:await f.exists(w.join(process.cwd(),"bun.lockb"))?["bun","add","-D"]:await f.exists(w.join(process.cwd(),"deno.lock"))?["deno","add","-D"]:["npm","install","-D"],A=async(l,e,t,r,o=true)=>{let s=it.createInterface({input:process.stdin,output:process.stdout}),c=t.join(", "),a=`Do you want to install the following ${o?"dev":""} dependencies using ${e}?
5
5
  ${c}
6
6
  (y/n): `;return new Promise(d=>{s.question(a,u=>{if(s.close(),u.toLowerCase()==="y"||u.toLowerCase()==="yes"){execSync(l,r),d(true);return}d(false);});})};var D=class extends q{static commandName="build";static description="Build the project for production, node.js only";static help=["Build the project for production, node.js only","It will create a production build of the project in the dist directory","Must have a tsconfig.json file in the root of the project","Must have esbuild installed as a dependency while running the command","Must have esbuild-plugin-copy installed as a dependency while running the command if you want to copy assets to the output directory","Example: npx balda build -t ./tsconfig.json -a ./assets"];static clearDist;static entry;static output;static tsconfig;static assets;static format;static packages;static sourcemap;static async handle(){if(typeof process===void 0&&(this.logger.error("Build command is only supported in node.js"),process.exit(1)),["esm","cjs"].includes(this.format)||(this.logger.error("Invalid format, must be 'esm' or 'cjs'"),process.exit(1)),["bundle","external"].includes(this.packages)||(this.logger.error("Invalid packages, must be 'bundle' or 'external'"),process.exit(1)),!await import('esbuild').then(a=>true).catch(()=>false)){let[a,d,u]=await F();await A(`${a} ${d} esbuild ${u}`,a,["esbuild"],{stdio:"inherit"})||(this.logger.warn("User chose to not continue with the installation of esbuild, exiting..."),process.exit(0));}let t=await import('esbuild').catch(a=>{throw this.logger.error("esbuild is not installed, please install it with `npm install -D esbuild` to use the build command"),new Error("esbuild is not installed")}),r=Ee.join(this.output,"assets"),o=[];if(this.assets){let{copy:a}=await import('esbuild-plugin-copy').catch(d=>{throw this.logger.error("esbuild-plugin-copy is not installed, please install it with `npm install -D esbuild-plugin-copy` to use the build command"),new Error("esbuild-plugin-copy is not installed")});xe.existsSync(r)||xe.mkdirSync(r,{recursive:true}),o.push(a({assets:{from:this.assets,to:r}}));}this.clearDist&&xe.existsSync(this.output)&&(this.logger.info("Clearing dist directory..."),xe.rmSync(this.output,{recursive:true})),this.logger.info("Building project...");let s=Ee.join(this.output,"server.js"),c=await t.build({tsconfig:this.tsconfig,entryPoints:[this.entry],bundle:true,platform:"node",outfile:s,minify:true,sourcemap:this.sourcemap,plugins:o,format:this.format,packages:this.packages});c.errors.length&&(this.logger.error(JSON.stringify({message:"Failed to build the project",errors:c.errors},null,2)),process.exit(1)),c.warnings.length&&this.logger.warn(JSON.stringify({message:"Failed to build the project",warnings:c.warnings},null,2)),this.logger.info(JSON.stringify({message:`Project built successfully in ${s}`,output:s,assets:!!this.assets},null,2)),process.exit(0);}};x([P({type:"boolean",aliases:["c"],name:"clear-dist",required:false,defaultValue:false,description:"Whether to clear the dist directory before building the project"})],D,"clearDist"),x([P({type:"string",aliases:["e"],name:"entry",required:false,defaultValue:"./src/index.ts",description:"The entry point of the project, default is ./src/index.ts"})],D,"entry"),x([P({type:"string",aliases:["o"],name:"output",required:false,defaultValue:"./dist",description:"The path to the output directory, default is ./dist"})],D,"output"),x([P({type:"string",aliases:["t"],name:"tsconfig",required:false,defaultValue:"./tsconfig.json",description:"The path to the tsconfig.json file, default is ./tsconfig.json"})],D,"tsconfig"),x([P({type:"string",aliases:["a"],name:"assets",required:false,description:"The path to the assets directory that will be loaded in the production build"})],D,"assets"),x([P({type:"string",aliases:["f"],name:"format",required:false,defaultValue:"esm",description:"The format to build the project, default is esm, can be 'esm' or 'cjs'"})],D,"format"),x([P({type:"string",aliases:["p"],name:"packages",required:false,defaultValue:"external",description:"Weather to bundle node_modules or not, default is external, can be 'bundle' or 'external'"})],D,"packages"),x([P({type:"boolean",aliases:["s"],name:"sourcemap",required:false,defaultValue:true,description:"Whether to generate sourcemaps or not, default is true"})],D,"sourcemap");var I=class extends Error{constructor(e){super(e);}};var ye=class extends I{constructor(){super("Zod v4 is required with the toJSONSchema() method. Install it with: npm install zod@^4.0.0");}};var Ae=class extends I{constructor(e){super(`Failed to convert Zod schema to JSON Schema. This usually happens when using Zod v3 schemas with Zod v4. Make sure you're importing from 'zod' (v4) and not 'zod/v3'. Original error: ${e.message}`);}};var Q=class{static zodModule=null;static zodSchemaCache=new WeakSet;static load(){if(this.zodModule)return this.zodModule;try{return this.zodModule=Me("zod"),this.ensureZodV4(),this.zodModule}catch{throw new Error(`Zod is not installed. Install it with: npm install zod
7
7
  Zod is a peer dependency required when using Zod schemas for validation.`)}}static get(){return this.load()}static isZodSchema(e){try{this.load();}catch{return false}if(typeof e!="object"||e===null)return false;if(this.zodSchemaCache.has(e))return true;let t="_def"in e&&typeof e.parse=="function"&&typeof e.safeParse=="function";return t&&this.zodSchemaCache.add(e),t}static ensureZodV4(){let e=this.zodModule?.z;if(!e)throw new ye;if(!("toJSONSchema"in e))throw new ye}static toJSONSchema(e){this.load(),this.ensureZodV4();let t=this.zodModule?.z;if(!t?.toJSONSchema)throw new ye;if(!e||typeof e!="object"||!("_def"in e))throw new Error(`Invalid Zod schema provided. Make sure you're using Zod v4 schemas. If you're importing from 'zod/v3', change to 'zod' or '{ z } from "zod"'.`);try{return t.toJSONSchema(e)}catch(r){throw r instanceof Error&&r.message.includes("Cannot read properties of undefined")?new Ae(r):r}}};var ke=class extends I{constructor(){super("TypeBox is not installed. Install it with: npm install @sinclair/typebox");}};var G=class{static typeboxModule=null;static typeboxSchemaCache=new WeakSet;static load(){if(this.typeboxModule)return this.typeboxModule;try{return this.typeboxModule=Me("@sinclair/typebox"),this.typeboxModule}catch{throw new ke}}static get(){return this.load()}static isTypeBoxSchema(e){try{this.load();}catch{return false}if(typeof e!="object"||e===null)return false;if(this.typeboxSchemaCache.has(e))return true;let t="type"in e&&Object.getOwnPropertySymbols(e).some(r=>r.toString()==="Symbol(TypeBox.Kind)");return t&&this.typeboxSchemaCache.add(e),t}};var E=class{static ajv=new Ajv({validateSchema:false,strict:false});static serializerCache=new WeakMap;static responseSerializersCache=new WeakMap;static refCounter=0;static schemaKeyCache=new WeakMap;static setGlobalInstance(e){this.ajv=e,this.ajv.opts.strict=false,this.ajv.opts.validateSchema=false;}static getSchemaKey(e,t){let r=this.schemaKeyCache.get(e);r||(r=new Map,this.schemaKeyCache.set(e,r));let o=r.get(t);return o||(o=`${t}_${++this.refCounter}`,r.set(t,o)),o}static getOrCompileValidator(e,t){let r=this.getSchemaKey(e,t),o=this.ajv.getSchema(r);if(o)return o;this.ajv.addSchema(e,r);let s=this.ajv.getSchema(r);if(!s)throw new Error(`Failed to compile schema with key: ${r}`);return s}static getOrCreateSerializer(e,t){if(!e||typeof e!="object")return null;let r=this.serializerCache.get(e);r||(r=new Map,this.serializerCache.set(e,r));let o=r.get(t);if(o)return o;try{let s=Ot(e,{ajv:this.ajv.opts});return r.set(t,s),s}catch{return null}}static getOrCreateResponseSerializers(e){if(!e)return null;let t=this.responseSerializersCache.get(e);if(t)return t;let r=new Map;for(let[o,s]of Object.entries(e)){let c=Number(o),a=null;if(Q.isZodSchema(s)){let d=Q.toJSONSchema(s);a=this.getOrCreateSerializer(d,"fast_stringify_zod");}else G.isTypeBoxSchema(s)?a=this.getOrCreateSerializer(s,"fast_stringify_typebox"):typeof s=="object"&&s!==null&&(a=this.getOrCreateSerializer(s,"fast_stringify_json"));a&&r.set(c,a);}return this.responseSerializersCache.set(e,r),r}static storeJsonSchema(e,t){let r=this.getSchemaKey(e,t);this.ajv.getSchema(r)||this.ajv.addSchema(e,r);}static getJsonSchema(e,t){let r=this.schemaKeyCache.get(e);if(!r)return;let o=r.get(t);return o?this.ajv.getSchema(o)?.schema:void 0}static clearAllCaches(){this.ajv=new Ajv({validateSchema:false,strict:false}),this.serializerCache=new WeakMap,this.schemaKeyCache=new WeakMap,this.refCounter=0;}static getSchemaCount(){return Object.keys(this.ajv.schemas).length}static getCacheStats(){return {schemaCount:this.getSchemaCount(),totalRefsCreated:this.refCounter}}};var $t=l=>{if(Q.isZodSchema(l)){try{let t=Q.toJSONSchema(l);E.storeJsonSchema(t,"serialize_zod"),E.getOrCompileValidator(t,"serialize_zod");}catch(t){M.warn({error:t,schemaType:"zod",context:"serialize_decorator"},"Failed to compile Zod schema for validation. Schema may contain unsupported types (e.g., z.instanceof). Runtime validation will still work, but Swagger documentation may be incomplete.");return}return}if(G.isTypeBoxSchema(l)){try{E.storeJsonSchema(l,"serialize_typebox"),E.getOrCompileValidator(l,"serialize_typebox");}catch(t){M.warn({error:t,schemaType:"typebox",context:"serialize_decorator"},"Failed to compile TypeBox schema for validation. Schema may be invalid or use unsupported features.");return}return}if(typeof l=="object"&&l!==null){try{E.storeJsonSchema(l,"serialize_json"),E.getOrCompileValidator(l,"serialize_json");}catch(t){M.warn({error:t,schemaType:"json",context:"serialize_decorator"},"Failed to compile JSON schema for validation. Schema may be invalid or malformed.");return}return}let e=JSON.stringify(l);try{let t={type:typeof l};E.storeJsonSchema(t,`serialize_primitive_${e}`),E.getOrCompileValidator(t,`serialize_primitive_${e}`);}catch(t){M.warn({error:t,schemaType:"primitive",cacheKey:e,context:"serialize_decorator"},"Failed to compile schema for validation. Schema format may be unsupported.");}},ct=l=>{if(Q.isZodSchema(l)){try{let t=Q.toJSONSchema(l);E.storeJsonSchema(t,"zod_schema"),E.getOrCompileValidator(t,"zod_schema");}catch(t){M.warn({error:t,schemaType:"zod",context:"request_validation"},"Failed to compile Zod schema for request validation. Schema may contain unsupported types (e.g., z.instanceof). Swagger documentation may be incomplete.");return}return}if(G.isTypeBoxSchema(l)){try{E.storeJsonSchema(l,"typebox_schema"),E.getOrCompileValidator(l,"typebox_schema");}catch(t){M.warn({error:t,schemaType:"typebox",context:"request_validation"},"Failed to compile TypeBox schema for request validation. Schema may be invalid or use unsupported features.");return}return}if(typeof l=="object"&&l!==null){try{E.storeJsonSchema(l,"json_schema"),E.getOrCompileValidator(l,"json_schema");}catch(t){M.warn({error:t,schemaType:"json",context:"request_validation"},"Failed to compile JSON schema for request validation. Schema may be invalid or malformed.");return}return}let e=JSON.stringify(l);try{let t={type:typeof l};E.storeJsonSchema(t,`primitive_${e}`),E.getOrCompileValidator(t,`primitive_${e}`);}catch(t){M.warn({error:t,schemaType:"primitive",cacheKey:e,context:"request_validation"},"Failed to compile schema for request validation. Schema format may be unsupported.");}},dt=(l,e)=>{l&&ct(l),e&&ct(e);},ut=l=>{if(!l||Object.keys(l).length===0)return;let e={};for(let[t,r]of Object.entries(l)){let o=Number(t);if(e[o]=r,$t(r),Q.isZodSchema(r))try{let s=Q.toJSONSchema(r);E.getOrCreateSerializer(s,"fast_stringify_zod");}catch{}else G.isTypeBoxSchema(r)?E.getOrCreateSerializer(r,"fast_stringify_typebox"):typeof r=="object"&&r!==null&&E.getOrCreateSerializer(r,"fast_stringify_json");}return e};var pt=(l,e)=>async function(t,r,...o){try{let s=[t,r,...o];if(e.body){let c=t.validate(e.body,!0);s.push(c);}if(e.query){let c=t.validateQuery(e.query,!0);s.push(c);}if(e.all){let c=t.validateAll(e.all,!0);s.push(c);}return l(...s)}catch(s){return r.badRequest(s)}};var be=class{staticChildren;paramChild;wildcardChild;middleware;handler;paramName;constructor(){this.staticChildren=new Map,this.paramChild=null,this.wildcardChild=null,this.middleware=null,this.handler=null,this.paramName=null;}},Ve=class l{trees;routes;middlewares;basePath;staticRouteCache;handlerResponseSchemas;constructor(e="",t=[]){this.trees=new Map,this.routes=[],this.middlewares=t,this.basePath=this.normalizeBasePath(e),this.staticRouteCache=new Map,this.handlerResponseSchemas=new Map;}getRoutes(){return this.routes.slice()}addOrUpdate(e,t,r,o,s,c){e=e.toUpperCase();let a=t.split("?")[0];dt(s?.body,s?.query);let d=ut(c?.responses),u=s&&(s.body||s.query||s.all),i=u?pt(o,s):o,n=u?s:void 0,p=this.trees.get(e);p||(p=new be,this.trees.set(e,p));let m=a.replace(/^\/+|\/+$/g,""),h=m.length===0?[]:m.split("/"),g=true,y=[],b=p;for(let S of h){if(S==="*"){g=false,b.wildcardChild||(b.wildcardChild=new be),b=b.wildcardChild;break}if(S.startsWith(":")){g=false;let v=S.slice(1);y.push(v),b.paramChild||(b.paramChild={node:new be,name:v}),b=b.paramChild.node;continue}b.staticChildren.has(S)||b.staticChildren.set(S,new be),b=b.staticChildren.get(S);}if(b.middleware=r,b.handler=i,y.length>0&&(b.paramName=y.join(",")),d&&this.handlerResponseSchemas.set(o,d),g){let S="/"+m,v=`${e}:${S}`;this.staticRouteCache.set(v,{middleware:r,handler:i,params:{},responseSchemas:d});}else {let S="/"+m.replace(/:[^/]+/g,"").replace(/\/+/g,"/"),v=`${e}:${S}`;this.staticRouteCache.delete(v);}let T=this.routes.findIndex(S=>S.method===e&&S.path===t);if(T!==-1){this.routes[T].middleware=r,this.routes[T].handler=i,this.routes[T].swaggerOptions=c,this.routes[T].responseSchemas=d,this.routes[T].validationSchemas=n;return}this.routes.push({method:e,path:t,middleware:r,handler:i,swaggerOptions:c,responseSchemas:d,validationSchemas:n});}find(e,t){e=e.toUpperCase();let r=t,o=t.indexOf("?");o!==-1&&(r=t.substring(0,o));let s=`${e}:${r}`,c=this.staticRouteCache.get(s);if(c)return c;let a=this.trees.get(e);if(!a)return null;let d=r.replace(/^\/+|\/+$/g,""),u=d.length===0?[]:d.split("/"),i={},n=a;for(let m=0;m<u.length;m++){let h=u[m];if(n.staticChildren.has(h)){n=n.staticChildren.get(h);continue}if(n.paramChild){i[n.paramChild.name]=h,n=n.paramChild.node;continue}if(n.wildcardChild){i["*"]=u.slice(m).join("/"),n=n.wildcardChild;break}return null}if(!n.handler||!n.middleware)return null;let p=this.handlerResponseSchemas.get(n.handler);return {middleware:n.middleware,handler:n.handler,params:i,responseSchemas:p}}extractOptionsAndHandler(e,t){if(typeof e=="function")return {middlewares:[],handler:e,swaggerOptions:void 0};let r=e;return {middlewares:Array.isArray(r.middlewares)?r.middlewares:r.middlewares?[r.middlewares]:[],handler:t,body:r.body,query:r.query,all:r.all,swaggerOptions:r.swagger}}get(e,t,r){let o=this.joinPath(e),{middlewares:s,handler:c,body:a,query:d,all:u,swaggerOptions:i}=this.extractOptionsAndHandler(t,r),n=[...this.middlewares,...s],p={body:a,query:d,all:u};this.addOrUpdate("GET",o,n,c,p,i);}post(e,t,r){let o=this.joinPath(e),{middlewares:s,handler:c,body:a,query:d,all:u,swaggerOptions:i}=this.extractOptionsAndHandler(t,r),n=[...this.middlewares,...s],p={body:a,query:d,all:u};this.addOrUpdate("POST",o,n,c,p,i);}patch(e,t,r){let o=this.joinPath(e),{middlewares:s,handler:c,body:a,query:d,all:u,swaggerOptions:i}=this.extractOptionsAndHandler(t,r),n=[...this.middlewares,...s],p={body:a,query:d,all:u};this.addOrUpdate("PATCH",o,n,c,p,i);}put(e,t,r){let o=this.joinPath(e),{middlewares:s,handler:c,body:a,query:d,all:u,swaggerOptions:i}=this.extractOptionsAndHandler(t,r),n=[...this.middlewares,...s],p={body:a,query:d,all:u};this.addOrUpdate("PUT",o,n,c,p,i);}delete(e,t,r){let o=this.joinPath(e),{middlewares:s,handler:c,body:a,query:d,all:u,swaggerOptions:i}=this.extractOptionsAndHandler(t,r),n=[...this.middlewares,...s],p={body:a,query:d,all:u};this.addOrUpdate("DELETE",o,n,c,p,i);}options(e,t,r){let o=this.joinPath(e),{middlewares:s,handler:c,body:a,query:d,all:u,swaggerOptions:i}=this.extractOptionsAndHandler(t,r),n=[...this.middlewares,...s],p={body:a,query:d,all:u};this.addOrUpdate("OPTIONS",o,n,c,p,i);}head(e,t,r){let o=this.joinPath(e),{middlewares:s,handler:c,body:a,query:d,all:u,swaggerOptions:i}=this.extractOptionsAndHandler(t,r),n=[...this.middlewares,...s],p={body:a,query:d,all:u};this.addOrUpdate("HEAD",o,n,c,p,i);}group(e,t,r){let o=Array.isArray(t)?t:typeof t=="function"?[]:t?[t]:[],s=Array.isArray(t)?r:typeof t=="function"?t:void 0,c=this.joinPath(e),a=new l(c,[...this.middlewares,...o]);s?.(a);for(let d of a.getRoutes())this.addOrUpdate(d.method,d.path,d.middleware,d.handler,d.validationSchemas,d.swaggerOptions);}applyGlobalMiddlewaresToAllRoutes(e){for(let t of this.routes){let r=[...e,...t.middleware||[]];this.addOrUpdate(t.method,t.path,r,t.handler);}}normalizeBasePath(e){if(!e)return "";let t=e.replace(/\s+/g,"");return t=t.replace(/\/+/g,"/"),t.startsWith("/")||(t="/"+t),t.length>1&&(t=t.replace(/\/+$/g,"")),t}joinPath(e){let r=[this.basePath,e].filter(o=>typeof o=="string"&&o.length>0).join("/");return r=r.replace(/\/+/g,"/"),r.startsWith("/")||(r="/"+r),r.length>1&&(r=r.replace(/\/+$/g,"")),r}clearRoutes(){this.routes=[],this.staticRouteCache.clear(),this.handlerResponseSchemas.clear(),this.trees.clear();}};new Ve;var K=class{static scheduledJobs=[];static logger=M.child({scope:"CronService"});static register(e,...t){t[2]={name:e,...t[2]},this.scheduledJobs.push({name:e,args:t});}static async run(){let e=(await import('node-cron').catch(()=>{throw new I("node-cron not installed as a dependency, it is required in order to run cron jobs with the @cron decorator")})).default;if(this.logger.info("Scheduling cron jobs"),!this.scheduledJobs.length){this.logger.info("No cron jobs to schedule");return}for(let{name:t,args:r}of this.scheduledJobs)this.logger.info(`Scheduling cron job: ${t}`),e.schedule(...r).on("execution:failed",s=>this.globalErrorHandler(s));this.logger.info("Cron jobs scheduled");}static globalErrorHandler(e){this.logger.error(e.execution?.error);}static async massiveImportCronJobs(e){let t=[];for(let r of e){let o=await f.glob(r,{cwd:N.getCwd()});t.push(...o);}await Promise.all(t.map(async r=>{await import(r).catch(o=>{this.logger.error(`Error importing cron job: ${r}`),M.error(o);});}));}};var te=class extends q{static commandName="cron-start";static description="Start cron job scheduler";static help=["Start the cron job scheduler to run scheduled tasks","Loads cron jobs from specified patterns and starts scheduling","Example: npx balda cron-start","Example: npx balda cron-start src/crons/**/*.ts --patterns src/schedules/**/*.ts"];static options={keepAlive:true};static pattern;static additionalPatterns;static async handle(){this.logger.info("Starting cron scheduler...");let e=[this.pattern];this.additionalPatterns&&this.additionalPatterns.length>0&&e.push(...this.additionalPatterns),this.logger.info(`Loading cron jobs from patterns: ${e.join(", ")}`),await K.massiveImportCronJobs(e);let t=K.scheduledJobs.length;if(t===0){this.logger.warn("No cron jobs found. Make sure your cron jobs are decorated with @cron decorator");return}this.logger.info(`Found ${t} cron job(s)`),K.run().then(()=>{this.logger.info("Cron scheduler started successfully. Press Ctrl+C to stop.");}).catch(r=>{this.logger.error("Error starting cron scheduler",r);});}};x([$({required:false,defaultValue:"src/crons/**/*.{ts,js}",description:"Primary glob pattern for cron jobs (default: src/crons/**/*.{ts,js})"})],te,"pattern"),x([P.array({aliases:["p"],name:"patterns",required:false,description:"Additional glob patterns for cron jobs"})],te,"additionalPatterns");var ve=class extends q{static commandName="generate-command";static description="Generate a new command in the specified path";static help=["Generate a new cli command in the specified path","Example: npx balda generate-command my-command -p src/commands"];static path="src/commands";static name;static async handle(){if(U.getCommand(this.name)){let o=U.isBuiltInCommand(this.name)?"built-in":"user-defined";this.logger.error({commandName:this.name,type:o},`Command "${this.name}" already exists as a ${o} command. Cannot override existing commands.`);return}let t=this.getCommandTemplate();this.path=w.join(this.path,`${this.name}.ts`),await f.exists(w.join(process.cwd(),this.path))||await f.mkdir(w.join(process.cwd(),this.path.split("/").slice(0,-1).join("/")),{recursive:true}),await f.writeFile(this.path,new TextEncoder().encode(t)),this.logger.info(`Command ${this.name} created successfully at ${this.path}`);}static getCommandTemplate(){return `import { Command, CommandOptions } from "balda";
@@ -127,7 +127,7 @@ export default class extends BaseQueue {
127
127
  `);}catch(v){console.error("\x1B[31m\u274C Error generating SDK:\x1B[0m",v);}finally{try{await f.unlink(T);}catch{}if(n){let v=i;try{console.log("\u{1F6D1} Stopping server..."),await v.close?.(),console.log(`\u2705 Server stopped.
128
128
  `);}catch{console.log(`\x1B[33m\u26A0\uFE0F Could not stop server gracefully.\x1B[0m
129
129
  `);}}}console.log(`\x1B[32m\u2728 SDK generation complete!\x1B[0m
130
- `);}};x([$({description:"Path to the server instance file (should export a Server instance)",required:false,defaultValue:"test/server/instance.ts"})],k,"serverPath"),x([P({description:"Output directory for generated SDK",type:"string",aliases:["o"],name:"output",required:false,defaultValue:"sdk"})],k,"outputPath"),x([P({description:"Swagger UI path on your server",type:"string",aliases:["s"],name:"swagger-path",required:false})],k,"swaggerPath"),x([P({description:"HTTP client to use (axios or fetch)",type:"string",aliases:["c"],name:"client",required:false,defaultValue:"fetch"})],k,"httpClient"),x([P({description:"Unwrap response data automatically",type:"boolean",name:"unwrap-response-data",required:false,defaultValue:false})],k,"unwrapResponseData"),x([P({description:"Generate single HTTP client instance",type:"boolean",name:"single-http-client",required:false,defaultValue:false})],k,"singleHttpClient"),x([P({description:"Add prefix to all generated types",type:"string",name:"type-prefix",required:false})],k,"typePrefix"),x([P({description:"Add suffix to all generated types",type:"string",name:"type-suffix",required:false})],k,"typeSuffix"),x([P({description:"Use enum names as values",type:"boolean",name:"enum-names-as-values",required:false,defaultValue:false})],k,"enumNamesAsValues"),x([P({description:"Sort types alphabetically",type:"boolean",name:"sort-types",required:false,defaultValue:false})],k,"sortTypes");var H=class extends q{static commandName="init";static description="Initialize a new balda project in the current directory";static help=["Initialize a new balda project, it is given for granted that balda is installed in the project as a dependency","All the files are created in the /src directory (created if not exists)","It adds a server.ts for the file instance and a index.ts for the entry point with a dummy hello world route","Example: npx balda init -p ./src -t true"];static srcPath;static typescript;static mqtt;static cron;static graphql;static devDependencies=["esbuild","esbuild-plugin-copy","tsx","typescript"];static async handle(){this.logger.info("Initializing project...");let[e,t,r]=await F();if(["npm","yarn","pnpm"].includes(e)){let d=await V(this.devDependencies);if(d.length&&(this.logger.info(`Found ${d.length} missing dev dependencies`),!await A(`${e} ${t} ${d.join(" ")} -${r}`,e,d,{stdio:"inherit"}))){this.logger.info("Installation cancelled by user. Project initialization aborted.");return}d.length||this.logger.info("All dev dependencies are already installed");}if(this.mqtt&&["npm","yarn","pnpm"].includes(e)){let d=await V(["mqtt"]);d.length&&(await A(`${e} ${t} mqtt`,e,["mqtt"],{stdio:"inherit"},false)||(this.logger.info("MQTT installation cancelled by user. Skipping MQTT scaffolding."),this.mqtt=false)),d.length||this.logger.info("MQTT package is already installed");}if(this.cron&&["npm","yarn","pnpm"].includes(e)){let d=await V(["node-cron"]);d.length>0&&(await A(`${e} ${t} node-cron`,e,["node-cron"],{stdio:"inherit"},false)||(this.logger.info("node-cron installation cancelled by user. Skipping Cron scaffolding."),this.cron=false)),d.length||this.logger.info("node-cron package is already installed");}if(this.graphql&&["npm","yarn","pnpm"].includes(e)){let d=await V(["@apollo/server","@graphql-tools/schema","graphql"]);d.length>0&&(await A(`${e} ${t} ${d.join(" ")}`,e,d,{stdio:"inherit"},false)||(this.logger.info("GraphQL installation cancelled by user. Skipping GraphQL scaffolding."),this.graphql=false)),d.length||this.logger.info("GraphQL packages are already installed");}let o=this.typescript?"ts":"js",s=this.getServerTemplate(),c=this.getIndexTemplate();f.exists(this.srcPath)||await f.mkdir(this.srcPath,{recursive:true}),this.logger.info(`Creating server.${o} file...`),await f.writeFile(`${this.srcPath}/server.${o}`,new TextEncoder().encode(s)),this.logger.info(`Creating index.${o} file...`),await f.writeFile(`${this.srcPath}/index.${o}`,new TextEncoder().encode(c));let a=this.getLoggerTemplate();if(this.logger.info(`Creating logger.${o} file...`),await f.writeFile(`${this.srcPath}/logger.${o}`,new TextEncoder().encode(a)),this.mqtt){let d=w.join(this.srcPath,"mqtt");await f.exists(d)||await f.mkdir(d,{recursive:true});let u=this.getMqttConfigTemplate();this.logger.info(`Creating mqtt/mqtt.config.${o} file...`),await f.writeFile(w.join(d,`mqtt.config.${o}`),new TextEncoder().encode(u));}if(this.cron){let d=w.join(this.srcPath,"cron");await f.exists(d)||await f.mkdir(d,{recursive:true});let u=this.getCronConfigTemplate();this.logger.info(`Creating cron/cron.config.${o} file...`),await f.writeFile(w.join(d,`cron.config.${o}`),new TextEncoder().encode(u));}if(this.graphql){let d=w.join(this.srcPath,"graphql");await f.exists(d)||await f.mkdir(d,{recursive:true});let u=this.getGraphqlConfigTemplate();this.logger.info(`Creating graphql/graphql.config.${o} file...`),await f.writeFile(w.join(d,`graphql.config.${o}`),new TextEncoder().encode(u));}this.logger.info("Project initialized successfully!");}static getServerTemplate(){return `import { Server } from "balda";
130
+ `);}};x([$({description:"Path to the server instance file (should export a Server instance)",required:false,defaultValue:"test/server/instance.ts"})],k,"serverPath"),x([P({description:"Output directory for generated SDK",type:"string",aliases:["o"],name:"output",required:false,defaultValue:"sdk"})],k,"outputPath"),x([P({description:"Swagger UI path on your server",type:"string",aliases:["s"],name:"swagger-path",required:false})],k,"swaggerPath"),x([P({description:"HTTP client to use (axios or fetch)",type:"string",aliases:["c"],name:"client",required:false,defaultValue:"fetch"})],k,"httpClient"),x([P({description:"Unwrap response data automatically",type:"boolean",name:"unwrap-response-data",required:false,defaultValue:false})],k,"unwrapResponseData"),x([P({description:"Generate single HTTP client instance",type:"boolean",name:"single-http-client",required:false,defaultValue:false})],k,"singleHttpClient"),x([P({description:"Add prefix to all generated types",type:"string",name:"type-prefix",required:false})],k,"typePrefix"),x([P({description:"Add suffix to all generated types",type:"string",name:"type-suffix",required:false})],k,"typeSuffix"),x([P({description:"Use enum names as values",type:"boolean",name:"enum-names-as-values",required:false,defaultValue:false})],k,"enumNamesAsValues"),x([P({description:"Sort types alphabetically",type:"boolean",name:"sort-types",required:false,defaultValue:false})],k,"sortTypes");var J=class extends q{static commandName="init";static description="Initialize a new balda project in the current directory";static help=["Initialize a new balda project, it is given for granted that balda is installed in the project as a dependency","All the files are created in the /src directory (created if not exists)","It adds a server.ts for the file instance and a index.ts for the entry point with a dummy hello world route","Example: npx balda init -p ./src -t true"];static srcPath;static typescript;static mqtt;static cron;static graphql;static devDependencies=["esbuild","esbuild-plugin-copy","tsx","typescript"];static async handle(){this.logger.info("Initializing project...");let[e,t,r]=await F();if(["npm","yarn","pnpm"].includes(e)){let d=await V(this.devDependencies);if(d.length&&(this.logger.info(`Found ${d.length} missing dev dependencies`),!await A(`${e} ${t} ${d.join(" ")} -${r}`,e,d,{stdio:"inherit"}))){this.logger.info("Installation cancelled by user. Project initialization aborted.");return}d.length||this.logger.info("All dev dependencies are already installed");}if(this.mqtt&&["npm","yarn","pnpm"].includes(e)){let d=await V(["mqtt"]);d.length&&(await A(`${e} ${t} mqtt`,e,["mqtt"],{stdio:"inherit"},false)||(this.logger.info("MQTT installation cancelled by user. Skipping MQTT scaffolding."),this.mqtt=false)),d.length||this.logger.info("MQTT package is already installed");}if(this.cron&&["npm","yarn","pnpm"].includes(e)){let d=await V(["node-cron"]);d.length>0&&(await A(`${e} ${t} node-cron`,e,["node-cron"],{stdio:"inherit"},false)||(this.logger.info("node-cron installation cancelled by user. Skipping Cron scaffolding."),this.cron=false)),d.length||this.logger.info("node-cron package is already installed");}if(this.graphql&&["npm","yarn","pnpm"].includes(e)){let d=await V(["@apollo/server","@graphql-tools/schema","graphql"]);d.length>0&&(await A(`${e} ${t} ${d.join(" ")}`,e,d,{stdio:"inherit"},false)||(this.logger.info("GraphQL installation cancelled by user. Skipping GraphQL scaffolding."),this.graphql=false)),d.length||this.logger.info("GraphQL packages are already installed");}let o=this.typescript?"ts":"js",s=this.getServerTemplate(),c=this.getIndexTemplate();f.exists(this.srcPath)||await f.mkdir(this.srcPath,{recursive:true}),this.logger.info(`Creating server.${o} file...`),await f.writeFile(`${this.srcPath}/server.${o}`,new TextEncoder().encode(s)),this.logger.info(`Creating index.${o} file...`),await f.writeFile(`${this.srcPath}/index.${o}`,new TextEncoder().encode(c));let a=this.getLoggerTemplate();if(this.logger.info(`Creating logger.${o} file...`),await f.writeFile(`${this.srcPath}/logger.${o}`,new TextEncoder().encode(a)),this.mqtt){let d=w.join(this.srcPath,"mqtt");await f.exists(d)||await f.mkdir(d,{recursive:true});let u=this.getMqttConfigTemplate();this.logger.info(`Creating mqtt/mqtt.config.${o} file...`),await f.writeFile(w.join(d,`mqtt.config.${o}`),new TextEncoder().encode(u));}if(this.cron){let d=w.join(this.srcPath,"cron");await f.exists(d)||await f.mkdir(d,{recursive:true});let u=this.getCronConfigTemplate();this.logger.info(`Creating cron/cron.config.${o} file...`),await f.writeFile(w.join(d,`cron.config.${o}`),new TextEncoder().encode(u));}if(this.graphql){let d=w.join(this.srcPath,"graphql");await f.exists(d)||await f.mkdir(d,{recursive:true});let u=this.getGraphqlConfigTemplate();this.logger.info(`Creating graphql/graphql.config.${o} file...`),await f.writeFile(w.join(d,`graphql.config.${o}`),new TextEncoder().encode(u));}this.logger.info("Project initialized successfully!");}static getServerTemplate(){return `import { Server } from "balda";
131
131
  import { logger } from "./logger.js";
132
132
 
133
133
  const serverInstance = new Server({
@@ -193,9 +193,11 @@ server.listen(({ url }) => {
193
193
  // The GraphQL endpoint is automatically available at /graphql
194
194
  // You can extend the schema using server.graphql.addTypeDef() and server.graphql.addResolver()
195
195
  `}static getLoggerTemplate(){return `import pino from "pino";
196
+ import { CommandRegistry } from "../command_registry.js";
196
197
 
197
198
  export const logger = pino({ level: "info" });
198
- `}};x([P.string({description:"The path to the project, default is the current directory /src",aliases:"p",name:"path",required:false,defaultValue:"./src"})],H,"srcPath"),x([P.boolean({description:"Whether to use typescript, default is true",aliases:"t",name:"typescript",required:false,defaultValue:true})],H,"typescript"),x([P.boolean({description:"Initialize MQTT service connection",aliases:"m",name:"mqtt",required:false,defaultValue:false})],H,"mqtt"),x([P.boolean({description:"Initialize Cron service",aliases:"c",name:"cron",required:false,defaultValue:false})],H,"cron"),x([P.boolean({description:"Initialize GraphQL service",aliases:"g",name:"graphql",required:false,defaultValue:false})],H,"graphql");var ae=class extends q{static commandName="init-mailer";static description="Initialize mailer configuration with required dependencies";static help=["Initialize a mailer configuration file with basic setup","Automatically installs required packages for nodemailer and optional template engines","Supports Handlebars, EJS, Edge.js, Mustache, or custom adapters","Example: npx balda init-mailer -t handlebars -o src/mailer"];static templateEngine;static outputPath;static mailerDependencies={base:["nodemailer","@types/nodemailer"],handlebars:["handlebars","@types/handlebars"],ejs:["ejs","@types/ejs"],edge:["edge.js"],mustache:["mustache","@types/mustache"]};static async handle(){if(this.logger.info("Initializing mailer configuration..."),!["handlebars","ejs","edge","mustache","custom","none"].includes(this.templateEngine)){this.logger.error(`Invalid template engine: ${this.templateEngine}. Must be one of: handlebars, ejs, edge, mustache, custom, none`);return}let[e,t]=await F();if(["npm","yarn","pnpm"].includes(e)){let c=[...this.mailerDependencies.base,...this.templateEngine!=="none"&&this.templateEngine!=="custom"?this.mailerDependencies[this.templateEngine]||[]:[]],a=await V(c);if(a.length>0&&(this.logger.info(`Found ${a.length} missing dependencies for mailer`),!await A(`${e} ${t} ${a.join(" ")}`,e,a,{stdio:"inherit"},false))){this.logger.info("Installation cancelled by user. Mailer initialization aborted.");return}a.length===0&&this.logger.info("All mailer dependencies are already installed");}let r=this.getConfigTemplate(),o="mailer.config.ts",s=w.join(this.outputPath,o);await f.exists(this.outputPath)||await f.mkdir(this.outputPath,{recursive:true}),this.logger.info(`Creating ${o} file at ${this.outputPath}...`),await f.writeFile(s,new TextEncoder().encode(r)),this.logger.info(`Mailer configuration initialized successfully at ${s}`),this.logger.info("Remember to update the configuration with your actual SMTP credentials"),this.templateEngine!=="none"&&this.logger.info(`Template engine '${this.templateEngine}' configured and ready to use`);}static getConfigTemplate(){let e=this.templateEngine!=="none";return `import { createTransport } from "nodemailer";
199
+ CommandRegistry.setLogger(logger);
200
+ `}};x([P.string({description:"The path to the project, default is the current directory /src",aliases:"p",name:"path",required:false,defaultValue:"./src"})],J,"srcPath"),x([P.boolean({description:"Whether to use typescript, default is true",aliases:"t",name:"typescript",required:false,defaultValue:true})],J,"typescript"),x([P.boolean({description:"Initialize MQTT service connection",aliases:"m",name:"mqtt",required:false,defaultValue:false})],J,"mqtt"),x([P.boolean({description:"Initialize Cron service",aliases:"c",name:"cron",required:false,defaultValue:false})],J,"cron"),x([P.boolean({description:"Initialize GraphQL service",aliases:"g",name:"graphql",required:false,defaultValue:false})],J,"graphql");var ae=class extends q{static commandName="init-mailer";static description="Initialize mailer configuration with required dependencies";static help=["Initialize a mailer configuration file with basic setup","Automatically installs required packages for nodemailer and optional template engines","Supports Handlebars, EJS, Edge.js, Mustache, or custom adapters","Example: npx balda init-mailer -t handlebars -o src/mailer"];static templateEngine;static outputPath;static mailerDependencies={base:["nodemailer","@types/nodemailer"],handlebars:["handlebars","@types/handlebars"],ejs:["ejs","@types/ejs"],edge:["edge.js"],mustache:["mustache","@types/mustache"]};static async handle(){if(this.logger.info("Initializing mailer configuration..."),!["handlebars","ejs","edge","mustache","custom","none"].includes(this.templateEngine)){this.logger.error(`Invalid template engine: ${this.templateEngine}. Must be one of: handlebars, ejs, edge, mustache, custom, none`);return}let[e,t]=await F();if(["npm","yarn","pnpm"].includes(e)){let c=[...this.mailerDependencies.base,...this.templateEngine!=="none"&&this.templateEngine!=="custom"?this.mailerDependencies[this.templateEngine]||[]:[]],a=await V(c);if(a.length>0&&(this.logger.info(`Found ${a.length} missing dependencies for mailer`),!await A(`${e} ${t} ${a.join(" ")}`,e,a,{stdio:"inherit"},false))){this.logger.info("Installation cancelled by user. Mailer initialization aborted.");return}a.length===0&&this.logger.info("All mailer dependencies are already installed");}let r=this.getConfigTemplate(),o="mailer.config.ts",s=w.join(this.outputPath,o);await f.exists(this.outputPath)||await f.mkdir(this.outputPath,{recursive:true}),this.logger.info(`Creating ${o} file at ${this.outputPath}...`),await f.writeFile(s,new TextEncoder().encode(r)),this.logger.info(`Mailer configuration initialized successfully at ${s}`),this.logger.info("Remember to update the configuration with your actual SMTP credentials"),this.templateEngine!=="none"&&this.logger.info(`Template engine '${this.templateEngine}' configured and ready to use`);}static getConfigTemplate(){let e=this.templateEngine!=="none";return `import { createTransport } from "nodemailer";
199
201
  import { Mailer${e?`, ${this.getAdapterImport()}`:""} } from "balda";
200
202
 
201
203
  /**
@@ -502,7 +504,7 @@ ${o}
502
504
  `),t.length>0){console.log(`\x1B[1;33mUser Commands:\x1B[0m
503
505
  `);let r=this.groupByCategory(t);this.displayCategorizedCommands(r);}if(e.length>0){console.log(`\x1B[1;32mBuilt-in Commands:\x1B[0m
504
506
  `);let r=e.sort((s,c)=>s.commandName.localeCompare(c.commandName)),o=Math.max(...r.map(s=>s.commandName.length));for(let s of r){let c=s.commandName.padEnd(o+2),a=s.description||"No description available",d="";s.options?.deprecated&&(d=" \x1B[33m[deprecated]\x1B[0m"),console.log(` \x1B[36m${c}\x1B[0m ${a}${d}`);}console.log("");}console.log(`\x1B[90mRun 'npx balda <command> -h' for more information on a specific command.\x1B[0m
505
- `);}static groupByCategory(e){let t=new Map;for(let r of e){let o=r.options?.category||"other";t.has(o)||t.set(o,[]),t.get(o).push(r);}return t}static displayCategorizedCommands(e){let t=Array.from(e.keys()).sort();for(let r of t){let o=e.get(r).filter(d=>d&&d.commandName).sort((d,u)=>d.commandName.localeCompare(u.commandName));if(o.length===0)continue;let c={generator:"\x1B[35m",setup:"\x1B[34m",production:"\x1B[32m",utility:"\x1B[36m",other:"\x1B[37m"}[r]||"\x1B[37m";console.log(` ${c}${r.toUpperCase()}:\x1B[0m`);let a=Math.max(...o.map(d=>d.commandName.length));for(let d of o){let u=d.commandName.padEnd(a+2),i=d.description||"No description available",n="";d.options?.deprecated&&(n=" \x1B[33m[deprecated]\x1B[0m"),console.log(` \x1B[36m${u}\x1B[0m ${i}${n}`);}console.log("");}}};var z=class extends I{constructor(...e){super(`Library not installed: ${e.join(", ")}, try run npm install ${e.join(" ")}`);}};var Ke=class{randomUUID(){return crypto.randomUUID()}},Ce=new Ke;var X=class{static options={connection:{}}};var Ne=class{queues=new Map;workers=new Map;async publish(e,t,r){let o=await this.getQueue(e),s=Ce.randomUUID();return await o.add(e,t,{jobId:s,...X.options?.defaultJobOptions,...r}),{id:s}}async subscribe(e,t){if(this.workers.has(e))throw new Error(`[BullMQ] Already subscribed to topic "${e}"`);let{errorHandler:r,...o}=X.options??{},s=await this.getBullMQClient(),c=new s.Worker(e,async a=>{try{await t(a.data);}catch(d){await r?.(a,d)??Promise.reject(d);}},{...o});this.workers.set(e,c);}async unsubscribe(e){let t=this.workers.get(e);t&&(await t.close(),this.workers.delete(e));}async getQueue(e){if(!this.queues.has(e)){let t=await import('bullmq').catch(()=>{throw new z("bullmq","ioredis")}),r=new t.Queue(e,{...X.options||{connection:{}}});this.queues.set(e,r);}return this.queues.get(e)}async getBullMQClient(){return this.bullmqClient||(this.bullmqClient=await import('bullmq').catch(()=>{throw new z("bullmq","ioredis")})),this.bullmqClient}async publishWithConfig(e,t,r,o){let s=await this.getQueueWithConfig(e,o),c=Ce.randomUUID(),a={jobId:c,...X.options?.defaultJobOptions,...o?.defaultJobOptions,...r};return await s.add(e,t,a),{id:c}}async subscribeWithConfig(e,t,r){let o=this.getWorkerKey(e,r);if(this.workers.has(o))throw new Error(`[BullMQ] Already subscribed to topic "${e}"`);let s=X.options??{},{errorHandler:c}=s,a=await this.getBullMQClient(),d={...s,...r};delete d.errorHandler,delete d.defaultJobOptions;let u=new a.Worker(e,async i=>{try{await t(i.data);}catch(n){await c?.(i,n)??Promise.reject(n);}},d);this.workers.set(o,u);}async getQueueWithConfig(e,t){let r=this.getQueueKey(e,t);if(!this.queues.has(r)){let o=await import('bullmq').catch(()=>{throw new z("bullmq","ioredis")}),s={...X.options||{connection:{}},...t},c=new o.Queue(e,s);this.queues.set(r,c);}return this.queues.get(r)}getQueueKey(e,t){return t?.connection?`${e}:${JSON.stringify(t.connection)}`:e}getWorkerKey(e,t){return this.getQueueKey(e,t)}};var _e=class{subscribers=new Map;messageQueue=[];maxQueueSize;processingPromise=null;constructor(e=1e4){this.maxQueueSize=e;}clear(){this.subscribers.clear(),this.messageQueue=[],this.processingPromise=null;}async publish(e,t,r){if(this.messageQueue.length>=this.maxQueueSize)throw new Error(`Queue full: ${this.maxQueueSize} messages pending`);let o=Ce.randomUUID();return this.messageQueue.push({topic:e,payload:t}),this.processingPromise||(this.processingPromise=this.processQueue().catch(s=>{console.error("[MemoryPubSub] Fatal queue processing error:",s);}).finally(()=>{this.processingPromise=null;})),{id:o}}async subscribe(e,t){this.subscribers.has(e)||this.subscribers.set(e,new Set);let r=t;this.subscribers.get(e).add(r);}async unsubscribe(e){this.subscribers.delete(e);}async processQueue(){for(;this.messageQueue.length>0;){let e=this.messageQueue.shift();if(!e)break;let t=this.subscribers.get(e.topic);t&&t.size>0&&await Promise.allSettled(Array.from(t).map(r=>r(e.payload).catch(o=>{console.error(`[MemoryPubSub] Handler error for topic "${e.topic}":`,o);})));}}};var J=class{static options={}};var Fe=class{createdQueues=new Set;workers=new Map;async publish(e,t,r){let o=await this.getBoss();await this.ensureQueue(e);let s=r||{},c=await o.send(e,t,s);return {id:String(c??"")}}async subscribe(e,t){let r=await this.getBoss();await this.ensureQueue(e);let o=J.options;o.errorHandler&&r.on("error",o.errorHandler);let s=await r.work(e,async c=>{let a=Array.isArray(c)?c:[c];for(let d of a)await t(d.data);});this.workers.set(e,s);}async unsubscribe(e){let t=await this.getBoss(),r=this.workers.get(e);r&&(await t.offWork(r),this.workers.delete(e));}async getBoss(){if(this.boss)return this.boss;let e=await import('pg-boss').catch(()=>{throw new z("pg-boss","pg")}),r=e.PgBoss.default??e.PgBoss,{connectionString:o,boss:s}=J.options,c=o??s,a=new r(c);return J.options?.errorHandler&&a.on("error",J.options.errorHandler),await a.start(),this.boss=a,this.boss}async ensureQueue(e){if(this.createdQueues.has(e))return;let t=await this.getBoss();typeof t.createQueue=="function"&&await t.createQueue(e),this.createdQueues.add(e);}async publishWithConfig(e,t,r,o){let s=await this.getBossWithConfig(o);await this.ensureQueueWithBoss(e,s);let c=r||{},a=await s.send(e,t,c);return {id:String(a??"")}}async subscribeWithConfig(e,t,r){let o=await this.getBossWithConfig(r);await this.ensureQueueWithBoss(e,o);let s=J.options;s.errorHandler&&o.on("error",s.errorHandler);let c=`${e}:${r?.connectionString??"default"}`,a=await o.work(e,async d=>{let u=Array.isArray(d)?d:[d];for(let i of u)await t(i.data);});this.workers.set(c,a);}bossInstances=new Map;async getBossWithConfig(e){if(!e?.connectionString)return this.getBoss();let t=e.connectionString;if(this.bossInstances.has(t))return this.bossInstances.get(t);let r=await import('pg-boss').catch(()=>{throw new z("pg-boss","pg")}),s=r.PgBoss.default??r.PgBoss,c=new s(e.connectionString);return J.options?.errorHandler&&c.on("error",J.options.errorHandler),await c.start(),this.bossInstances.set(t,c),c}async ensureQueueWithBoss(e,t){this.createdQueues.has(e)||(typeof t.createQueue=="function"&&await t.createQueue(e),this.createdQueues.add(e));}};var ce=class{static options={}};var Ie=class{consumers=new Map;client;async publish(e,t,r){let o=await this.getClient(),{SendMessageCommand:s}=await this.getSqsLib(),c=await this.resolveQueueUrl(e);if(!c)throw new Error(`[SQS] Queue url not configured for topic "${e}"`);let a=new s({MessageBody:JSON.stringify(t),MessageAttributes:{topic:{DataType:"String",StringValue:e}},QueueUrl:c,...r??{}});return {id:(await o.send(a)).MessageId??""}}async subscribe(e,t){if(this.consumers.has(e))throw new Error(`[SQS] Already subscribed to topic "${e}"`);let r=ce.options,o=await this.getSqsConsumerLib(),s={...r.consumer||{},sqs:await this.getClient(),queueUrl:await this.resolveQueueUrl(e),handleMessage:async d=>{let u=JSON.parse(d.Body||"{}");await t(u);}},c=o.Consumer.create(s),a=r.errorHandler;a&&(c.on("error",a),c.on("processing_error",a)),c.start(),this.consumers.set(e,c);}async unsubscribe(e){let t=this.consumers.get(e);t&&(t.stop(),this.consumers.delete(e));}async getClient(){if(this.client)return this.client;let{SQSClient:e}=await this.getSqsLib(),t=ce.options.client;return this.client=new e(t??{}),this.client}async getSqsLib(){return this.sqsLib||(this.sqsLib=await import('@aws-sdk/client-sqs').catch(()=>{throw new z("@aws-sdk/client-sqs","sqs-consumer")})),this.sqsLib}async getSqsConsumerLib(){return this.sqsConsumerLib||(this.sqsConsumerLib=await import('sqs-consumer').catch(()=>{throw new z("sqs-consumer")})),this.sqsConsumerLib}async resolveQueueUrl(e){let r=ce.options.consumer?.queueUrlMap;if(!r?.[e])throw new Error(`[SQS] Queue url not configured for topic "${e}"`);return r[e]}async publishWithConfig(e,t,r,o){let{...s}=r??{},c=await this.getClientWithConfig(o?.client),{SendMessageCommand:a}=await this.getSqsLib(),d=o?.queueUrl??await this.resolveQueueUrl(e),u=new a({...s,MessageBody:JSON.stringify(t),MessageAttributes:{topic:{DataType:"String",StringValue:e}},QueueUrl:d});return {id:(await c.send(u)).MessageId??""}}async subscribeWithConfig(e,t,r){if(this.consumers.has(e))throw new Error(`[SQS] Already subscribed to topic "${e}"`);let o=ce.options,s=await this.getSqsConsumerLib(),c=r?.queueUrl??await this.resolveQueueUrl(e),a={...o.consumer||{},sqs:await this.getClientWithConfig(r?.client),queueUrl:c,handleMessage:async i=>{let n=JSON.parse(i.Body||"{}");await t(n);}},d=s.Consumer.create(a),u=o.errorHandler;u&&(d.on("error",u),d.on("processing_error",u)),d.start(),this.consumers.set(e,d);}async getClientWithConfig(e){if(e){let{SQSClient:t}=await this.getSqsLib();return new t(e)}return this.getClient()}};var De=class{static map=new Map;static{this.map.set("bullmq",new Ne),this.map.set("sqs",new Ie),this.map.set("pgboss",new Fe),this.map.set("memory",new _e);}static getProvider(e){if(!this.map.has(e))throw new Error(`[QueueSubscriber] Provider ${e} not found`);return this.map.get(e)}static setProvider(e,t){this.map.set(e,t);}static clearMemoryProvider(){let e=this.map.get("memory");e&&"clear"in e&&e.clear();}};var de=class{static typedQueueSubscribers=new Map;static customQueueSubscribers=new Map;static logger=M.child({scope:"QueueService"});static instanceFactory=e=>new e;static registerTypedQueue(e,t,r,o,s){let c=`${o}:${t}:${e}`;this.typedQueueSubscribers.has(c)&&this.logger.warn(`Queue handler for ${c} already registered, overwriting previous handler`),this.typedQueueSubscribers.set(c,{name:e,topic:t,handler:r,provider:o,queueOptions:s});}static registerCustomQueue(e,t,r,o){let s=`${o.constructor.name}:${t}:${e}`;this.customQueueSubscribers.has(s)&&this.logger.warn(`Custom queue handler for ${s} already registered, overwriting previous handler`),this.customQueueSubscribers.set(s,{name:e,topic:t,handler:r,pubsub:o});}static async run(){this.logger.info("Subscribing queue handlers");let e=this.typedQueueSubscribers.size>0,t=this.customQueueSubscribers.size>0;if(!e&&!t){this.logger.info("No queue handlers to subscribe");return}for(let r of this.typedQueueSubscribers.values()){let{topic:o,handler:s,provider:c,queueOptions:a}=r;this.logger.info(`Subscribing to queue: ${o}`);let d=De.getProvider(c);a&&"subscribeWithConfig"in d&&typeof d.subscribeWithConfig=="function"?await d.subscribeWithConfig(o,s,a):await d.subscribe(o,s);}for(let{topic:r,handler:o,pubsub:s}of this.customQueueSubscribers.values())this.logger.info(`Subscribing to custom queue: ${r}`),await s.subscribe(r,o);this.logger.info("Queue handlers subscribed");}static async massiveImportQueues(e,t={}){let r=[];for(let o of e){let s=await f.glob(o,{cwd:N.getCwd()});this.logger.info(`Pattern "${o}" matched ${s.length} file(s)`),r.push(...s);}if(r.length===0){this.logger.warn("No files matched the provided patterns");return}this.logger.info(`Importing ${r.length} queue handler file(s)`),await Promise.all(r.map(async o=>{this.logger.debug(`Importing: ${o}`),await import(o).catch(s=>{if(this.logger.error(`Error importing queue handler: ${o}`),this.logger.error(s),t.throwOnError)throw s});})),this.logger.info(`Successfully imported ${r.length} file(s)`);}};var ue=class extends q{static commandName="queue-start";static description="Start queue workers to process jobs";static help=["Start queue workers to process jobs from registered queues","Loads queue handlers from specified patterns and starts processing","Example: npx balda queue-start","Example: npx balda queue-start src/queues/**/*.ts --patterns src/jobs/**/*.ts"];static options={keepAlive:true};static pattern;static additionalPatterns;static async handle(){this.logger.info("Starting queue workers...");let e=[this.pattern];this.additionalPatterns&&this.additionalPatterns.length>0&&e.push(...this.additionalPatterns),this.logger.info(`Loading queue handlers from patterns: ${e.join(", ")}`),await de.massiveImportQueues(e,{throwOnError:false});let t=de.typedQueueSubscribers.size,r=de.customQueueSubscribers.size,o=t+r;if(o===0){this.logger.warn("No queue handlers found. Make sure your queue handlers are decorated with @queue decorator");return}this.logger.info(`Found ${o} queue handler(s) (${t} typed, ${r} custom)`),de.run().then(()=>{this.logger.info("Queue workers started successfully. Press Ctrl+C to stop.");}).catch(s=>{this.logger.error("Error starting queue workers",s);});}};x([$({required:false,defaultValue:"src/queues/**/*.{ts,js}",description:"Primary glob pattern for queue handlers (default: src/queues/**/*.{ts,js})"})],ue,"pattern"),x([P.list({aliases:["p"],name:"patterns",required:false,description:"Additional glob patterns for queue handlers"})],ue,"additionalPatterns");var pe=class extends q{static commandName="serve";static description="Run the server in dev mode with hot reload";static help=["This command is intended to be run from the root of the project","Bun and Deno have native dev hot reload","Runtime is automatically inferred","Node.js requires tsx to be installed for both typescript and javascript files","Node.js dev dependencies (tsx) are installed automatically if not detected"];static runtime=O.type;static options={keepAlive:true};static entry;static denoImportMap;static async handle(){if(this.runtime==="bun"){execSync(`bun run --watch ${this.entry}`,{stdio:"inherit",cwd:N.getCwd()});return}if(this.runtime==="deno"){let e="deno run --watch --unstable-sloppy-imports --allow-all";this.denoImportMap&&(e=`${e} --import-map ${this.denoImportMap}`),execSync(`${e} ${this.entry}`,{stdio:"inherit",cwd:N.getCwd()});return}this.handleNodeHotReload();}static async handleNodeHotReload(){if(!xe.existsSync("node_modules/.bin/tsx")){let[r,o,s]=await F();if(!await A(`${r} ${o} tsx ${s}`,r,["tsx"],{stdio:"inherit"})){this.logger.info("Installation cancelled by user. Cannot start dev server without tsx.");return}}let t=this.calledBy!=="node"?this.calledBy:"npx";execSync(`${t} tsx watch ${this.entry}`,{stdio:"inherit",cwd:process.cwd()});}};x([$({required:false,defaultValue:"src/index.ts",description:"The entry point of the project, default is src/index.ts"})],pe,"entry"),x([P.string({aliases:["d"],name:"deno-import-map",required:false,description:"Path to deno import map"})],pe,"denoImportMap");var me=class extends q{static commandName="init-storage";static description="Setup storage provider with required dependencies";static help=["Install dependencies and create storage configuration for a specific provider","Flags:"," -t, --type <provider> Storage provider type (s3, azure, local)"," -o, --output <path> Output directory for storage setup (default: src/storage/)","","Examples:"," npx balda setup:storage -t s3"," npx balda setup:storage --type azure --output src/config/"];static storageType;static outputPath;static async handle(){if(!this.storageType){console.error("\x1B[31m\u274C Error: Storage type is required. Use -t or --type flag.\x1B[0m"),console.log(`\x1B[90mExample: npx balda setup:storage -t s3\x1B[0m
507
+ `);}static groupByCategory(e){let t=new Map;for(let r of e){let o=r.options?.category||"other";t.has(o)||t.set(o,[]),t.get(o).push(r);}return t}static displayCategorizedCommands(e){let t=Array.from(e.keys()).sort();for(let r of t){let o=e.get(r).filter(d=>d&&d.commandName).sort((d,u)=>d.commandName.localeCompare(u.commandName));if(o.length===0)continue;let c={generator:"\x1B[35m",setup:"\x1B[34m",production:"\x1B[32m",utility:"\x1B[36m",other:"\x1B[37m"}[r]||"\x1B[37m";console.log(` ${c}${r.toUpperCase()}:\x1B[0m`);let a=Math.max(...o.map(d=>d.commandName.length));for(let d of o){let u=d.commandName.padEnd(a+2),i=d.description||"No description available",n="";d.options?.deprecated&&(n=" \x1B[33m[deprecated]\x1B[0m"),console.log(` \x1B[36m${u}\x1B[0m ${i}${n}`);}console.log("");}}};var z=class extends I{constructor(...e){super(`Library not installed: ${e.join(", ")}, try run npm install ${e.join(" ")}`);}};var Ke=class{randomUUID(){return crypto.randomUUID()}},Ce=new Ke;var X=class{static options={connection:{}}};var Ne=class{queues=new Map;workers=new Map;async publish(e,t,r){let o=await this.getQueue(e),s=Ce.randomUUID();return await o.add(e,t,{jobId:s,...X.options?.defaultJobOptions,...r}),{id:s}}async subscribe(e,t){if(this.workers.has(e))throw new Error(`[BullMQ] Already subscribed to topic "${e}"`);let{errorHandler:r,...o}=X.options??{},s=await this.getBullMQClient(),c=new s.Worker(e,async a=>{try{await t(a.data);}catch(d){await r?.(a,d)??Promise.reject(d);}},{...o});this.workers.set(e,c);}async unsubscribe(e){let t=this.workers.get(e);t&&(await t.close(),this.workers.delete(e));}async getQueue(e){if(!this.queues.has(e)){let t=await import('bullmq').catch(()=>{throw new z("bullmq","ioredis")}),r=new t.Queue(e,{...X.options||{connection:{}}});this.queues.set(e,r);}return this.queues.get(e)}async getBullMQClient(){return this.bullmqClient||(this.bullmqClient=await import('bullmq').catch(()=>{throw new z("bullmq","ioredis")})),this.bullmqClient}async publishWithConfig(e,t,r,o){let s=await this.getQueueWithConfig(e,o),c=Ce.randomUUID(),a={jobId:c,...X.options?.defaultJobOptions,...o?.defaultJobOptions,...r};return await s.add(e,t,a),{id:c}}async subscribeWithConfig(e,t,r){let o=this.getWorkerKey(e,r);if(this.workers.has(o))throw new Error(`[BullMQ] Already subscribed to topic "${e}"`);let s=X.options??{},{errorHandler:c}=s,a=await this.getBullMQClient(),d={...s,...r};delete d.errorHandler,delete d.defaultJobOptions;let u=new a.Worker(e,async i=>{try{await t(i.data);}catch(n){await c?.(i,n)??Promise.reject(n);}},d);this.workers.set(o,u);}async getQueueWithConfig(e,t){let r=this.getQueueKey(e,t);if(!this.queues.has(r)){let o=await import('bullmq').catch(()=>{throw new z("bullmq","ioredis")}),s={...X.options||{connection:{}},...t},c=new o.Queue(e,s);this.queues.set(r,c);}return this.queues.get(r)}getQueueKey(e,t){return t?.connection?`${e}:${JSON.stringify(t.connection)}`:e}getWorkerKey(e,t){return this.getQueueKey(e,t)}};var _e=class{subscribers=new Map;messageQueue=[];maxQueueSize;processingPromise=null;constructor(e=1e4){this.maxQueueSize=e;}clear(){this.subscribers.clear(),this.messageQueue=[],this.processingPromise=null;}async publish(e,t,r){if(this.messageQueue.length>=this.maxQueueSize)throw new Error(`Queue full: ${this.maxQueueSize} messages pending`);let o=Ce.randomUUID();return this.messageQueue.push({topic:e,payload:t}),this.processingPromise||(this.processingPromise=this.processQueue().catch(s=>{console.error("[MemoryPubSub] Fatal queue processing error:",s);}).finally(()=>{this.processingPromise=null;})),{id:o}}async subscribe(e,t){this.subscribers.has(e)||this.subscribers.set(e,new Set);let r=t;this.subscribers.get(e).add(r);}async unsubscribe(e){this.subscribers.delete(e);}async processQueue(){for(;this.messageQueue.length>0;){let e=this.messageQueue.shift();if(!e)break;let t=this.subscribers.get(e.topic);t&&t.size>0&&await Promise.allSettled(Array.from(t).map(r=>r(e.payload).catch(o=>{console.error(`[MemoryPubSub] Handler error for topic "${e.topic}":`,o);})));}}};var W=class{static options={}};var Fe=class{createdQueues=new Set;workers=new Map;async publish(e,t,r){let o=await this.getBoss();await this.ensureQueue(e);let s=r||{},c=await o.send(e,t,s);return {id:String(c??"")}}async subscribe(e,t){let r=await this.getBoss();await this.ensureQueue(e);let o=W.options;o.errorHandler&&r.on("error",o.errorHandler);let s=await r.work(e,async c=>{let a=Array.isArray(c)?c:[c];for(let d of a)await t(d.data);});this.workers.set(e,s);}async unsubscribe(e){let t=await this.getBoss(),r=this.workers.get(e);r&&(await t.offWork(r),this.workers.delete(e));}async getBoss(){if(this.boss)return this.boss;let e=await import('pg-boss').catch(()=>{throw new z("pg-boss","pg")}),r=e.PgBoss.default??e.PgBoss,{connectionString:o,boss:s}=W.options,c=o??s,a=new r(c);return W.options?.errorHandler&&a.on("error",W.options.errorHandler),await a.start(),this.boss=a,this.boss}async ensureQueue(e){if(this.createdQueues.has(e))return;let t=await this.getBoss();typeof t.createQueue=="function"&&await t.createQueue(e),this.createdQueues.add(e);}async publishWithConfig(e,t,r,o){let s=await this.getBossWithConfig(o);await this.ensureQueueWithBoss(e,s);let c=r||{},a=await s.send(e,t,c);return {id:String(a??"")}}async subscribeWithConfig(e,t,r){let o=await this.getBossWithConfig(r);await this.ensureQueueWithBoss(e,o);let s=W.options;s.errorHandler&&o.on("error",s.errorHandler);let c=`${e}:${r?.connectionString??"default"}`,a=await o.work(e,async d=>{let u=Array.isArray(d)?d:[d];for(let i of u)await t(i.data);});this.workers.set(c,a);}bossInstances=new Map;async getBossWithConfig(e){if(!e?.connectionString)return this.getBoss();let t=e.connectionString;if(this.bossInstances.has(t))return this.bossInstances.get(t);let r=await import('pg-boss').catch(()=>{throw new z("pg-boss","pg")}),s=r.PgBoss.default??r.PgBoss,c=new s(e.connectionString);return W.options?.errorHandler&&c.on("error",W.options.errorHandler),await c.start(),this.bossInstances.set(t,c),c}async ensureQueueWithBoss(e,t){this.createdQueues.has(e)||(typeof t.createQueue=="function"&&await t.createQueue(e),this.createdQueues.add(e));}};var ce=class{static options={}};var Ie=class{consumers=new Map;client;async publish(e,t,r){let o=await this.getClient(),{SendMessageCommand:s}=await this.getSqsLib(),c=await this.resolveQueueUrl(e);if(!c)throw new Error(`[SQS] Queue url not configured for topic "${e}"`);let a=new s({MessageBody:JSON.stringify(t),MessageAttributes:{topic:{DataType:"String",StringValue:e}},QueueUrl:c,...r??{}});return {id:(await o.send(a)).MessageId??""}}async subscribe(e,t){if(this.consumers.has(e))throw new Error(`[SQS] Already subscribed to topic "${e}"`);let r=ce.options,o=await this.getSqsConsumerLib(),s={...r.consumer||{},sqs:await this.getClient(),queueUrl:await this.resolveQueueUrl(e),handleMessage:async d=>{let u=JSON.parse(d.Body||"{}");await t(u);}},c=o.Consumer.create(s),a=r.errorHandler;a&&(c.on("error",a),c.on("processing_error",a)),c.start(),this.consumers.set(e,c);}async unsubscribe(e){let t=this.consumers.get(e);t&&(t.stop(),this.consumers.delete(e));}async getClient(){if(this.client)return this.client;let{SQSClient:e}=await this.getSqsLib(),t=ce.options.client;return this.client=new e(t??{}),this.client}async getSqsLib(){return this.sqsLib||(this.sqsLib=await import('@aws-sdk/client-sqs').catch(()=>{throw new z("@aws-sdk/client-sqs","sqs-consumer")})),this.sqsLib}async getSqsConsumerLib(){return this.sqsConsumerLib||(this.sqsConsumerLib=await import('sqs-consumer').catch(()=>{throw new z("sqs-consumer")})),this.sqsConsumerLib}async resolveQueueUrl(e){let r=ce.options.consumer?.queueUrlMap;if(!r?.[e])throw new Error(`[SQS] Queue url not configured for topic "${e}"`);return r[e]}async publishWithConfig(e,t,r,o){let{...s}=r??{},c=await this.getClientWithConfig(o?.client),{SendMessageCommand:a}=await this.getSqsLib(),d=o?.queueUrl??await this.resolveQueueUrl(e),u=new a({...s,MessageBody:JSON.stringify(t),MessageAttributes:{topic:{DataType:"String",StringValue:e}},QueueUrl:d});return {id:(await c.send(u)).MessageId??""}}async subscribeWithConfig(e,t,r){if(this.consumers.has(e))throw new Error(`[SQS] Already subscribed to topic "${e}"`);let o=ce.options,s=await this.getSqsConsumerLib(),c=r?.queueUrl??await this.resolveQueueUrl(e),a={...o.consumer||{},sqs:await this.getClientWithConfig(r?.client),queueUrl:c,handleMessage:async i=>{let n=JSON.parse(i.Body||"{}");await t(n);}},d=s.Consumer.create(a),u=o.errorHandler;u&&(d.on("error",u),d.on("processing_error",u)),d.start(),this.consumers.set(e,d);}async getClientWithConfig(e){if(e){let{SQSClient:t}=await this.getSqsLib();return new t(e)}return this.getClient()}};var De=class{static map=new Map;static{this.map.set("bullmq",new Ne),this.map.set("sqs",new Ie),this.map.set("pgboss",new Fe),this.map.set("memory",new _e);}static getProvider(e){if(!this.map.has(e))throw new Error(`[QueueSubscriber] Provider ${e} not found`);return this.map.get(e)}static setProvider(e,t){this.map.set(e,t);}static clearMemoryProvider(){let e=this.map.get("memory");e&&"clear"in e&&e.clear();}};var de=class{static typedQueueSubscribers=new Map;static customQueueSubscribers=new Map;static logger=M.child({scope:"QueueService"});static instanceFactory=e=>new e;static registerTypedQueue(e,t,r,o,s){let c=`${o}:${t}:${e}`;this.typedQueueSubscribers.has(c)&&this.logger.warn(`Queue handler for ${c} already registered, overwriting previous handler`),this.typedQueueSubscribers.set(c,{name:e,topic:t,handler:r,provider:o,queueOptions:s});}static registerCustomQueue(e,t,r,o){let s=`${o.constructor.name}:${t}:${e}`;this.customQueueSubscribers.has(s)&&this.logger.warn(`Custom queue handler for ${s} already registered, overwriting previous handler`),this.customQueueSubscribers.set(s,{name:e,topic:t,handler:r,pubsub:o});}static async run(){this.logger.info("Subscribing queue handlers");let e=this.typedQueueSubscribers.size>0,t=this.customQueueSubscribers.size>0;if(!e&&!t){this.logger.info("No queue handlers to subscribe");return}for(let r of this.typedQueueSubscribers.values()){let{topic:o,handler:s,provider:c,queueOptions:a}=r;this.logger.info(`Subscribing to queue: ${o}`);let d=De.getProvider(c);a&&"subscribeWithConfig"in d&&typeof d.subscribeWithConfig=="function"?await d.subscribeWithConfig(o,s,a):await d.subscribe(o,s);}for(let{topic:r,handler:o,pubsub:s}of this.customQueueSubscribers.values())this.logger.info(`Subscribing to custom queue: ${r}`),await s.subscribe(r,o);this.logger.info("Queue handlers subscribed");}static async massiveImportQueues(e,t={}){let r=[];for(let o of e){let s=await f.glob(o,{cwd:N.getCwd()});this.logger.info(`Pattern "${o}" matched ${s.length} file(s)`),r.push(...s);}if(r.length===0){this.logger.warn("No files matched the provided patterns");return}this.logger.info(`Importing ${r.length} queue handler file(s)`),await Promise.all(r.map(async o=>{this.logger.debug(`Importing: ${o}`),await import(o).catch(s=>{if(this.logger.error(`Error importing queue handler: ${o}`),this.logger.error(s),t.throwOnError)throw s});})),this.logger.info(`Successfully imported ${r.length} file(s)`);}};var ue=class extends q{static commandName="queue-start";static description="Start queue workers to process jobs";static help=["Start queue workers to process jobs from registered queues","Loads queue handlers from specified patterns and starts processing","Example: npx balda queue-start","Example: npx balda queue-start src/queues/**/*.ts --patterns src/jobs/**/*.ts"];static options={keepAlive:true};static pattern;static additionalPatterns;static async handle(){this.logger.info("Starting queue workers...");let e=[this.pattern];this.additionalPatterns&&this.additionalPatterns.length>0&&e.push(...this.additionalPatterns),this.logger.info(`Loading queue handlers from patterns: ${e.join(", ")}`),await de.massiveImportQueues(e,{throwOnError:false});let t=de.typedQueueSubscribers.size,r=de.customQueueSubscribers.size,o=t+r;if(o===0){this.logger.warn("No queue handlers found. Make sure your queue handlers are decorated with @queue decorator");return}this.logger.info(`Found ${o} queue handler(s) (${t} typed, ${r} custom)`),de.run().then(()=>{this.logger.info("Queue workers started successfully. Press Ctrl+C to stop.");}).catch(s=>{this.logger.error("Error starting queue workers",s);});}};x([$({required:false,defaultValue:"src/queues/**/*.{ts,js}",description:"Primary glob pattern for queue handlers (default: src/queues/**/*.{ts,js})"})],ue,"pattern"),x([P.list({aliases:["p"],name:"patterns",required:false,description:"Additional glob patterns for queue handlers"})],ue,"additionalPatterns");var pe=class extends q{static commandName="serve";static description="Run the server in dev mode with hot reload";static help=["This command is intended to be run from the root of the project","Bun and Deno have native dev hot reload","Runtime is automatically inferred","Node.js requires tsx to be installed for both typescript and javascript files","Node.js dev dependencies (tsx) are installed automatically if not detected"];static runtime=O.type;static options={keepAlive:true};static entry;static denoImportMap;static async handle(){if(this.runtime==="bun"){execSync(`bun run --watch ${this.entry}`,{stdio:"inherit",cwd:N.getCwd()});return}if(this.runtime==="deno"){let e="deno run --watch --unstable-sloppy-imports --allow-all";this.denoImportMap&&(e=`${e} --import-map ${this.denoImportMap}`),execSync(`${e} ${this.entry}`,{stdio:"inherit",cwd:N.getCwd()});return}this.handleNodeHotReload();}static async handleNodeHotReload(){if(!xe.existsSync("node_modules/.bin/tsx")){let[r,o,s]=await F();if(!await A(`${r} ${o} tsx ${s}`,r,["tsx"],{stdio:"inherit"})){this.logger.info("Installation cancelled by user. Cannot start dev server without tsx.");return}}let t=this.calledBy!=="node"?this.calledBy:"npx";execSync(`${t} tsx watch ${this.entry}`,{stdio:"inherit",cwd:process.cwd()});}};x([$({required:false,defaultValue:"src/index.ts",description:"The entry point of the project, default is src/index.ts"})],pe,"entry"),x([P.string({aliases:["d"],name:"deno-import-map",required:false,description:"Path to deno import map"})],pe,"denoImportMap");var me=class extends q{static commandName="init-storage";static description="Setup storage provider with required dependencies";static help=["Install dependencies and create storage configuration for a specific provider","Flags:"," -t, --type <provider> Storage provider type (s3, azure, local)"," -o, --output <path> Output directory for storage setup (default: src/storage/)","","Examples:"," npx balda setup:storage -t s3"," npx balda setup:storage --type azure --output src/config/"];static storageType;static outputPath;static async handle(){if(!this.storageType){console.error("\x1B[31m\u274C Error: Storage type is required. Use -t or --type flag.\x1B[0m"),console.log(`\x1B[90mExample: npx balda setup:storage -t s3\x1B[0m
506
508
  `);return}this.outputPath||await f.mkdir(w.join(process.cwd(),this.outputPath),{recursive:true});let e=["s3","azure","local"];if(!e.includes(this.storageType)){console.error(`\x1B[31m\u274C Error: Invalid storage type '${this.storageType}'. Valid types: ${e.join(", ")}\x1B[0m
507
509
  `);return}console.log(`
508
510
  \u{1F680} Setting up ${this.storageType.toUpperCase()} storage provider...
@@ -592,11 +594,11 @@ export const storage = new Storage(
592
594
  defaultProvider: "local",
593
595
  },
594
596
  );
595
- `}[e]||""}};x([P({description:"Storage provider type (s3, azure, local)",type:"string",aliases:["t"],name:"type",required:true})],me,"storageType"),x([P({description:"Output directory for storage setup",type:"string",aliases:["o"],name:"output",required:false,defaultValue:"src/storage/"})],me,"outputPath");var Nt=[ie,ve,se,ne,Z,re,oe,k,H,ae,le,Se,D,pe,me,we,ue,te],W=class l{commands;builtInCommands;static commandsPattern="src/commands/**/*.{ts,js}";static loggerPath="src/logger.ts";static logger=M.child({scope:"CommandRegistry"});static setLogger(e){l.logger=e.child({scope:"CommandRegistry"}),q.logger=e.child({scope:"Command"});}static async loadLogger(e){let t=e||l.loggerPath;try{let r=await import(w.join(N.getCwd(),t));r.logger&&l.setLogger(r.logger);}catch{l.logger.debug(`Could not load logger from ${t}, using default logger`);}}constructor(){this.commands=new Map,this.builtInCommands=new Set;}static getInstance(){return new l}static setCommandsPattern(e){this.commandsPattern=e;}getCommand(e){return this.commands.get(e)??null}getCommands(){return Array.from(this.commands.values())}getBuiltInCommands(){return Array.from(this.commands.values()).filter(e=>this.builtInCommands.has(e.commandName))}getUserDefinedCommands(){return Array.from(this.commands.values()).filter(e=>!this.builtInCommands.has(e.commandName))}isBuiltInCommand(e){return this.builtInCommands.has(e)}async loadCommands(e){l.logger.info(`Loading commands from ${e}`);let t=await f.glob(e,{cwd:N.getCwd()});if(t.some(r=>r.endsWith(".ts")))try{let{register:r}=await import('module');r("ts-node/esm",import.meta.url);}catch{l.logger.error("Failed to register ts-node/esm, you need to install it in your project in order to use typescript in the cli\ntry running: `npm install -D ts-node`"),process.exit(1);}for(let r of t){let o=await import(r).then(s=>s.default?s.default:s).catch(s=>(l.logger.error(`Error loading command ${r}: ${s}`),null));o&&this.commands.set(o.commandName,o);}for(let r of Nt)this.commands.set(r.commandName,r),this.builtInCommands.add(r.commandName);}},U=W.getInstance();var _t=l=>{let e=new Map;for(let t of l){let r=t.options?.category||"other";e.has(r)||e.set(r,[]),e.get(r).push(t);}return e},Ft=l=>{let e=Array.from(l.keys()).sort();for(let t of e){let r=l.get(t).filter(a=>a&&a.commandName);if(!r.length)continue;let s={generator:"\x1B[35m",setup:"\x1B[34m",production:"\x1B[32m",utility:"\x1B[36m",other:"\x1B[37m"}[t]||"\x1B[37m";console.log(` ${s}${t.toUpperCase()}:\x1B[0m`);let c=Math.max(...r.map(a=>a.commandName.length));for(let a of r){let d=a.commandName.padEnd(c+2),u=a.description||"No description available",i="";a.options?.deprecated&&(i=" \x1B[33m[deprecated]\x1B[0m"),console.log(` \x1B[36m${d}\x1B[0m ${u}${i}`);}console.log("");}},Ye=async()=>{await U.loadCommands(W.commandsPattern);let[l,...e]=fe.getCliArgs();if(!l||l==="-h"||l==="--help"){let s=U.getBuiltInCommands(),c=U.getUserDefinedCommands();if(console.log(`
597
+ `}[e]||""}};x([P({description:"Storage provider type (s3, azure, local)",type:"string",aliases:["t"],name:"type",required:true})],me,"storageType"),x([P({description:"Output directory for storage setup",type:"string",aliases:["o"],name:"output",required:false,defaultValue:"src/storage/"})],me,"outputPath");var Nt=[ie,ve,se,ne,Z,re,oe,k,J,ae,le,Se,D,pe,me,we,ue,te],L=class l{commands;builtInCommands;static commandsPattern="src/commands/**/*.{ts,js}";static loggerPath="src/logger.ts";static logger=M.child({scope:"CommandRegistry"});static setLogger(e){l.logger=e.child({scope:"CommandRegistry"}),q.logger=e.child({scope:"Command"});}static async loadLogger(e){let t=e||l.loggerPath;try{let r=await import(w.join(N.getCwd(),t));r.logger&&l.setLogger(r.logger);}catch{l.logger.debug(`Could not load logger from ${t}, using default logger`);}}constructor(){this.commands=new Map,this.builtInCommands=new Set;}static getInstance(){return new l}static setCommandsPattern(e){this.commandsPattern=e;}getLogger(){return l.logger}setLogger(e){l.logger=e.child({scope:"CommandRegistry"}),q.logger=e.child({scope:"Command"});}getCommand(e){return this.commands.get(e)??null}getCommands(){return Array.from(this.commands.values())}getBuiltInCommands(){return Array.from(this.commands.values()).filter(e=>this.builtInCommands.has(e.commandName))}getUserDefinedCommands(){return Array.from(this.commands.values()).filter(e=>!this.builtInCommands.has(e.commandName))}isBuiltInCommand(e){return this.builtInCommands.has(e)}async loadCommands(e){l.logger.info(`Loading commands from ${e}`);let t=await f.glob(e,{cwd:N.getCwd()});if(t.some(r=>r.endsWith(".ts")))try{let{register:r}=await import('module');r("ts-node/esm",import.meta.url);}catch{l.logger.error("Failed to register ts-node/esm, you need to install it in your project in order to use typescript in the cli\ntry running: `npm install -D ts-node`"),process.exit(1);}for(let r of t){let o=await import(r).then(s=>s.default?s.default:s).catch(s=>(l.logger.error(`Error loading command ${r}: ${s}`),null));o&&this.commands.set(o.commandName,o);}for(let r of Nt)this.commands.set(r.commandName,r),this.builtInCommands.add(r.commandName);}},U=L.getInstance();var _t=l=>{let e=new Map;for(let t of l){let r=t.options?.category||"other";e.has(r)||e.set(r,[]),e.get(r).push(t);}return e},Ft=l=>{let e=Array.from(l.keys()).sort();for(let t of e){let r=l.get(t).filter(a=>a&&a.commandName);if(!r.length)continue;let s={generator:"\x1B[35m",setup:"\x1B[34m",production:"\x1B[32m",utility:"\x1B[36m",other:"\x1B[37m"}[t]||"\x1B[37m";console.log(` ${s}${t.toUpperCase()}:\x1B[0m`);let c=Math.max(...r.map(a=>a.commandName.length));for(let a of r){let d=a.commandName.padEnd(c+2),u=a.description||"No description available",i="";a.options?.deprecated&&(i=" \x1B[33m[deprecated]\x1B[0m"),console.log(` \x1B[36m${d}\x1B[0m ${u}${i}`);}console.log("");}},Ye=async()=>{await L.loadLogger(),await U.loadCommands(L.commandsPattern);let[l,...e]=fe.getCliArgs();if(!l||l==="-h"||l==="--help"){let s=U.getBuiltInCommands(),c=U.getUserDefinedCommands();if(console.log(`
596
598
  \u2728 Available Balda Commands:
597
599
  `),c.length&&(console.log(`\x1B[1;33mUser Commands:\x1B[0m
598
600
  `),Ft(_t(c))),s.length){console.log(`\x1B[1;32mBuilt-in Commands:\x1B[0m
599
601
  `);let a=Math.max(...s.map(d=>d.commandName.length));for(let d of s){let u=d.commandName.padEnd(a+2),i=d.description||"No description available",n="";d.options?.deprecated&&(n=" \x1B[33m[deprecated]\x1B[0m"),console.log(` \x1B[36m${u}\x1B[0m ${i}${n}`);}console.log("");}console.log(`\x1B[90mRun 'npx balda <command> -h' for more information on a specific command.\x1B[0m
600
- `),L.exit(0);return}let t=U.getCommand(l);if(!t){console.error(ot(l,U.getCommands().filter(s=>s&&s.commandName).map(s=>s.commandName))||`Command ${l} not found`),L.exit(1);return}let r=t;if(r.calledBy=w.basename(fe.getCliCaller()),r.options?.deprecated){let s=r.options.deprecated.message||"This command is deprecated",c=r.options.deprecated.replacement;console.warn(`\x1B[33m\u26A0\uFE0F Warning: ${s}\x1B[0m`),c&&console.warn(`\x1B[33m Use '${c}' instead.\x1B[0m
601
- `);}if(await W.loadLogger(r.options?.loggerPath),r.handleHelpFlag(r.flags),r.validateUnknownFlags(r),r.validateContext(r),r.options?.validate&&!await r.options.validate(r)){console.error("Command validation failed"),L.exit(1);return}await r.handle(),(t.options?.keepAlive??false)||L.exit(0);};typeof process<"u"?Ye().catch(async l=>{if(l?.message?.includes("SyntaxError")||l?.code==="ERR_UNKNOWN_FILE_EXTENSION")try{let{register:e}=await import('module');e("ts-node/esm",import.meta.url),Ye().catch(t=>{W.logger.error(t),process.exit(1);});}catch{W.logger.error("Failed to register ts-node/esm, you need to install it in your project in order to use typescript in the cli\ntry running: `npm install -D ts-node`"),process.exit(1);}else W.logger.error(l),process.exit(1);}):Ye().catch(l=>{W.logger.error(l),L.exit(1);});export{Ye as cli};//# sourceMappingURL=cli.js.map
602
+ `),H.exit(0);return}let t=U.getCommand(l);if(!t){console.error(ot(l,U.getCommands().filter(s=>s&&s.commandName).map(s=>s.commandName))||`Command ${l} not found`),H.exit(1);return}let r=t;if(r.calledBy=w.basename(fe.getCliCaller()),r.options?.deprecated){let s=r.options.deprecated.message||"This command is deprecated",c=r.options.deprecated.replacement;console.warn(`\x1B[33m\u26A0\uFE0F Warning: ${s}\x1B[0m`),c&&console.warn(`\x1B[33m Use '${c}' instead.\x1B[0m
603
+ `);}if(await L.loadLogger(r.options?.loggerPath),r.handleHelpFlag(r.flags),r.validateUnknownFlags(r),r.validateContext(r),r.options?.validate&&!await r.options.validate(r)){console.error("Command validation failed"),H.exit(1);return}await r.handle(),(t.options?.keepAlive??false)||H.exit(0);};typeof process<"u"?Ye().catch(async l=>{if(l?.message?.includes("SyntaxError")||l?.code==="ERR_UNKNOWN_FILE_EXTENSION")try{let{register:e}=await import('module');e("ts-node/esm",import.meta.url),Ye().catch(t=>{L.logger.error(t),process.exit(1);});}catch{L.logger.error("Failed to register ts-node/esm, you need to install it in your project in order to use typescript in the cli\ntry running: `npm install -D ts-node`"),process.exit(1);}else L.logger.error(l),process.exit(1);}):Ye().catch(l=>{L.logger.error(l),H.exit(1);});export{Ye as cli};//# sourceMappingURL=cli.js.map
602
604
  //# sourceMappingURL=cli.js.map