@ooneex/cli 1.7.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +267 -217
- package/dist/index.js.map +22 -22
- package/package.json +22 -9
package/dist/index.js
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
var
|
|
4
|
-
`),
|
|
5
|
-
`+s,width:
|
|
6
|
-
`)o.name="enter";else if(e==="\t")o.name="tab";else if(e==="\b"||e==="\x7F"||e==="\x1B\x7F"||e==="\x1B\b")o.name="backspace",o.meta=e.charAt(0)==="\x1B";else if(e==="\x1B"||e==="\x1B\x1B")o.name="escape",o.meta=e.length===2;else if(e===" "||e==="\x1B ")o.name="space",o.meta=e.length===2;else if(e<="\x1A")o.name=String.fromCharCode(e.charCodeAt(0)+97-1),o.ctrl=!0;else if(e.length===1&&e>="0"&&e<="9")o.name="number";else if(e.length===1&&e>="a"&&e<="z")o.name=e;else if(e.length===1&&e>="A"&&e<="Z")o.name=e.toLowerCase(),o.shift=!0;else if(s=cn.exec(e))o.meta=!0,o.shift=/^[A-Z]$/.test(s[1]);else if(s=pn.exec(e)){let r=[...e];if(r[0]==="\x1B"&&r[1]==="\x1B")o.option=!0;let a=[s[1],s[2],s[4],s[6]].filter(Boolean).join(""),i=(s[3]||s[5]||1)-1;o.ctrl=!!(i&4),o.meta=!!(i&10),o.shift=!!(i&1),o.code=a,o.name=un[a],o.shift=hn(a)||o.shift,o.ctrl=fn(a)||o.ctrl}return o};_e.listen=(e={},t)=>{let{stdin:s}=e;if(!s||s!==process.stdin&&!s.isTTY)throw Error("Invalid stream passed");let o=ns.createInterface({terminal:!0,input:s});ns.emitKeypressEvents(s,o);let r=new mn((n,l)=>t(n,_e(n,l),o)),a=s.isRaw;if(s.isTTY)s.setRawMode(!0);return s.on("keypress",r.enqueue),o.resume(),()=>{if(s.isTTY)s.setRawMode(a);s.removeListener("keypress",r.enqueue),r.destroy(),o.pause(),o.close()}};_e.action=(e,t,s)=>{let o={...dn,...s};if(t.ctrl)return t.action=o.ctrl[t.name],t;if(t.option&&o.option)return t.action=o.option[t.name],t;if(t.shift)return t.action=o.shift[t.name],t;return t.action=o.keys[t.name],t};ls.exports=_e});var ms=x((tp,ds)=>{ds.exports=(e)=>{e.timers=e.timers||{};let t=e.options.timers;if(!t)return;for(let s of Object.keys(t)){let o=t[s];if(typeof o==="number")o={interval:o};gn(e,s,o)}};function gn(e,t,s={}){let o=e.timers[t]={name:t,start:Date.now(),ms:0,tick:0},r=s.interval||120;o.frames=s.frames||[],o.loading=!0;let a=setInterval(()=>{o.ms=Date.now()-o.start,o.tick++,e.render()},r);return o.stop=()=>{o.loading=!1,clearInterval(a)},Reflect.defineProperty(o,"interval",{value:a}),e.once("close",()=>o.stop()),o.stop}});var us=x((sp,ps)=>{var{define:yn,width:bn}=R();class cs{constructor(e){let t=e.options;yn(this,"_prompt",e),this.type=e.type,this.name=e.name,this.message="",this.header="",this.footer="",this.error="",this.hint="",this.input="",this.cursor=0,this.index=0,this.lines=0,this.tick=0,this.prompt="",this.buffer="",this.width=bn(t.stdout||process.stdout),Object.assign(this,t),this.name=this.name||this.message,this.message=this.message||this.name,this.symbols=e.symbols,this.styles=e.styles,this.required=new Set,this.cancelled=!1,this.submitted=!1}clone(){let e={...this};return e.status=this.status,e.buffer=Buffer.from(e.buffer),delete e.clone,e}set color(e){this._color=e}get color(){let e=this.prompt.styles;if(this.cancelled)return e.cancelled;if(this.submitted)return e.submitted;let t=this._color||e[this.status];return typeof t==="function"?t:e.pending}set loading(e){this._loading=e}get loading(){if(typeof this._loading==="boolean")return this._loading;if(this.loadingChoices)return"choices";return!1}get status(){if(this.cancelled)return"cancelled";if(this.submitted)return"submitted";return"pending"}}ps.exports=cs});var fs=x((op,hs)=>{var ct=R(),M=Me(),pt={default:M.noop,noop:M.noop,set inverse(e){this._inverse=e},get inverse(){return this._inverse||ct.inverse(this.primary)},set complement(e){this._complement=e},get complement(){return this._complement||ct.complement(this.primary)},primary:M.cyan,success:M.green,danger:M.magenta,strong:M.bold,warning:M.yellow,muted:M.dim,disabled:M.gray,dark:M.dim.gray,underline:M.underline,set info(e){this._info=e},get info(){return this._info||this.primary},set em(e){this._em=e},get em(){return this._em||this.primary.underline},set heading(e){this._heading=e},get heading(){return this._heading||this.muted.underline},set pending(e){this._pending=e},get pending(){return this._pending||this.primary},set submitted(e){this._submitted=e},get submitted(){return this._submitted||this.success},set cancelled(e){this._cancelled=e},get cancelled(){return this._cancelled||this.danger},set typing(e){this._typing=e},get typing(){return this._typing||this.dim},set placeholder(e){this._placeholder=e},get placeholder(){return this._placeholder||this.primary.dim},set highlight(e){this._highlight=e},get highlight(){return this._highlight||this.inverse}};pt.merge=(e={})=>{if(e.styles&&typeof e.styles.enabled==="boolean")M.enabled=e.styles.enabled;if(e.styles&&typeof e.styles.visible==="boolean")M.visible=e.styles.visible;let t=ct.merge({},pt,e.styles);delete t.merge;for(let s of Object.keys(M))if(!hasOwnProperty.call(t,s))Reflect.defineProperty(t,s,{get:()=>M[s]});for(let s of Object.keys(M.styles))if(!hasOwnProperty.call(t,s))Reflect.defineProperty(t,s,{get:()=>M[s]});return t};hs.exports=pt});var ys=x((rp,gs)=>{var ut=process.platform==="win32",F=Me(),wn=R(),ht={...F.symbols,upDownDoubleArrow:"\u21D5",upDownDoubleArrow2:"\u2B0D",upDownArrow:"\u2195",asterisk:"*",asterism:"\u2042",bulletWhite:"\u25E6",electricArrow:"\u2301",ellipsisLarge:"\u22EF",ellipsisSmall:"\u2026",fullBlock:"\u2588",identicalTo:"\u2261",indicator:F.symbols.check,leftAngle:"\u2039",mark:"\u203B",minus:"\u2212",multiplication:"\xD7",obelus:"\xF7",percent:"%",pilcrow:"\xB6",pilcrow2:"\u2761",pencilUpRight:"\u2710",pencilDownRight:"\u270E",pencilRight:"\u270F",plus:"+",plusMinus:"\xB1",pointRight:"\u261E",rightAngle:"\u203A",section:"\xA7",hexagon:{off:"\u2B21",on:"\u2B22",disabled:"\u2B22"},ballot:{on:"\u2611",off:"\u2610",disabled:"\u2612"},stars:{on:"\u2605",off:"\u2606",disabled:"\u2606"},folder:{on:"\u25BC",off:"\u25B6",disabled:"\u25B6"},prefix:{pending:F.symbols.question,submitted:F.symbols.check,cancelled:F.symbols.cross},separator:{pending:F.symbols.pointerSmall,submitted:F.symbols.middot,cancelled:F.symbols.middot},radio:{off:ut?"( )":"\u25EF",on:ut?"(*)":"\u25C9",disabled:ut?"(|)":"\u24BE"},numbers:["\u24EA","\u2460","\u2461","\u2462","\u2463","\u2464","\u2465","\u2466","\u2467","\u2468","\u2469","\u246A","\u246B","\u246C","\u246D","\u246E","\u246F","\u2470","\u2471","\u2472","\u2473","\u3251","\u3252","\u3253","\u3254","\u3255","\u3256","\u3257","\u3258","\u3259","\u325A","\u325B","\u325C","\u325D","\u325E","\u325F","\u32B1","\u32B2","\u32B3","\u32B4","\u32B5","\u32B6","\u32B7","\u32B8","\u32B9","\u32BA","\u32BB","\u32BC","\u32BD","\u32BE","\u32BF"]};ht.merge=(e)=>{let t=wn.merge({},F.symbols,ht,e.symbols);return delete t.merge,t};gs.exports=ht});var ws=x((ap,bs)=>{var xn=fs(),En=ys(),An=R();bs.exports=(e)=>{e.options=An.merge({},e.options.theme,e.options),e.symbols=En.merge(e.options),e.styles=xn.merge(e.options)}});var vs=x((Es,As)=>{var xs=process.env.TERM_PROGRAM==="Apple_Terminal",vn=se(),ft=R(),L=As.exports=Es,gt=!1,oe=L.code={bell:"\x07",beep:"\x07",beginning:"\x1B[G",down:"\x1B[J",esc:"\x1B[",getPosition:"\x1B[6n",hide:"\x1B[?25l",line:"\x1B[2K",lineEnd:"\x1B[K",lineStart:"\x1B[1K",restorePosition:"\x1B["+(xs?"8":"u"),savePosition:"\x1B["+(xs?"7":"s"),screen:"\x1B[2J",show:"\x1B[?25h",up:"\x1B[1J"},ne=L.cursor={get hidden(){return gt},hide(){return gt=!0,oe.hide},show(){return gt=!1,oe.show},forward:(e=1)=>`\x1B[${e}C`,backward:(e=1)=>`\x1B[${e}D`,nextLine:(e=1)=>"\x1B[E".repeat(e),prevLine:(e=1)=>"\x1B[F".repeat(e),up:(e=1)=>e?`\x1B[${e}A`:"",down:(e=1)=>e?`\x1B[${e}B`:"",right:(e=1)=>e?`\x1B[${e}C`:"",left:(e=1)=>e?`\x1B[${e}D`:"",to(e,t){return t?`\x1B[${t+1};${e+1}H`:`\x1B[${e+1}G`},move(e=0,t=0){let s="";return s+=e<0?ne.left(-e):e>0?ne.right(e):"",s+=t<0?ne.up(-t):t>0?ne.down(t):"",s},strLen(e){var t=0,s=e.length,o=-1;for(var r=0;r<s;r++)if(o=e.charCodeAt(r),o>=0&&o<=128)t+=1;else t+=2;return t},restore(e={}){let{after:t,cursor:s,initial:o,input:r,prompt:a,size:i,value:n}=e;if(o=ft.isPrimitive(o)?String(o):"",r=ft.isPrimitive(r)?String(r):"",n=ft.isPrimitive(n)?String(n):"",i){let l=L.cursor.up(i)+L.cursor.to(this.strLen(a)),d=r.length-s;if(d>0)l+=L.cursor.left(d);return l}if(n||t){let l=!r&&!!o?-this.strLen(o):-this.strLen(r)+s;if(t)l-=this.strLen(t);if(r===""&&o&&!a.includes(o))l+=this.strLen(o);return L.cursor.move(l)}}},yt=L.erase={screen:oe.screen,up:oe.up,down:oe.down,line:oe.line,lineEnd:oe.lineEnd,lineStart:oe.lineStart,lines(e){let t="";for(let s=0;s<e;s++)t+=L.erase.line+(s<e-1?L.cursor.up(1):"");if(e)t+=L.code.beginning;return t}};L.clear=(e="",t=process.stdout.columns)=>{if(!t)return yt.line+ne.to(0);let s=(a)=>[...vn(a)].length,o=e.split(/\r?\n/),r=0;for(let a of o)r+=1+Math.floor(Math.max(s(a)-1,0)/t);return(yt.line+ne.prevLine()).repeat(r-1)+yt.line+ne.to(0)}});var ue=x((ip,Ts)=>{var Nn=be("events"),Ns=se(),bt=mt(),Tn=ms(),Sn=us(),Cn=ws(),_=R(),le=vs();class wt extends Nn{constructor(e={}){super();this.name=e.name,this.type=e.type,this.options=e,Cn(this),Tn(this),this.state=new Sn(this),this.initial=[e.initial,e.default].find((t)=>t!=null),this.stdout=e.stdout||process.stdout,this.stdin=e.stdin||process.stdin,this.scale=e.scale||1,this.term=this.options.term||process.env.TERM_PROGRAM,this.margin=Rn(this.options.margin),this.setMaxListeners(0),Mn(this)}async keypress(e,t={}){this.keypressed=!0;let s=bt.action(e,bt(e,t),this.options.actions);this.state.keypress=s,this.emit("keypress",e,s),this.emit("state",this.state.clone());let o=this.options[s.action]||this[s.action]||this.dispatch;if(typeof o==="function")return await o.call(this,e,s);this.alert()}alert(){if(delete this.state.alert,this.options.show===!1)this.emit("alert");else this.stdout.write(le.code.beep)}cursorHide(){this.stdout.write(le.cursor.hide());let e=_.onExit(()=>this.cursorShow());this.on("close",()=>{this.cursorShow(),e()})}cursorShow(){this.stdout.write(le.cursor.show())}write(e){if(!e)return;if(this.stdout&&this.state.show!==!1)this.stdout.write(e);this.state.buffer+=e}clear(e=0){let t=this.state.buffer;if(this.state.buffer="",!t&&!e||this.options.show===!1)return;this.stdout.write(le.cursor.down(e)+le.clear(t,this.width))}restore(){if(this.state.closed||this.options.show===!1)return;let{prompt:e,after:t,rest:s}=this.sections(),{cursor:o,initial:r="",input:a="",value:i=""}=this,n=this.state.size=s.length,l={after:t,cursor:o,initial:r,input:a,prompt:e,size:n,value:i},d=le.cursor.restore(l);if(d)this.stdout.write(d)}sections(){let{buffer:e,input:t,prompt:s}=this.state;s=Ns(s);let o=Ns(e),r=o.indexOf(s),a=o.slice(0,r),n=o.slice(r).split(`
|
|
7
|
-
`),
|
|
3
|
+
var ma=Object.create;var{getPrototypeOf:pa,defineProperty:Ht,getOwnPropertyNames:ua}=Object;var ha=Object.prototype.hasOwnProperty;function fa(e){return this[e]}var ya,ga,te=(e,t,s)=>{var r=e!=null&&typeof e==="object";if(r){var o=t?ya??=new WeakMap:ga??=new WeakMap,i=o.get(e);if(i)return i}s=e!=null?ma(pa(e)):{};let a=t||!e||!e.__esModule?Ht(s,"default",{value:e,enumerable:!0}):s;for(let n of ua(e))if(!ha.call(a,n))Ht(a,n,{get:fa.bind(e,n),enumerable:!0});if(r)o.set(e,a);return a};var w=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var b=function(e,t,s,r){var o=arguments.length,i=o<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,s):r,a;if(typeof Reflect==="object"&&typeof Reflect.decorate==="function")i=Reflect.decorate(e,t,s,r);else for(var n=e.length-1;n>=0;n--)if(a=e[n])i=(o<3?a(i):o>3?a(t,s,i):a(t,s))||i;return o>3&&i&&Object.defineProperty(t,s,i),i};var be=import.meta.require;var Xt=w((zm,xe)=>{var Sa=typeof process<"u"&&process.env.TERM_PROGRAM==="Hyper",Ta=typeof process<"u"&&process.platform==="win32",zt=typeof process<"u"&&process.platform==="linux",dt={ballotDisabled:"\u2612",ballotOff:"\u2610",ballotOn:"\u2611",bullet:"\u2022",bulletWhite:"\u25E6",fullBlock:"\u2588",heart:"\u2764",identicalTo:"\u2261",line:"\u2500",mark:"\u203B",middot:"\xB7",minus:"\uFF0D",multiplication:"\xD7",obelus:"\xF7",pencilDownRight:"\u270E",pencilRight:"\u270F",pencilUpRight:"\u2710",percent:"%",pilcrow2:"\u2761",pilcrow:"\xB6",plusMinus:"\xB1",question:"?",section:"\xA7",starsOff:"\u2606",starsOn:"\u2605",upDownArrow:"\u2195"},Zt=Object.assign({},dt,{check:"\u221A",cross:"\xD7",ellipsisLarge:"...",ellipsis:"...",info:"i",questionSmall:"?",pointer:">",pointerSmall:"\xBB",radioOff:"( )",radioOn:"(*)",warning:"\u203C"}),Qt=Object.assign({},dt,{ballotCross:"\u2718",check:"\u2714",cross:"\u2716",ellipsisLarge:"\u22EF",ellipsis:"\u2026",info:"\u2139",questionFull:"\uFF1F",questionSmall:"\uFE56",pointer:zt?"\u25B8":"\u276F",pointerSmall:zt?"\u2023":"\u203A",radioOff:"\u25EF",radioOn:"\u25C9",warning:"\u26A0"});xe.exports=Ta&&!Sa?Zt:Qt;Reflect.defineProperty(xe.exports,"common",{enumerable:!1,value:dt});Reflect.defineProperty(xe.exports,"windows",{enumerable:!1,value:Zt});Reflect.defineProperty(xe.exports,"other",{enumerable:!1,value:Qt})});var Me=w((Zm,lt)=>{var Ra=(e)=>e!==null&&typeof e==="object"&&!Array.isArray(e),Ma=/[\u001b\u009b][[\]#;?()]*(?:(?:(?:[^\W_]*;?[^\W_]*)\u0007)|(?:(?:[0-9]{1,4}(;[0-9]{0,4})*)?[~0-9=<>cf-nqrtyA-PRZ]))/g,Ca=()=>{if(typeof process<"u")return process.env.FORCE_COLOR!=="0";return!1},Jt=()=>{let e={enabled:Ca(),visible:!0,styles:{},keys:{}},t=(i)=>{let a=i.open=`\x1B[${i.codes[0]}m`,n=i.close=`\x1B[${i.codes[1]}m`,d=i.regex=new RegExp(`\\u001b\\[${i.codes[1]}m`,"g");return i.wrap=(l,c)=>{if(l.includes(n))l=l.replace(d,n+a);let u=a+l+n;return c?u.replace(/\r*\n/g,`${n}$&${a}`):u},i},s=(i,a,n)=>{return typeof i==="function"?i(a):i.wrap(a,n)},r=(i,a)=>{if(i===""||i==null)return"";if(e.enabled===!1)return i;if(e.visible===!1)return"";let n=""+i,d=n.includes(`
|
|
4
|
+
`),l=a.length;if(l>0&&a.includes("unstyle"))a=[...new Set(["unstyle",...a])].reverse();while(l-- >0)n=s(e.styles[a[l]],n,d);return n},o=(i,a,n)=>{e.styles[i]=t({name:i,codes:a}),(e.keys[n]||(e.keys[n]=[])).push(i),Reflect.defineProperty(e,i,{configurable:!0,enumerable:!0,set(l){e.alias(i,l)},get(){let l=(c)=>r(c,l.stack);return Reflect.setPrototypeOf(l,e),l.stack=this.stack?this.stack.concat(i):[i],l}})};return o("reset",[0,0],"modifier"),o("bold",[1,22],"modifier"),o("dim",[2,22],"modifier"),o("italic",[3,23],"modifier"),o("underline",[4,24],"modifier"),o("inverse",[7,27],"modifier"),o("hidden",[8,28],"modifier"),o("strikethrough",[9,29],"modifier"),o("black",[30,39],"color"),o("red",[31,39],"color"),o("green",[32,39],"color"),o("yellow",[33,39],"color"),o("blue",[34,39],"color"),o("magenta",[35,39],"color"),o("cyan",[36,39],"color"),o("white",[37,39],"color"),o("gray",[90,39],"color"),o("grey",[90,39],"color"),o("bgBlack",[40,49],"bg"),o("bgRed",[41,49],"bg"),o("bgGreen",[42,49],"bg"),o("bgYellow",[43,49],"bg"),o("bgBlue",[44,49],"bg"),o("bgMagenta",[45,49],"bg"),o("bgCyan",[46,49],"bg"),o("bgWhite",[47,49],"bg"),o("blackBright",[90,39],"bright"),o("redBright",[91,39],"bright"),o("greenBright",[92,39],"bright"),o("yellowBright",[93,39],"bright"),o("blueBright",[94,39],"bright"),o("magentaBright",[95,39],"bright"),o("cyanBright",[96,39],"bright"),o("whiteBright",[97,39],"bright"),o("bgBlackBright",[100,49],"bgBright"),o("bgRedBright",[101,49],"bgBright"),o("bgGreenBright",[102,49],"bgBright"),o("bgYellowBright",[103,49],"bgBright"),o("bgBlueBright",[104,49],"bgBright"),o("bgMagentaBright",[105,49],"bgBright"),o("bgCyanBright",[106,49],"bgBright"),o("bgWhiteBright",[107,49],"bgBright"),e.ansiRegex=Ma,e.hasColor=e.hasAnsi=(i)=>{return e.ansiRegex.lastIndex=0,typeof i==="string"&&i!==""&&e.ansiRegex.test(i)},e.alias=(i,a)=>{let n=typeof a==="string"?e[a]:a;if(typeof n!=="function")throw TypeError("Expected alias to be the name of an existing color (string) or a function");if(!n.stack)Reflect.defineProperty(n,"name",{value:i}),e.styles[i]=n,n.stack=[i];Reflect.defineProperty(e,i,{configurable:!0,enumerable:!0,set(d){e.alias(i,d)},get(){let d=(l)=>r(l,d.stack);return Reflect.setPrototypeOf(d,e),d.stack=this.stack?this.stack.concat(n.stack):n.stack,d}})},e.theme=(i)=>{if(!Ra(i))throw TypeError("Expected theme to be an object");for(let a of Object.keys(i))e.alias(a,i[a]);return e},e.alias("unstyle",(i)=>{if(typeof i==="string"&&i!=="")return e.ansiRegex.lastIndex=0,i.replace(e.ansiRegex,"");return""}),e.alias("noop",(i)=>i),e.none=e.clear=e.noop,e.stripColor=e.unstyle,e.symbols=Xt(),e.define=o,e};lt.exports=Jt();lt.exports.create=Jt});var C=w((Ia)=>{var _a=Object.prototype.toString,B=Me(),jt=!1,we=new Set,es={yellow:"blue",cyan:"red",green:"magenta",black:"white",blue:"yellow",red:"cyan",magenta:"green",white:"black"};Ia.longest=(e,t)=>{return e.reduce((s,r)=>Math.max(s,t?r[t].length:r.length),0)};Ia.hasColor=(e)=>!!e&&B.hasColor(e);var Ce=Ia.isObject=(e)=>{return e!==null&&typeof e==="object"&&!Array.isArray(e)};Ia.nativeType=(e)=>{return _a.call(e).slice(8,-1).toLowerCase().replace(/\s/g,"")};Ia.isAsyncFn=(e)=>{return Ia.nativeType(e)==="asyncfunction"};Ia.isPrimitive=(e)=>{return e!=null&&typeof e!=="object"&&typeof e!=="function"};Ia.resolve=(e,t,...s)=>{if(typeof t==="function")return t.call(e,...s);return t};Ia.scrollDown=(e=[])=>[...e.slice(1),e[0]];Ia.scrollUp=(e=[])=>[e.pop(),...e];Ia.reorder=(e=[])=>{let t=e.slice();return t.sort((s,r)=>{if(s.index>r.index)return 1;if(s.index<r.index)return-1;return 0}),t};Ia.swap=(e,t,s)=>{let r=e.length,o=s===r?0:s<0?r-1:s,i=e[t];e[t]=e[o],e[o]=i};Ia.width=(e,t=80)=>{let s=e&&e.columns?e.columns:t;if(e&&typeof e.getWindowSize==="function")s=e.getWindowSize()[0];if(process.platform==="win32")return s-1;return s};Ia.height=(e,t=20)=>{let s=e&&e.rows?e.rows:t;if(e&&typeof e.getWindowSize==="function")s=e.getWindowSize()[1];return s};Ia.wordWrap=(e,t={})=>{if(!e)return e;if(typeof t==="number")t={width:t};let{indent:s="",newline:r=`
|
|
5
|
+
`+s,width:o=80}=t,i=(r+s).match(/[^\S\n]/g)||[];o-=i.length;let a=`.{1,${o}}([\\s\\u200B]+|$)|[^\\s\\u200B]+?([\\s\\u200B]+|$)`,n=e.trim(),d=new RegExp(a,"g"),l=n.match(d)||[];if(l=l.map((c)=>c.replace(/\n$/,"")),t.padEnd)l=l.map((c)=>c.padEnd(o," "));if(t.padStart)l=l.map((c)=>c.padStart(o," "));return s+l.join(r)};Ia.unmute=(e)=>{let t=e.stack.find((r)=>B.keys.color.includes(r));if(t)return B[t];if(e.stack.find((r)=>r.slice(2)==="bg"))return B[t.slice(2)];return(r)=>r};Ia.pascal=(e)=>e?e[0].toUpperCase()+e.slice(1):"";Ia.inverse=(e)=>{if(!e||!e.stack)return e;let t=e.stack.find((r)=>B.keys.color.includes(r));if(t){let r=B["bg"+Ia.pascal(t)];return r?r.black:e}let s=e.stack.find((r)=>r.slice(0,2)==="bg");if(s)return B[s.slice(2).toLowerCase()]||e;return B.none};Ia.complement=(e)=>{if(!e||!e.stack)return e;let t=e.stack.find((r)=>B.keys.color.includes(r)),s=e.stack.find((r)=>r.slice(0,2)==="bg");if(t&&!s)return B[es[t]||t];if(s){let r=s.slice(2).toLowerCase(),o=es[r];if(!o)return e;return B["bg"+Ia.pascal(o)]||e}return B.none};Ia.meridiem=(e)=>{let t=e.getHours(),s=e.getMinutes(),r=t>=12?"pm":"am";t=t%12;let o=t===0?12:t,i=s<10?"0"+s:s;return o+":"+i+" "+r};Ia.set=(e={},t="",s)=>{return t.split(".").reduce((r,o,i,a)=>{let n=a.length-1>i?r[o]||{}:s;if(!Ia.isObject(n)&&i<a.length-1)n={};return r[o]=n},e)};Ia.get=(e={},t="",s)=>{let r=e[t]==null?t.split(".").reduce((o,i)=>o&&o[i],e):e[t];return r==null?s:r};Ia.mixin=(e,t)=>{if(!Ce(e))return t;if(!Ce(t))return e;for(let s of Object.keys(t)){let r=Object.getOwnPropertyDescriptor(t,s);if(hasOwnProperty.call(r,"value"))if(hasOwnProperty.call(e,s)&&Ce(r.value)){let o=Object.getOwnPropertyDescriptor(e,s);if(Ce(o.value)&&o.value!==r.value)e[s]=Ia.merge({},e[s],t[s]);else Reflect.defineProperty(e,s,r)}else Reflect.defineProperty(e,s,r);else Reflect.defineProperty(e,s,r)}return e};Ia.merge=(...e)=>{let t={};for(let s of e)Ia.mixin(t,s);return t};Ia.mixinEmitter=(e,t)=>{let s=t.constructor.prototype;for(let r of Object.keys(s)){let o=s[r];if(typeof o==="function")Ia.define(e,r,o.bind(t));else Ia.define(e,r,o)}};var _e=(e,t)=>{if(jt)return;if(jt=!0,we.forEach((s)=>s()),e===!0)process.exit(128+t)},ts=_e.bind(null,!0,15),ss=_e.bind(null,!0,2);Ia.onExit=(e)=>{if(we.size===0)process.once("SIGTERM",ts),process.once("SIGINT",ss),process.once("exit",_e);return we.add(e),()=>{if(we.delete(e),we.size===0)process.off("SIGTERM",ts),process.off("SIGINT",ss),process.off("exit",_e)}};Ia.define=(e,t,s)=>{Reflect.defineProperty(e,t,{value:s})};Ia.defineExport=(e,t,s)=>{let r;Reflect.defineProperty(e,t,{enumerable:!0,configurable:!0,set(o){r=o},get(){return r?r():s()}})}});var ns=w((Xm,as)=>{as.exports=({onlyFirst:e=!1}={})=>{let t=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"].join("|");return new RegExp(t,e?void 0:"g")}});var se=w((Jm,ds)=>{var tn=ns();ds.exports=(e)=>typeof e==="string"?e.replace(tn(),""):e});var ls=w((sn)=>{sn.ctrl={a:"first",b:"backward",c:"cancel",d:"deleteForward",e:"last",f:"forward",g:"reset",i:"tab",k:"cutForward",l:"reset",n:"newItem",m:"cancel",j:"submit",p:"search",r:"remove",s:"save",u:"undo",w:"cutLeft",x:"toggleCursor",v:"paste"};sn.shift={up:"shiftUp",down:"shiftDown",left:"shiftLeft",right:"shiftRight",tab:"prev"};sn.fn={up:"pageUp",down:"pageDown",left:"pageLeft",right:"pageRight",delete:"deleteForward"};sn.option={b:"backward",f:"forward",d:"cutRight",left:"cutLeft",up:"altUp",down:"altDown"};sn.keys={pageup:"pageUp",pagedown:"pageDown",home:"home",end:"end",cancel:"cancel",delete:"deleteForward",backspace:"delete",down:"down",enter:"submit",escape:"cancel",left:"left",space:"space",number:"number",return:"submit",right:"right",tab:"next",up:"up"}});var ms=w((ep,cs)=>{cs.exports=class{_queue=[];_executing=!1;_jobRunner=null;constructor(t){this._jobRunner=t}enqueue=(...t)=>{this._queue.push(t),this._dequeue()};destroy(){this._queue.length=0,this._jobRunner=null}_dequeue(){if(this._executing||!this._queue.length)return;this._executing=!0,this._jobRunner(...this._queue.shift()),setTimeout(()=>{this._executing=!1,this._dequeue()})}}});var mt=w((tp,us)=>{var ps=be("readline"),ln=ls(),cn=ms(),mn=/^(?:\x1b)([a-zA-Z0-9])$/,pn=/^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/,un={OP:"f1",OQ:"f2",OR:"f3",OS:"f4","[11~":"f1","[12~":"f2","[13~":"f3","[14~":"f4","[[A":"f1","[[B":"f2","[[C":"f3","[[D":"f4","[[E":"f5","[15~":"f5","[17~":"f6","[18~":"f7","[19~":"f8","[20~":"f9","[21~":"f10","[23~":"f11","[24~":"f12","[A":"up","[B":"down","[C":"right","[D":"left","[E":"clear","[F":"end","[H":"home",OA:"up",OB:"down",OC:"right",OD:"left",OE:"clear",OF:"end",OH:"home","[1~":"home","[2~":"insert","[3~":"delete","[4~":"end","[5~":"pageup","[6~":"pagedown","[[5~":"pageup","[[6~":"pagedown","[7~":"home","[8~":"end","[a":"up","[b":"down","[c":"right","[d":"left","[e":"clear","[2$":"insert","[3$":"delete","[5$":"pageup","[6$":"pagedown","[7$":"home","[8$":"end",Oa:"up",Ob:"down",Oc:"right",Od:"left",Oe:"clear","[2^":"insert","[3^":"delete","[5^":"pageup","[6^":"pagedown","[7^":"home","[8^":"end","[Z":"tab"};function hn(e){return["[a","[b","[c","[d","[e","[2$","[3$","[5$","[6$","[7$","[8$","[Z"].includes(e)}function fn(e){return["Oa","Ob","Oc","Od","Oe","[2^","[3^","[5^","[6^","[7^","[8^"].includes(e)}var Ie=(e="",t={})=>{let s,r={name:t.name,ctrl:!1,meta:!1,shift:!1,option:!1,sequence:e,raw:e,...t};if(Buffer.isBuffer(e))if(e[0]>127&&e[1]===void 0)e[0]-=128,e="\x1B"+String(e);else e=String(e);else if(e!==void 0&&typeof e!=="string")e=String(e);else if(!e)e=r.sequence||"";if(r.sequence=r.sequence||e||r.name,e==="\r")r.raw=void 0,r.name="return";else if(e===`
|
|
6
|
+
`)r.name="enter";else if(e==="\t")r.name="tab";else if(e==="\b"||e==="\x7F"||e==="\x1B\x7F"||e==="\x1B\b")r.name="backspace",r.meta=e.charAt(0)==="\x1B";else if(e==="\x1B"||e==="\x1B\x1B")r.name="escape",r.meta=e.length===2;else if(e===" "||e==="\x1B ")r.name="space",r.meta=e.length===2;else if(e<="\x1A")r.name=String.fromCharCode(e.charCodeAt(0)+97-1),r.ctrl=!0;else if(e.length===1&&e>="0"&&e<="9")r.name="number";else if(e.length===1&&e>="a"&&e<="z")r.name=e;else if(e.length===1&&e>="A"&&e<="Z")r.name=e.toLowerCase(),r.shift=!0;else if(s=mn.exec(e))r.meta=!0,r.shift=/^[A-Z]$/.test(s[1]);else if(s=pn.exec(e)){let o=[...e];if(o[0]==="\x1B"&&o[1]==="\x1B")r.option=!0;let i=[s[1],s[2],s[4],s[6]].filter(Boolean).join(""),a=(s[3]||s[5]||1)-1;r.ctrl=!!(a&4),r.meta=!!(a&10),r.shift=!!(a&1),r.code=i,r.name=un[i],r.shift=hn(i)||r.shift,r.ctrl=fn(i)||r.ctrl}return r};Ie.listen=(e={},t)=>{let{stdin:s}=e;if(!s||s!==process.stdin&&!s.isTTY)throw Error("Invalid stream passed");let r=ps.createInterface({terminal:!0,input:s});ps.emitKeypressEvents(s,r);let o=new cn((n,d)=>t(n,Ie(n,d),r)),i=s.isRaw;if(s.isTTY)s.setRawMode(!0);return s.on("keypress",o.enqueue),r.resume(),()=>{if(s.isTTY)s.setRawMode(i);s.removeListener("keypress",o.enqueue),o.destroy(),r.pause(),r.close()}};Ie.action=(e,t,s)=>{let r={...ln,...s};if(t.ctrl)return t.action=r.ctrl[t.name],t;if(t.option&&r.option)return t.action=r.option[t.name],t;if(t.shift)return t.action=r.shift[t.name],t;return t.action=r.keys[t.name],t};us.exports=Ie});var fs=w((sp,hs)=>{hs.exports=(e)=>{e.timers=e.timers||{};let t=e.options.timers;if(!t)return;for(let s of Object.keys(t)){let r=t[s];if(typeof r==="number")r={interval:r};yn(e,s,r)}};function yn(e,t,s={}){let r=e.timers[t]={name:t,start:Date.now(),ms:0,tick:0},o=s.interval||120;r.frames=s.frames||[],r.loading=!0;let i=setInterval(()=>{r.ms=Date.now()-r.start,r.tick++,e.render()},o);return r.stop=()=>{r.loading=!1,clearInterval(i)},Reflect.defineProperty(r,"interval",{value:i}),e.once("close",()=>r.stop()),r.stop}});var bs=w((rp,gs)=>{var{define:gn,width:bn}=C();class ys{constructor(e){let t=e.options;gn(this,"_prompt",e),this.type=e.type,this.name=e.name,this.message="",this.header="",this.footer="",this.error="",this.hint="",this.input="",this.cursor=0,this.index=0,this.lines=0,this.tick=0,this.prompt="",this.buffer="",this.width=bn(t.stdout||process.stdout),Object.assign(this,t),this.name=this.name||this.message,this.message=this.message||this.name,this.symbols=e.symbols,this.styles=e.styles,this.required=new Set,this.cancelled=!1,this.submitted=!1}clone(){let e={...this};return e.status=this.status,e.buffer=Buffer.from(e.buffer),delete e.clone,e}set color(e){this._color=e}get color(){let e=this.prompt.styles;if(this.cancelled)return e.cancelled;if(this.submitted)return e.submitted;let t=this._color||e[this.status];return typeof t==="function"?t:e.pending}set loading(e){this._loading=e}get loading(){if(typeof this._loading==="boolean")return this._loading;if(this.loadingChoices)return"choices";return!1}get status(){if(this.cancelled)return"cancelled";if(this.submitted)return"submitted";return"pending"}}gs.exports=ys});var ws=w((op,xs)=>{var pt=C(),M=Me(),ut={default:M.noop,noop:M.noop,set inverse(e){this._inverse=e},get inverse(){return this._inverse||pt.inverse(this.primary)},set complement(e){this._complement=e},get complement(){return this._complement||pt.complement(this.primary)},primary:M.cyan,success:M.green,danger:M.magenta,strong:M.bold,warning:M.yellow,muted:M.dim,disabled:M.gray,dark:M.dim.gray,underline:M.underline,set info(e){this._info=e},get info(){return this._info||this.primary},set em(e){this._em=e},get em(){return this._em||this.primary.underline},set heading(e){this._heading=e},get heading(){return this._heading||this.muted.underline},set pending(e){this._pending=e},get pending(){return this._pending||this.primary},set submitted(e){this._submitted=e},get submitted(){return this._submitted||this.success},set cancelled(e){this._cancelled=e},get cancelled(){return this._cancelled||this.danger},set typing(e){this._typing=e},get typing(){return this._typing||this.dim},set placeholder(e){this._placeholder=e},get placeholder(){return this._placeholder||this.primary.dim},set highlight(e){this._highlight=e},get highlight(){return this._highlight||this.inverse}};ut.merge=(e={})=>{if(e.styles&&typeof e.styles.enabled==="boolean")M.enabled=e.styles.enabled;if(e.styles&&typeof e.styles.visible==="boolean")M.visible=e.styles.visible;let t=pt.merge({},ut,e.styles);delete t.merge;for(let s of Object.keys(M))if(!hasOwnProperty.call(t,s))Reflect.defineProperty(t,s,{get:()=>M[s]});for(let s of Object.keys(M.styles))if(!hasOwnProperty.call(t,s))Reflect.defineProperty(t,s,{get:()=>M[s]});return t};xs.exports=ut});var As=w((ip,Es)=>{var ht=process.platform==="win32",K=Me(),xn=C(),ft={...K.symbols,upDownDoubleArrow:"\u21D5",upDownDoubleArrow2:"\u2B0D",upDownArrow:"\u2195",asterisk:"*",asterism:"\u2042",bulletWhite:"\u25E6",electricArrow:"\u2301",ellipsisLarge:"\u22EF",ellipsisSmall:"\u2026",fullBlock:"\u2588",identicalTo:"\u2261",indicator:K.symbols.check,leftAngle:"\u2039",mark:"\u203B",minus:"\u2212",multiplication:"\xD7",obelus:"\xF7",percent:"%",pilcrow:"\xB6",pilcrow2:"\u2761",pencilUpRight:"\u2710",pencilDownRight:"\u270E",pencilRight:"\u270F",plus:"+",plusMinus:"\xB1",pointRight:"\u261E",rightAngle:"\u203A",section:"\xA7",hexagon:{off:"\u2B21",on:"\u2B22",disabled:"\u2B22"},ballot:{on:"\u2611",off:"\u2610",disabled:"\u2612"},stars:{on:"\u2605",off:"\u2606",disabled:"\u2606"},folder:{on:"\u25BC",off:"\u25B6",disabled:"\u25B6"},prefix:{pending:K.symbols.question,submitted:K.symbols.check,cancelled:K.symbols.cross},separator:{pending:K.symbols.pointerSmall,submitted:K.symbols.middot,cancelled:K.symbols.middot},radio:{off:ht?"( )":"\u25EF",on:ht?"(*)":"\u25C9",disabled:ht?"(|)":"\u24BE"},numbers:["\u24EA","\u2460","\u2461","\u2462","\u2463","\u2464","\u2465","\u2466","\u2467","\u2468","\u2469","\u246A","\u246B","\u246C","\u246D","\u246E","\u246F","\u2470","\u2471","\u2472","\u2473","\u3251","\u3252","\u3253","\u3254","\u3255","\u3256","\u3257","\u3258","\u3259","\u325A","\u325B","\u325C","\u325D","\u325E","\u325F","\u32B1","\u32B2","\u32B3","\u32B4","\u32B5","\u32B6","\u32B7","\u32B8","\u32B9","\u32BA","\u32BB","\u32BC","\u32BD","\u32BE","\u32BF"]};ft.merge=(e)=>{let t=xn.merge({},K.symbols,ft,e.symbols);return delete t.merge,t};Es.exports=ft});var Ns=w((ap,vs)=>{var wn=ws(),En=As(),An=C();vs.exports=(e)=>{e.options=An.merge({},e.options.theme,e.options),e.symbols=En.merge(e.options),e.styles=wn.merge(e.options)}});var Ms=w((Ts,Rs)=>{var Ss=process.env.TERM_PROGRAM==="Apple_Terminal",vn=se(),yt=C(),L=Rs.exports=Ts,gt=!1,re=L.code={bell:"\x07",beep:"\x07",beginning:"\x1B[G",down:"\x1B[J",esc:"\x1B[",getPosition:"\x1B[6n",hide:"\x1B[?25l",line:"\x1B[2K",lineEnd:"\x1B[K",lineStart:"\x1B[1K",restorePosition:"\x1B["+(Ss?"8":"u"),savePosition:"\x1B["+(Ss?"7":"s"),screen:"\x1B[2J",show:"\x1B[?25h",up:"\x1B[1J"},ne=L.cursor={get hidden(){return gt},hide(){return gt=!0,re.hide},show(){return gt=!1,re.show},forward:(e=1)=>`\x1B[${e}C`,backward:(e=1)=>`\x1B[${e}D`,nextLine:(e=1)=>"\x1B[E".repeat(e),prevLine:(e=1)=>"\x1B[F".repeat(e),up:(e=1)=>e?`\x1B[${e}A`:"",down:(e=1)=>e?`\x1B[${e}B`:"",right:(e=1)=>e?`\x1B[${e}C`:"",left:(e=1)=>e?`\x1B[${e}D`:"",to(e,t){return t?`\x1B[${t+1};${e+1}H`:`\x1B[${e+1}G`},move(e=0,t=0){let s="";return s+=e<0?ne.left(-e):e>0?ne.right(e):"",s+=t<0?ne.up(-t):t>0?ne.down(t):"",s},strLen(e){var t=0,s=e.length,r=-1;for(var o=0;o<s;o++)if(r=e.charCodeAt(o),r>=0&&r<=128)t+=1;else t+=2;return t},restore(e={}){let{after:t,cursor:s,initial:r,input:o,prompt:i,size:a,value:n}=e;if(r=yt.isPrimitive(r)?String(r):"",o=yt.isPrimitive(o)?String(o):"",n=yt.isPrimitive(n)?String(n):"",a){let d=L.cursor.up(a)+L.cursor.to(this.strLen(i)),l=o.length-s;if(l>0)d+=L.cursor.left(l);return d}if(n||t){let d=!o&&!!r?-this.strLen(r):-this.strLen(o)+s;if(t)d-=this.strLen(t);if(o===""&&r&&!i.includes(r))d+=this.strLen(r);return L.cursor.move(d)}}},bt=L.erase={screen:re.screen,up:re.up,down:re.down,line:re.line,lineEnd:re.lineEnd,lineStart:re.lineStart,lines(e){let t="";for(let s=0;s<e;s++)t+=L.erase.line+(s<e-1?L.cursor.up(1):"");if(e)t+=L.code.beginning;return t}};L.clear=(e="",t=process.stdout.columns)=>{if(!t)return bt.line+ne.to(0);let s=(i)=>[...vn(i)].length,r=e.split(/\r?\n/),o=0;for(let i of r)o+=1+Math.floor(Math.max(s(i)-1,0)/t);return(bt.line+ne.prevLine()).repeat(o-1)+bt.line+ne.to(0)}});var ue=w((np,_s)=>{var Nn=be("events"),Cs=se(),xt=mt(),Sn=fs(),Tn=bs(),Rn=Ns(),I=C(),de=Ms();class wt extends Nn{constructor(e={}){super();this.name=e.name,this.type=e.type,this.options=e,Rn(this),Sn(this),this.state=new Tn(this),this.initial=[e.initial,e.default].find((t)=>t!=null),this.stdout=e.stdout||process.stdout,this.stdin=e.stdin||process.stdin,this.scale=e.scale||1,this.term=this.options.term||process.env.TERM_PROGRAM,this.margin=Cn(this.options.margin),this.setMaxListeners(0),Mn(this)}async keypress(e,t={}){this.keypressed=!0;let s=xt.action(e,xt(e,t),this.options.actions);this.state.keypress=s,this.emit("keypress",e,s),this.emit("state",this.state.clone());let r=this.options[s.action]||this[s.action]||this.dispatch;if(typeof r==="function")return await r.call(this,e,s);this.alert()}alert(){if(delete this.state.alert,this.options.show===!1)this.emit("alert");else this.stdout.write(de.code.beep)}cursorHide(){this.stdout.write(de.cursor.hide());let e=I.onExit(()=>this.cursorShow());this.on("close",()=>{this.cursorShow(),e()})}cursorShow(){this.stdout.write(de.cursor.show())}write(e){if(!e)return;if(this.stdout&&this.state.show!==!1)this.stdout.write(e);this.state.buffer+=e}clear(e=0){let t=this.state.buffer;if(this.state.buffer="",!t&&!e||this.options.show===!1)return;this.stdout.write(de.cursor.down(e)+de.clear(t,this.width))}restore(){if(this.state.closed||this.options.show===!1)return;let{prompt:e,after:t,rest:s}=this.sections(),{cursor:r,initial:o="",input:i="",value:a=""}=this,n=this.state.size=s.length,d={after:t,cursor:r,initial:o,input:i,prompt:e,size:n,value:a},l=de.cursor.restore(d);if(l)this.stdout.write(l)}sections(){let{buffer:e,input:t,prompt:s}=this.state;s=Cs(s);let r=Cs(e),o=r.indexOf(s),i=r.slice(0,o),n=r.slice(o).split(`
|
|
7
|
+
`),d=n[0],l=n[n.length-1],u=(s+(t?" "+t:"")).length,p=u<d.length?d.slice(u+1):"";return{header:i,prompt:d,after:p,rest:n.slice(1),last:l}}async submit(){if(this.state.submitted=!0,this.state.validating=!0,this.options.onSubmit)await this.options.onSubmit.call(this,this.name,this.value,this);let e=this.state.error||await this.validate(this.value,this.state);if(e!==!0){let t=`
|
|
8
8
|
`+this.symbols.pointer+" ";if(typeof e==="string")t+=e.trim();else t+="Invalid input";this.state.error=`
|
|
9
|
-
`+this.styles.danger(t),this.state.submitted=!1,await this.render(),await this.alert(),this.state.validating=!1,this.state.error=void 0;return}this.state.validating=!1,await this.render(),await this.close(),this.value=await this.result(this.value),this.emit("submit",this.value)}async cancel(e){if(this.state.cancelled=this.state.submitted=!0,await this.render(),await this.close(),typeof this.options.onCancel==="function")await this.options.onCancel.call(this,this.name,this.value,this);this.emit("cancel",await this.error(e))}async close(){this.state.closed=!0;try{let e=this.sections(),t=Math.ceil(e.prompt.length/this.width);if(e.rest)this.write(
|
|
10
|
-
`.repeat(t))}catch(e){}this.emit("close")}start(){if(!this.stop&&this.options.show!==!1)this.stop=
|
|
11
|
-
`:" ",o=[];for(let r=0;r<4;r++){let a=s(r);if(t[r])o.push(a.repeat(t[r]));else o.push("")}return o}Ts.exports=wt});var Ms=x((np,Cs)=>{var Dn=R(),Ss={default(e,t){return t},checkbox(e,t){throw Error("checkbox role is not implemented yet")},editable(e,t){throw Error("editable role is not implemented yet")},expandable(e,t){throw Error("expandable role is not implemented yet")},heading(e,t){return t.disabled="",t.indicator=[t.indicator," "].find((s)=>s!=null),t.message=t.message||"",t},input(e,t){throw Error("input role is not implemented yet")},option(e,t){return Ss.default(e,t)},radio(e,t){throw Error("radio role is not implemented yet")},separator(e,t){return t.disabled="",t.indicator=[t.indicator," "].find((s)=>s!=null),t.message=t.message||e.symbols.line.repeat(5),t},spacer(e,t){return t}};Cs.exports=(e,t={})=>{let s=Dn.merge({},Ss,t.roles);return s[e]||s.default}});var Ee=x((lp,Is)=>{var _n=se(),In=ue(),Pn=Ms(),Ie=R(),{reorder:xt,scrollUp:On,scrollDown:Bn,isObject:Rs,swap:Ln}=Ie;class _s extends In{constructor(e){super(e);this.cursorHide(),this.maxSelected=e.maxSelected||1/0,this.multiple=e.multiple||!1,this.initial=e.initial||0,this.delay=e.delay||0,this.longest=0,this.num=""}async initialize(){if(typeof this.options.initial==="function")this.initial=await this.options.initial.call(this);await this.reset(!0),await super.initialize()}async reset(){let{choices:e,initial:t,autofocus:s,suggest:o}=this.options;if(this.state._choices=[],this.state.choices=[],this.choices=await Promise.all(await this.toChoices(e)),this.choices.forEach((r)=>r.enabled=!1),typeof o!=="function"&&this.selectable.length===0)throw Error("At least one choice must be selectable");if(Rs(t))t=Object.keys(t);if(Array.isArray(t)){if(s!=null)this.index=this.findIndex(s);t.forEach((r)=>this.enable(this.find(r))),await this.render()}else{if(s!=null)t=s;if(typeof t==="string")t=this.findIndex(t);if(typeof t==="number"&&t>-1)this.index=Math.max(0,Math.min(t,this.choices.length)),this.enable(this.find(this.index))}if(this.isDisabled(this.focused))await this.down()}async toChoices(e,t){this.state.loadingChoices=!0;let s=[],o=0,r=async(a,i)=>{if(typeof a==="function")a=await a.call(this);if(a instanceof Promise)a=await a;for(let n=0;n<a.length;n++){let l=a[n]=await this.toChoice(a[n],o++,i);if(s.push(l),l.choices)await r(l.choices,l)}return s};return r(e,t).then((a)=>{return this.state.loadingChoices=!1,a})}async toChoice(e,t,s){if(typeof e==="function")e=await e.call(this,this);if(e instanceof Promise)e=await e;if(typeof e==="string")e={name:e};if(e.normalized)return e;e.normalized=!0;let o=e.value;if(e=Pn(e.role,this.options)(this,e),typeof e.disabled==="string"&&!e.hint)e.hint=e.disabled,e.disabled=!0;if(e.disabled===!0&&e.hint==null)e.hint="(disabled)";if(e.index!=null)return e;if(e.name=e.name||e.key||e.title||e.value||e.message,e.message=e.message||e.name||"",e.value=[e.value,e.name].find(this.isValue.bind(this)),e.input="",e.index=t,e.cursor=0,Ie.define(e,"parent",s),e.level=s?s.level+1:1,e.indent==null)e.indent=s?s.indent+" ":e.indent||"";if(e.path=s?s.path+"."+e.name:e.name,e.enabled=!!(this.multiple&&!this.isDisabled(e)&&(e.enabled||this.isSelected(e))),!this.isDisabled(e))this.longest=Math.max(this.longest,_n(e.message).length);let a={...e};if(e.reset=(i=a.input,n=a.value)=>{for(let l of Object.keys(a))e[l]=a[l];e.input=i,e.value=n},o==null&&typeof e.initial==="function")e.input=await e.initial.call(this,this.state,e,t);return e}async onChoice(e,t){if(this.emit("choice",e,t,this),typeof e.onChoice==="function")await e.onChoice.call(this,this.state,e,t)}async addChoice(e,t,s){let o=await this.toChoice(e,t,s);return this.choices.push(o),this.index=this.choices.length-1,this.limit=this.choices.length,o}async newItem(e,t,s){let o={name:"New choice name?",editable:!0,newChoice:!0,...e},r=await this.addChoice(o,t,s);return r.updateChoice=()=>{delete r.newChoice,r.name=r.message=r.input,r.input="",r.cursor=0},this.render()}indent(e){if(e.indent==null)return e.level>1?" ".repeat(e.level-1):"";return e.indent}dispatch(e,t){if(this.multiple&&this[t.name])return this[t.name]();this.alert()}focus(e,t){if(typeof t!=="boolean")t=e.enabled;if(t&&!e.enabled&&this.selected.length>=this.maxSelected)return this.alert();return this.index=e.index,e.enabled=t&&!this.isDisabled(e),e}space(){if(!this.multiple)return this.alert();if(!this.focused)return;return this.toggle(this.focused),this.render()}a(){if(this.maxSelected<this.choices.length)return this.alert();let e=this.selectable.every((t)=>t.enabled);return this.choices.forEach((t)=>t.enabled=!e),this.render()}i(){if(this.choices.length-this.selected.length>this.maxSelected)return this.alert();return this.choices.forEach((e)=>e.enabled=!e.enabled),this.render()}g(){if(!this.choices.some((t)=>!!t.parent))return this.a();let e=this.focused;return this.toggle(e.parent&&!e.choices?e.parent:e),this.render()}toggle(e,t){if(!e.enabled&&this.selected.length>=this.maxSelected)return this.alert();if(typeof t!=="boolean")t=!e.enabled;if(e.enabled=t,e.choices)e.choices.forEach((o)=>this.toggle(o,t));let s=e.parent;while(s){let o=s.choices.filter((r)=>this.isDisabled(r));s.enabled=o.every((r)=>r.enabled===!0),s=s.parent}return Ds(this,this.choices),this.emit("toggle",e,this),e}enable(e){if(this.selected.length>=this.maxSelected)return this.alert();return e.enabled=!this.isDisabled(e),e.choices&&e.choices.forEach(this.enable.bind(this)),e}disable(e){return e.enabled=!1,e.choices&&e.choices.forEach(this.disable.bind(this)),e}number(e){this.num+=e;let t=(s)=>{let o=Number(s);if(o>this.choices.length-1)return this.alert();let r=this.focused,a=this.choices.find((i)=>o===i.index);if(!a.enabled&&this.selected.length>=this.maxSelected)return this.alert();if(this.visible.indexOf(a)===-1){let i=xt(this.choices),n=i.indexOf(a);if(r.index>n){let l=i.slice(n,n+this.limit),d=i.filter((m)=>!l.includes(m));this.choices=l.concat(d)}else{let l=n-this.limit+1;this.choices=i.slice(l).concat(i.slice(0,l))}}return this.index=this.choices.indexOf(a),this.toggle(this.focused),this.render()};return clearTimeout(this.numberTimeout),new Promise((s)=>{let o=this.choices.length,r=this.num,a=(i=!1,n)=>{if(clearTimeout(this.numberTimeout),i)n=t(r);this.num="",s(n)};if(r==="0"||r.length===1&&Number(r+"0")>o)return a(!0);if(Number(r)>o)return a(!1,this.alert());this.numberTimeout=setTimeout(()=>a(!0),this.delay)})}home(){return this.choices=xt(this.choices),this.index=0,this.render()}end(){let e=this.choices.length-this.limit,t=xt(this.choices);return this.choices=t.slice(e).concat(t.slice(0,e)),this.index=this.limit-1,this.render()}first(){return this.index=0,this.render()}last(){return this.index=this.visible.length-1,this.render()}prev(){if(this.visible.length<=1)return this.alert();return this.up()}next(){if(this.visible.length<=1)return this.alert();return this.down()}right(){if(this.cursor>=this.input.length)return this.alert();return this.cursor++,this.render()}left(){if(this.cursor<=0)return this.alert();return this.cursor--,this.render()}up(){let e=this.choices.length,t=this.visible.length,s=this.index;if(this.options.scroll===!1&&s===0)return this.alert();if(e>t&&s===0)return this.scrollUp();if(this.index=(s-1%e+e)%e,this.isDisabled()&&!this.allChoicesAreDisabled())return this.up();return this.render()}down(){let e=this.choices.length,t=this.visible.length,s=this.index;if(this.options.scroll===!1&&s===t-1)return this.alert();if(e>t&&s===t-1)return this.scrollDown();if(this.index=(s+1)%e,this.isDisabled()&&!this.allChoicesAreDisabled())return this.down();return this.render()}scrollUp(e=0){if(this.choices=On(this.choices),this.index=e,this.isDisabled())return this.up();return this.render()}scrollDown(e=this.visible.length-1){if(this.choices=Bn(this.choices),this.index=e,this.isDisabled())return this.down();return this.render()}async shiftUp(){if(this.options.sort===!0){this.sorting=!0,this.swap(this.index-1),await this.up(),this.sorting=!1;return}return this.scrollUp(this.index)}async shiftDown(){if(this.options.sort===!0){this.sorting=!0,this.swap(this.index+1),await this.down(),this.sorting=!1;return}return this.scrollDown(this.index)}pageUp(){if(this.visible.length<=1)return this.alert();if(this.limit=Math.max(this.limit-1,0),this.index=Math.min(this.limit-1,this.index),this._limit=this.limit,this.isDisabled())return this.up();return this.render()}pageDown(){if(this.visible.length>=this.choices.length)return this.alert();if(this.index=Math.max(0,this.index),this.limit=Math.min(this.limit+1,this.choices.length),this._limit=this.limit,this.isDisabled())return this.down();return this.render()}swap(e){Ln(this.choices,this.index,e)}allChoicesAreDisabled(e=this.choices){return e.every((t)=>this.isDisabled(t))}isDisabled(e=this.focused){if(e&&["disabled","collapsed","hidden","completing","readonly"].some((s)=>e[s]===!0))return!0;return e&&e.role==="heading"}isEnabled(e=this.focused){if(Array.isArray(e))return e.every((t)=>this.isEnabled(t));if(e.choices){let t=e.choices.filter((s)=>!this.isDisabled(s));return e.enabled&&t.every((s)=>this.isEnabled(s))}return e.enabled&&!this.isDisabled(e)}isChoice(e,t){return e.name===t||e.index===Number(t)}isSelected(e){if(Array.isArray(this.initial))return this.initial.some((t)=>this.isChoice(e,t));return this.isChoice(e,this.initial)}map(e=[],t="value"){return[].concat(e||[]).reduce((s,o)=>{return s[o]=this.find(o,t),s},{})}filter(e,t){let o=typeof e==="function"?e:(i,n)=>[i.name,n].includes(e),a=(this.options.multiple?this.state._choices:this.choices).filter(o);if(t)return a.map((i)=>i[t]);return a}find(e,t){if(Rs(e))return t?e[t]:e;let o=typeof e==="function"?e:(a,i)=>[a.name,i].includes(e),r=this.choices.find(o);if(r)return t?r[t]:r}findIndex(e){return this.choices.indexOf(this.find(e))}async submit(){let e=this.focused;if(!e)return this.alert();if(e.newChoice){if(!e.input)return this.alert();return e.updateChoice(),this.render()}if(this.choices.some((a)=>a.newChoice))return this.alert();let{reorder:t,sort:s}=this.options,o=this.multiple===!0,r=this.selected;if(r===void 0)return this.alert();if(Array.isArray(r)&&t!==!1&&s!==!0)r=Ie.reorder(r);return this.value=o?r.map((a)=>a.name):r.name,super.submit()}set choices(e=[]){this.state._choices=this.state._choices||[],this.state.choices=e;for(let t of e)if(!this.state._choices.some((s)=>s.name===t.name))this.state._choices.push(t);if(!this._initial&&this.options.initial){this._initial=!0;let t=this.initial;if(typeof t==="string"||typeof t==="number"){let s=this.find(t);if(s)this.initial=s.index,this.focus(s,!0)}}}get choices(){return Ds(this,this.state.choices||[])}set visible(e){this.state.visible=e}get visible(){return(this.state.visible||this.choices).slice(0,this.limit)}set limit(e){this.state.limit=e}get limit(){let{state:e,options:t,choices:s}=this,o=e.limit||this._limit||t.limit||s.length;return Math.min(o,this.height)}set value(e){super.value=e}get value(){if(typeof super.value!=="string"&&super.value===this.initial)return this.input;return super.value}set index(e){this.state.index=e}get index(){return Math.max(0,this.state?this.state.index:0)}get enabled(){return this.filter(this.isEnabled.bind(this))}get focused(){let e=this.choices[this.index];if(e&&this.state.submitted&&this.multiple!==!0)e.enabled=!0;return e}get selectable(){return this.choices.filter((e)=>!this.isDisabled(e))}get selected(){return this.multiple?this.enabled:this.focused}}function Ds(e,t){if(t instanceof Promise)return t;if(typeof t==="function"){if(Ie.isAsyncFn(t))return t;t=t.call(e,e)}for(let s of t){if(Array.isArray(s.choices)){let o=s.choices.filter((r)=>!e.isDisabled(r));s.enabled=o.every((r)=>r.enabled===!0)}if(e.isDisabled(s)===!0)delete s.enabled}return t}Is.exports=_s});var re=x((dp,Os)=>{var Un=Ee(),Et=R();class Ps extends Un{constructor(e){super(e);this.emptyError=this.options.emptyError||"No items were selected"}async dispatch(e,t){if(this.multiple)return this[t.name]?await this[t.name](e,t):await super.dispatch(e,t);this.alert()}separator(){if(this.options.separator)return super.separator();let e=this.styles.muted(this.symbols.ellipsis);return this.state.submitted?super.separator():e}pointer(e,t){return!this.multiple||this.options.pointer?super.pointer(e,t):""}indicator(e,t){return this.multiple?super.indicator(e,t):""}choiceMessage(e,t){let s=this.resolve(e.message,this.state,e,t);if(e.role==="heading"&&!Et.hasColor(s))s=this.styles.strong(s);return this.resolve(s,this.state,e,t)}choiceSeparator(){return":"}async renderChoice(e,t){await this.onChoice(e,t);let s=this.index===t,o=await this.pointer(e,t),r=await this.indicator(e,t)+(e.pad||""),a=await this.resolve(e.hint,this.state,e,t);if(a&&!Et.hasColor(a))a=this.styles.muted(a);let i=this.indent(e),n=await this.choiceMessage(e,t),l=()=>[this.margin[3],i+o+r,n,this.margin[1],a].filter(Boolean).join(" ");if(e.role==="heading")return l();if(e.disabled){if(!Et.hasColor(n))n=this.styles.disabled(n);return l()}if(s)n=this.styles.em(n);return l()}async renderChoices(){if(this.state.loading==="choices")return this.styles.warning("Loading choices");if(this.state.submitted)return"";let e=this.visible.map(async(r,a)=>await this.renderChoice(r,a)),t=await Promise.all(e);if(!t.length)t.push(this.styles.danger("No matching choices"));let s=this.margin[0]+t.join(`
|
|
12
|
-
`),
|
|
13
|
-
`)}format(){if(!this.state.submitted||this.state.cancelled)return"";if(Array.isArray(this.selected))return this.selected.map((e)=>this.styles.primary(e.name)).join(", ");return this.styles.primary(this.selected.name)}async render(){let{submitted:e,size:t}=this.state,s="",
|
|
14
|
-
`)),this.write(this.margin[2]),this.restore()}}
|
|
15
|
-
`)),this.restore()}set value(e){super.value=e}get value(){return this.cast(super.value)}}
|
|
16
|
-
`,t)}return super.keypress(e,t)}moveCursor(e){this.cursor+=e}reset(){return this.input=this.value="",this.cursor=0,this.render()}dispatch(e,t){if(!e||t.ctrl||t.code)return this.alert();this.append(e)}append(e){let{cursor:t,input:s}=this.state;this.input=`${s}`.slice(0,t)+e+`${s}`.slice(t),this.moveCursor(String(e).length),this.render()}insert(e){this.append(e)}delete(){let{cursor:e,input:t}=this.state;if(e<=0)return this.alert();this.input=`${t}`.slice(0,e-1)+`${t}`.slice(e),this.moveCursor(-1),this.render()}deleteForward(){let{cursor:e,input:t}=this.state;if(t[e]===void 0)return this.alert();this.input=`${t}`.slice(0,e)+`${t}`.slice(e+1),this.render()}cutForward(){let e=this.cursor;if(this.input.length<=e)return this.alert();this.state.clipboard.push(this.input.slice(e)),this.input=this.input.slice(0,e),this.render()}cutLeft(){let e=this.cursor;if(e===0)return this.alert();let t=this.input.slice(0,e),s=this.input.slice(e),
|
|
17
|
-
`)),this.restore()}}
|
|
18
|
-
`;let t=e.startNumber||1;if(typeof this.scale==="number")this.scaleKey=!1,this.scale=Array(this.scale).fill(0).map((s,
|
|
19
|
-
`)}renderScaleHeading(e){let t=this.scale.map((n)=>n.name);if(typeof this.options.renderScaleHeading==="function")t=this.options.renderScaleHeading.call(this,e);let s=this.scaleLength-t.join("").length,
|
|
20
|
-
`).map((
|
|
21
|
-
`)].filter(Boolean)}async renderChoices(){if(this.state.submitted)return"";this.tableize();let e=this.visible.map(async(o
|
|
22
|
-
`)}async render(){let{submitted:e,size:t}=this.state,s=await this.prefix(),
|
|
23
|
-
`)),!this.state.submitted)this.write(this.margin[2]);this.restore()}submit(){this.value={};for(let e of this.choices)this.value[e.name]=e.scaleIndex;return this.base.submit.call(this)}}
|
|
24
|
-
`){
|
|
25
|
-
`).map((E)=>" "+E),
|
|
26
|
-
`),
|
|
27
|
-
`].find((
|
|
28
|
-
`;return this.state.error=
|
|
29
|
-
`).map((
|
|
30
|
-
`);return this.value={values:
|
|
31
|
-
`)}}async toChoices(...e){if(this.createdScales)return!1;this.createdScales=!0;let t=await super.toChoices(...e);for(let s of t)s.scale=
|
|
32
|
-
`);if(s)
|
|
33
|
-
`)}format(){if(this.state.submitted)return this.choices.map((t)=>this.styles.info(t.scaleIdx)).join(", ");return""}async render(){let{submitted:e,size:t}=this.state,s=await this.prefix(),
|
|
34
|
-
`)),this.restore()}submit(){this.value={};for(let e of this.choices)this.value[e.name]=e.scaleIdx;return this.base.submit.call(this)}}function
|
|
35
|
-
`)),this.write(this.margin[2]),this.restore()}}Go.exports=ko});var Fo=x((Ip,Ko)=>{var El=re();class qo extends El{constructor(e){super(e);if(typeof this.options.correctChoice!=="number"||this.options.correctChoice<0)throw Error("Please specify the index of the correct answer from the list of choices")}async toChoices(e,t){let s=await super.toChoices(e,t);if(s.length<2)throw Error("Please give at least two choices to the user");if(this.options.correctChoice>s.length)throw Error("Please specify the index of the correct answer from the list of choices");return s}check(e){return e.index===this.options.correctChoice}async result(e){return{selectedAnswer:e,correctAnswer:this.options.choices[this.options.correctChoice].value,correct:await this.check(this.state)}}}Ko.exports=qo});var Vo=x((Mt)=>{var Ho=R(),T=(e,t)=>{Ho.defineExport(Mt,e,t),Ho.defineExport(Mt,e.toLowerCase(),t)};T("AutoComplete",()=>Us());T("BasicAuth",()=>Hs());T("Confirm",()=>Zs());T("Editable",()=>Js());T("Form",()=>Pe());T("Input",()=>Tt());T("Invisible",()=>mo());T("List",()=>uo());T("MultiSelect",()=>go());T("Numeral",()=>St());T("Password",()=>Eo());T("Scale",()=>To());T("Select",()=>re());T("Snippet",()=>Io());T("Sort",()=>Bo());T("Survey",()=>$o());T("Text",()=>Tt());T("Toggle",()=>Wo());T("Quiz",()=>Fo())});var jo=x((Op,Yo)=>{Yo.exports={ArrayPrompt:Ee(),AuthPrompt:Nt(),BooleanPrompt:Oe(),NumberPrompt:St(),StringPrompt:de()}});var ie=x((Bp,Zo)=>{var zo=be("assert"),Dt=be("events"),ae=R();class U extends Dt{constructor(e,t){super();this.options=ae.merge({},e),this.answers={...t}}register(e,t){if(ae.isObject(e)){for(let o of Object.keys(e))this.register(o,e[o]);return this}zo.equal(typeof t,"function","expected a function");let s=e.toLowerCase();if(t.prototype instanceof this.Prompt)this.prompts[s]=t;else this.prompts[s]=t(this.Prompt,this);return this}async prompt(e=[]){for(let t of[].concat(e))try{if(typeof t==="function")t=await t.call(this);await this.ask(ae.merge({},this.options,t))}catch(s){return Promise.reject(s)}return this.answers}async ask(e){if(typeof e==="function")e=await e.call(this);let t=ae.merge({},this.options,e),{type:s,name:o}=e,{set:r,get:a}=ae;if(typeof s==="function")s=await s.call(this,e,this.answers);if(!s)return this.answers[o];if(s==="number")s="numeral";zo(this.prompts[s],`Prompt "${s}" is not registered`);let i=new this.prompts[s](t),n=a(this.answers,o);if(i.state.answers=this.answers,i.enquirer=this,o)i.on("submit",(d)=>{this.emit("answer",o,d,i),r(this.answers,o,d)});let l=i.emit.bind(i);if(i.emit=(...d)=>{return this.emit.call(this,...d),l(...d)},this.emit("prompt",i,this),t.autofill&&n!=null){if(i.value=i.input=n,t.autofill==="show")await i.submit()}else n=i.value=await i.run();return n}use(e){return e.call(this,this),this}set Prompt(e){this._Prompt=e}get Prompt(){return this._Prompt||this.constructor.Prompt}get prompts(){return this.constructor.prompts}static set Prompt(e){this._Prompt=e}static get Prompt(){return this._Prompt||ue()}static get prompts(){return Vo()}static get types(){return jo()}static get prompt(){let e=(t,...s)=>{let o=new this(...s),r=o.emit.bind(o);return o.emit=(...a)=>{return e.emit(...a),r(...a)},o.prompt(t)};return ae.mixinEmitter(e,new Dt),e}}ae.mixinEmitter(U,new Dt);var Rt=U.prompts;for(let e of Object.keys(Rt)){let t=e.toLowerCase(),s=(o)=>new Rt[e](o).run();if(U.prompt[t]=s,U[t]=s,!U[e])Reflect.defineProperty(U,e,{get:()=>Rt[e]})}var Ae=(e)=>{ae.defineExport(U,e,()=>U.types[e])};Ae("ArrayPrompt");Ae("AuthPrompt");Ae("BooleanPrompt");Ae("NumberPrompt");Ae("StringPrompt");Zo.exports=U});var Ra=x((Lt,Ut)=>{(function(e,t){if(typeof Lt==="object"&&typeof Ut==="object")Ut.exports=t();else if(typeof define==="function"&&define.amd)define(function(){return t()});else e.pluralize=t()})(Lt,function(){var e=[],t=[],s={},o={},r={};function a(p){if(typeof p==="string")return new RegExp("^"+p+"$","i");return p}function i(p,u){if(p===u)return u;if(p===p.toLowerCase())return u.toLowerCase();if(p===p.toUpperCase())return u.toUpperCase();if(p[0]===p[0].toUpperCase())return u.charAt(0).toUpperCase()+u.substr(1).toLowerCase();return u.toLowerCase()}function n(p,u){return p.replace(/\$(\d{1,2})/g,function(f,y){return u[y]||""})}function l(p,u){return p.replace(u[0],function(f,y){var g=n(u[1],arguments);if(f==="")return i(p[y-1],g);return i(f,g)})}function d(p,u,f){if(!p.length||s.hasOwnProperty(p))return u;var y=f.length;while(y--){var g=f[y];if(g[0].test(u))return l(u,g)}return u}function m(p,u,f){return function(y){var g=y.toLowerCase();if(u.hasOwnProperty(g))return i(y,g);if(p.hasOwnProperty(g))return i(y,p[g]);return d(g,y,f)}}function h(p,u,f,y){return function(g){var E=g.toLowerCase();if(u.hasOwnProperty(E))return!0;if(p.hasOwnProperty(E))return!1;return d(E,E,f)===E}}function c(p,u,f){var y=u===1?c.singular(p):c.plural(p);return(f?u+" ":"")+y}return c.plural=m(r,o,e),c.isPlural=h(r,o,e),c.singular=m(o,r,t),c.isSingular=h(o,r,t),c.addPluralRule=function(p,u){e.push([a(p),u])},c.addSingularRule=function(p,u){t.push([a(p),u])},c.addUncountableRule=function(p){if(typeof p==="string"){s[p.toLowerCase()]=!0;return}c.addPluralRule(p,"$0"),c.addSingularRule(p,"$0")},c.addIrregularRule=function(p,u){u=u.toLowerCase(),p=p.toLowerCase(),r[p]=u,o[u]=p},[["I","we"],["me","us"],["he","they"],["she","they"],["them","them"],["myself","ourselves"],["yourself","yourselves"],["itself","themselves"],["herself","themselves"],["himself","themselves"],["themself","themselves"],["is","are"],["was","were"],["has","have"],["this","these"],["that","those"],["echo","echoes"],["dingo","dingoes"],["volcano","volcanoes"],["tornado","tornadoes"],["torpedo","torpedoes"],["genus","genera"],["viscus","viscera"],["stigma","stigmata"],["stoma","stomata"],["dogma","dogmata"],["lemma","lemmata"],["schema","schemata"],["anathema","anathemata"],["ox","oxen"],["axe","axes"],["die","dice"],["yes","yeses"],["foot","feet"],["eave","eaves"],["goose","geese"],["tooth","teeth"],["quiz","quizzes"],["human","humans"],["proof","proofs"],["carve","carves"],["valve","valves"],["looey","looies"],["thief","thieves"],["groove","grooves"],["pickaxe","pickaxes"],["passerby","passersby"]].forEach(function(p){return c.addIrregularRule(p[0],p[1])}),[[/s?$/i,"s"],[/[^\u0000-\u007F]$/i,"$0"],[/([^aeiou]ese)$/i,"$1"],[/(ax|test)is$/i,"$1es"],[/(alias|[^aou]us|t[lm]as|gas|ris)$/i,"$1es"],[/(e[mn]u)s?$/i,"$1s"],[/([^l]ias|[aeiou]las|[ejzr]as|[iu]am)$/i,"$1"],[/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i,"$1i"],[/(alumn|alg|vertebr)(?:a|ae)$/i,"$1ae"],[/(seraph|cherub)(?:im)?$/i,"$1im"],[/(her|at|gr)o$/i,"$1oes"],[/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i,"$1a"],[/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i,"$1a"],[/sis$/i,"ses"],[/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i,"$1$2ves"],[/([^aeiouy]|qu)y$/i,"$1ies"],[/([^ch][ieo][ln])ey$/i,"$1ies"],[/(x|ch|ss|sh|zz)$/i,"$1es"],[/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i,"$1ices"],[/\b((?:tit)?m|l)(?:ice|ouse)$/i,"$1ice"],[/(pe)(?:rson|ople)$/i,"$1ople"],[/(child)(?:ren)?$/i,"$1ren"],[/eaux$/i,"$0"],[/m[ae]n$/i,"men"],["thou","you"]].forEach(function(p){return c.addPluralRule(p[0],p[1])}),[[/s$/i,""],[/(ss)$/i,"$1"],[/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i,"$1fe"],[/(ar|(?:wo|[ae])l|[eo][ao])ves$/i,"$1f"],[/ies$/i,"y"],[/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i,"$1ie"],[/\b(mon|smil)ies$/i,"$1ey"],[/\b((?:tit)?m|l)ice$/i,"$1ouse"],[/(seraph|cherub)im$/i,"$1"],[/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i,"$1"],[/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i,"$1sis"],[/(movie|twelve|abuse|e[mn]u)s$/i,"$1"],[/(test)(?:is|es)$/i,"$1is"],[/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i,"$1us"],[/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i,"$1um"],[/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i,"$1on"],[/(alumn|alg|vertebr)ae$/i,"$1a"],[/(cod|mur|sil|vert|ind)ices$/i,"$1ex"],[/(matr|append)ices$/i,"$1ix"],[/(pe)(rson|ople)$/i,"$1rson"],[/(child)ren$/i,"$1"],[/(eau)x?$/i,"$1"],[/men$/i,"man"]].forEach(function(p){return c.addSingularRule(p[0],p[1])}),["adulthood","advice","agenda","aid","aircraft","alcohol","ammo","analytics","anime","athletics","audio","bison","blood","bream","buffalo","butter","carp","cash","chassis","chess","clothing","cod","commerce","cooperation","corps","debris","diabetes","digestion","elk","energy","equipment","excretion","expertise","firmware","flounder","fun","gallows","garbage","graffiti","hardware","headquarters","health","herpes","highjinks","homework","housework","information","jeans","justice","kudos","labour","literature","machinery","mackerel","mail","media","mews","moose","music","mud","manga","news","only","personnel","pike","plankton","pliers","police","pollution","premises","rain","research","rice","salmon","scissors","series","sewage","shambles","shrimp","software","species","staff","swine","tennis","traffic","transportation","trout","tuna","wealth","welfare","whiting","wildebeest","wildlife","you",/pok[e\u00E9]mon$/i,/[^aeiou]ese$/i,/deer$/i,/fish$/i,/measles$/i,/o[iu]s$/i,/pox$/i,/sheep$/i].forEach(c.addUncountableRule),c})});import{parseArgs as Tc}from"util";import{Exception as ii}from"@ooneex/exception";import{TerminalLogger as Sc}from"@ooneex/logger";import{container as bi}from"@ooneex/container";var Se=[];var Gt=(e)=>{let t=null;return Se.find((s)=>{return t=bi.get(s),t.getName()===e}),t};import{homedir as vi}from"os";import{join as it}from"path";import{TerminalLogger as Ni}from"@ooneex/logger";import{container as wi,EContainerScope as xi}from"@ooneex/container";var w={command:(e=xi.Singleton)=>{return(t)=>{wi.add(t,e),Se.push(t)}}};var Wt=`#compdef oo ooneex
|
|
9
|
+
`+this.styles.danger(t),this.state.submitted=!1,await this.render(),await this.alert(),this.state.validating=!1,this.state.error=void 0;return}this.state.validating=!1,await this.render(),await this.close(),this.value=await this.result(this.value),this.emit("submit",this.value)}async cancel(e){if(this.state.cancelled=this.state.submitted=!0,await this.render(),await this.close(),typeof this.options.onCancel==="function")await this.options.onCancel.call(this,this.name,this.value,this);this.emit("cancel",await this.error(e))}async close(){this.state.closed=!0;try{let e=this.sections(),t=Math.ceil(e.prompt.length/this.width);if(e.rest)this.write(de.cursor.down(e.rest.length));this.write(`
|
|
10
|
+
`.repeat(t))}catch(e){}this.emit("close")}start(){if(!this.stop&&this.options.show!==!1)this.stop=xt.listen(this,this.keypress.bind(this)),this.once("close",this.stop),this.emit("start",this)}async skip(){if(this.skipped=this.options.skip===!0,typeof this.options.skip==="function")this.skipped=await this.options.skip.call(this,this.name,this.value);return this.skipped}async initialize(){let{format:e,options:t,result:s}=this;if(this.format=()=>e.call(this,this.value),this.result=()=>s.call(this,this.value),typeof t.initial==="function")this.initial=await t.initial.call(this,this);if(typeof t.onRun==="function")await t.onRun.call(this,this);if(typeof t.onSubmit==="function"){let r=t.onSubmit.bind(this),o=this.submit.bind(this);delete this.options.onSubmit,this.submit=async()=>{return await r(this.name,this.value,this),o()}}await this.start(),await this.render()}render(){throw Error("expected prompt to have a custom render method")}run(){return new Promise(async(e,t)=>{if(this.once("submit",e),this.once("cancel",t),await this.skip())return this.render=()=>{},this.submit();await this.initialize(),this.emit("run")})}async element(e,t,s){let{options:r,state:o,symbols:i,timers:a}=this,n=a&&a[e];o.timer=n;let d=r[e]||o[e]||i[e],l=t&&t[e]!=null?t[e]:await d;if(l==="")return l;let c=await this.resolve(l,o,t,s);if(!c&&t&&t[e])return this.resolve(d,o,t,s);return c}async prefix(){let e=await this.element("prefix")||this.symbols,t=this.timers&&this.timers.prefix,s=this.state;if(s.timer=t,I.isObject(e))e=e[s.status]||e.pending;if(!I.hasColor(e))return(this.styles[s.status]||this.styles.pending)(e);return e}async message(){let e=await this.element("message");if(!I.hasColor(e))return this.styles.strong(e);return e}async separator(){let e=await this.element("separator")||this.symbols,t=this.timers&&this.timers.separator,s=this.state;s.timer=t;let r=e[s.status]||e.pending||s.separator,o=await this.resolve(r,s);if(I.isObject(o))o=o[s.status]||o.pending;if(!I.hasColor(o))return this.styles.muted(o);return o}async pointer(e,t){let s=await this.element("pointer",e,t);if(typeof s==="string"&&I.hasColor(s))return s;if(s){let r=this.styles,o=this.index===t,i=o?r.primary:(d)=>d,a=await this.resolve(s[o?"on":"off"]||s,this.state),n=!I.hasColor(a)?i(a):a;return o?n:" ".repeat(a.length)}}async indicator(e,t){let s=await this.element("indicator",e,t);if(typeof s==="string"&&I.hasColor(s))return s;if(s){let r=this.styles,o=e.enabled===!0,i=o?r.success:r.dark,a=s[o?"on":"off"]||s;return!I.hasColor(a)?i(a):a}return""}body(){return null}footer(){if(this.state.status==="pending")return this.element("footer")}header(){if(this.state.status==="pending")return this.element("header")}async hint(){if(this.state.status==="pending"&&!this.isValue(this.state.input)){let e=await this.element("hint");if(!I.hasColor(e))return this.styles.muted(e);return e}}error(e){return!this.state.submitted?e||this.state.error:""}format(e){return e}result(e){return e}validate(e){if(this.options.required===!0)return this.isValue(e);return!0}isValue(e){return e!=null&&e!==""}resolve(e,...t){return I.resolve(this,e,...t)}get base(){return wt.prototype}get style(){return this.styles[this.state.status]}get height(){return this.options.rows||I.height(this.stdout,25)}get width(){return this.options.columns||I.width(this.stdout,80)}get size(){return{width:this.width,height:this.height}}set cursor(e){this.state.cursor=e}get cursor(){return this.state.cursor}set input(e){this.state.input=e}get input(){return this.state.input}set value(e){this.state.value=e}get value(){let{input:e,value:t}=this.state,s=[t,e].find(this.isValue.bind(this));return this.isValue(s)?s:this.initial}static get prompt(){return(e)=>new this(e).run()}}function Mn(e){let t=(o)=>{return e[o]===void 0||typeof e[o]==="function"},s=["actions","choices","initial","margin","roles","styles","symbols","theme","timers","value"],r=["body","footer","error","header","hint","indicator","message","prefix","separator","skip"];for(let o of Object.keys(e.options)){if(s.includes(o))continue;if(/^on[A-Z]/.test(o))continue;let i=e.options[o];if(typeof i==="function"&&t(o)){if(!r.includes(o))e[o]=i.bind(e)}else if(typeof e[o]!=="function")e[o]=i}}function Cn(e){if(typeof e==="number")e=[e,e,e,e];let t=[].concat(e||[]),s=(o)=>o%2===0?`
|
|
11
|
+
`:" ",r=[];for(let o=0;o<4;o++){let i=s(o);if(t[o])r.push(i.repeat(t[o]));else r.push("")}return r}_s.exports=wt});var Ds=w((dp,Os)=>{var _n=C(),Is={default(e,t){return t},checkbox(e,t){throw Error("checkbox role is not implemented yet")},editable(e,t){throw Error("editable role is not implemented yet")},expandable(e,t){throw Error("expandable role is not implemented yet")},heading(e,t){return t.disabled="",t.indicator=[t.indicator," "].find((s)=>s!=null),t.message=t.message||"",t},input(e,t){throw Error("input role is not implemented yet")},option(e,t){return Is.default(e,t)},radio(e,t){throw Error("radio role is not implemented yet")},separator(e,t){return t.disabled="",t.indicator=[t.indicator," "].find((s)=>s!=null),t.message=t.message||e.symbols.line.repeat(5),t},spacer(e,t){return t}};Os.exports=(e,t={})=>{let s=_n.merge({},Is,t.roles);return s[e]||s.default}});var Ee=w((lp,Us)=>{var In=se(),On=ue(),Dn=Ds(),Oe=C(),{reorder:Et,scrollUp:Bn,scrollDown:Pn,isObject:Bs,swap:Ln}=Oe;class Ls extends On{constructor(e){super(e);this.cursorHide(),this.maxSelected=e.maxSelected||1/0,this.multiple=e.multiple||!1,this.initial=e.initial||0,this.delay=e.delay||0,this.longest=0,this.num=""}async initialize(){if(typeof this.options.initial==="function")this.initial=await this.options.initial.call(this);await this.reset(!0),await super.initialize()}async reset(){let{choices:e,initial:t,autofocus:s,suggest:r}=this.options;if(this.state._choices=[],this.state.choices=[],this.choices=await Promise.all(await this.toChoices(e)),this.choices.forEach((o)=>o.enabled=!1),typeof r!=="function"&&this.selectable.length===0)throw Error("At least one choice must be selectable");if(Bs(t))t=Object.keys(t);if(Array.isArray(t)){if(s!=null)this.index=this.findIndex(s);t.forEach((o)=>this.enable(this.find(o))),await this.render()}else{if(s!=null)t=s;if(typeof t==="string")t=this.findIndex(t);if(typeof t==="number"&&t>-1)this.index=Math.max(0,Math.min(t,this.choices.length)),this.enable(this.find(this.index))}if(this.isDisabled(this.focused))await this.down()}async toChoices(e,t){this.state.loadingChoices=!0;let s=[],r=0,o=async(i,a)=>{if(typeof i==="function")i=await i.call(this);if(i instanceof Promise)i=await i;for(let n=0;n<i.length;n++){let d=i[n]=await this.toChoice(i[n],r++,a);if(s.push(d),d.choices)await o(d.choices,d)}return s};return o(e,t).then((i)=>{return this.state.loadingChoices=!1,i})}async toChoice(e,t,s){if(typeof e==="function")e=await e.call(this,this);if(e instanceof Promise)e=await e;if(typeof e==="string")e={name:e};if(e.normalized)return e;e.normalized=!0;let r=e.value;if(e=Dn(e.role,this.options)(this,e),typeof e.disabled==="string"&&!e.hint)e.hint=e.disabled,e.disabled=!0;if(e.disabled===!0&&e.hint==null)e.hint="(disabled)";if(e.index!=null)return e;if(e.name=e.name||e.key||e.title||e.value||e.message,e.message=e.message||e.name||"",e.value=[e.value,e.name].find(this.isValue.bind(this)),e.input="",e.index=t,e.cursor=0,Oe.define(e,"parent",s),e.level=s?s.level+1:1,e.indent==null)e.indent=s?s.indent+" ":e.indent||"";if(e.path=s?s.path+"."+e.name:e.name,e.enabled=!!(this.multiple&&!this.isDisabled(e)&&(e.enabled||this.isSelected(e))),!this.isDisabled(e))this.longest=Math.max(this.longest,In(e.message).length);let i={...e};if(e.reset=(a=i.input,n=i.value)=>{for(let d of Object.keys(i))e[d]=i[d];e.input=a,e.value=n},r==null&&typeof e.initial==="function")e.input=await e.initial.call(this,this.state,e,t);return e}async onChoice(e,t){if(this.emit("choice",e,t,this),typeof e.onChoice==="function")await e.onChoice.call(this,this.state,e,t)}async addChoice(e,t,s){let r=await this.toChoice(e,t,s);return this.choices.push(r),this.index=this.choices.length-1,this.limit=this.choices.length,r}async newItem(e,t,s){let r={name:"New choice name?",editable:!0,newChoice:!0,...e},o=await this.addChoice(r,t,s);return o.updateChoice=()=>{delete o.newChoice,o.name=o.message=o.input,o.input="",o.cursor=0},this.render()}indent(e){if(e.indent==null)return e.level>1?" ".repeat(e.level-1):"";return e.indent}dispatch(e,t){if(this.multiple&&this[t.name])return this[t.name]();this.alert()}focus(e,t){if(typeof t!=="boolean")t=e.enabled;if(t&&!e.enabled&&this.selected.length>=this.maxSelected)return this.alert();return this.index=e.index,e.enabled=t&&!this.isDisabled(e),e}space(){if(!this.multiple)return this.alert();if(!this.focused)return;return this.toggle(this.focused),this.render()}a(){if(this.maxSelected<this.choices.length)return this.alert();let e=this.selectable.every((t)=>t.enabled);return this.choices.forEach((t)=>t.enabled=!e),this.render()}i(){if(this.choices.length-this.selected.length>this.maxSelected)return this.alert();return this.choices.forEach((e)=>e.enabled=!e.enabled),this.render()}g(){if(!this.choices.some((t)=>!!t.parent))return this.a();let e=this.focused;return this.toggle(e.parent&&!e.choices?e.parent:e),this.render()}toggle(e,t){if(!e.enabled&&this.selected.length>=this.maxSelected)return this.alert();if(typeof t!=="boolean")t=!e.enabled;if(e.enabled=t,e.choices)e.choices.forEach((r)=>this.toggle(r,t));let s=e.parent;while(s){let r=s.choices.filter((o)=>this.isDisabled(o));s.enabled=r.every((o)=>o.enabled===!0),s=s.parent}return Ps(this,this.choices),this.emit("toggle",e,this),e}enable(e){if(this.selected.length>=this.maxSelected)return this.alert();return e.enabled=!this.isDisabled(e),e.choices&&e.choices.forEach(this.enable.bind(this)),e}disable(e){return e.enabled=!1,e.choices&&e.choices.forEach(this.disable.bind(this)),e}number(e){this.num+=e;let t=(s)=>{let r=Number(s);if(r>this.choices.length-1)return this.alert();let o=this.focused,i=this.choices.find((a)=>r===a.index);if(!i.enabled&&this.selected.length>=this.maxSelected)return this.alert();if(this.visible.indexOf(i)===-1){let a=Et(this.choices),n=a.indexOf(i);if(o.index>n){let d=a.slice(n,n+this.limit),l=a.filter((c)=>!d.includes(c));this.choices=d.concat(l)}else{let d=n-this.limit+1;this.choices=a.slice(d).concat(a.slice(0,d))}}return this.index=this.choices.indexOf(i),this.toggle(this.focused),this.render()};return clearTimeout(this.numberTimeout),new Promise((s)=>{let r=this.choices.length,o=this.num,i=(a=!1,n)=>{if(clearTimeout(this.numberTimeout),a)n=t(o);this.num="",s(n)};if(o==="0"||o.length===1&&Number(o+"0")>r)return i(!0);if(Number(o)>r)return i(!1,this.alert());this.numberTimeout=setTimeout(()=>i(!0),this.delay)})}home(){return this.choices=Et(this.choices),this.index=0,this.render()}end(){let e=this.choices.length-this.limit,t=Et(this.choices);return this.choices=t.slice(e).concat(t.slice(0,e)),this.index=this.limit-1,this.render()}first(){return this.index=0,this.render()}last(){return this.index=this.visible.length-1,this.render()}prev(){if(this.visible.length<=1)return this.alert();return this.up()}next(){if(this.visible.length<=1)return this.alert();return this.down()}right(){if(this.cursor>=this.input.length)return this.alert();return this.cursor++,this.render()}left(){if(this.cursor<=0)return this.alert();return this.cursor--,this.render()}up(){let e=this.choices.length,t=this.visible.length,s=this.index;if(this.options.scroll===!1&&s===0)return this.alert();if(e>t&&s===0)return this.scrollUp();if(this.index=(s-1%e+e)%e,this.isDisabled()&&!this.allChoicesAreDisabled())return this.up();return this.render()}down(){let e=this.choices.length,t=this.visible.length,s=this.index;if(this.options.scroll===!1&&s===t-1)return this.alert();if(e>t&&s===t-1)return this.scrollDown();if(this.index=(s+1)%e,this.isDisabled()&&!this.allChoicesAreDisabled())return this.down();return this.render()}scrollUp(e=0){if(this.choices=Bn(this.choices),this.index=e,this.isDisabled())return this.up();return this.render()}scrollDown(e=this.visible.length-1){if(this.choices=Pn(this.choices),this.index=e,this.isDisabled())return this.down();return this.render()}async shiftUp(){if(this.options.sort===!0){this.sorting=!0,this.swap(this.index-1),await this.up(),this.sorting=!1;return}return this.scrollUp(this.index)}async shiftDown(){if(this.options.sort===!0){this.sorting=!0,this.swap(this.index+1),await this.down(),this.sorting=!1;return}return this.scrollDown(this.index)}pageUp(){if(this.visible.length<=1)return this.alert();if(this.limit=Math.max(this.limit-1,0),this.index=Math.min(this.limit-1,this.index),this._limit=this.limit,this.isDisabled())return this.up();return this.render()}pageDown(){if(this.visible.length>=this.choices.length)return this.alert();if(this.index=Math.max(0,this.index),this.limit=Math.min(this.limit+1,this.choices.length),this._limit=this.limit,this.isDisabled())return this.down();return this.render()}swap(e){Ln(this.choices,this.index,e)}allChoicesAreDisabled(e=this.choices){return e.every((t)=>this.isDisabled(t))}isDisabled(e=this.focused){if(e&&["disabled","collapsed","hidden","completing","readonly"].some((s)=>e[s]===!0))return!0;return e&&e.role==="heading"}isEnabled(e=this.focused){if(Array.isArray(e))return e.every((t)=>this.isEnabled(t));if(e.choices){let t=e.choices.filter((s)=>!this.isDisabled(s));return e.enabled&&t.every((s)=>this.isEnabled(s))}return e.enabled&&!this.isDisabled(e)}isChoice(e,t){return e.name===t||e.index===Number(t)}isSelected(e){if(Array.isArray(this.initial))return this.initial.some((t)=>this.isChoice(e,t));return this.isChoice(e,this.initial)}map(e=[],t="value"){return[].concat(e||[]).reduce((s,r)=>{return s[r]=this.find(r,t),s},{})}filter(e,t){let r=typeof e==="function"?e:(a,n)=>[a.name,n].includes(e),i=(this.options.multiple?this.state._choices:this.choices).filter(r);if(t)return i.map((a)=>a[t]);return i}find(e,t){if(Bs(e))return t?e[t]:e;let r=typeof e==="function"?e:(i,a)=>[i.name,a].includes(e),o=this.choices.find(r);if(o)return t?o[t]:o}findIndex(e){return this.choices.indexOf(this.find(e))}async submit(){let e=this.focused;if(!e)return this.alert();if(e.newChoice){if(!e.input)return this.alert();return e.updateChoice(),this.render()}if(this.choices.some((i)=>i.newChoice))return this.alert();let{reorder:t,sort:s}=this.options,r=this.multiple===!0,o=this.selected;if(o===void 0)return this.alert();if(Array.isArray(o)&&t!==!1&&s!==!0)o=Oe.reorder(o);return this.value=r?o.map((i)=>i.name):o.name,super.submit()}set choices(e=[]){this.state._choices=this.state._choices||[],this.state.choices=e;for(let t of e)if(!this.state._choices.some((s)=>s.name===t.name))this.state._choices.push(t);if(!this._initial&&this.options.initial){this._initial=!0;let t=this.initial;if(typeof t==="string"||typeof t==="number"){let s=this.find(t);if(s)this.initial=s.index,this.focus(s,!0)}}}get choices(){return Ps(this,this.state.choices||[])}set visible(e){this.state.visible=e}get visible(){return(this.state.visible||this.choices).slice(0,this.limit)}set limit(e){this.state.limit=e}get limit(){let{state:e,options:t,choices:s}=this,r=e.limit||this._limit||t.limit||s.length;return Math.min(r,this.height)}set value(e){super.value=e}get value(){if(typeof super.value!=="string"&&super.value===this.initial)return this.input;return super.value}set index(e){this.state.index=e}get index(){return Math.max(0,this.state?this.state.index:0)}get enabled(){return this.filter(this.isEnabled.bind(this))}get focused(){let e=this.choices[this.index];if(e&&this.state.submitted&&this.multiple!==!0)e.enabled=!0;return e}get selectable(){return this.choices.filter((e)=>!this.isDisabled(e))}get selected(){return this.multiple?this.enabled:this.focused}}function Ps(e,t){if(t instanceof Promise)return t;if(typeof t==="function"){if(Oe.isAsyncFn(t))return t;t=t.call(e,e)}for(let s of t){if(Array.isArray(s.choices)){let r=s.choices.filter((o)=>!e.isDisabled(o));s.enabled=r.every((o)=>o.enabled===!0)}if(e.isDisabled(s)===!0)delete s.enabled}return t}Us.exports=Ls});var oe=w((cp,ks)=>{var Un=Ee(),At=C();class Gs extends Un{constructor(e){super(e);this.emptyError=this.options.emptyError||"No items were selected"}async dispatch(e,t){if(this.multiple)return this[t.name]?await this[t.name](e,t):await super.dispatch(e,t);this.alert()}separator(){if(this.options.separator)return super.separator();let e=this.styles.muted(this.symbols.ellipsis);return this.state.submitted?super.separator():e}pointer(e,t){return!this.multiple||this.options.pointer?super.pointer(e,t):""}indicator(e,t){return this.multiple?super.indicator(e,t):""}choiceMessage(e,t){let s=this.resolve(e.message,this.state,e,t);if(e.role==="heading"&&!At.hasColor(s))s=this.styles.strong(s);return this.resolve(s,this.state,e,t)}choiceSeparator(){return":"}async renderChoice(e,t){await this.onChoice(e,t);let s=this.index===t,r=await this.pointer(e,t),o=await this.indicator(e,t)+(e.pad||""),i=await this.resolve(e.hint,this.state,e,t);if(i&&!At.hasColor(i))i=this.styles.muted(i);let a=this.indent(e),n=await this.choiceMessage(e,t),d=()=>[this.margin[3],a+r+o,n,this.margin[1],i].filter(Boolean).join(" ");if(e.role==="heading")return d();if(e.disabled){if(!At.hasColor(n))n=this.styles.disabled(n);return d()}if(s)n=this.styles.em(n);return d()}async renderChoices(){if(this.state.loading==="choices")return this.styles.warning("Loading choices");if(this.state.submitted)return"";let e=this.visible.map(async(o,i)=>await this.renderChoice(o,i)),t=await Promise.all(e);if(!t.length)t.push(this.styles.danger("No matching choices"));let s=this.margin[0]+t.join(`
|
|
12
|
+
`),r;if(this.options.choicesHeader)r=await this.resolve(this.options.choicesHeader,this.state);return[r,s].filter(Boolean).join(`
|
|
13
|
+
`)}format(){if(!this.state.submitted||this.state.cancelled)return"";if(Array.isArray(this.selected))return this.selected.map((e)=>this.styles.primary(e.name)).join(", ");return this.styles.primary(this.selected.name)}async render(){let{submitted:e,size:t}=this.state,s="",r=await this.header(),o=await this.prefix(),i=await this.separator(),a=await this.message();if(this.options.promptLine!==!1)s=[o,a,i,""].join(" "),this.state.prompt=s;let n=await this.format(),d=await this.error()||await this.hint(),l=await this.renderChoices(),c=await this.footer();if(n)s+=n;if(d&&!s.includes(d))s+=" "+d;if(e&&!n&&!l.trim()&&this.multiple&&this.emptyError!=null)s+=this.styles.danger(this.emptyError);this.clear(t),this.write([r,s,l,c].filter(Boolean).join(`
|
|
14
|
+
`)),this.write(this.margin[2]),this.restore()}}ks.exports=Gs});var qs=w((mp,Ws)=>{var Gn=oe(),kn=(e,t)=>{let s=e?new RegExp(e,"ig"):/$^/;return(r)=>{return e?r.replace(s,(o)=>t(o)):r}};class $s extends Gn{constructor(e){super(e);this.cursorShow()}moveCursor(e){this.state.cursor+=e}dispatch(e){return this.append(e)}space(e){return this.options.multiple?super.space(e):this.append(e)}append(e){let{cursor:t,input:s}=this.state;return this.input=s.slice(0,t)+e+s.slice(t),this.moveCursor(1),this.complete()}delete(){let{cursor:e,input:t}=this.state;if(!t)return this.alert();return this.input=t.slice(0,e-1)+t.slice(e),this.moveCursor(-1),this.complete()}deleteForward(){let{cursor:e,input:t}=this.state;if(t[e]===void 0)return this.alert();return this.input=`${t}`.slice(0,e)+`${t}`.slice(e+1),this.complete()}number(e){return this.append(e)}async complete(){this.completing=!0,this.choices=await this.suggest(this.input,this.state._choices),this.state.limit=void 0,this.index=Math.min(Math.max(this.visible.length-1,0),this.index),await this.render(),this.completing=!1}suggest(e=this.input,t=this.state._choices){if(typeof this.options.suggest==="function")return this.options.suggest.call(this,e,t);let s=e.toLowerCase();return t.filter((r)=>r.message.toLowerCase().includes(s))}pointer(){return""}format(){if(!this.focused)return this.input;if(this.options.multiple&&this.state.submitted)return this.selected.map((e)=>this.styles.primary(e.message)).join(", ");if(this.state.submitted){let e=this.value=this.input=this.focused.value;return this.styles.primary(e)}return this.input}async render(){if(this.state.status!=="pending")return super.render();let e=this.options.highlight||this.styles.complement,t=(o,i)=>{if(!o)return o;if(e.stack)return e(o);return e.call(this,o)},s=kn(this.input,t),r=this.choices;this.choices=r.map((o)=>({...o,message:s(o.message)})),await super.render(),this.choices=r}submit(){if(this.options.multiple)this.value=this.selected.map((e)=>e.name);return super.submit()}}Ws.exports=$s});var Nt=w((pp,Ks)=>{var vt=C();Ks.exports=(e,t={})=>{e.cursorHide();let{input:s="",initial:r="",pos:o,showCursor:i=!0,color:a}=t,n=a||e.styles.placeholder,d=vt.inverse(e.styles.primary),l=(f)=>d(e.styles.black(f)),c=s,u=" ",p=l(u);if(e.blink&&e.blink.off===!0)l=(f)=>f,p="";if(i&&o===0&&r===""&&s==="")return l(u);if(i&&o===0&&(s===r||s===""))return l(r[0])+n(r.slice(1));r=vt.isPrimitive(r)?`${r}`:"",s=vt.isPrimitive(s)?`${s}`:"";let m=r&&r.startsWith(s)&&r!==s,h=m?l(r[s.length]):p;if(o!==s.length&&i===!0)c=s.slice(0,o)+l(s[o])+s.slice(o+1),h="";if(i===!1)h="";if(m){let f=e.styles.unstyle(c+h);return c+h+n(r.slice(f.length))}return c+h}});var De=w((up,Fs)=>{var $n=se(),Wn=oe(),qn=Nt();class Hs extends Wn{constructor(e){super({...e,multiple:!0});this.type="form",this.initial=this.options.initial,this.align=[this.options.align,"right"].find((t)=>t!=null),this.emptyError="",this.values={}}async reset(e){if(await super.reset(),e===!0)this._index=this.index;return this.index=this._index,this.values={},this.choices.forEach((t)=>t.reset&&t.reset()),this.render()}dispatch(e){return!!e&&this.append(e)}append(e){let t=this.focused;if(!t)return this.alert();let{cursor:s,input:r}=t;return t.value=t.input=r.slice(0,s)+e+r.slice(s),t.cursor++,this.render()}delete(){let e=this.focused;if(!e||e.cursor<=0)return this.alert();let{cursor:t,input:s}=e;return e.value=e.input=s.slice(0,t-1)+s.slice(t),e.cursor--,this.render()}deleteForward(){let e=this.focused;if(!e)return this.alert();let{cursor:t,input:s}=e;if(s[t]===void 0)return this.alert();let r=`${s}`.slice(0,t)+`${s}`.slice(t+1);return e.value=e.input=r,this.render()}right(){let e=this.focused;if(!e)return this.alert();if(e.cursor>=e.input.length)return this.alert();return e.cursor++,this.render()}left(){let e=this.focused;if(!e)return this.alert();if(e.cursor<=0)return this.alert();return e.cursor--,this.render()}space(e,t){return this.dispatch(e,t)}number(e,t){return this.dispatch(e,t)}next(){let e=this.focused;if(!e)return this.alert();let{initial:t,input:s}=e;if(t&&t.startsWith(s)&&s!==t)return e.value=e.input=t,e.cursor=e.value.length,this.render();return super.next()}prev(){let e=this.focused;if(!e)return this.alert();if(e.cursor===0)return super.prev();return e.value=e.input="",e.cursor=0,this.render()}separator(){return""}format(e){return!this.state.submitted?super.format(e):""}pointer(){return""}indicator(e){return e.input?"\u29BF":"\u2299"}async choiceSeparator(e,t){let s=await this.resolve(e.separator,this.state,e,t)||":";return s?" "+this.styles.disabled(s):""}async renderChoice(e,t){await this.onChoice(e,t);let{state:s,styles:r}=this,{cursor:o,initial:i="",name:a,input:n=""}=e,{muted:d,submitted:l,primary:c,danger:u}=r,p=this.index===t,m=e.validate||(()=>!0),h=await this.choiceSeparator(e,t),f=e.message;if(this.align==="right")f=f.padStart(this.longest+1," ");if(this.align==="left")f=f.padEnd(this.longest+1," ");let g=this.values[a]=n||i,y=n?"success":"dark";if(await m.call(e,g,this.state)!==!0)y="danger";let E=r[y],A=E(await this.indicator(e,t))+(e.pad||""),N=this.indent(e),R=()=>[N,A,f+h,n].filter(Boolean).join(" ");if(s.submitted)return f=$n(f),n=l(n),R();if(e.format)n=await e.format.call(this,n,e,t);else{let _=this.styles.muted;n=qn(this,{input:n,initial:i,pos:o,showCursor:p,color:_})}if(!this.isValue(n))n=this.styles.muted(this.symbols.ellipsis);if(e.result)this.values[a]=await e.result.call(this,g,e,t);if(p)f=c(f);if(e.error)n+=(n?" ":"")+u(e.error.trim());else if(e.hint)n+=(n?" ":"")+d(e.hint.trim());return R()}async submit(){return this.value=this.values,super.base.submit.call(this)}}Fs.exports=Hs});var St=w((hp,Ys)=>{var Kn=De(),Hn=()=>{throw Error("expected prompt to have a custom authenticate method")},Vs=(e=Hn)=>{class t extends Kn{constructor(s){super(s)}async submit(){this.value=await e.call(this,this.values,this.state),super.base.submit.call(this)}static create(s){return Vs(s)}}return t};Ys.exports=Vs()});var Qs=w((fp,Zs)=>{var Fn=St();function Vn(e,t){if(e.username===this.options.username&&e.password===this.options.password)return!0;return!1}var zs=(e=Vn)=>{let t=[{name:"username",message:"username"},{name:"password",message:"password",format(r){if(this.options.showPassword)return r;return(this.state.submitted?this.styles.primary:this.styles.muted)(this.symbols.asterisk.repeat(r.length))}}];class s extends Fn.create(e){constructor(r){super({...r,choices:t})}static create(r){return zs(r)}}return s};Zs.exports=zs()});var Be=w((yp,Js)=>{var Yn=ue(),{isPrimitive:zn,hasColor:Zn}=C();class Xs extends Yn{constructor(e){super(e);this.cursorHide()}async initialize(){let e=await this.resolve(this.initial,this.state);this.input=await this.cast(e),await super.initialize()}dispatch(e){if(!this.isValue(e))return this.alert();return this.input=e,this.submit()}format(e){let{styles:t,state:s}=this;return!s.submitted?t.primary(e):t.success(e)}cast(e){return this.isTrue(e)}isTrue(e){return/^[ty1]/i.test(e)}isFalse(e){return/^[fn0]/i.test(e)}isValue(e){return zn(e)&&(this.isTrue(e)||this.isFalse(e))}async hint(){if(this.state.status==="pending"){let e=await this.element("hint");if(!Zn(e))return this.styles.muted(e);return e}}async render(){let{input:e,size:t}=this.state,s=await this.prefix(),r=await this.separator(),o=await this.message(),i=this.styles.muted(this.default),a=[s,o,i,r].filter(Boolean).join(" ");this.state.prompt=a;let n=await this.header(),d=this.value=this.cast(e),l=await this.format(d),c=await this.error()||await this.hint(),u=await this.footer();if(c&&!a.includes(c))l+=" "+c;a+=" "+l,this.clear(t),this.write([n,a,u].filter(Boolean).join(`
|
|
15
|
+
`)),this.restore()}set value(e){super.value=e}get value(){return this.cast(super.value)}}Js.exports=Xs});var tr=w((gp,er)=>{var Qn=Be();class js extends Qn{constructor(e){super(e);this.default=this.options.default||(this.initial?"(Y/n)":"(y/N)")}}er.exports=js});var or=w((bp,rr)=>{var Xn=oe(),Jn=De(),he=Jn.prototype;class sr extends Xn{constructor(e){super({...e,multiple:!0});this.align=[this.options.align,"left"].find((t)=>t!=null),this.emptyError="",this.values={}}dispatch(e,t){let s=this.focused,r=s.parent||{};if(!s.editable&&!r.editable){if(e==="a"||e==="i")return super[e]()}return he.dispatch.call(this,e,t)}append(e,t){return he.append.call(this,e,t)}delete(e,t){return he.delete.call(this,e,t)}space(e){return this.focused.editable?this.append(e):super.space()}number(e){return this.focused.editable?this.append(e):super.number(e)}next(){return this.focused.editable?he.next.call(this):super.next()}prev(){return this.focused.editable?he.prev.call(this):super.prev()}async indicator(e,t){let s=e.indicator||"",r=e.editable?s:super.indicator(e,t);return await this.resolve(r,this.state,e,t)||""}indent(e){return e.role==="heading"?"":e.editable?" ":" "}async renderChoice(e,t){if(e.indent="",e.editable)return he.renderChoice.call(this,e,t);return super.renderChoice(e,t)}error(){return""}footer(){return this.state.error}async validate(){let e=!0;for(let t of this.choices){if(typeof t.validate!=="function")continue;if(t.role==="heading")continue;let s=t.parent?this.value[t.parent.name]:this.value;if(t.editable)s=t.value===t.name?t.initial||"":t.value;else if(!this.isDisabled(t))s=t.enabled===!0;if(e=await t.validate(s,this.state),e!==!0)break}if(e!==!0)this.state.error=typeof e==="string"?e:"Invalid Input";return e}submit(){if(this.focused.newChoice===!0)return super.submit();if(this.choices.some((e)=>e.newChoice))return this.alert();this.value={};for(let e of this.choices){let t=e.parent?this.value[e.parent.name]:this.value;if(e.role==="heading"){this.value[e.name]={};continue}if(e.editable)t[e.name]=e.value===e.name?e.initial||"":e.value;else if(!this.isDisabled(e))t[e.name]=e.enabled===!0}return this.base.submit.call(this)}}rr.exports=sr});var le=w((xp,ar)=>{var jn=ue(),ed=mt(),td=Nt(),{isPrimitive:sd}=C();class ir extends jn{constructor(e){super(e);if(this.initial=sd(this.initial)?String(this.initial):"",this.initial)this.cursorHide();this.state.prevCursor=0,this.state.clipboard=[],this.keypressTimeout=this.options.keypressTimeout!==void 0?this.options.keypressTimeout:null}async keypress(e,t=e?ed(e,{}):{}){let s=Date.now(),r=s-this.lastKeypress;this.lastKeypress=s;let o=t.name==="return"||t.name==="enter",i=this.state.prevKeypress,a;if(this.state.prevKeypress=t,this.keypressTimeout!=null&&o){if(r<this.keypressTimeout)return this.submit();this.state.multilineBuffer=this.state.multilineBuffer||"",this.state.multilineBuffer+=e,a=!0,i=null}if(a||this.options.multiline&&o){if(!i||i.name!=="return")return this.append(`
|
|
16
|
+
`,t)}return super.keypress(e,t)}moveCursor(e){this.cursor+=e}reset(){return this.input=this.value="",this.cursor=0,this.render()}dispatch(e,t){if(!e||t.ctrl||t.code)return this.alert();this.append(e)}append(e){let{cursor:t,input:s}=this.state;this.input=`${s}`.slice(0,t)+e+`${s}`.slice(t),this.moveCursor(String(e).length),this.render()}insert(e){this.append(e)}delete(){let{cursor:e,input:t}=this.state;if(e<=0)return this.alert();this.input=`${t}`.slice(0,e-1)+`${t}`.slice(e),this.moveCursor(-1),this.render()}deleteForward(){let{cursor:e,input:t}=this.state;if(t[e]===void 0)return this.alert();this.input=`${t}`.slice(0,e)+`${t}`.slice(e+1),this.render()}cutForward(){let e=this.cursor;if(this.input.length<=e)return this.alert();this.state.clipboard.push(this.input.slice(e)),this.input=this.input.slice(0,e),this.render()}cutLeft(){let e=this.cursor;if(e===0)return this.alert();let t=this.input.slice(0,e),s=this.input.slice(e),r=t.split(" ");this.state.clipboard.push(r.pop()),this.input=r.join(" "),this.cursor=this.input.length,this.input+=s,this.render()}paste(){if(!this.state.clipboard.length)return this.alert();this.insert(this.state.clipboard.pop()),this.render()}toggleCursor(){if(this.state.prevCursor)this.cursor=this.state.prevCursor,this.state.prevCursor=0;else this.state.prevCursor=this.cursor,this.cursor=0;this.render()}first(){this.cursor=0,this.render()}last(){this.cursor=this.input.length-1,this.render()}next(){let e=this.initial!=null?String(this.initial):"";if(!e||!e.startsWith(this.input))return this.alert();this.input=this.initial,this.cursor=this.initial.length,this.render()}prev(){if(!this.input)return this.alert();this.reset()}backward(){return this.left()}forward(){return this.right()}right(){if(this.cursor>=this.input.length)return this.alert();return this.moveCursor(1),this.render()}left(){if(this.cursor<=0)return this.alert();return this.moveCursor(-1),this.render()}isValue(e){return!!e}async format(e=this.value){let t=await this.resolve(this.initial,this.state);if(!this.state.submitted)return td(this,{input:e,initial:t,pos:this.cursor});return this.styles.submitted(e||t)}async render(){let e=this.state.size,t=await this.prefix(),s=await this.separator(),r=await this.message(),o=[t,r,s].filter(Boolean).join(" ");this.state.prompt=o;let i=await this.header(),a=await this.format(),n=await this.error()||await this.hint(),d=await this.footer();if(n&&!a.includes(n))a+=" "+n;o+=" "+a,this.clear(e),this.write([i,o,d].filter(Boolean).join(`
|
|
17
|
+
`)),this.restore()}}ar.exports=ir});var dr=w((wp,nr)=>{var rd=(e)=>e.filter((t,s)=>e.lastIndexOf(t)===s),Pe=(e)=>rd(e).filter(Boolean);nr.exports=(e,t={},s="")=>{let{past:r=[],present:o=""}=t,i,a;switch(e){case"prev":case"undo":return i=r.slice(0,r.length-1),a=r[r.length-1]||"",{past:Pe([s,...i]),present:a};case"next":case"redo":return i=r.slice(1),a=r[0]||"",{past:Pe([...i,s]),present:a};case"save":return{past:Pe([...r,s]),present:""};case"remove":if(a=Pe(r.filter((n)=>n!==s)),o="",a.length)o=a.pop();return{past:a,present:o};default:throw Error(`Invalid action: "${e}"`)}}});var Tt=w((Ep,mr)=>{var od=le(),lr=dr();class cr extends od{constructor(e){super(e);let t=this.options.history;if(t&&t.store){let s=t.values||this.initial;this.autosave=!!t.autosave,this.store=t.store,this.data=this.store.get("values")||{past:[],present:s},this.initial=this.data.present||this.data.past[this.data.past.length-1]}}completion(e){if(!this.store)return this.alert();if(this.data=lr(e,this.data,this.input),!this.data.present)return this.alert();return this.input=this.data.present,this.cursor=this.input.length,this.render()}altUp(){return this.completion("prev")}altDown(){return this.completion("next")}prev(){return this.save(),super.prev()}save(){if(!this.store)return;this.data=lr("save",this.data,this.input),this.store.set("values",this.data)}submit(){if(this.store&&this.autosave===!0)this.save();return super.submit()}}mr.exports=cr});var hr=w((Ap,ur)=>{var id=le();class pr extends id{format(){return""}}ur.exports=pr});var gr=w((vp,yr)=>{var ad=le();class fr extends ad{constructor(e={}){super(e);this.sep=this.options.separator||/, */,this.initial=e.initial||""}split(e=this.value){return e?String(e).split(this.sep):[]}format(){let e=this.state.submitted?this.styles.primary:(t)=>t;return this.list.map(e).join(", ")}async submit(e){let t=this.state.error||await this.validate(this.list,this.state);if(t!==!0)return this.state.error=t,super.submit();return this.value=this.list,super.submit()}get list(){return this.split()}}yr.exports=fr});var wr=w((Np,xr)=>{var nd=oe();class br extends nd{constructor(e){super({...e,multiple:!0})}}xr.exports=br});var Rt=w((Sp,Ar)=>{var dd=le();class Er extends dd{constructor(e={}){super({style:"number",...e});this.min=this.isValue(e.min)?this.toNumber(e.min):-1/0,this.max=this.isValue(e.max)?this.toNumber(e.max):1/0,this.delay=e.delay!=null?e.delay:1000,this.float=e.float!==!1,this.round=e.round===!0||e.float===!1,this.major=e.major||10,this.minor=e.minor||1,this.initial=e.initial!=null?e.initial:"",this.input=String(this.initial),this.cursor=this.input.length,this.cursorShow()}append(e){if(!/[-+.]/.test(e)||e==="."&&this.input.includes("."))return this.alert("invalid number");return super.append(e)}number(e){return super.append(e)}next(){if(this.input&&this.input!==this.initial)return this.alert();if(!this.isValue(this.initial))return this.alert();return this.input=this.initial,this.cursor=String(this.initial).length,this.render()}up(e){let t=e||this.minor,s=this.toNumber(this.input);if(s>this.max+t)return this.alert();return this.input=`${s+t}`,this.render()}down(e){let t=e||this.minor,s=this.toNumber(this.input);if(s<this.min-t)return this.alert();return this.input=`${s-t}`,this.render()}shiftDown(){return this.down(this.major)}shiftUp(){return this.up(this.major)}format(e=this.input){if(typeof this.options.format==="function")return this.options.format.call(this,e);return this.styles.info(e)}toNumber(e=""){return this.float?+e:Math.round(+e)}isValue(e){return/^[-+]?[0-9]+((\.)|(\.[0-9]+))?$/.test(e)}submit(){let e=[this.input,this.initial].find((t)=>this.isValue(t));return this.value=this.toNumber(e||0),super.submit()}}Ar.exports=Er});var Sr=w((Tp,Nr)=>{var ld=le();class vr extends ld{constructor(e){super(e);this.cursorShow()}format(e=this.input){if(!this.keypressed)return"";return(this.state.submitted?this.styles.primary:this.styles.muted)(this.symbols.asterisk.repeat(e.length))}}Nr.exports=vr});var Cr=w((Rp,Mr)=>{var cd=se(),md=Ee(),Tr=C();class Rr extends md{constructor(e={}){super(e);this.widths=[].concat(e.messageWidth||50),this.align=[].concat(e.align||"left"),this.linebreak=e.linebreak||!1,this.edgeLength=e.edgeLength||3,this.newline=e.newline||`
|
|
18
|
+
`;let t=e.startNumber||1;if(typeof this.scale==="number")this.scaleKey=!1,this.scale=Array(this.scale).fill(0).map((s,r)=>({name:r+t}))}async reset(){return this.tableized=!1,await super.reset(),this.render()}tableize(){if(this.tableized===!0)return;this.tableized=!0;let e=0;for(let t of this.choices){e=Math.max(e,t.message.length),t.scaleIndex=t.initial||2,t.scale=[];for(let s=0;s<this.scale.length;s++)t.scale.push({index:s})}this.widths[0]=Math.min(this.widths[0],e+3)}async dispatch(e,t){if(this.multiple)return this[t.name]?await this[t.name](e,t):await super.dispatch(e,t);this.alert()}heading(e,t,s){return this.styles.strong(e)}separator(){return this.styles.muted(this.symbols.ellipsis)}right(){let e=this.focused;if(e.scaleIndex>=this.scale.length-1)return this.alert();return e.scaleIndex++,this.render()}left(){let e=this.focused;if(e.scaleIndex<=0)return this.alert();return e.scaleIndex--,this.render()}indent(){return""}format(){if(this.state.submitted)return this.choices.map((t)=>this.styles.info(t.index)).join(", ");return""}pointer(){return""}renderScaleKey(){if(this.scaleKey===!1)return"";if(this.state.submitted)return"";return["",...this.scale.map((s)=>` ${s.name} - ${s.message}`)].map((s)=>this.styles.muted(s)).join(`
|
|
19
|
+
`)}renderScaleHeading(e){let t=this.scale.map((n)=>n.name);if(typeof this.options.renderScaleHeading==="function")t=this.options.renderScaleHeading.call(this,e);let s=this.scaleLength-t.join("").length,r=Math.round(s/(t.length-1)),i=t.map((n)=>this.styles.strong(n)).join(" ".repeat(r)),a=" ".repeat(this.widths[0]);return this.margin[3]+a+this.margin[1]+i}scaleIndicator(e,t,s){if(typeof this.options.scaleIndicator==="function")return this.options.scaleIndicator.call(this,e,t,s);let r=e.scaleIndex===t.index;if(t.disabled)return this.styles.hint(this.symbols.radio.disabled);if(r)return this.styles.success(this.symbols.radio.on);return this.symbols.radio.off}renderScale(e,t){let s=e.scale.map((o)=>this.scaleIndicator(e,o,t)),r=this.term==="Hyper"?"":" ";return s.join(r+this.symbols.line.repeat(this.edgeLength))}async renderChoice(e,t){await this.onChoice(e,t);let s=this.index===t,r=await this.pointer(e,t),o=await e.hint;if(o&&!Tr.hasColor(o))o=this.styles.muted(o);let i=(m)=>this.margin[3]+m.replace(/\s+$/,"").padEnd(this.widths[0]," "),a=this.newline,n=this.indent(e),d=await this.resolve(e.message,this.state,e,t),l=await this.renderScale(e,t),c=this.margin[1]+this.margin[3];this.scaleLength=cd(l).length,this.widths[0]=Math.min(this.widths[0],this.width-this.scaleLength-c.length);let p=Tr.wordWrap(d,{width:this.widths[0],newline:a}).split(`
|
|
20
|
+
`).map((m)=>i(m)+this.margin[1]);if(s)l=this.styles.info(l),p=p.map((m)=>this.styles.info(m));if(p[0]+=l,this.linebreak)p.push("");return[n+r,p.join(`
|
|
21
|
+
`)].filter(Boolean)}async renderChoices(){if(this.state.submitted)return"";this.tableize();let e=this.visible.map(async(r,o)=>await this.renderChoice(r,o)),t=await Promise.all(e),s=await this.renderScaleHeading();return this.margin[0]+[s,...t.map((r)=>r.join(" "))].join(`
|
|
22
|
+
`)}async render(){let{submitted:e,size:t}=this.state,s=await this.prefix(),r=await this.separator(),o=await this.message(),i="";if(this.options.promptLine!==!1)i=[s,o,r,""].join(" "),this.state.prompt=i;let a=await this.header(),n=await this.format(),d=await this.renderScaleKey(),l=await this.error()||await this.hint(),c=await this.renderChoices(),u=await this.footer(),p=this.emptyError;if(n)i+=n;if(l&&!i.includes(l))i+=" "+l;if(e&&!n&&!c.trim()&&this.multiple&&p!=null)i+=this.styles.danger(p);if(this.clear(t),this.write([a,i,d,c,u].filter(Boolean).join(`
|
|
23
|
+
`)),!this.state.submitted)this.write(this.margin[2]);this.restore()}submit(){this.value={};for(let e of this.choices)this.value[e.name]=e.scaleIndex;return this.base.submit.call(this)}}Mr.exports=Rr});var Dr=w((Mp,Or)=>{var _r=se(),pd=(e="")=>{return typeof e==="string"?e.replace(/^['"]|['"]$/g,""):""};class Ir{constructor(e){this.name=e.key,this.field=e.field||{},this.value=pd(e.initial||this.field.initial||""),this.message=e.message||this.name,this.cursor=0,this.input="",this.lines=[]}}var ud=async(e={},t={},s=(r)=>r)=>{let r=new Set,o=e.fields||[],i=e.template,a=[],n=[],d=[],l=1;if(typeof i==="function")i=await i();let c=-1,u=()=>i[++c],p=()=>i[c+1],m=(h)=>{h.line=l,a.push(h)};m({type:"bos",value:""});while(c<i.length-1){let h=u();if(/^[^\S\n ]$/.test(h)){m({type:"text",value:h});continue}if(h===`
|
|
24
|
+
`){m({type:"newline",value:h}),l++;continue}if(h==="\\"){h+=u(),m({type:"text",value:h});continue}if((h==="$"||h==="#"||h==="{")&&p()==="{"){let g=u();h+=g;let y={type:"template",open:h,inner:"",close:"",value:h},E;while(E=u()){if(E==="}"){if(p()==="}")E+=u();y.value+=E,y.close=E;break}if(E===":")y.initial="",y.key=y.inner;else if(y.initial!==void 0)y.initial+=E;y.value+=E,y.inner+=E}if(y.template=y.open+(y.initial||y.inner)+y.close,y.key=y.key||y.inner,hasOwnProperty.call(t,y.key))y.initial=t[y.key];y=s(y),m(y),d.push(y.key),r.add(y.key);let A=n.find((N)=>N.name===y.key);if(y.field=o.find((N)=>N.name===y.key),!A)A=new Ir(y),n.push(A);A.lines.push(y.line-1);continue}let f=a[a.length-1];if(f.type==="text"&&f.line===l)f.value+=h;else m({type:"text",value:h})}return m({type:"eos",value:""}),{input:i,tabstops:a,unique:r,keys:d,items:n}};Or.exports=async(e)=>{let t=e.options,s=new Set(t.required===!0?[]:t.required||[]),r={...t.values,...t.initial},{tabstops:o,items:i,keys:a}=await ud(t,r),n=Mt("result",e,t),d=Mt("format",e,t),l=Mt("validate",e,t,!0),c=e.isValue.bind(e);return async(u={},p=!1)=>{let m=0;u.required=s,u.items=i,u.keys=a,u.output="";let h=async(E,A,N,R)=>{let _=await l(E,A,N,R);if(_===!1)return"Invalid field "+N.name;return _};for(let E of o){let{value:A,key:N}=E;if(E.type!=="template"){if(A)u.output+=A;continue}if(E.type==="template"){let R=i.find((pe)=>pe.name===N);if(t.required===!0)u.required.add(R.name);let _=[R.input,u.values[R.value],R.value,A].find(c),ee=(R.field||{}).message||E.inner;if(p){let pe=await h(u.values[N],u,R,m);if(pe&&typeof pe==="string"||pe===!1){u.invalid.set(N,pe);continue}u.invalid.delete(N);let ca=await n(u.values[N],u,R,m);u.output+=_r(ca);continue}R.placeholder=!1;let Kt=A;if(A=await d(A,u,R,m),_!==A)u.values[N]=_,A=e.styles.typing(_),u.missing.delete(ee);else if(u.values[N]=void 0,_=`<${ee}>`,A=e.styles.primary(_),R.placeholder=!0,u.required.has(N))u.missing.add(ee);if(u.missing.has(ee)&&u.validating)A=e.styles.warning(_);if(u.invalid.has(N)&&u.validating)A=e.styles.danger(_);if(m===u.index)if(Kt!==A)A=e.styles.underline(A);else A=e.styles.heading(_r(A));m++}if(A)u.output+=A}let f=u.output.split(`
|
|
25
|
+
`).map((E)=>" "+E),g=i.length,y=0;for(let E of i){if(u.invalid.has(E.name))E.lines.forEach((A)=>{if(f[A][0]!==" ")return;f[A]=u.styles.danger(u.symbols.bullet)+f[A].slice(1)});if(e.isValue(u.values[E.name]))y++}return u.completed=(y/g*100).toFixed(0),u.output=f.join(`
|
|
26
|
+
`),u.output}};function Mt(e,t,s,r){return(o,i,a,n)=>{if(typeof a.field[e]==="function")return a.field[e].call(t,o,i,a,n);return[r,o].find((d)=>t.isValue(d))}}});var Lr=w((Cp,Pr)=>{var hd=se(),fd=Dr(),yd=ue();class Br extends yd{constructor(e){super(e);this.cursorHide(),this.reset(!0)}async initialize(){this.interpolate=await fd(this),await super.initialize()}async reset(e){if(this.state.keys=[],this.state.invalid=new Map,this.state.missing=new Set,this.state.completed=0,this.state.values={},e!==!0)await this.initialize(),await this.render()}moveCursor(e){let t=this.getItem();this.cursor+=e,t.cursor+=e}dispatch(e,t){if(!t.code&&!t.ctrl&&e!=null&&this.getItem()){this.append(e,t);return}this.alert()}append(e,t){let s=this.getItem(),r=s.input.slice(0,this.cursor),o=s.input.slice(this.cursor);this.input=s.input=`${r}${e}${o}`,this.moveCursor(1),this.render()}delete(){let e=this.getItem();if(this.cursor<=0||!e.input)return this.alert();let t=e.input.slice(this.cursor),s=e.input.slice(0,this.cursor-1);this.input=e.input=`${s}${t}`,this.moveCursor(-1),this.render()}increment(e){return e>=this.state.keys.length-1?0:e+1}decrement(e){return e<=0?this.state.keys.length-1:e-1}first(){this.state.index=0,this.render()}last(){this.state.index=this.state.keys.length-1,this.render()}right(){if(this.cursor>=this.input.length)return this.alert();this.moveCursor(1),this.render()}left(){if(this.cursor<=0)return this.alert();this.moveCursor(-1),this.render()}prev(){this.state.index=this.decrement(this.state.index),this.getItem(),this.render()}next(){this.state.index=this.increment(this.state.index),this.getItem(),this.render()}up(){this.prev()}down(){this.next()}format(e){let t=this.state.completed<100?this.styles.warning:this.styles.success;if(this.state.submitted===!0&&this.state.completed!==100)t=this.styles.danger;return t(`${this.state.completed}% completed`)}async render(){let{index:e,keys:t=[],submitted:s,size:r}=this.state,o=[this.options.newline,`
|
|
27
|
+
`].find((y)=>y!=null),i=await this.prefix(),a=await this.separator(),n=await this.message(),d=[i,n,a].filter(Boolean).join(" ");this.state.prompt=d;let l=await this.header(),c=await this.error()||"",u=await this.hint()||"",p=s?"":await this.interpolate(this.state),m=this.state.key=t[e]||"",h=await this.format(m),f=await this.footer();if(h)d+=" "+h;if(u&&!h&&this.state.completed===0)d+=" "+u;this.clear(r);let g=[l,d,p,f,c.trim()];this.write(g.filter(Boolean).join(o)),this.restore()}getItem(e){let{items:t,keys:s,index:r}=this.state,o=t.find((i)=>i.name===s[r]);if(o&&o.input!=null)this.input=o.input,this.cursor=o.cursor;return o}async submit(){if(typeof this.interpolate!=="function")await this.initialize();await this.interpolate(this.state,!0);let{invalid:e,missing:t,output:s,values:r}=this.state;if(e.size){let a="";for(let[n,d]of e)a+=`Invalid ${n}: ${d}
|
|
28
|
+
`;return this.state.error=a,super.submit()}if(t.size)return this.state.error="Required: "+[...t.keys()].join(", "),super.submit();let i=hd(s).split(`
|
|
29
|
+
`).map((a)=>a.slice(1)).join(`
|
|
30
|
+
`);return this.value={values:r,result:i},super.submit()}}Pr.exports=Br});var kr=w((_p,Gr)=>{var gd=oe();class Ur extends gd{constructor(e){super({...e,reorder:!1,sort:!0,multiple:!0});this.state.hint=[this.options.hint,"(Use <shift>+<up/down> to sort)"].find(this.isValue.bind(this))}indicator(){return""}async renderChoice(e,t){let s=await super.renderChoice(e,t),r=this.symbols.identicalTo+" ",o=this.index===t&&this.sorting?this.styles.muted(r):" ";if(this.options.drag===!1)o="";if(this.options.numbered===!0)return o+`${t+1} - `+s;return o+s}get selected(){return this.choices}submit(){return this.value=this.choices.map((e)=>e.value),super.submit()}}Gr.exports=Ur});var qr=w((Ip,Wr)=>{var bd=Ee();class $r extends bd{constructor(e={}){super(e);if(this.emptyError=e.emptyError||"No items were selected",this.term=process.env.TERM_PROGRAM,!this.options.header){let t=["","4 - Strongly Agree","3 - Agree","2 - Neutral","1 - Disagree","0 - Strongly Disagree",""];t=t.map((s)=>this.styles.muted(s)),this.state.header=t.join(`
|
|
31
|
+
`)}}async toChoices(...e){if(this.createdScales)return!1;this.createdScales=!0;let t=await super.toChoices(...e);for(let s of t)s.scale=xd(5,this.options),s.scaleIdx=2;return t}dispatch(){this.alert()}space(){let e=this.focused,t=e.scale[e.scaleIdx],s=t.selected;return e.scale.forEach((r)=>r.selected=!1),t.selected=!s,this.render()}indicator(){return""}pointer(){return""}separator(){return this.styles.muted(this.symbols.ellipsis)}right(){let e=this.focused;if(e.scaleIdx>=e.scale.length-1)return this.alert();return e.scaleIdx++,this.render()}left(){let e=this.focused;if(e.scaleIdx<=0)return this.alert();return e.scaleIdx--,this.render()}indent(){return" "}async renderChoice(e,t){await this.onChoice(e,t);let s=this.index===t,r=this.term==="Hyper",o=!r?8:9,i=!r?" ":"",a=this.symbols.line.repeat(o),n=" ".repeat(o+(r?0:1)),d=(E)=>(E?this.styles.success("\u25C9"):"\u25EF")+i,l=t+1+".",c=s?this.styles.heading:this.styles.noop,u=await this.resolve(e.message,this.state,e,t),p=this.indent(e),m=p+e.scale.map((E,A)=>d(A===e.scaleIdx)).join(a),h=(E)=>E===e.scaleIdx?c(E):E,f=p+e.scale.map((E,A)=>h(A)).join(n),g=()=>[l,u].filter(Boolean).join(" "),y=()=>[g(),m,f," "].filter(Boolean).join(`
|
|
32
|
+
`);if(s)m=this.styles.cyan(m),f=this.styles.cyan(f);return y()}async renderChoices(){if(this.state.submitted)return"";let e=this.visible.map(async(s,r)=>await this.renderChoice(s,r)),t=await Promise.all(e);if(!t.length)t.push(this.styles.danger("No matching choices"));return t.join(`
|
|
33
|
+
`)}format(){if(this.state.submitted)return this.choices.map((t)=>this.styles.info(t.scaleIdx)).join(", ");return""}async render(){let{submitted:e,size:t}=this.state,s=await this.prefix(),r=await this.separator(),o=await this.message(),i=[s,o,r].filter(Boolean).join(" ");this.state.prompt=i;let a=await this.header(),n=await this.format(),d=await this.error()||await this.hint(),l=await this.renderChoices(),c=await this.footer();if(n||!d)i+=" "+n;if(d&&!i.includes(d))i+=" "+d;if(e&&!n&&!l&&this.multiple&&this.type!=="form")i+=this.styles.danger(this.emptyError);this.clear(t),this.write([i,a,l,c].filter(Boolean).join(`
|
|
34
|
+
`)),this.restore()}submit(){this.value={};for(let e of this.choices)this.value[e.name]=e.scaleIdx;return this.base.submit.call(this)}}function xd(e,t={}){if(Array.isArray(t.scale))return t.scale.map((r)=>({...r}));let s=[];for(let r=1;r<e+1;r++)s.push({i:r,selected:!1});return s}Wr.exports=$r});var Fr=w((Op,Hr)=>{var wd=Be();class Kr extends wd{async initialize(){await super.initialize(),this.value=this.initial=this.resolve(this.options.initial),this.disabled=this.options.disabled||"no",this.enabled=this.options.enabled||"yes",await this.render()}reset(){this.value=this.initial,this.render()}delete(){this.alert()}toggle(){this.value=!this.value,this.render()}enable(){if(this.value===!0)return this.alert();this.value=!0,this.render()}disable(){if(this.value===!1)return this.alert();this.value=!1,this.render()}up(){this.toggle()}down(){this.toggle()}right(){this.toggle()}left(){this.toggle()}next(){this.toggle()}prev(){this.toggle()}dispatch(e="",t){switch(e.toLowerCase()){case" ":return this.toggle();case"1":case"y":case"t":return this.enable();case"0":case"n":case"f":return this.disable();default:return this.alert()}}format(){let e=(s)=>this.styles.primary.underline(s);return[this.value?this.disabled:e(this.disabled),this.value?e(this.enabled):this.enabled].join(this.styles.muted(" / "))}async render(){let{size:e}=this.state,t=await this.header(),s=await this.prefix(),r=await this.separator(),o=await this.message(),i=await this.format(),a=await this.error()||await this.hint(),n=await this.footer(),d=[s,o,r,i].join(" ");if(this.state.prompt=d,a&&!d.includes(a))d+=" "+a;this.clear(e),this.write([t,d,n].filter(Boolean).join(`
|
|
35
|
+
`)),this.write(this.margin[2]),this.restore()}}Hr.exports=Kr});var zr=w((Dp,Yr)=>{var Ed=oe();class Vr extends Ed{constructor(e){super(e);if(typeof this.options.correctChoice!=="number"||this.options.correctChoice<0)throw Error("Please specify the index of the correct answer from the list of choices")}async toChoices(e,t){let s=await super.toChoices(e,t);if(s.length<2)throw Error("Please give at least two choices to the user");if(this.options.correctChoice>s.length)throw Error("Please specify the index of the correct answer from the list of choices");return s}check(e){return e.index===this.options.correctChoice}async result(e){return{selectedAnswer:e,correctAnswer:this.options.choices[this.options.correctChoice].value,correct:await this.check(this.state)}}}Yr.exports=Vr});var Qr=w((Ct)=>{var Zr=C(),S=(e,t)=>{Zr.defineExport(Ct,e,t),Zr.defineExport(Ct,e.toLowerCase(),t)};S("AutoComplete",()=>qs());S("BasicAuth",()=>Qs());S("Confirm",()=>tr());S("Editable",()=>or());S("Form",()=>De());S("Input",()=>Tt());S("Invisible",()=>hr());S("List",()=>gr());S("MultiSelect",()=>wr());S("Numeral",()=>Rt());S("Password",()=>Sr());S("Scale",()=>Cr());S("Select",()=>oe());S("Snippet",()=>Lr());S("Sort",()=>kr());S("Survey",()=>qr());S("Text",()=>Tt());S("Toggle",()=>Fr());S("Quiz",()=>zr())});var Jr=w((Pp,Xr)=>{Xr.exports={ArrayPrompt:Ee(),AuthPrompt:St(),BooleanPrompt:Be(),NumberPrompt:Rt(),StringPrompt:le()}});var ae=w((Lp,eo)=>{var jr=be("assert"),It=be("events"),ie=C();class U extends It{constructor(e,t){super();this.options=ie.merge({},e),this.answers={...t}}register(e,t){if(ie.isObject(e)){for(let r of Object.keys(e))this.register(r,e[r]);return this}jr.equal(typeof t,"function","expected a function");let s=e.toLowerCase();if(t.prototype instanceof this.Prompt)this.prompts[s]=t;else this.prompts[s]=t(this.Prompt,this);return this}async prompt(e=[]){for(let t of[].concat(e))try{if(typeof t==="function")t=await t.call(this);await this.ask(ie.merge({},this.options,t))}catch(s){return Promise.reject(s)}return this.answers}async ask(e){if(typeof e==="function")e=await e.call(this);let t=ie.merge({},this.options,e),{type:s,name:r}=e,{set:o,get:i}=ie;if(typeof s==="function")s=await s.call(this,e,this.answers);if(!s)return this.answers[r];if(s==="number")s="numeral";jr(this.prompts[s],`Prompt "${s}" is not registered`);let a=new this.prompts[s](t),n=i(this.answers,r);if(a.state.answers=this.answers,a.enquirer=this,r)a.on("submit",(l)=>{this.emit("answer",r,l,a),o(this.answers,r,l)});let d=a.emit.bind(a);if(a.emit=(...l)=>{return this.emit.call(this,...l),d(...l)},this.emit("prompt",a,this),t.autofill&&n!=null){if(a.value=a.input=n,t.autofill==="show")await a.submit()}else n=a.value=await a.run();return n}use(e){return e.call(this,this),this}set Prompt(e){this._Prompt=e}get Prompt(){return this._Prompt||this.constructor.Prompt}get prompts(){return this.constructor.prompts}static set Prompt(e){this._Prompt=e}static get Prompt(){return this._Prompt||ue()}static get prompts(){return Qr()}static get types(){return Jr()}static get prompt(){let e=(t,...s)=>{let r=new this(...s),o=r.emit.bind(r);return r.emit=(...i)=>{return e.emit(...i),o(...i)},r.prompt(t)};return ie.mixinEmitter(e,new It),e}}ie.mixinEmitter(U,new It);var _t=U.prompts;for(let e of Object.keys(_t)){let t=e.toLowerCase(),s=(r)=>new _t[e](r).run();if(U.prompt[t]=s,U[t]=s,!U[e])Reflect.defineProperty(U,e,{get:()=>_t[e]})}var Ae=(e)=>{ie.defineExport(U,e,()=>U.types[e])};Ae("ArrayPrompt");Ae("AuthPrompt");Ae("BooleanPrompt");Ae("NumberPrompt");Ae("StringPrompt");eo.exports=U});var Bi=w((Ut,Gt)=>{(function(e,t){if(typeof Ut==="object"&&typeof Gt==="object")Gt.exports=t();else if(typeof define==="function"&&define.amd)define(function(){return t()});else e.pluralize=t()})(Ut,function(){var e=[],t=[],s={},r={},o={};function i(m){if(typeof m==="string")return new RegExp("^"+m+"$","i");return m}function a(m,h){if(m===h)return h;if(m===m.toLowerCase())return h.toLowerCase();if(m===m.toUpperCase())return h.toUpperCase();if(m[0]===m[0].toUpperCase())return h.charAt(0).toUpperCase()+h.substr(1).toLowerCase();return h.toLowerCase()}function n(m,h){return m.replace(/\$(\d{1,2})/g,function(f,g){return h[g]||""})}function d(m,h){return m.replace(h[0],function(f,g){var y=n(h[1],arguments);if(f==="")return a(m[g-1],y);return a(f,y)})}function l(m,h,f){if(!m.length||s.hasOwnProperty(m))return h;var g=f.length;while(g--){var y=f[g];if(y[0].test(h))return d(h,y)}return h}function c(m,h,f){return function(g){var y=g.toLowerCase();if(h.hasOwnProperty(y))return a(g,y);if(m.hasOwnProperty(y))return a(g,m[y]);return l(y,g,f)}}function u(m,h,f,g){return function(y){var E=y.toLowerCase();if(h.hasOwnProperty(E))return!0;if(m.hasOwnProperty(E))return!1;return l(E,E,f)===E}}function p(m,h,f){var g=h===1?p.singular(m):p.plural(m);return(f?h+" ":"")+g}return p.plural=c(o,r,e),p.isPlural=u(o,r,e),p.singular=c(r,o,t),p.isSingular=u(r,o,t),p.addPluralRule=function(m,h){e.push([i(m),h])},p.addSingularRule=function(m,h){t.push([i(m),h])},p.addUncountableRule=function(m){if(typeof m==="string"){s[m.toLowerCase()]=!0;return}p.addPluralRule(m,"$0"),p.addSingularRule(m,"$0")},p.addIrregularRule=function(m,h){h=h.toLowerCase(),m=m.toLowerCase(),o[m]=h,r[h]=m},[["I","we"],["me","us"],["he","they"],["she","they"],["them","them"],["myself","ourselves"],["yourself","yourselves"],["itself","themselves"],["herself","themselves"],["himself","themselves"],["themself","themselves"],["is","are"],["was","were"],["has","have"],["this","these"],["that","those"],["echo","echoes"],["dingo","dingoes"],["volcano","volcanoes"],["tornado","tornadoes"],["torpedo","torpedoes"],["genus","genera"],["viscus","viscera"],["stigma","stigmata"],["stoma","stomata"],["dogma","dogmata"],["lemma","lemmata"],["schema","schemata"],["anathema","anathemata"],["ox","oxen"],["axe","axes"],["die","dice"],["yes","yeses"],["foot","feet"],["eave","eaves"],["goose","geese"],["tooth","teeth"],["quiz","quizzes"],["human","humans"],["proof","proofs"],["carve","carves"],["valve","valves"],["looey","looies"],["thief","thieves"],["groove","grooves"],["pickaxe","pickaxes"],["passerby","passersby"]].forEach(function(m){return p.addIrregularRule(m[0],m[1])}),[[/s?$/i,"s"],[/[^\u0000-\u007F]$/i,"$0"],[/([^aeiou]ese)$/i,"$1"],[/(ax|test)is$/i,"$1es"],[/(alias|[^aou]us|t[lm]as|gas|ris)$/i,"$1es"],[/(e[mn]u)s?$/i,"$1s"],[/([^l]ias|[aeiou]las|[ejzr]as|[iu]am)$/i,"$1"],[/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i,"$1i"],[/(alumn|alg|vertebr)(?:a|ae)$/i,"$1ae"],[/(seraph|cherub)(?:im)?$/i,"$1im"],[/(her|at|gr)o$/i,"$1oes"],[/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i,"$1a"],[/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i,"$1a"],[/sis$/i,"ses"],[/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i,"$1$2ves"],[/([^aeiouy]|qu)y$/i,"$1ies"],[/([^ch][ieo][ln])ey$/i,"$1ies"],[/(x|ch|ss|sh|zz)$/i,"$1es"],[/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i,"$1ices"],[/\b((?:tit)?m|l)(?:ice|ouse)$/i,"$1ice"],[/(pe)(?:rson|ople)$/i,"$1ople"],[/(child)(?:ren)?$/i,"$1ren"],[/eaux$/i,"$0"],[/m[ae]n$/i,"men"],["thou","you"]].forEach(function(m){return p.addPluralRule(m[0],m[1])}),[[/s$/i,""],[/(ss)$/i,"$1"],[/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i,"$1fe"],[/(ar|(?:wo|[ae])l|[eo][ao])ves$/i,"$1f"],[/ies$/i,"y"],[/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i,"$1ie"],[/\b(mon|smil)ies$/i,"$1ey"],[/\b((?:tit)?m|l)ice$/i,"$1ouse"],[/(seraph|cherub)im$/i,"$1"],[/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i,"$1"],[/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i,"$1sis"],[/(movie|twelve|abuse|e[mn]u)s$/i,"$1"],[/(test)(?:is|es)$/i,"$1is"],[/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i,"$1us"],[/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i,"$1um"],[/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i,"$1on"],[/(alumn|alg|vertebr)ae$/i,"$1a"],[/(cod|mur|sil|vert|ind)ices$/i,"$1ex"],[/(matr|append)ices$/i,"$1ix"],[/(pe)(rson|ople)$/i,"$1rson"],[/(child)ren$/i,"$1"],[/(eau)x?$/i,"$1"],[/men$/i,"man"]].forEach(function(m){return p.addSingularRule(m[0],m[1])}),["adulthood","advice","agenda","aid","aircraft","alcohol","ammo","analytics","anime","athletics","audio","bison","blood","bream","buffalo","butter","carp","cash","chassis","chess","clothing","cod","commerce","cooperation","corps","debris","diabetes","digestion","elk","energy","equipment","excretion","expertise","firmware","flounder","fun","gallows","garbage","graffiti","hardware","headquarters","health","herpes","highjinks","homework","housework","information","jeans","justice","kudos","labour","literature","machinery","mackerel","mail","media","mews","moose","music","mud","manga","news","only","personnel","pike","plankton","pliers","police","pollution","premises","rain","research","rice","salmon","scissors","series","sewage","shambles","shrimp","software","species","staff","swine","tennis","traffic","transportation","trout","tuna","wealth","welfare","whiting","wildebeest","wildlife","you",/pok[e\u00E9]mon$/i,/[^aeiou]ese$/i,/deer$/i,/fish$/i,/measles$/i,/o[iu]s$/i,/pox$/i,/sheep$/i].forEach(p.addUncountableRule),p})});import{parseArgs as Tm}from"util";import{Exception as na}from"@ooneex/exception";import{TerminalLogger as Rm}from"@ooneex/logger";import{container as ba}from"@ooneex/container";var Te=[];var Ft=(e)=>{let t=null;return Te.find((s)=>{return t=ba.get(s),t.getName()===e}),t};import{homedir as va}from"os";import{join as nt}from"path";import{TerminalLogger as Na}from"@ooneex/logger";import{container as xa,EContainerScope as wa}from"@ooneex/container";var x={command:(e=wa.Singleton)=>{return(t)=>{xa.add(t,e),Te.push(t)}}};var Vt=`#compdef oo ooneex
|
|
36
36
|
|
|
37
37
|
_oo_modules() {
|
|
38
38
|
local -a modules
|
|
@@ -145,7 +145,7 @@ _oo() {
|
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
_oo "$@"
|
|
148
|
-
`;var
|
|
148
|
+
`;var Yt=`#compdef oo ooneex
|
|
149
149
|
|
|
150
150
|
_ooneex_modules() {
|
|
151
151
|
local -a modules
|
|
@@ -258,9 +258,9 @@ _ooneex() {
|
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
_ooneex "$@"
|
|
261
|
-
`;class
|
|
261
|
+
`;class Re{getName(){return"completion:zsh"}getDescription(){return"Install Zsh completion for oo command"}async run(){let e=nt(va(),".zsh"),t=nt(e,"_oo");await Bun.write(t,Vt);let s=nt(e,"_ooneex");await Bun.write(s,Yt);let r=new Na;r.success(`${t} created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),r.success(`${s} created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),r.info(`Add the following to your .zshrc if not already present:
|
|
262
262
|
fpath=(~/.zsh $fpath)
|
|
263
|
-
autoload -Uz compinit && compinit`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0})}}
|
|
263
|
+
autoload -Uz compinit && compinit`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0})}}Re=b([x.command()],Re);import{join as H}from"path";import{TerminalLogger as Md}from"@ooneex/logger";import{toPascalCase as Cd}from"@ooneex/utils";var to=te(ae(),1);import{Assert as Ad,Validation as vd}from"@ooneex/validation";var Nd=1,Sd=/^[a-zA-Z][a-zA-Z0-9-]*$/;class ve extends vd{getConstraint(){return Ad(`string >= ${Nd}`)}getErrorMessage(){return"Name must start with a letter and contain only letters, numbers, and hyphens"}validate(e,t){let s=super.validate(e,t);if(!s.isValid)return s;let r=e;if(!Sd.test(r))return{isValid:!1,message:this.getErrorMessage()||"Invalid name format"};return{isValid:!0}}}var v=async(e)=>{return(await to.prompt({type:"input",name:"name",message:e.message,validate:(s)=>{let o=new ve().validate(s);if(!o.isValid)return o.message||"Controller name is invalid";return!0}})).name};var so=`import { describe, expect, test } from "bun:test";
|
|
264
264
|
import { {{NAME}}Ai } from "@/ai/{{NAME}}Ai";
|
|
265
265
|
|
|
266
266
|
describe("{{NAME}}Ai", () => {
|
|
@@ -278,7 +278,7 @@ describe("{{NAME}}Ai", () => {
|
|
|
278
278
|
expect(typeof {{NAME}}Ai.prototype.runStream).toBe("function");
|
|
279
279
|
});
|
|
280
280
|
});
|
|
281
|
-
`;var
|
|
281
|
+
`;var ro=`import { decorator, type IAiChat, OpenAi, type OpenAiConfigType } from "@ooneex/ai";
|
|
282
282
|
import { inject } from "@ooneex/container";
|
|
283
283
|
|
|
284
284
|
@decorator.ai()
|
|
@@ -296,7 +296,7 @@ export class {{NAME}}Ai implements IAiChat<OpenAiConfigType> {
|
|
|
296
296
|
yield* this.ai.runStream(prompt || "My prompt", config);
|
|
297
297
|
}
|
|
298
298
|
}
|
|
299
|
-
`;class Le{getName(){return"make:ai"}getDescription(){return"Generate a new AI class"}async run(e){let{name:t,module:s}=e;if(!t)t=await v({message:"Enter name"});t=
|
|
299
|
+
`;class Le{getName(){return"make:ai"}getDescription(){return"Generate a new AI class"}async run(e){let{name:t,module:s}=e;if(!t)t=await v({message:"Enter name"});t=Cd(t).replace(/Ai$/,"");let r=ro.replace(/{{NAME}}/g,t),o=s?H("modules",s):".",i=H(o,"src","ai"),a=H(process.cwd(),i),n=H(a,`${t}Ai.ts`);await Bun.write(n,r);let d=so.replace(/{{NAME}}/g,t),l=H(o,"tests","ai"),c=H(process.cwd(),l),u=H(c,`${t}Ai.spec.ts`);await Bun.write(u,d);let p=new Md;p.success(`${H(i,t)}Ai.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),p.success(`${H(l,t)}Ai.spec.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),await Bun.spawn(["bun","add","@ooneex/ai"],{cwd:process.cwd(),stdout:"inherit",stderr:"inherit"}).exited}}Le=b([x.command()],Le);import{join as F}from"path";import{TerminalLogger as Od}from"@ooneex/logger";import{toPascalCase as Dd}from"@ooneex/utils";var oo=`import { describe, expect, test } from "bun:test";
|
|
300
300
|
import { {{NAME}}Analytics } from "@/analytics/{{NAME}}Analytics";
|
|
301
301
|
|
|
302
302
|
describe("{{NAME}}Analytics", () => {
|
|
@@ -309,7 +309,7 @@ describe("{{NAME}}Analytics", () => {
|
|
|
309
309
|
expect(typeof {{NAME}}Analytics.prototype.capture).toBe("function");
|
|
310
310
|
});
|
|
311
311
|
});
|
|
312
|
-
`;var
|
|
312
|
+
`;var io=`import { decorator } from "@ooneex/analytics";
|
|
313
313
|
import type { IAnalytics } from "@ooneex/analytics";
|
|
314
314
|
|
|
315
315
|
type CaptureOptionsType = Record<string, unknown>;
|
|
@@ -320,7 +320,7 @@ export class {{NAME}}Analytics<T extends CaptureOptionsType = CaptureOptionsType
|
|
|
320
320
|
// console.log("Analytics captured:", options);
|
|
321
321
|
}
|
|
322
322
|
}
|
|
323
|
-
`;class Ue{getName(){return"make:analytics"}getDescription(){return"Generate a new analytics class"}async run(e){let{name:t,module:s}=e;if(!t)t=await v({message:"Enter analytics name"});t=
|
|
323
|
+
`;class Ue{getName(){return"make:analytics"}getDescription(){return"Generate a new analytics class"}async run(e){let{name:t,module:s}=e;if(!t)t=await v({message:"Enter analytics name"});t=Dd(t).replace(/Analytics$/,"");let r=io.replace(/{{NAME}}/g,t),o=s?F("modules",s):".",i=F(o,"src","analytics"),a=F(process.cwd(),i),n=F(a,`${t}Analytics.ts`);await Bun.write(n,r);let d=oo.replace(/{{NAME}}/g,t),l=F(o,"tests","analytics"),c=F(process.cwd(),l),u=F(c,`${t}Analytics.spec.ts`);await Bun.write(u,d);let p=new Od;p.success(`${F(i,t)}Analytics.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),p.success(`${F(l,t)}Analytics.spec.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),await Bun.spawn(["bun","add","@ooneex/analytics"],{cwd:process.cwd(),stdout:"inherit",stderr:"inherit"}).exited}}Ue=b([x.command()],Ue);import{join as T}from"path";import{TerminalLogger as wl}from"@ooneex/logger";import{toKebabCase as El,toSnakeCase as Al}from"@ooneex/utils";var ao=te(ae(),1);var no=async(e)=>{let t=new ve;return(await ao.prompt({type:"input",name:"destination",message:e.message,initial:e.initial||".",validate:(r)=>{let o=t.validate(r);if(!o.isValid)return o.message||"Invalid destination";return!0}})).destination};var lo=`import { RuleConfigSeverity, type UserConfig } from "@commitlint/types";
|
|
324
324
|
|
|
325
325
|
const Configuration: UserConfig = {
|
|
326
326
|
extends: ["@commitlint/config-conventional"],
|
|
@@ -460,7 +460,7 @@ const Configuration: UserConfig = {
|
|
|
460
460
|
};
|
|
461
461
|
|
|
462
462
|
export default Configuration;
|
|
463
|
-
`;var
|
|
463
|
+
`;var co=`# Logs
|
|
464
464
|
logs
|
|
465
465
|
*.log
|
|
466
466
|
npm-debug.log*
|
|
@@ -610,7 +610,7 @@ vite.config.ts.timestamp-*
|
|
|
610
610
|
|
|
611
611
|
# Application
|
|
612
612
|
var/
|
|
613
|
-
`;var
|
|
613
|
+
`;var mo=`import { inject } from "@ooneex/container";
|
|
614
614
|
import { AppEnv } from "@ooneex/app-env";
|
|
615
615
|
import { DataSource } from "typeorm";
|
|
616
616
|
import { TypeormDatabase, DatabaseException, decorator } from "@ooneex/database";
|
|
@@ -644,7 +644,7 @@ export class AppDatabase extends TypeormDatabase {
|
|
|
644
644
|
return this.source;
|
|
645
645
|
}
|
|
646
646
|
}
|
|
647
|
-
`;var
|
|
647
|
+
`;var po=`{
|
|
648
648
|
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
|
|
649
649
|
"vcs": {
|
|
650
650
|
"enabled": true,
|
|
@@ -723,7 +723,7 @@ export class AppDatabase extends TypeormDatabase {
|
|
|
723
723
|
}
|
|
724
724
|
}
|
|
725
725
|
}
|
|
726
|
-
`;var
|
|
726
|
+
`;var uo=`[test]
|
|
727
727
|
coverage = true
|
|
728
728
|
|
|
729
729
|
[workspace]
|
|
@@ -754,7 +754,7 @@ buildDependencies = [
|
|
|
754
754
|
"@swc/core",
|
|
755
755
|
"nx",
|
|
756
756
|
]
|
|
757
|
-
`;var
|
|
757
|
+
`;var ho=`# use the official Bun image
|
|
758
758
|
# see all versions at https://hub.docker.com/r/oven/bun/tags
|
|
759
759
|
FROM oven/bun:1 AS base
|
|
760
760
|
WORKDIR /{{NAME}}
|
|
@@ -801,7 +801,7 @@ COPY --from=prerelease /{{NAME}}/dist .
|
|
|
801
801
|
USER bun
|
|
802
802
|
EXPOSE 3000/tcp
|
|
803
803
|
ENTRYPOINT [ "bun", "run", "index.js" ]
|
|
804
|
-
`;var
|
|
804
|
+
`;var fo=`services:
|
|
805
805
|
# PostgreSQL - Primary relational database
|
|
806
806
|
# Docs: https://www.postgresql.org/docs/
|
|
807
807
|
# Connection: postgresql://ooneex:ooneex@localhost:5432/ooneex
|
|
@@ -835,7 +835,7 @@ ENTRYPOINT [ "bun", "run", "index.js" ]
|
|
|
835
835
|
volumes:
|
|
836
836
|
{{NAME}}_db_data:
|
|
837
837
|
{{NAME}}_redis_data:
|
|
838
|
-
`;var
|
|
838
|
+
`;var Ot=`# =============================================================================
|
|
839
839
|
# App
|
|
840
840
|
# =============================================================================
|
|
841
841
|
|
|
@@ -1036,7 +1036,7 @@ SYSTEM_USERS=
|
|
|
1036
1036
|
SUPER_ADMIN_USERS=
|
|
1037
1037
|
# Comma-separated admin user emails
|
|
1038
1038
|
ADMIN_USERS=
|
|
1039
|
-
`;var
|
|
1039
|
+
`;var yo=`import { PostHogAnalytics } from "@ooneex/analytics";
|
|
1040
1040
|
import { App } from "@ooneex/app";
|
|
1041
1041
|
import { RedisCache } from "@ooneex/cache";
|
|
1042
1042
|
import { LogtailLogger, ExceptionLogger, TerminalLogger } from "@ooneex/logger";
|
|
@@ -1049,7 +1049,7 @@ import { AppDatabase } from "./databases/AppDatabase";
|
|
|
1049
1049
|
|
|
1050
1050
|
const app = new App({
|
|
1051
1051
|
prefix: "api",
|
|
1052
|
-
|
|
1052
|
+
healthcheckPath: "/api/v1/healthcheck",
|
|
1053
1053
|
loggers: [LogtailLogger, TerminalLogger],
|
|
1054
1054
|
onException: ExceptionLogger,
|
|
1055
1055
|
analytics: PostHogAnalytics,
|
|
@@ -1065,7 +1065,7 @@ const app = new App({
|
|
|
1065
1065
|
});
|
|
1066
1066
|
|
|
1067
1067
|
await app.run();
|
|
1068
|
-
`;var
|
|
1068
|
+
`;var go=`{
|
|
1069
1069
|
"$schema": "./node_modules/nx/schemas/nx-schema.json",
|
|
1070
1070
|
"targetDefaults": {
|
|
1071
1071
|
"build": {
|
|
@@ -1095,7 +1095,7 @@ await app.run();
|
|
|
1095
1095
|
],
|
|
1096
1096
|
"packageManager": "bun"
|
|
1097
1097
|
}
|
|
1098
|
-
`;var
|
|
1098
|
+
`;var bo=`{
|
|
1099
1099
|
"name": "{{NAME}}",
|
|
1100
1100
|
"scripts": {
|
|
1101
1101
|
"dev": "bun run --filter app dev",
|
|
@@ -1112,54 +1112,6 @@ await app.run();
|
|
|
1112
1112
|
"workspaces": [
|
|
1113
1113
|
"modules/*"
|
|
1114
1114
|
],
|
|
1115
|
-
"dependencies": {
|
|
1116
|
-
"@ooneex/analytics": "^1.1.0",
|
|
1117
|
-
"@ooneex/app": "^1.2.0",
|
|
1118
|
-
"@ooneex/app-env": "^1.1.0",
|
|
1119
|
-
"@ooneex/auth": "^1.2.0",
|
|
1120
|
-
"@ooneex/cache": "^1.1.0",
|
|
1121
|
-
"@ooneex/container": "^1.1.0",
|
|
1122
|
-
"@ooneex/database": "^1.1.0",
|
|
1123
|
-
"@ooneex/logger": "^1.2.0",
|
|
1124
|
-
"@ooneex/mailer": "^1.1.0",
|
|
1125
|
-
"@ooneex/middleware": "^1.2.0",
|
|
1126
|
-
"@ooneex/module": "^1.2.0",
|
|
1127
|
-
"@ooneex/rate-limit": "^1.1.0",
|
|
1128
|
-
"@ooneex/role": "^1.1.0",
|
|
1129
|
-
"@ooneex/routing": "^1.2.0",
|
|
1130
|
-
"@ooneex/storage": "^1.1.0",
|
|
1131
|
-
"@ooneex/translation": "^1.1.0",
|
|
1132
|
-
"@ooneex/types": "^1.1.0",
|
|
1133
|
-
"@ooneex/utils": "^0.2.1",
|
|
1134
|
-
"@ooneex/validation": "^1.1.0",
|
|
1135
|
-
"@ooneex/controller": "^1.3.0",
|
|
1136
|
-
"pg": "^8.16.3",
|
|
1137
|
-
"apache-arrow": "^21.1.0",
|
|
1138
|
-
"reflect-metadata": "^0.2.2",
|
|
1139
|
-
"typeorm": "^0.3.28"
|
|
1140
|
-
},
|
|
1141
|
-
"devDependencies": {
|
|
1142
|
-
"@biomejs/biome": "2.3.7",
|
|
1143
|
-
"@commitlint/cli": "^20.3.1",
|
|
1144
|
-
"@commitlint/config-conventional": "^20.3.1",
|
|
1145
|
-
"@commitlint/prompt-cli": "^20.3.1",
|
|
1146
|
-
"@commitlint/types": "^20.3.1",
|
|
1147
|
-
"@nx/js": "^22.3.3",
|
|
1148
|
-
"@nx/workspace": "^22.3.3",
|
|
1149
|
-
"@ooneex/migrations": "^1.2.0",
|
|
1150
|
-
"@ooneex/seeds": "^1.2.0",
|
|
1151
|
-
"@swc-node/register": "^1.11.1",
|
|
1152
|
-
"@swc/core": "^1.15.8",
|
|
1153
|
-
"@swc/helpers": "~0.5.18",
|
|
1154
|
-
"@types/bun": "latest",
|
|
1155
|
-
"@types/node": "^25.5.0",
|
|
1156
|
-
"@typescript/native-preview": "^7.0.0-dev.20260113.1",
|
|
1157
|
-
"husky": "^9.1.7",
|
|
1158
|
-
"lint-staged": "^16.2.7",
|
|
1159
|
-
"nx": "22.0.2",
|
|
1160
|
-
"typescript": "^6.0.2",
|
|
1161
|
-
"undici-types": "^7.18.2"
|
|
1162
|
-
},
|
|
1163
1115
|
"lint-staged": {
|
|
1164
1116
|
"*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}": [
|
|
1165
1117
|
"biome check --files-ignore-unknown=true",
|
|
@@ -1167,7 +1119,7 @@ await app.run();
|
|
|
1167
1119
|
]
|
|
1168
1120
|
}
|
|
1169
1121
|
}
|
|
1170
|
-
`;var
|
|
1122
|
+
`;var xo=`# {{NAME}}
|
|
1171
1123
|
|
|
1172
1124
|
A modular, enterprise-grade backend framework built with TypeScript and Bun, powered by the **@ooneex** ecosystem.
|
|
1173
1125
|
|
|
@@ -1229,7 +1181,6 @@ Each module under \`modules/\` follows a consistent structure and registers its
|
|
|
1229
1181
|
@decorator.module({
|
|
1230
1182
|
controllers: [], // HTTP / WebSocket route handlers
|
|
1231
1183
|
entities: [], // TypeORM database entities
|
|
1232
|
-
permissions: [], // Role-based access control
|
|
1233
1184
|
middlewares: [], // HTTP middleware pipeline
|
|
1234
1185
|
cronJobs: [], // Scheduled tasks
|
|
1235
1186
|
events: [], // Pub/Sub event handlers
|
|
@@ -1324,7 +1275,7 @@ This creates \`.claude/skills/\` in your project with skill guides for each \`ma
|
|
|
1324
1275
|
## License
|
|
1325
1276
|
|
|
1326
1277
|
Proprietary - All rights reserved.
|
|
1327
|
-
`;var
|
|
1278
|
+
`;var wo=`{
|
|
1328
1279
|
"compilerOptions": {
|
|
1329
1280
|
"jsx": "react-jsx",
|
|
1330
1281
|
"lib": ["ES2022", "DOM"],
|
|
@@ -1349,11 +1300,113 @@ Proprietary - All rights reserved.
|
|
|
1349
1300
|
"emitDecoratorMetadata": true,
|
|
1350
1301
|
"experimentalDecorators": true,
|
|
1351
1302
|
"strictNullChecks": true,
|
|
1352
|
-
"exactOptionalPropertyTypes":
|
|
1303
|
+
"exactOptionalPropertyTypes": false
|
|
1353
1304
|
},
|
|
1354
1305
|
"exclude": ["node_modules", ".github", ".husky", ".nx", ".zed", ".vscode"]
|
|
1355
1306
|
}
|
|
1356
|
-
`;
|
|
1307
|
+
`;var Eo=`{
|
|
1308
|
+
"formatter": "language_server",
|
|
1309
|
+
"format_on_save": "on",
|
|
1310
|
+
"languages": {
|
|
1311
|
+
"JavaScript": {
|
|
1312
|
+
"formatter": {
|
|
1313
|
+
"language_server": {
|
|
1314
|
+
"name": "biome"
|
|
1315
|
+
}
|
|
1316
|
+
},
|
|
1317
|
+
"code_actions_on_format": {
|
|
1318
|
+
"source.fixAll.biome": true,
|
|
1319
|
+
"source.organizeImports.biome": true
|
|
1320
|
+
}
|
|
1321
|
+
},
|
|
1322
|
+
"TypeScript": {
|
|
1323
|
+
"formatter": {
|
|
1324
|
+
"language_server": {
|
|
1325
|
+
"name": "biome"
|
|
1326
|
+
}
|
|
1327
|
+
},
|
|
1328
|
+
"code_actions_on_format": {
|
|
1329
|
+
"source.fixAll.biome": true,
|
|
1330
|
+
"source.organizeImports.biome": true
|
|
1331
|
+
}
|
|
1332
|
+
},
|
|
1333
|
+
"TSX": {
|
|
1334
|
+
"formatter": {
|
|
1335
|
+
"language_server": {
|
|
1336
|
+
"name": "biome"
|
|
1337
|
+
}
|
|
1338
|
+
},
|
|
1339
|
+
"code_actions_on_format": {
|
|
1340
|
+
"source.fixAll.biome": true,
|
|
1341
|
+
"source.organizeImports.biome": true
|
|
1342
|
+
}
|
|
1343
|
+
},
|
|
1344
|
+
"JSON": {
|
|
1345
|
+
"formatter": {
|
|
1346
|
+
"language_server": {
|
|
1347
|
+
"name": "biome"
|
|
1348
|
+
}
|
|
1349
|
+
},
|
|
1350
|
+
"code_actions_on_format": {
|
|
1351
|
+
"source.fixAll.biome": true
|
|
1352
|
+
}
|
|
1353
|
+
},
|
|
1354
|
+
"JSONC": {
|
|
1355
|
+
"formatter": {
|
|
1356
|
+
"language_server": {
|
|
1357
|
+
"name": "biome"
|
|
1358
|
+
}
|
|
1359
|
+
},
|
|
1360
|
+
"code_actions_on_format": {
|
|
1361
|
+
"source.fixAll.biome": true
|
|
1362
|
+
}
|
|
1363
|
+
},
|
|
1364
|
+
"Astro": {
|
|
1365
|
+
"formatter": {
|
|
1366
|
+
"language_server": {
|
|
1367
|
+
"name": "biome"
|
|
1368
|
+
}
|
|
1369
|
+
},
|
|
1370
|
+
"code_actions_on_format": {
|
|
1371
|
+
"source.fixAll.biome": true,
|
|
1372
|
+
"source.organizeImports.biome": true
|
|
1373
|
+
}
|
|
1374
|
+
},
|
|
1375
|
+
"Svelte": {
|
|
1376
|
+
"formatter": {
|
|
1377
|
+
"language_server": {
|
|
1378
|
+
"name": "biome"
|
|
1379
|
+
}
|
|
1380
|
+
},
|
|
1381
|
+
"code_actions_on_format": {
|
|
1382
|
+
"source.fixAll.biome": true,
|
|
1383
|
+
"source.organizeImports.biome": true
|
|
1384
|
+
}
|
|
1385
|
+
},
|
|
1386
|
+
"CSS": {
|
|
1387
|
+
"formatter": {
|
|
1388
|
+
"language_server": {
|
|
1389
|
+
"name": "biome"
|
|
1390
|
+
}
|
|
1391
|
+
},
|
|
1392
|
+
"code_actions_on_format": {
|
|
1393
|
+
"source.fixAll.biome": true
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
},
|
|
1397
|
+
"lsp": {
|
|
1398
|
+
"typescript-language-server": {
|
|
1399
|
+
"settings": {
|
|
1400
|
+
"typescript": {
|
|
1401
|
+
"preferences": {
|
|
1402
|
+
"includePackageJsonAutoImports": "on"
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
`;import{basename as ll,join as O}from"path";import{TerminalLogger as cl}from"@ooneex/logger";import{toKebabCase as ml,toPascalCase as Ge,trim as pl}from"@ooneex/utils";var Ao=te(ae(),1),fe=async(e)=>{return(await Ao.prompt({type:"confirm",name:"confirm",message:e.message})).confirm};var Ne=["GET","POST","PUT","DELETE","PATCH","OPTIONS","HEAD"];var vo=te(ae(),1);import{Assert as zd,Validation as Zd}from"@ooneex/validation";class Dt extends Zd{getConstraint(){return zd("string >= 3")}getErrorMessage(){return`Route method must be one of: ${Ne.join(", ")}`}validate(e,t){let s=super.validate(e,t);if(!s.isValid)return s;let r=e;if(r.trim()!==r)return{isValid:!1,message:this.getErrorMessage()||"Invalid route method format"};let o=r.toUpperCase();if(!Ne.includes(o))return{isValid:!1,message:this.getErrorMessage()||"Invalid route method"};return{isValid:!0}}}var No=async(e)=>{return(await vo.prompt({type:"select",name:"method",message:e.message,initial:e.initial??0,choices:Ne.map((s)=>s),validate:(s)=>{let o=new Dt().validate(s);if(!o.isValid)return o.message||"Route method is invalid";return!0}})).method};var So=te(ae(),1);import{Assert as Qd,Validation as Xd}from"@ooneex/validation";var Jd=/^[a-zA-Z0-9]+\.[a-zA-Z0-9]+\.[a-zA-Z0-9]+$/;class Bt extends Xd{getConstraint(){return Qd("string >= 7")}getErrorMessage(){return"Route name must follow format: namespace.resource.action (e.g., 'api.users.list')"}validate(e,t){let s=super.validate(e,t);if(!s.isValid)return s;let r=e;if(r.trim()!==r)return{isValid:!1,message:this.getErrorMessage()||"Invalid route name format"};if(!Jd.test(r))return{isValid:!1,message:this.getErrorMessage()||"Invalid route name format"};let o=r.split(".");if(o.length!==3)return{isValid:!1,message:this.getErrorMessage()||"Invalid route name format"};let[i,a,n]=o;if(!i||!a||!n)return{isValid:!1,message:this.getErrorMessage()||"Invalid route name format"};return{isValid:!0}}}var To=async(e)=>{return(await So.prompt({type:"input",name:"routeName",message:e.message,validate:(s)=>{let o=new Bt().validate(s);if(!o.isValid)return o.message||"Route name is invalid";return!0}})).routeName};var Ro=te(ae(),1);import{Assert as jd,Validation as el}from"@ooneex/validation";var tl=1,sl=/^\/[\w\-/:]*$/,rl=/^[a-zA-Z0-9\-_]+$/,ol=/^:[a-zA-Z][a-zA-Z0-9]*$/;class Pt extends el{getConstraint(){return jd(`string >= ${tl}`)}getErrorMessage(){return"Route path must start with '/' and contain only valid segments (e.g., '/users', '/api/users/:id')"}validate(e,t){let s=super.validate(e,t);if(!s.isValid)return s;let r=e;if(r.trim()!==r)return{isValid:!1,message:this.getErrorMessage()||"Invalid route path format"};if(!r.startsWith("/"))return{isValid:!1,message:"Route path must start with '/'"};if(r.length>1&&r.endsWith("/"))return{isValid:!1,message:"Route path cannot end with '/' (except for root path)"};if(!sl.test(r))return{isValid:!1,message:this.getErrorMessage()||"Invalid route path format"};if(r==="/")return{isValid:!0};let o=r.slice(1).split("/");for(let i of o){if(!i)return{isValid:!1,message:"Route path cannot contain empty segments (double slashes)"};if(i.startsWith(":")){if(!ol.test(i))return{isValid:!1,message:`Invalid parameter segment '${i}'. Parameters must follow format ':paramName' with alphanumeric characters only`}}else if(!rl.test(i))return{isValid:!1,message:`Invalid path segment '${i}'. Segments must contain only letters, numbers, hyphens, and underscores`}}return{isValid:!0}}}var Mo=async(e)=>{return(await Ro.prompt({type:"input",name:"path",message:e.message,initial:e.initial??"/",validate:(s)=>{let o=new Pt().validate(s);if(!o.isValid)return o.message||"Route path is invalid";return!0}})).path};var Co=`import type { ContextType } from "@ooneex/socket";
|
|
1357
1410
|
import { ERole } from "@ooneex/role";
|
|
1358
1411
|
import { Route } from "@ooneex/routing";
|
|
1359
1412
|
import { Assert } from "@ooneex/validation";
|
|
@@ -1386,7 +1439,7 @@ export class {{NAME}}Controller {
|
|
|
1386
1439
|
});
|
|
1387
1440
|
}
|
|
1388
1441
|
}
|
|
1389
|
-
`;var
|
|
1442
|
+
`;var _o=`import { describe, expect, test } from "bun:test";
|
|
1390
1443
|
import { {{NAME}}Controller } from "@/controllers/{{NAME}}Controller";
|
|
1391
1444
|
|
|
1392
1445
|
describe("{{NAME}}Controller", () => {
|
|
@@ -1399,11 +1452,11 @@ describe("{{NAME}}Controller", () => {
|
|
|
1399
1452
|
expect(typeof {{NAME}}Controller.prototype.index).toBe("function");
|
|
1400
1453
|
});
|
|
1401
1454
|
});
|
|
1402
|
-
`;var
|
|
1455
|
+
`;var Io=`import type { ContextType } from "@ooneex/controller";
|
|
1403
1456
|
import { ERole } from "@ooneex/role";
|
|
1404
1457
|
import { Route } from "@ooneex/routing";
|
|
1405
1458
|
import { Assert } from "@ooneex/validation";
|
|
1406
|
-
import type { {{TYPE_NAME}}RouteType } from "
|
|
1459
|
+
import type { {{TYPE_NAME}}RouteType } from "@/types/routes/{{TYPE_NAME_FILE}}";
|
|
1407
1460
|
|
|
1408
1461
|
@Route.{{ROUTE_METHOD}}("{{ROUTE_PATH}}", {
|
|
1409
1462
|
name: "{{ROUTE_NAME}}",
|
|
@@ -1432,7 +1485,7 @@ export class {{NAME}}Controller {
|
|
|
1432
1485
|
});
|
|
1433
1486
|
}
|
|
1434
1487
|
}
|
|
1435
|
-
`;var
|
|
1488
|
+
`;var Oo=`export type {{TYPE_NAME}}RouteType = {
|
|
1436
1489
|
params: {
|
|
1437
1490
|
|
|
1438
1491
|
},
|
|
@@ -1446,19 +1499,18 @@ export class {{NAME}}Controller {
|
|
|
1446
1499
|
|
|
1447
1500
|
},
|
|
1448
1501
|
};
|
|
1449
|
-
`;class
|
|
1450
|
-
`,
|
|
1451
|
-
`,
|
|
1502
|
+
`;class ye{getName(){return"make:controller"}getDescription(){return"Generate a new controller class"}async addToModule(e,t){let s=await Bun.file(e).text(),r=`${t}Controller`,o=`import { ${r} } from "./controllers/${r}";
|
|
1503
|
+
`,i=s.lastIndexOf("import "),a=s.indexOf(`
|
|
1504
|
+
`,i);s=`${s.slice(0,a+1)}${o}${s.slice(a+1)}`;let n=/(controllers:\s*\[)([^\]]*)/s,d=s.match(n);if(d){let l=d[2]?.trim(),c=l?`${l}, ${r}`:r;s=s.replace(n,`$1${c}`)}await Bun.write(e,s)}async run(e){let{name:t,module:s,isSocket:r}=e;if(!t)t=await v({message:"Enter controller name"});if(r===void 0)r=await fe({message:"Is this a socket controller?"});t=Ge(t).replace(/Controller$/,"");let{route:o={}}=e,a=(r?Co:Io).replaceAll("{{NAME}}",t),n="",d="";if(!o.name)o.name=await To({message:"Enter route name (e.g., api.user.create)"});if(n=Ge(o.name),d=o.name,a=a.replaceAll("{{ROUTE_NAME}}",o.name).replaceAll("{{TYPE_NAME}}",n).replaceAll("{{TYPE_NAME_FILE}}",d),!o.path)o.path=await Mo({message:"Enter route path",initial:"/"});let l=`/${ml(pl(o.path,"/"))}`;if(a=a.replaceAll("{{ROUTE_PATH}}",l),!r&&!o.method)o.method=await No({message:"Enter route method"});if(!r&&o.method)a=a.replaceAll("{{ROUTE_METHOD}}",o.method.toLowerCase());let c=s?O("modules",s):".",u=O(c,"src","controllers"),p=O(process.cwd(),u),m=O(p,`${t}Controller.ts`);await Bun.write(m,a);let h=O(c,"src","types","routes"),f=O(process.cwd(),h),g=O(f,`${d}.ts`),y=Oo.replaceAll("{{TYPE_NAME}}",n);await Bun.write(g,y);let E=_o.replace(/{{NAME}}/g,t),A=O(c,"tests","controllers"),N=O(process.cwd(),A),R=O(N,`${t}Controller.spec.ts`);await Bun.write(R,E);let _=s?Ge(s):Ge(ll(process.cwd())),Se=O(process.cwd(),c,"src",`${_}Module.ts`);if(await Bun.file(Se).exists())await this.addToModule(Se,t);let ee=new cl;ee.success(`${O(u,t)}Controller.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),ee.success(`${O(h,d)}.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),ee.success(`${O(A,t)}Controller.spec.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),await Bun.spawn(["bun","add","@ooneex/controller"],{cwd:process.cwd(),stdout:"inherit",stderr:"inherit"}).exited}}ye=b([x.command()],ye);import{join as P}from"path";import{TerminalLogger as gl}from"@ooneex/logger";import{toKebabCase as bl,toPascalCase as xl}from"@ooneex/utils";var Do=`import type { ModuleType } from "@ooneex/module";
|
|
1452
1505
|
|
|
1453
1506
|
export const {{NAME}}Module: ModuleType = {
|
|
1454
1507
|
controllers: [],
|
|
1455
1508
|
entities: [],
|
|
1456
|
-
permissions: [],
|
|
1457
1509
|
middlewares: [],
|
|
1458
1510
|
cronJobs: [],
|
|
1459
1511
|
events: [],
|
|
1460
1512
|
};
|
|
1461
|
-
`;var
|
|
1513
|
+
`;var Bo=`{
|
|
1462
1514
|
"name": "@module/{{NAME}}",
|
|
1463
1515
|
"description": "",
|
|
1464
1516
|
"version": "0.0.1",
|
|
@@ -1467,7 +1519,7 @@ export const {{NAME}}Module: ModuleType = {
|
|
|
1467
1519
|
"lint": "tsgo --noEmit && bunx biome lint"
|
|
1468
1520
|
}
|
|
1469
1521
|
}
|
|
1470
|
-
`;var
|
|
1522
|
+
`;var Po=`import { describe, expect, test } from "bun:test";
|
|
1471
1523
|
import { {{NAME}}Module } from "@/{{NAME}}Module";
|
|
1472
1524
|
|
|
1473
1525
|
describe("{{NAME}}Module", () => {
|
|
@@ -1479,8 +1531,8 @@ describe("{{NAME}}Module", () => {
|
|
|
1479
1531
|
expect(Array.isArray({{NAME}}Module.entities)).toBe(true);
|
|
1480
1532
|
});
|
|
1481
1533
|
|
|
1482
|
-
test("should have
|
|
1483
|
-
expect(Array.isArray({{NAME}}Module.
|
|
1534
|
+
test("should have middlewares array", () => {
|
|
1535
|
+
expect(Array.isArray({{NAME}}Module.middlewares)).toBe(true);
|
|
1484
1536
|
});
|
|
1485
1537
|
|
|
1486
1538
|
test("should have cronJobs array", () => {
|
|
@@ -1491,7 +1543,7 @@ describe("{{NAME}}Module", () => {
|
|
|
1491
1543
|
expect(Array.isArray({{NAME}}Module.events)).toBe(true);
|
|
1492
1544
|
});
|
|
1493
1545
|
});
|
|
1494
|
-
`;var
|
|
1546
|
+
`;var Lo=`{
|
|
1495
1547
|
"extends": "../../tsconfig.json",
|
|
1496
1548
|
"compilerOptions": {
|
|
1497
1549
|
"types": ["@types/bun"],
|
|
@@ -1502,13 +1554,13 @@ describe("{{NAME}}Module", () => {
|
|
|
1502
1554
|
"include": ["src/**/*.ts", "src/**/*.tsx", "tests/**/*.ts", "tests/**/*.tsx"],
|
|
1503
1555
|
"exclude": ["node_modules", "dist"]
|
|
1504
1556
|
}
|
|
1505
|
-
`;class
|
|
1506
|
-
`,n=
|
|
1507
|
-
`,n);
|
|
1508
|
-
${
|
|
1509
|
-
${
|
|
1510
|
-
$3`),await Bun.write(e,s)}}}async addPathAlias(e,t){let s=await Bun.file(e).text(),
|
|
1511
|
-
`)}async run(e){let{cwd:t=process.cwd(),silent:s=!1,skipMigrations:
|
|
1557
|
+
`;class ge{getName(){return"make:module"}getDescription(){return"Generate a new module"}async addToAppModule(e,t,s){let r=await Bun.file(e).text(),o=`${t}Module`,i=`@${s}/${o}`,a=`import { ${o} } from "${i}";
|
|
1558
|
+
`,n=r.lastIndexOf("import "),d=r.indexOf(`
|
|
1559
|
+
`,n);r=`${r.slice(0,d+1)}${a}${r.slice(d+1)}`;let l=["controllers","entities","middlewares","cronJobs","events"];for(let c of l){let u=new RegExp(`(${c}:\\s*\\[)([^\\]]*)`,"s"),p=r.match(u);if(p){let m=p[2]?.trim(),h=`...${o}.${c}`,f=m?`${m}, ${h}`:h;r=r.replace(u,`$1${f}`)}}await Bun.write(e,r)}async addModuleScope(e,t){let s=await Bun.file(e).text(),r=/("scope-enum":\s*\[\s*RuleConfigSeverity\.Error,\s*"always",\s*\[)([\s\S]*?)(\])/,o=s.match(r);if(o){let i=o[2]?.trim()??"",a=`"${t}"`;if(!i.includes(a)){let n=i?`${i}
|
|
1560
|
+
${a},`:`
|
|
1561
|
+
${a},`;s=s.replace(r,`$1${n}
|
|
1562
|
+
$3`),await Bun.write(e,s)}}}async addPathAlias(e,t){let s=await Bun.file(e).text(),r=JSON.parse(s);r.compilerOptions??={},r.compilerOptions.paths??={},r.compilerOptions.paths[`@${t}/*`]=[`../${t}/src/*`],await Bun.write(e,`${JSON.stringify(r,null,2)}
|
|
1563
|
+
`)}async run(e){let{cwd:t=process.cwd(),silent:s=!1,skipMigrations:r=!1,skipSeeds:o=!1}=e,{name:i}=e;if(!i)i=await v({message:"Enter module name"});let a=xl(i).replace(/Module$/,""),n=bl(a),d=P(t,"modules",n),l=P(d,"src"),c=P(d,"tests"),u=Do.replace(/{{NAME}}/g,a),p=Bo.replace(/{{NAME}}/g,n),m=Po.replace(/{{NAME}}/g,a);if(await Bun.write(P(l,`${a}Module.ts`),u),!r)await Bun.write(P(l,"migrations","migrations.ts"),"");if(!o)await Bun.write(P(l,"seeds","seeds.ts"),"");if(await Bun.write(P(d,"package.json"),p),await Bun.write(P(d,"tsconfig.json"),Lo),await Bun.write(P(c,`${a}Module.spec.ts`),m),n!=="app"){let g=P(t,"modules","app","src","AppModule.ts");if(await Bun.file(g).exists())await this.addToAppModule(g,a,n);let y=P(t,"modules","app","tsconfig.json");if(await Bun.file(y).exists())await this.addPathAlias(y,n)}let h=P(t,".commitlintrc.ts");if(await Bun.file(h).exists())await this.addModuleScope(h,n);if(!s)new gl().success(`modules/${n} created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0});await Bun.spawn(["bun","add","@ooneex/module"],{cwd:process.cwd(),stdout:"inherit",stderr:"inherit"}).exited}}ge=b([x.command()],ge);class ke{getName(){return"make:app"}getDescription(){return"Generate a new application"}async run(e){let{name:t,destination:s}=e;if(!t)t=await v({message:"Enter application name"});let r=El(t);if(!s)s=await no({message:"Enter destination path",initial:r});let o=bo.replace(/{{NAME}}/g,r);await Bun.write(T(s,".commitlintrc.ts"),lo),await Bun.write(T(s,".gitignore"),co),await Bun.write(T(s,"biome.jsonc"),po),await Bun.write(T(s,"bunfig.toml"),uo),await Bun.write(T(s,"nx.json"),go),await Bun.write(T(s,"package.json"),o),await Bun.write(T(s,"README.md"),xo.replace(/{{NAME}}/g,r)),await Bun.write(T(s,"tsconfig.json"),wo),await Bun.write(T(s,".zed","settings.json"),Eo),await Bun.write(T(s,".husky","commit-msg"),'bunx commitlint --edit "$1"'),await Bun.write(T(s,".husky","pre-commit"),"lint-staged"),await new ge().run({name:"app",cwd:s,silent:!0,skipMigrations:!0,skipSeeds:!0});let a=T(s,"modules","app","package.json"),n=await Bun.file(a).json();n.scripts.dev="docker compose up -d && bun --hot run ./src/index.ts",n.scripts.build="bun build ./src/index.ts --outdir ./dist --target bun",await Bun.write(a,JSON.stringify(n,null,2));let d=Ot.replace(/^DATABASE_URL=/m,'DATABASE_URL="postgresql://ooneex:ooneex@localhost:5432/ooneex"').replace(/^CACHE_REDIS_URL=/m,'CACHE_REDIS_URL="redis://localhost:6379"').replace(/^PUBSUB_REDIS_URL=/m,'PUBSUB_REDIS_URL="redis://localhost:6379"').replace(/^RATE_LIMIT_REDIS_URL=/m,'RATE_LIMIT_REDIS_URL="redis://localhost:6379"').replace(/^DATABASE_REDIS_URL=/m,'DATABASE_REDIS_URL="redis://localhost:6379"');await Bun.write(T(s,"modules","app",".env"),d),await Bun.write(T(s,"modules","app",".env.example"),Ot),await Bun.write(T(s,"modules","app","src","databases","AppDatabase.ts"),mo),await Bun.write(T(s,"modules","app","src","index.ts"),yo);let l=Al(t),c=fo.replace(/{{NAME}}/g,l);await Bun.write(T(s,"modules","app","docker-compose.yml"),c);let u=ho.replace(/{{NAME}}/g,l);await Bun.write(T(s,"modules","app","Dockerfile"),u),await Bun.write(T(s,"modules","app","var",".gitkeep"),""),await new ye().run({name:"HealthCheck",isSocket:!1,module:"app",route:{name:"api.health.check",path:"/healthcheck",method:"GET"}}),await Bun.spawn(["git","init"],{cwd:s,stdout:"inherit",stderr:"inherit"}).exited,await Bun.spawn(["bun","add","@ooneex/analytics","@ooneex/app","@ooneex/app-env","@ooneex/auth","@ooneex/cache","@ooneex/container","@ooneex/database","@ooneex/logger","@ooneex/mailer","@ooneex/middleware","@ooneex/module","@ooneex/rate-limit","@ooneex/role","@ooneex/routing","@ooneex/storage","@ooneex/translation","@ooneex/types","@ooneex/user","@ooneex/utils","@ooneex/validation","@ooneex/controller","pg","apache-arrow","reflect-metadata","typeorm"],{cwd:s,stdout:"inherit",stderr:"inherit"}).exited,await Bun.spawn(["bun","add","-D","@biomejs/biome","@commitlint/cli","@commitlint/config-conventional","@commitlint/prompt-cli","@commitlint/types","@nx/js","@nx/workspace","@swc-node/register","@swc/core","@swc/helpers","@types/bun","@types/node","@typescript/native-preview","husky","lint-staged","nx","typescript","undici-types"],{cwd:s,stdout:"inherit",stderr:"inherit"}).exited,new wl().success(`${r} created successfully at ${s}`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0})}}ke=b([x.command()],ke);import{join as V}from"path";import{TerminalLogger as Sl}from"@ooneex/logger";import{toPascalCase as Tl}from"@ooneex/utils";var Uo=`import { describe, expect, test } from "bun:test";
|
|
1512
1564
|
import { {{NAME}}Cache } from "@/cache/{{NAME}}Cache";
|
|
1513
1565
|
|
|
1514
1566
|
describe("{{NAME}}Cache", () => {
|
|
@@ -1536,7 +1588,7 @@ describe("{{NAME}}Cache", () => {
|
|
|
1536
1588
|
expect(typeof {{NAME}}Cache.prototype.has).toBe("function");
|
|
1537
1589
|
});
|
|
1538
1590
|
});
|
|
1539
|
-
`;var
|
|
1591
|
+
`;var Go=`import { CacheException, decorator } from "@ooneex/cache";
|
|
1540
1592
|
import type { ICache } from "@ooneex/cache";
|
|
1541
1593
|
|
|
1542
1594
|
@decorator.cache()
|
|
@@ -1557,7 +1609,7 @@ export class {{NAME}}Cache implements ICache {
|
|
|
1557
1609
|
throw new CacheException(\`Failed to check if key "\${key}" exists: Not implemented\`);
|
|
1558
1610
|
}
|
|
1559
1611
|
}
|
|
1560
|
-
`;class
|
|
1612
|
+
`;class $e{getName(){return"make:cache"}getDescription(){return"Generate a new cache class"}async run(e){let{name:t,module:s}=e;if(!t)t=await v({message:"Enter cache name"});t=Tl(t).replace(/Cache$/,"");let r=Go.replace(/{{NAME}}/g,t),o=s?V("modules",s):".",i=V(o,"src","cache"),a=V(process.cwd(),i),n=V(a,`${t}Cache.ts`);await Bun.write(n,r);let d=Uo.replace(/{{NAME}}/g,t),l=V(o,"tests","cache"),c=V(process.cwd(),l),u=V(c,`${t}Cache.spec.ts`);await Bun.write(u,d);let p=new Sl;p.success(`${V(i,t)}Cache.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),p.success(`${V(l,t)}Cache.spec.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),await Bun.spawn(["bun","add","@ooneex/cache"],{cwd:process.cwd(),stdout:"inherit",stderr:"inherit"}).exited}}$e=b([x.command()],$e);import{join as We}from"path";import{TerminalLogger as Yl}from"@ooneex/logger";var ko=`---
|
|
1561
1613
|
name: commit
|
|
1562
1614
|
description: Create commit messages grouped by module. Analyzes git changes, groups files under modules/ by module name, and creates separate commits following commitlint conventions. Uses common scope for non-module changes.
|
|
1563
1615
|
---
|
|
@@ -1749,7 +1801,7 @@ Use \`refactor\` for file reorganization:
|
|
|
1749
1801
|
git add modules/product/
|
|
1750
1802
|
git commit -m "refactor(product): Reorganize service file structure"
|
|
1751
1803
|
\`\`\`
|
|
1752
|
-
`;var Or="---\nname: make:ai\ndescription: Generate a new AI class with its test file, then complete the generated code. Use when creating a new AI chat class that uses OpenAI via the @ooneex/ai package.\n---\n\n# Make AI Class\n\nGenerate a new AI class and its test file using the `make:ai` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the AI class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:ai --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/ai/<Name>Ai.ts` - The AI class file (or `modules/<module>/src/ai/<Name>Ai.ts` with `--module`)\n- `tests/ai/<Name>Ai.spec.ts` - The test file (or `modules/<module>/tests/ai/<Name>Ai.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the AI class\n\nEdit `src/ai/<Name>Ai.ts` to complete the implementation:\n\n- Update the prompt in the `run` method from `\"My prompt\"` to a meaningful prompt based on the class purpose\n- Update the prompt in the `runStream` method from `\"My prompt\"` to a meaningful prompt based on the class purpose\n- Add any additional configuration or methods relevant to the AI class purpose\n- Ensure proper typing for the `run<T>()` generic return type\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { decorator, type IAiChat, OpenAi, type OpenAiConfigType } from \"@ooneex/ai\";\nimport { inject } from \"@ooneex/container\";\n\n@decorator.ai()\nexport class <Name>Ai implements IAiChat<OpenAiConfigType> {\n constructor(@inject(OpenAi) private readonly ai: OpenAi) {}\n\n public async run<T>(prompt?: string, config?: Omit<OpenAiConfigType, \"prompt\">): Promise<T> {\n return this.ai.run<T>(prompt || \"My prompt\", config);\n }\n\n public async *runStream(\n prompt?: string,\n config?: Omit<OpenAiConfigType, \"prompt\" | \"output\">,\n ): AsyncGenerator<string, void, unknown> {\n yield* this.ai.runStream(prompt || \"My prompt\", config);\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/ai/<Name>Ai.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, run method, runStream method)\n- Add tests relevant to the specific AI class behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Ai } from \"@/ai/<Name>Ai\";\n\ndescribe(\"<Name>Ai\", () => {\n test(\"should have class name ending with 'Ai'\", () => {\n expect(<Name>Ai.name.endsWith(\"Ai\")).toBe(true);\n });\n\n test(\"should have 'run' method\", () => {\n expect(<Name>Ai.prototype.run).toBeDefined();\n expect(typeof <Name>Ai.prototype.run).toBe(\"function\");\n });\n\n test(\"should have 'runStream' method\", () => {\n expect(<Name>Ai.prototype.runStream).toBeDefined();\n expect(typeof <Name>Ai.prototype.runStream).toBe(\"function\");\n });\n});\n```\n\n### 5. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/ai/<Name>Ai.ts tests/ai/<Name>Ai.spec.ts\n```\n";var Br="---\nname: make:analytics\ndescription: Generate a new analytics class with its test file, then complete the generated code. Use when creating a new analytics tracking class that uses the @ooneex/analytics package.\n---\n\n# Make Analytics Class\n\nGenerate a new analytics class and its test file using the `make:analytics` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the analytics class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:analytics --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/analytics/<Name>Analytics.ts` - The analytics class file (or `modules/<module>/src/analytics/<Name>Analytics.ts` with `--module`)\n- `tests/analytics/<Name>Analytics.spec.ts` - The test file (or `modules/<module>/tests/analytics/<Name>Analytics.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the analytics class\n\nEdit `src/analytics/<Name>Analytics.ts` to complete the implementation:\n\n- Implement the `capture` method with actual analytics tracking logic\n- Define a proper type for `CaptureOptionsType` instead of `Record<string, unknown>` based on the analytics purpose\n- Add any additional methods or properties relevant to the analytics class purpose\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { decorator } from \"@ooneex/analytics\";\nimport type { IAnalytics } from \"@ooneex/analytics\";\n\ntype CaptureOptionsType = Record<string, unknown>;\n\n@decorator.analytics()\nexport class <Name>Analytics<T extends CaptureOptionsType = CaptureOptionsType> implements IAnalytics<T> {\n public capture(options: T): void {\n // console.log(\"Analytics captured:\", options);\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/analytics/<Name>Analytics.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, capture method)\n- Add tests relevant to the specific analytics class behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Analytics } from \"@/analytics/<Name>Analytics\";\n\ndescribe(\"<Name>Analytics\", () => {\n test(\"should have class name ending with 'Analytics'\", () => {\n expect(<Name>Analytics.name.endsWith(\"Analytics\")).toBe(true);\n });\n\n test(\"should have 'capture' method\", () => {\n expect(<Name>Analytics.prototype.capture).toBeDefined();\n expect(typeof <Name>Analytics.prototype.capture).toBe(\"function\");\n });\n});\n```\n\n### 5. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/analytics/<Name>Analytics.ts tests/analytics/<Name>Analytics.spec.ts\n```\n";var Lr="---\nname: make:cache\ndescription: Generate a new cache adapter class with its test file, then complete the generated code. Use when creating a new cache adapter that implements the ICache interface from @ooneex/cache.\n---\n\n# Make Cache Class\n\nGenerate a new cache class and its test file using the `make:cache` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the cache class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:cache --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/cache/<Name>Cache.ts` - The cache class file (or `modules/<module>/src/cache/<Name>Cache.ts` with `--module`)\n- `tests/cache/<Name>Cache.spec.ts` - The test file (or `modules/<module>/tests/cache/<Name>Cache.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the cache class\n\nEdit `src/cache/<Name>Cache.ts` to complete the implementation:\n\n- Implement the `get` method to retrieve cached values by key\n- Implement the `set` method to store values with optional TTL\n- Implement the `delete` method to remove cached entries\n- Implement the `has` method to check key existence\n- Replace the `CacheException` throws with actual cache logic\n- Inject any required dependencies (e.g., Redis client) via the constructor\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { CacheException, decorator } from \"@ooneex/cache\";\nimport type { ICache } from \"@ooneex/cache\";\n\n@decorator.cache()\nexport class <Name>Cache implements ICache {\n public async get<T = unknown>(key: string): Promise<T | undefined> {\n throw new CacheException(`Failed to get key \"${key}\": Not implemented`);\n }\n\n public async set<T = unknown>(key: string, value: T, ttl?: number): Promise<void> {\n throw new CacheException(`Failed to set key \"${key}\": Not implemented`);\n }\n\n public async delete(key: string): Promise<boolean> {\n throw new CacheException(`Failed to delete key \"${key}\": Not implemented`);\n }\n\n public async has(key: string): Promise<boolean> {\n throw new CacheException(`Failed to check if key \"${key}\" exists: Not implemented`);\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/cache/<Name>Cache.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, get, set, delete, has methods)\n- Add tests relevant to the specific cache class behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Cache } from \"@/cache/<Name>Cache\";\n\ndescribe(\"<Name>Cache\", () => {\n test(\"should have class name ending with 'Cache'\", () => {\n expect(<Name>Cache.name.endsWith(\"Cache\")).toBe(true);\n });\n\n test(\"should have 'get' method\", () => {\n expect(<Name>Cache.prototype.get).toBeDefined();\n expect(typeof <Name>Cache.prototype.get).toBe(\"function\");\n });\n\n test(\"should have 'set' method\", () => {\n expect(<Name>Cache.prototype.set).toBeDefined();\n expect(typeof <Name>Cache.prototype.set).toBe(\"function\");\n });\n\n test(\"should have 'delete' method\", () => {\n expect(<Name>Cache.prototype.delete).toBeDefined();\n expect(typeof <Name>Cache.prototype.delete).toBe(\"function\");\n });\n\n test(\"should have 'has' method\", () => {\n expect(<Name>Cache.prototype.has).toBeDefined();\n expect(typeof <Name>Cache.prototype.has).toBe(\"function\");\n });\n});\n```\n\n### 5. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/cache/<Name>Cache.ts tests/cache/<Name>Cache.spec.ts\n```\n";var Ur="---\nname: make:controller\ndescription: Generate a new controller class with route type and test file, then complete the generated code. Use when creating a new HTTP or WebSocket controller with routing, validation, and role-based access.\n---\n\n# Make Controller Class\n\nGenerate a new controller class, its route type, and test file using the `make:controller` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the controller class and related files:\n\n```bash\nbunx @ooneex/cli@latest make:controller --name <name> --module <module> --is-socket <true|false> --route.name <route.name> --route.path <route.path> --route.method <route.method>\n```\n\nWhere:\n- `<name>` is the controller name provided by the user\n- `--module` is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root\n- `--is-socket` determines HTTP vs WebSocket controller (defaults to `false`)\n- `--route.name` is the route name using dot notation: `<resource>.<action>` (e.g., `user.create`, `book.list`, `flashcard.delete`)\n- `--route.path` is the route path (e.g., `/api/users`)\n- `--route.method` is the HTTP method (e.g., `get`, `post`, `put`, `patch`, `delete`) \u2014 only for HTTP controllers\n\nThe command will generate (paths prefixed with `modules/<module>/` when `--module` is provided):\n- `src/controllers/<Name>Controller.ts` - The controller class file\n- `src/types/routes/<route.name>.ts` - The route type file\n- `tests/controllers/<Name>Controller.spec.ts` - The test file\n\n### 2. Read the generated files\n\nRead all three generated files to understand the scaffolded code.\n\n### 3. Complete the route type\n\nEdit `src/types/routes/<route.name>.ts` to define the route's type contract.\n\n**Add or remove `params`, `payload`, and `queries` based on context:**\n\n- **`params`** \u2014 Include only when the route path contains dynamic segments (e.g., `/api/users/:id`). Remove entirely for routes with no URL parameters (e.g., `/api/users`).\n- **`payload`** \u2014 Include only for methods that accept a request body (`post`, `put`, `patch`). Remove entirely for `get` and `delete` routes.\n- **`queries`** \u2014 Include only when the route supports query string filtering, pagination, or sorting (e.g., list/search endpoints). Remove entirely when not needed.\n- **`response`** \u2014 Always include.\n\nThe generated route type structure follows this pattern (remove unused sections):\n\n```typescript\n// Example: GET /api/users (list) \u2014 no params, no payload, has queries\nexport type <TypeName>RouteType = {\n queries: {\n\n },\n response: {\n\n },\n};\n\n// Example: POST /api/users (create) \u2014 no params, has payload, no queries\nexport type <TypeName>RouteType = {\n payload: {\n\n },\n response: {\n\n },\n};\n\n// Example: GET /api/users/:id (detail) \u2014 has params, no payload, no queries\nexport type <TypeName>RouteType = {\n params: {\n\n },\n response: {\n\n },\n};\n\n// Example: PUT /api/users/:id (update) \u2014 has params, has payload, no queries\nexport type <TypeName>RouteType = {\n params: {\n\n },\n payload: {\n\n },\n response: {\n\n },\n};\n```\n\n### 4. Complete the controller class\n\nEdit `src/controllers/<Name>Controller.ts` to complete the implementation:\n\n- Set appropriate `roles` for access control\n- Add a meaningful `description` for the route that explains what the endpoint does (e.g., `\"Create a new user account\"`, `\"List all books with pagination\"`)\n- Implement the `index` method with actual controller logic\n- Inject any required dependencies (repositories, services) via the constructor\n\n**Add or remove `params`, `payload`, and `queries` in the `@Route` decorator to match the route type (step 3):**\n\n- **`params`** \u2014 Include with `Assert()` validators only when the route has URL parameters. Remove the `params` key entirely otherwise.\n- **`payload`** \u2014 Include with `Assert({...})` only for `post`, `put`, `patch` methods. Remove the `payload` key entirely for `get` and `delete`.\n- **`queries`** \u2014 Include with `Assert({...})` only when query parameters are expected. Remove the `queries` key entirely otherwise.\n- **`response`** \u2014 Always include with `Assert({...})`.\n\n**HTTP controller** generated structure (remove `params`, `payload`, `queries` as needed \u2014 see rules above):\n\n```typescript\nimport type { ContextType } from \"@ooneex/controller\";\nimport { ERole } from \"@ooneex/role\";\nimport { Route } from \"@ooneex/routing\";\nimport { Assert } from \"@ooneex/validation\";\nimport type { <TypeName>RouteType } from \"../types/routes/<route.name>\";\n\n@Route.<method>(\"<route.path>\", {\n name: \"<route.name>\",\n version: 1,\n description: \"\",\n params: {\n // id: Assert(\"string\"),\n },\n payload: Assert({\n\n }),\n queries: Assert({\n\n }),\n response: Assert({\n\n }),\n roles: [ERole.USER],\n})\nexport class <Name>Controller {\n public async index(context: ContextType<<TypeName>RouteType>) {\n // const { id } = context.params;\n\n return context.response.json({\n\n });\n }\n}\n```\n\n**Socket controller** generated structure (remove `params`, `payload`, `queries` as needed \u2014 see rules above):\n\n```typescript\nimport type { ContextType } from \"@ooneex/socket\";\nimport { ERole } from \"@ooneex/role\";\nimport { Route } from \"@ooneex/routing\";\nimport { Assert } from \"@ooneex/validation\";\nimport type { <TypeName>RouteType } from \"../types/routes/<route.name>\";\n\n@Route.socket(\"<route.path>\", {\n name: \"<route.name>\",\n version: 1,\n description: \"\",\n params: {\n // id: Assert(\"string\"),\n },\n payload: Assert({\n\n }),\n queries: Assert({\n\n }),\n response: Assert({\n\n }),\n roles: [ERole.USER],\n})\nexport class <Name>Controller {\n public async index(context: ContextType<<TypeName>RouteType>) {\n // const { id } = context.params;\n\n return context.response.json({\n\n });\n }\n}\n```\n\n### 5. Complete the test file\n\nEdit `tests/controllers/<Name>Controller.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, index method)\n- Add tests relevant to the specific controller behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Controller } from \"@/controllers/<Name>Controller\";\n\ndescribe(\"<Name>Controller\", () => {\n test(\"should have class name ending with 'Controller'\", () => {\n expect(<Name>Controller.name.endsWith(\"Controller\")).toBe(true);\n });\n\n test(\"should have 'index' method\", () => {\n expect(<Name>Controller.prototype.index).toBeDefined();\n expect(typeof <Name>Controller.prototype.index).toBe(\"function\");\n });\n});\n```\n\n### 6. Register the controller in the module\n\nAdd the new controller to the module's `controllers` array in `src/<PascalModuleName>Module.ts` (e.g., `src/BookModule.ts` for the `book` module):\n\n```typescript\nimport type { ModuleType } from \"@ooneex/module\";\nimport { <Name>Controller } from \"./controllers/<Name>Controller\";\n\nexport const <PascalModuleName>Module: ModuleType = {\n controllers: [<Name>Controller],\n entities: [],\n permissions: [],\n middlewares: [],\n cronJobs: [],\n events: [],\n};\n```\n\nThe module file uses PascalCase naming: `<PascalModuleName>Module.ts` with export `<PascalModuleName>Module`.\n\nIf the module already has other controllers registered, append the new controller to the existing `controllers` array and add the import alongside existing imports.\n\n### 7. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/controllers/<Name>Controller.ts src/types/routes/<route.name>.ts tests/controllers/<Name>Controller.spec.ts\n```\n\n### 8. Create the service\n\nAfter the controller is created, generate a service class for the controller's business logic using the `make:service` skill:\n\n```\n/make:service --name <Name>\n```\n\nWhere `<Name>` matches the controller name (e.g., if the controller is `CreateUserController`, the service is `CreateUserService`).\n\n### 9. Create the pubsub event\n\nAfter the service is created, generate a pubsub event class for the controller's domain events using the `make:pubsub` skill:\n\n```\n/make:pubsub --name <Name> --channel <resource>.<action>\n```\n\nWhere:\n- `<Name>` matches the controller name (e.g., if the controller is `CreateUserController`, the event is `CreateUserEvent`)\n- `<resource>.<action>` follows the same dot notation as the route name (e.g., `user.create`, `book.delete`)\n\nOnce the event is created:\n- Inject the **service** into the **event** via the constructor, and call the service's `execute` method from the event's `handler` method.\n- Inject the **event** into the **controller** via the constructor, and publish the event from the controller's `index` method.\n";var $r="---\nname: make:cron\ndescription: Generate a new cron job class with its test file, then complete the generated code. Use when creating a new scheduled task that extends the Cron base class from @ooneex/cron.\n---\n\n# Make Cron Class\n\nGenerate a new cron class and its test file using the `make:cron` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the cron class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:cron --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/cron/<Name>Cron.ts` - The cron class file (or `modules/<module>/src/cron/<Name>Cron.ts` with `--module`)\n- `tests/cron/<Name>Cron.spec.ts` - The test file (or `modules/<module>/tests/cron/<Name>Cron.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the cron class\n\nEdit `src/cron/<Name>Cron.ts` to complete the implementation:\n\n- Set the appropriate cron schedule in `getTime()` (e.g., `\"every 5 minutes\"`, `\"every 1 hours\"`, `\"every 30 seconds\"`)\n- Set the timezone in `getTimeZone()` if needed, or keep `null` for server timezone\n- Implement the `handler()` method with the actual cron job logic\n- Inject any required dependencies via the constructor\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport type { TimeZoneType } from \"@ooneex/country\";\nimport type { CronTimeType } from \"@ooneex/cron\";\nimport { Cron, decorator } from \"@ooneex/cron\";\n\n@decorator.cron()\nexport class <Name>Cron extends Cron {\n public getTime(): CronTimeType {\n // Examples: \"every 5 minutes\", \"every 1 hours\", \"every 30 seconds\"\n return \"every 1 hours\";\n }\n\n public getTimeZone(): TimeZoneType | null {\n // Return null to use server timezone, or specify a timezone like \"Europe/Paris\"\n return null;\n }\n\n public async handler(): Promise<void> {\n // Implement your cron handler logic here\n // console.log(\"<Name>Cron handler executed\");\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/cron/<Name>Cron.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, getTime, getTimeZone, handler methods)\n- Add tests relevant to the specific cron class behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Cron } from \"@/cron/<Name>Cron\";\n\ndescribe(\"<Name>Cron\", () => {\n test(\"should have class name ending with 'Cron'\", () => {\n expect(<Name>Cron.name.endsWith(\"Cron\")).toBe(true);\n });\n\n test(\"should have 'getTime' method\", () => {\n expect(<Name>Cron.prototype.getTime).toBeDefined();\n expect(typeof <Name>Cron.prototype.getTime).toBe(\"function\");\n });\n\n test(\"should have 'getTimeZone' method\", () => {\n expect(<Name>Cron.prototype.getTimeZone).toBeDefined();\n expect(typeof <Name>Cron.prototype.getTimeZone).toBe(\"function\");\n });\n\n test(\"should have 'handler' method\", () => {\n expect(<Name>Cron.prototype.handler).toBeDefined();\n expect(typeof <Name>Cron.prototype.handler).toBe(\"function\");\n });\n});\n```\n\n### 5. Register the cron job in the module\n\nAdd the new cron job to the module's `cronJobs` array in `src/<PascalModuleName>Module.ts` (e.g., `src/BookModule.ts` for the `book` module):\n\n```typescript\nimport type { ModuleType } from \"@ooneex/module\";\nimport { <Name>Cron } from \"./cron/<Name>Cron\";\n\nexport const <PascalModuleName>Module: ModuleType = {\n controllers: [],\n entities: [],\n permissions: [],\n middlewares: [],\n cronJobs: [<Name>Cron],\n events: [],\n};\n```\n\nThe module file uses PascalCase naming: `<PascalModuleName>Module.ts` with export `<PascalModuleName>Module`.\n\nIf the module already has other cron jobs registered, append the new cron job to the existing `cronJobs` array and add the import alongside existing imports.\n\n### 6. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/cron/<Name>Cron.ts tests/cron/<Name>Cron.spec.ts\n```\n";var kr="---\nname: make:database\ndescription: Generate a new database class with its test file, then complete the generated code. Use when creating a new database adapter that extends TypeormDatabase from @ooneex/database.\n---\n\n# Make Database Class\n\nGenerate a new database class and its test file using the `make:database` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the database class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:database --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/databases/<Name>Database.ts` - The database class file (or `modules/<module>/src/databases/<Name>Database.ts` with `--module`)\n- `tests/databases/<Name>Database.spec.ts` - The test file (or `modules/<module>/tests/databases/<Name>Database.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the database class\n\nEdit `src/databases/<Name>Database.ts` to complete the implementation:\n\n- Add entity imports and register them in the `entities` array\n- Adjust the database path if needed (default is `\"var/db\"`)\n- Configure DataSource options as appropriate (type, synchronize, etc.)\n- Inject any required dependencies via the constructor\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { DataSource } from \"typeorm\";\nimport { TypeormDatabase, DatabaseException, decorator } from \"@ooneex/database\";\n\n@decorator.database()\nexport class <Name>Database extends TypeormDatabase {\n public getSource(database?: string): DataSource {\n database = database || \"var/db\";\n\n this.source = new DataSource({\n synchronize: false,\n entities: [\n // TODO: Load your entities here\n ],\n enableWAL: true,\n busyErrorRetry: 2000,\n busyTimeout: 30_000,\n database,\n type: \"sqlite\",\n });\n\n return this.source;\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/databases/<Name>Database.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, getSource method)\n- Add tests relevant to the specific database class behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Database } from \"@/databases/<Name>Database\";\n\ndescribe(\"<Name>Database\", () => {\n test(\"should have class name ending with 'Database'\", () => {\n expect(<Name>Database.name.endsWith(\"Database\")).toBe(true);\n });\n\n test(\"should have 'getSource' method\", () => {\n expect(<Name>Database.prototype.getSource).toBeDefined();\n expect(typeof <Name>Database.prototype.getSource).toBe(\"function\");\n });\n});\n```\n\n### 5. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/databases/<Name>Database.ts tests/databases/<Name>Database.spec.ts\n```\n";var Gr="---\nname: make:entity\ndescription: Generate a new TypeORM entity class with its test file, then complete the generated code. Use when creating a new database entity with columns, relations, and table mapping.\n---\n\n# Make Entity Class\n\nGenerate a new entity class and its test file using the `make:entity` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the entity class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:entity --name <name> --module <module> --table-name <table_name>\n```\n\nWhere `<name>` is the name provided by the user. The `--table-name` option is optional \u2014 if omitted, it defaults to the snake_case pluralized form of the name (e.g., `UserProfile` becomes `user_profiles`). The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/entities/<Name>Entity.ts` - The entity class file (or `modules/<module>/src/entities/<Name>Entity.ts` with `--module`)\n- `tests/entities/<Name>Entity.spec.ts` - The test file (or `modules/<module>/tests/entities/<Name>Entity.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the entity class\n\nEdit `src/entities/<Name>Entity.ts` to complete the implementation:\n\n- Add entity-specific columns with appropriate TypeORM decorators (`@Column`)\n- Add relations if needed (`@ManyToOne`, `@OneToMany`, `@ManyToMany`, etc.)\n- Remove any scaffolded columns that are not relevant to the entity\n- Adjust column types, lengths, and constraints as needed\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport type { LocaleType } from \"@ooneex/translation\";\nimport { random } from \"@ooneex/utils\";\nimport { Column, CreateDateColumn, DeleteDateColumn, PrimaryColumn, UpdateDateColumn } from \"typeorm\";\n\n@Entity({\n name: \"<table_name>\",\n})\nexport class <Name>Entity extends BaseEntity {\n @PrimaryColumn({ name: \"id\", type: \"varchar\", length: 25 })\n id: string = random.nanoid(25);\n\n @Column({\n name: \"is_locked\",\n type: \"boolean\",\n default: false,\n nullable: true,\n })\n isLocked?: boolean;\n\n @Column({ name: \"locked_at\", type: \"timestamptz\", nullable: true })\n lockedAt?: Date;\n\n @Column({\n name: \"is_blocked\",\n type: \"boolean\",\n default: false,\n nullable: true,\n })\n isBlocked?: boolean;\n\n @Column({ name: \"blocked_at\", type: \"timestamptz\", nullable: true })\n blockedAt?: Date;\n\n @Column({ name: \"block_reason\", type: \"text\", nullable: true })\n blockReason?: string;\n\n @Column({ name: \"is_public\", type: \"boolean\", default: true, nullable: true })\n isPublic?: boolean;\n\n @Column({ name: \"lang\", type: \"varchar\", length: 10, nullable: true })\n lang?: LocaleType;\n\n @CreateDateColumn({ name: \"created_at\" })\n createdAt?: Date;\n\n @UpdateDateColumn({ name: \"updated_at\" })\n updatedAt?: Date;\n\n @DeleteDateColumn({ name: \"deleted_at\" })\n deletedAt?: Date;\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/entities/<Name>Entity.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, id, default columns)\n- Add tests for any new entity-specific columns and relations\n- Update tests if scaffolded columns were removed\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Entity } from \"@/entities/<Name>Entity\";\n\ndescribe(\"<Name>Entity\", () => {\n test(\"should have class name ending with 'Entity'\", () => {\n expect(<Name>Entity.name.endsWith(\"Entity\")).toBe(true);\n });\n\n test(\"should have 'id' property with default nanoid\", () => {\n const entity = new <Name>Entity();\n expect(entity.id).toBeDefined();\n expect(typeof entity.id).toBe(\"string\");\n expect(entity.id.length).toBe(25);\n });\n\n test(\"should have 'isLocked' property\", () => {\n const entity = new <Name>Entity();\n expect(\"isLocked\" in entity).toBe(true);\n });\n\n // ... additional property tests\n});\n```\n\n### 5. Register the entity in the module\n\nAdd the new entity to the module's `entities` array in `src/<PascalModuleName>Module.ts` (e.g., `src/BookModule.ts` for the `book` module):\n\n```typescript\nimport type { ModuleType } from \"@ooneex/module\";\nimport { <Name>Entity } from \"./entities/<Name>Entity\";\n\nexport const <PascalModuleName>Module: ModuleType = {\n controllers: [],\n entities: [<Name>Entity],\n permissions: [],\n middlewares: [],\n cronJobs: [],\n events: [],\n};\n```\n\nThe module file uses PascalCase naming: `<PascalModuleName>Module.ts` with export `<PascalModuleName>Module`.\n\nIf the module already has other entities registered, append the new entity to the existing `entities` array and add the import alongside existing imports.\n\n### 6. Create a migration for the entity\n\nAfter creating or updating an entity, generate a migration to apply the corresponding schema changes to the database.\n\nRun the generator:\n\n```bash\nbunx @ooneex/cli@latest make:migration\n```\n\nThen read the generated migration file in `src/migrations/` and complete it:\n\n- In the `up` method, write the SQL to create the table (or alter it if updating an existing entity). Include all columns, types, constraints, defaults, and indexes matching the entity definition.\n- In the `down` method, write the reverse SQL to undo the changes (e.g., `DROP TABLE` or `ALTER TABLE DROP COLUMN`).\n- If the migration depends on another migration (e.g., a foreign key referencing another table), add that migration class to the `getDependencies()` return array.\n\nExample `up` method for a new entity:\n\n```typescript\npublic async up(tx: TransactionSQL): Promise<void> {\n await tx`\n CREATE TABLE IF NOT EXISTS <table_name> (\n id VARCHAR(25) PRIMARY KEY,\n is_locked BOOLEAN DEFAULT false,\n locked_at TIMESTAMPTZ,\n is_blocked BOOLEAN DEFAULT false,\n blocked_at TIMESTAMPTZ,\n block_reason TEXT,\n is_public BOOLEAN DEFAULT true,\n lang VARCHAR(10),\n created_at TIMESTAMPTZ DEFAULT NOW(),\n updated_at TIMESTAMPTZ DEFAULT NOW(),\n deleted_at TIMESTAMPTZ\n )\n `;\n}\n```\n\n### 7. Create a repository for the entity\n\nAfter creating the entity, generate a repository to handle database operations for it.\n\nRun the generator:\n\n```bash\nbunx @ooneex/cli@latest make:repository --name <name>\n```\n\nWhere `<name>` is the same name used for the entity. The command will generate:\n- `src/repositories/<Name>Repository.ts` - The repository class\n- `tests/repositories/<Name>Repository.spec.ts` - The test file\n\nThen read the generated files and complete the repository implementation:\n\n- Adjust search fields in the `find()` method to match the entity's searchable columns\n- Customize relations loading in `findOne`/`findOneBy` if the entity has relations\n- Add any domain-specific methods relevant to the entity\n- Remove methods that don't apply to the entity\n- Update tests to match the final repository methods\n\n### 8. Lint and format\n\nRun linting and formatting on all generated files:\n\n```bash\nbunx biome check --fix src/entities/<Name>Entity.ts tests/entities/<Name>Entity.spec.ts src/repositories/<Name>Repository.ts tests/repositories/<Name>Repository.spec.ts src/migrations/\n```\n";var Wr="---\nname: make:logger\ndescription: Generate a new logger class with its test file, then complete the generated code. Use when creating a new logger that implements the ILogger interface from @ooneex/logger.\n---\n\n# Make Logger Class\n\nGenerate a new logger class and its test file using the `make:logger` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the logger class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:logger --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/loggers/<Name>Logger.ts` - The logger class file (or `modules/<module>/src/loggers/<Name>Logger.ts` with `--module`)\n- `tests/loggers/<Name>Logger.spec.ts` - The test file (or `modules/<module>/tests/loggers/<Name>Logger.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the logger class\n\nEdit `src/loggers/<Name>Logger.ts` to complete the implementation:\n\n- Implement the `init()` method to set up the logger (e.g., open file handles, configure transports)\n- Implement `log`, `debug`, `info`, `success`, `warn`, and `error` methods with actual logging logic\n- Inject any required dependencies via the constructor\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport type { IException } from \"@ooneex/exception\";\nimport type { ILogger } from \"@ooneex/logger\";\nimport type { ScalarType } from \"@ooneex/types\";\nimport { decorator } from \"@ooneex/logger\";\n\n@decorator.logger()\nexport class <Name>Logger implements ILogger {\n public async init(): Promise<void> {\n // Initialize your logger here\n }\n\n public log(message: string, data?: Record<string, ScalarType>): void {\n // Handle general logging\n }\n\n public debug(message: string, data?: Record<string, ScalarType>): void {\n // Handle debug logging\n }\n\n public info(message: string, data?: Record<string, ScalarType>): void {\n // Handle info logging\n }\n\n public success(message: string, data?: Record<string, ScalarType>): void {\n // Handle success logging\n }\n\n public warn(message: string, data?: Record<string, ScalarType>): void {\n // Handle warning logging\n }\n\n public error(message: string | IException, data?: Record<string, ScalarType>): void {\n // Handle error logging\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/loggers/<Name>Logger.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, init, log, debug, info, success, warn, error methods)\n- Add tests relevant to the specific logger class behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Logger } from \"@/loggers/<Name>Logger\";\n\ndescribe(\"<Name>Logger\", () => {\n test(\"should have class name ending with 'Logger'\", () => {\n expect(<Name>Logger.name.endsWith(\"Logger\")).toBe(true);\n });\n\n test(\"should have 'init' method\", () => {\n expect(<Name>Logger.prototype.init).toBeDefined();\n expect(typeof <Name>Logger.prototype.init).toBe(\"function\");\n });\n\n test(\"should have 'log' method\", () => {\n expect(<Name>Logger.prototype.log).toBeDefined();\n expect(typeof <Name>Logger.prototype.log).toBe(\"function\");\n });\n\n test(\"should have 'debug' method\", () => {\n expect(<Name>Logger.prototype.debug).toBeDefined();\n expect(typeof <Name>Logger.prototype.debug).toBe(\"function\");\n });\n\n test(\"should have 'info' method\", () => {\n expect(<Name>Logger.prototype.info).toBeDefined();\n expect(typeof <Name>Logger.prototype.info).toBe(\"function\");\n });\n\n test(\"should have 'success' method\", () => {\n expect(<Name>Logger.prototype.success).toBeDefined();\n expect(typeof <Name>Logger.prototype.success).toBe(\"function\");\n });\n\n test(\"should have 'warn' method\", () => {\n expect(<Name>Logger.prototype.warn).toBeDefined();\n expect(typeof <Name>Logger.prototype.warn).toBe(\"function\");\n });\n\n test(\"should have 'error' method\", () => {\n expect(<Name>Logger.prototype.error).toBeDefined();\n expect(typeof <Name>Logger.prototype.error).toBe(\"function\");\n });\n});\n```\n\n### 5. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/loggers/<Name>Logger.ts tests/loggers/<Name>Logger.spec.ts\n```\n";var qr="---\nname: make:mailer\ndescription: Generate a new mailer class with its template and test files, then complete the generated code. Use when creating a new email sender with JSX template using @ooneex/mailer.\n---\n\n# Make Mailer Class\n\nGenerate a new mailer class, its JSX template, and test files using the `make:mailer` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the mailer class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:mailer --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate (paths prefixed with `modules/<module>/` when `--module` is provided):\n- `src/mailers/<Name>Mailer.ts` - The mailer class file\n- `src/mailers/<Name>MailerTemplate.tsx` - The JSX email template\n- `tests/mailers/<Name>Mailer.spec.ts` - The mailer test file\n- `tests/mailers/<Name>MailerTemplate.spec.ts` - The template test file\n\n### 2. Read the generated files\n\nRead all four generated files to understand the scaffolded code.\n\n### 3. Complete the mailer class\n\nEdit `src/mailers/<Name>Mailer.ts` to complete the implementation:\n\n- Adjust the `send` method config type if additional parameters are needed\n- Add any pre-send logic (validation, data transformation, etc.)\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { inject } from \"@ooneex/container\";\nimport type { IMailer } from \"@ooneex/mailer\";\nimport { type <Name>MailerPropsType, <Name>MailerTemplate } from \"./<Name>MailerTemplate\";\n\nexport class <Name>Mailer implements IMailer {\n constructor(\n @inject(\"mailer\")\n private readonly mailer: IMailer,\n ) {}\n\n public send = async (config: {\n to: string[];\n subject: string;\n from?: { name: string; address: string };\n data?: <Name>MailerPropsType;\n }): Promise<void> => {\n const { data, ...rest } = config;\n\n await this.mailer.send({\n ...rest,\n content: <Name>MailerTemplate(data),\n });\n };\n}\n```\n\n### 4. Complete the mailer template\n\nEdit `src/mailers/<Name>MailerTemplate.tsx` to complete the implementation:\n\n- Update `<Name>MailerPropsType` with the actual props needed for the email\n- Build the email body using `MailerLayout` components (Header, Body, Footer)\n- Add email content, styling, and dynamic data rendering\n\nThe generated template structure follows this pattern:\n\n```tsx\nimport { MailerLayout } from \"@ooneex/mailer\";\n\nexport type <Name>MailerPropsType = {\n link: string;\n};\n\nexport const <Name>MailerTemplate = (props?: <Name>MailerPropsType) => (\n <MailerLayout>\n <MailerLayout.Header />\n <MailerLayout.Body>\n <a href={props?.link}>Login</a>\n </MailerLayout.Body>\n <MailerLayout.Footer />\n </MailerLayout>\n);\n```\n\n### 5. Complete the test files\n\nEdit `tests/mailers/<Name>Mailer.spec.ts` and `tests/mailers/<Name>MailerTemplate.spec.ts` to add meaningful tests beyond the scaffolded ones.\n\n### 6. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/mailers/<Name>Mailer.ts src/mailers/<Name>MailerTemplate.tsx tests/mailers/<Name>Mailer.spec.ts tests/mailers/<Name>MailerTemplate.spec.ts\n```\n";var Kr="---\nname: make:middleware\ndescription: Generate a new middleware class with its test file, then complete the generated code. Use when creating a new HTTP or WebSocket middleware that implements IMiddleware from @ooneex/middleware.\n---\n\n# Make Middleware Class\n\nGenerate a new middleware class and its test file using the `make:middleware` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the middleware class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:middleware --name <name> --module <module> --is-socket <true|false>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The `--is-socket` option determines whether to generate an HTTP middleware or a WebSocket middleware (defaults to `false` if omitted). The command will generate:\n- `src/middlewares/<Name>Middleware.ts` - The middleware class file (or `modules/<module>/src/middlewares/<Name>Middleware.ts` with `--module`)\n- `tests/middlewares/<Name>Middleware.spec.ts` - The test file (or `modules/<module>/tests/middlewares/<Name>Middleware.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the middleware class\n\nEdit `src/middlewares/<Name>Middleware.ts` to complete the implementation:\n\n- Implement the `handler` method with actual middleware logic\n- Add request/response transformations, authentication checks, logging, etc.\n- Inject any required dependencies via the constructor\n\n**HTTP middleware** generated structure:\n\n```typescript\nimport type { ContextType } from \"@ooneex/controller\";\nimport { decorator, type IMiddleware } from \"@ooneex/middleware\";\n\n@decorator.middleware()\nexport class <Name>Middleware implements IMiddleware {\n public async handler(context: ContextType): Promise<ContextType> {\n // Example: Add custom header\n // context.response.header(\"X-Custom-Header\", \"value\");\n\n return context\n }\n}\n```\n\n**Socket middleware** generated structure:\n\n```typescript\nimport type { ContextType } from \"@ooneex/socket\";\nimport { decorator, type IMiddleware } from \"@ooneex/middleware\";\n\n@decorator.middleware()\nexport class <Name>Middleware implements IMiddleware {\n public async handler(context: ContextType): Promise<ContextType> {\n // Example: Add custom header\n // context.response.header(\"X-Custom-Header\", \"value\");\n\n return context\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/middlewares/<Name>Middleware.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, handler method)\n- Add tests relevant to the specific middleware behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Middleware } from \"@/middlewares/<Name>Middleware\";\n\ndescribe(\"<Name>Middleware\", () => {\n test(\"should have class name ending with 'Middleware'\", () => {\n expect(<Name>Middleware.name.endsWith(\"Middleware\")).toBe(true);\n });\n\n test(\"should have 'handler' method\", () => {\n expect(<Name>Middleware.prototype.handler).toBeDefined();\n expect(typeof <Name>Middleware.prototype.handler).toBe(\"function\");\n });\n});\n```\n\n### 5. Register the middleware in the module\n\nAdd the new middleware to the module's `middlewares` array in `src/<PascalModuleName>Module.ts` (e.g., `src/BookModule.ts` for the `book` module):\n\n```typescript\nimport type { ModuleType } from \"@ooneex/module\";\nimport { <Name>Middleware } from \"./middlewares/<Name>Middleware\";\n\nexport const <PascalModuleName>Module: ModuleType = {\n controllers: [],\n entities: [],\n permissions: [],\n middlewares: [<Name>Middleware],\n cronJobs: [],\n events: [],\n};\n```\n\nThe module file uses PascalCase naming: `<PascalModuleName>Module.ts` with export `<PascalModuleName>Module`.\n\nIf the module already has other middlewares registered, append the new middleware to the existing `middlewares` array and add the import alongside existing imports.\n\n### 6. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/middlewares/<Name>Middleware.ts tests/middlewares/<Name>Middleware.spec.ts\n```\n";var Fr="---\nname: make:migration\ndescription: Generate a new database migration file, then complete the generated code. Use when creating a new database migration for schema changes using @ooneex/migrations.\n---\n\n# Make Migration\n\nGenerate a new migration file using the `make:migration` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the migration file:\n\n```bash\nbunx @ooneex/cli@latest make:migration --module <module>\n```\n\nThe `--module` option is optional \u2014 if provided, the migration file is generated under `modules/<module>/src/migrations/` instead of `src/migrations/`. The command will:\n- Generate a timestamped migration file in `src/migrations/` (or `modules/<module>/src/migrations/` with `--module`)\n- Add a `migration:up` script to `package.json` if not already present\n\n### 2. Read the generated file\n\nRead the generated migration file in `src/migrations/` to understand the scaffolded code.\n\n### 3. Complete the migration\n\nEdit the generated migration file to implement:\n\n- The `up` method with the schema changes (create tables, add columns, create indexes, etc.)\n- The `down` method with the reverse operations to undo the migration\n\n### 4. Lint and format\n\nRun linting and formatting on the generated file:\n\n```bash\nbunx biome check --fix src/migrations/\n```\n";var Hr="---\nname: make:permission\ndescription: Generate a new permission class with its test file, then complete the generated code. Use when creating a new permission that extends Permission from @ooneex/permission.\n---\n\n# Make Permission Class\n\nGenerate a new permission class and its test file using the `make:permission` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the permission class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:permission --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/permissions/<Name>Permission.ts` - The permission class file (or `modules/<module>/src/permissions/<Name>Permission.ts` with `--module`)\n- `tests/permissions/<Name>Permission.spec.ts` - The test file (or `modules/<module>/tests/permissions/<Name>Permission.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the permission class\n\nEdit `src/permissions/<Name>Permission.ts` to complete the implementation:\n\n- Implement the `allow()` method with permission rules using `this.ability.can()`\n- Implement the `setUserPermissions()` method with role-based permission logic\n- Define which actions (read, create, update, delete, manage) are allowed on which entities\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { decorator, Permission } from \"@ooneex/permission\";\nimport type { IUser } from \"@ooneex/user\";\n\n@decorator.permission()\nexport class <Name>Permission extends Permission {\n public allow(): this {\n // Example: Add permissions using this.ability.can()\n // this.ability.can(\"read\", \"YourEntity\");\n // this.ability.can([\"read\", \"update\"], \"YourEntity\", { userId: user.id });\n\n return this;\n }\n\n public setUserPermissions(user: IUser | null): this {\n if (!user) {\n return this;\n }\n\n // Example: Grant full access to admins\n // const { roles } = user;\n // if (roles.includes(ERole.ADMIN)) {\n // this.ability.can(\"manage\", \"all\");\n // return this;\n // }\n\n // Example: Grant specific permissions based on roles\n // for (const role of roles) {\n // if (role === ERole.USER) {\n // this.ability.can([\"read\", \"update\"], \"YourEntity\", { userId: user.id });\n // }\n //\n // if (role === ERole.GUEST) {\n // this.ability.can(\"read\", \"YourEntity\", { public: true });\n // }\n // }\n\n return this;\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/permissions/<Name>Permission.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, extends Permission, allow, setUserPermissions methods)\n- Add tests relevant to the specific permission rules\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { Permission } from \"@ooneex/permission\";\nimport { <Name>Permission } from \"@/permissions/<Name>Permission\";\n\ndescribe(\"<Name>Permission\", () => {\n test(\"should have class name ending with 'Permission'\", () => {\n expect(<Name>Permission.name.endsWith(\"Permission\")).toBe(true);\n });\n\n test(\"should extend Permission\", () => {\n const permission = new <Name>Permission();\n expect(permission).toBeInstanceOf(Permission);\n });\n\n test(\"should have 'allow' method\", () => {\n expect(<Name>Permission.prototype.allow).toBeDefined();\n expect(typeof <Name>Permission.prototype.allow).toBe(\"function\");\n });\n\n test(\"should have 'setUserPermissions' method\", () => {\n expect(<Name>Permission.prototype.setUserPermissions).toBeDefined();\n expect(typeof <Name>Permission.prototype.setUserPermissions).toBe(\"function\");\n });\n});\n```\n\n### 5. Register the permission in the module\n\nAdd the new permission to the module's `permissions` array in `src/<PascalModuleName>Module.ts` (e.g., `src/BookModule.ts` for the `book` module):\n\n```typescript\nimport type { ModuleType } from \"@ooneex/module\";\nimport { <Name>Permission } from \"./permissions/<Name>Permission\";\n\nexport const <PascalModuleName>Module: ModuleType = {\n controllers: [],\n entities: [],\n permissions: [<Name>Permission],\n middlewares: [],\n cronJobs: [],\n events: [],\n};\n```\n\nThe module file uses PascalCase naming: `<PascalModuleName>Module.ts` with export `<PascalModuleName>Module`.\n\nIf the module already has other permissions registered, append the new permission to the existing `permissions` array and add the import alongside existing imports.\n\n### 6. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/permissions/<Name>Permission.ts tests/permissions/<Name>Permission.spec.ts\n```\n";var Vr="---\nname: make:pubsub\ndescription: Generate a new PubSub event class with its test file, then complete the generated code. Use when creating a new publish/subscribe event that extends PubSub from @ooneex/pub-sub.\n---\n\n# Make PubSub Event Class\n\nGenerate a new PubSub event class and its test file using the `make:pubsub` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the PubSub event class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:pubsub --name <name> --module <module> --channel <channel>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The `--channel` option is optional \u2014 if omitted, it defaults to the kebab-case form of the name (e.g., `UserCreated` becomes `user-created`). The command will generate:\n- `src/events/<Name>Event.ts` - The event class file (or `modules/<module>/src/events/<Name>Event.ts` with `--module`)\n- `tests/events/<Name>Event.spec.ts` - The test file (or `modules/<module>/tests/events/<Name>Event.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the PubSub event class\n\nEdit `src/events/<Name>Event.ts` to complete the implementation:\n\n- Define a proper data type instead of `Record<string, ScalarType>` for the event payload\n- Implement the `handler()` method with actual event handling logic\n- Set the appropriate channel name in `getChannel()`\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { inject } from \"@ooneex/container\";\nimport type { ScalarType } from \"@ooneex/types\";\nimport { decorator, PubSub, RedisPubSub } from \"@ooneex/pub-sub\";\n\n@decorator.pubSub()\nexport class <Name>Event<Data extends Record<string, ScalarType> = Record<string, ScalarType>> extends PubSub<Data> {\n constructor(\n @inject(RedisPubSub)\n client: RedisPubSub<Data>,\n ) {\n super(client);\n }\n\n public getChannel(): string {\n return \"<channel>\";\n }\n\n public async handler(context: { data: Data; channel: string }): Promise<void> {\n console.log(context);\n // TODO: Implement handler logic here\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/events/<Name>Event.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, getChannel, handler, publish, subscribe, unsubscribe, unsubscribeAll methods)\n- Add tests relevant to the specific event behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>PubSub } from \"@/pubsub/<Name>PubSub\";\n\ndescribe(\"<Name>PubSub\", () => {\n test(\"should have class name ending with 'PubSub'\", () => {\n expect(<Name>PubSub.name.endsWith(\"PubSub\")).toBe(true);\n });\n\n test(\"should have 'getChannel' method\", () => {\n expect(<Name>PubSub.prototype.getChannel).toBeDefined();\n expect(typeof <Name>PubSub.prototype.getChannel).toBe(\"function\");\n });\n\n test(\"should have 'handler' method\", () => {\n expect(<Name>PubSub.prototype.handler).toBeDefined();\n expect(typeof <Name>PubSub.prototype.handler).toBe(\"function\");\n });\n\n test(\"should have 'publish' method\", () => {\n expect(<Name>PubSub.prototype.publish).toBeDefined();\n expect(typeof <Name>PubSub.prototype.publish).toBe(\"function\");\n });\n\n test(\"should have 'subscribe' method\", () => {\n expect(<Name>PubSub.prototype.subscribe).toBeDefined();\n expect(typeof <Name>PubSub.prototype.subscribe).toBe(\"function\");\n });\n\n test(\"should have 'unsubscribe' method\", () => {\n expect(<Name>PubSub.prototype.unsubscribe).toBeDefined();\n expect(typeof <Name>PubSub.prototype.unsubscribe).toBe(\"function\");\n });\n\n test(\"should have 'unsubscribeAll' method\", () => {\n expect(<Name>PubSub.prototype.unsubscribeAll).toBeDefined();\n expect(typeof <Name>PubSub.prototype.unsubscribeAll).toBe(\"function\");\n });\n});\n```\n\n### 5. Register the event in the module\n\nAdd the new event to the module's `events` array in `src/<PascalModuleName>Module.ts` (e.g., `src/BookModule.ts` for the `book` module):\n\n```typescript\nimport type { ModuleType } from \"@ooneex/module\";\nimport { <Name>Event } from \"./events/<Name>Event\";\n\nexport const <PascalModuleName>Module: ModuleType = {\n controllers: [],\n entities: [],\n permissions: [],\n middlewares: [],\n cronJobs: [],\n events: [<Name>Event],\n};\n```\n\nThe module file uses PascalCase naming: `<PascalModuleName>Module.ts` with export `<PascalModuleName>Module`.\n\nIf the module already has other events registered, append the new event to the existing `events` array and add the import alongside existing imports.\n\n### 6. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/events/<Name>Event.ts tests/events/<Name>Event.spec.ts\n```\n";var Yr="---\nname: make:repository\ndescription: Generate a new repository class with its test file, then complete the generated code. Use when creating a new TypeORM repository for database operations on an entity.\n---\n\n# Make Repository Class\n\nGenerate a new repository class and its test file using the `make:repository` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the repository class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:repository --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/repositories/<Name>Repository.ts` - The repository class file (or `modules/<module>/src/repositories/<Name>Repository.ts` with `--module`)\n- `tests/repositories/<Name>Repository.spec.ts` - The test file (or `modules/<module>/tests/repositories/<Name>Repository.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the repository class\n\nEdit `src/repositories/<Name>Repository.ts` to complete the implementation:\n\n- Verify the entity import path matches the actual entity location\n- Adjust the `find` method's search fields (default searches `name` with `ILike`)\n- Customize relations loading in `findOne`/`findOneBy` if needed\n\n#### Adding methods\n\nLook at the entity's fields, relations, and business context to determine if custom domain-specific methods are needed. For example:\n- A `SessionRepository` might need `revokeSession(sessionId: string)` and `revokeAllUserSessions(userId: string)`\n- A `NotificationRepository` might need `markAsRead(id: string)` and `markAllAsRead(userId: string)`\n- Entities with status fields may need methods like `archive(id: string)` or `activate(id: string)`\n\nRead related entities, services, or actions in the module to understand what operations the repository should support, then add the appropriate methods.\n\n#### Removing methods\n\nRemove scaffolded methods that don't make sense for the entity's context:\n- Remove `createMany`/`updateMany` if the entity is always managed individually (e.g., user profiles, settings)\n- Remove `delete` if the entity uses soft deletes only (use a custom `softDelete` or `archive` method instead)\n- Remove `find` if the entity is only ever accessed by ID or specific criteria (e.g., singleton config entities)\n- Remove `count` if there's no use case for counting records of this entity\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { inject } from \"@ooneex/container\";\nimport type { ITypeormDatabase } from \"@ooneex/database\";\nimport { decorator } from \"@ooneex/repository\";\nimport type { FilterResultType } from \"@ooneex/types\";\nimport type { FindManyOptions, FindOptionsWhere, Repository, SaveOptions, UpdateResult } from \"typeorm\";\nimport { ILike } from \"typeorm\";\nimport { <Name>Entity } from \"../entities/<Name>Entity\";\n\n@decorator.repository()\nexport class <Name>Repository {\n constructor(\n @inject(\"database\")\n private readonly database: ITypeormDatabase,\n ) {}\n\n public async open(): Promise<Repository<<Name>Entity>> {\n return await this.database.open(<Name>Entity);\n }\n\n public async close(): Promise<void> {\n await this.database.close();\n }\n\n public async find(\n criteria: FindManyOptions<<Name>Entity> & { page?: number; limit?: number; q?: string },\n ): Promise<FilterResultType<<Name>Entity>> {\n // ... pagination and search logic\n }\n\n public async findOne(id: string): Promise<<Name>Entity | null> { ... }\n public async findOneBy(criteria: FindOptionsWhere<<Name>Entity>): Promise<<Name>Entity | null> { ... }\n public async create(entity: <Name>Entity, options?: SaveOptions): Promise<<Name>Entity> { ... }\n public async createMany(entities: <Name>Entity[], options?: SaveOptions): Promise<<Name>Entity[]> { ... }\n public async update(entity: <Name>Entity, options?: SaveOptions): Promise<<Name>Entity> { ... }\n public async updateMany(entities: <Name>Entity[], options?: SaveOptions): Promise<<Name>Entity[]> { ... }\n public async delete(criteria: FindOptionsWhere<<Name>Entity> | FindOptionsWhere<<Name>Entity>[]): Promise<UpdateResult> { ... }\n public async count(criteria?: FindOptionsWhere<<Name>Entity> | FindOptionsWhere<<Name>Entity>[]): Promise<number> { ... }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/repositories/<Name>Repository.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep scaffolded tests for methods that remain in the repository (remove tests for methods that were removed)\n- Add tests for any custom domain-specific methods added to the repository\n- Add tests relevant to the specific repository behavior\n\n### 5. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/repositories/<Name>Repository.ts tests/repositories/<Name>Repository.spec.ts\n```\n";var jr="---\nname: make:seed\ndescription: Generate a new database seed file, then complete the generated code. Use when creating seed data for populating the database using @ooneex/seeds.\n---\n\n# Make Seed\n\nGenerate a new seed file using the `make:seed` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the seed file:\n\n```bash\nbunx @ooneex/cli@latest make:seed --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, the seed file is generated under `modules/<module>/src/seeds/` instead of `src/seeds/`. The command will:\n- Generate a seed file in `src/seeds/` (or `modules/<module>/src/seeds/` with `--module`)\n- Add a `seed:run` script to `package.json` if not already present\n\n### 2. Read the generated file\n\nRead the generated seed file in `src/seeds/` to understand the scaffolded code.\n\n### 3. Complete the seed\n\nEdit the generated seed file to implement:\n\n- Import the relevant entity classes\n- Create seed data with hardcoded nanoid values for `id` fields (generate via `bun -e \"import { random } from '@ooneex/utils'; console.log(random.nanoid())\"`)\n- Do NOT use sequential IDs like `\"item-1\"`, `\"item-2\"`\n- Ensure the same entity uses the same ID everywhere it appears\n\n### 4. Lint and format\n\nRun linting and formatting on the generated file:\n\n```bash\nbunx biome check --fix src/seeds/\n```\n";var zr="---\nname: make:service\ndescription: Generate a new service class with its test file, then complete the generated code. Use when creating a new business logic service that implements IService from @ooneex/service.\n---\n\n# Make Service Class\n\nGenerate a new service class and its test file using the `make:service` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the service class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:service --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/services/<Name>Service.ts` - The service class file (or `modules/<module>/src/services/<Name>Service.ts` with `--module`)\n- `tests/services/<Name>Service.spec.ts` - The test file (or `modules/<module>/tests/services/<Name>Service.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the service class\n\nEdit `src/services/<Name>Service.ts` to complete the implementation:\n\n- Define a proper type for `ServiceDataType` instead of `Record<string, unknown>`\n- Implement the `execute()` method with actual business logic\n- Inject any required dependencies (repositories, other services, etc.) via the constructor\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { decorator } from \"@ooneex/service\";\nimport type { IService } from \"@ooneex/service\";\n\ntype ServiceDataType = Record<string, unknown>;\n\n@decorator.service()\nexport class <Name>Service<T extends ServiceDataType = ServiceDataType> implements IService<T> {\n public async execute(data?: T): Promise<void> {\n // TODO: Implement service logic\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/services/<Name>Service.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, execute method)\n- Add tests relevant to the specific service behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Service } from \"@/services/<Name>Service\";\n\ndescribe(\"<Name>Service\", () => {\n test(\"should have class name ending with 'Service'\", () => {\n expect(<Name>Service.name.endsWith(\"Service\")).toBe(true);\n });\n\n test(\"should have 'execute' method\", () => {\n expect(<Name>Service.prototype.execute).toBeDefined();\n expect(typeof <Name>Service.prototype.execute).toBe(\"function\");\n });\n});\n```\n\n### 5. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/services/<Name>Service.ts tests/services/<Name>Service.spec.ts\n```\n";var Zr="---\nname: make:storage\ndescription: Generate a new storage class with its test file, then complete the generated code. Use when creating a new S3-compatible storage adapter that extends Storage from @ooneex/storage.\n---\n\n# Make Storage Class\n\nGenerate a new storage class and its test file using the `make:storage` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the storage class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:storage --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/storage/<Name>Storage.ts` - The storage class file (or `modules/<module>/src/storage/<Name>Storage.ts` with `--module`)\n- `tests/storage/<Name>Storage.spec.ts` - The test file (or `modules/<module>/tests/storage/<Name>Storage.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the storage class\n\nEdit `src/storage/<Name>Storage.ts` to complete the implementation:\n\n- Set the `bucket` property to the appropriate bucket name\n- Verify the environment variable names match the project configuration (`STORAGE_<NAME_UPPER>_ACCESS_KEY`, `STORAGE_<NAME_UPPER>_SECRET_KEY`, `STORAGE_<NAME_UPPER>_ENDPOINT`, `STORAGE_<NAME_UPPER>_REGION`)\n- Add any additional storage-specific methods if needed\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { Storage, decorator, StorageException } from \"@ooneex/storage\";\nimport type { S3Options } from \"bun\";\n\n@decorator.storage()\nexport class <Name>Storage extends Storage {\n protected bucket: string;\n private readonly accessKey: string;\n private readonly secretKey: string;\n private readonly endpoint: string;\n private readonly region: string;\n\n constructor(options?: {\n accessKey?: string;\n secretKey?: string;\n endpoint?: string;\n region?: string;\n }) {\n super();\n\n const accessKey = options?.accessKey || Bun.env.STORAGE_<NAME_UPPER>_ACCESS_KEY;\n const secretKey = options?.secretKey || Bun.env.STORAGE_<NAME_UPPER>_SECRET_KEY;\n const endpoint = options?.endpoint || Bun.env.STORAGE_<NAME_UPPER>_ENDPOINT;\n\n // ... validation throws StorageException if missing ...\n\n this.accessKey = accessKey;\n this.secretKey = secretKey;\n this.endpoint = endpoint;\n this.region = options?.region || Bun.env.STORAGE_<NAME_UPPER>_REGION || \"auto\";\n }\n\n public getOptions(): S3Options {\n return {\n accessKeyId: this.accessKey,\n secretAccessKey: this.secretKey,\n endpoint: this.endpoint,\n bucket: this.bucket,\n region: this.region,\n };\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/storage/<Name>Storage.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, bucket field, getOptions method)\n- Add tests relevant to the specific storage class behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>StorageAdapter } from \"@/storage/<Name>StorageAdapter\";\n\ndescribe(\"<Name>StorageAdapter\", () => {\n test(\"should have class name ending with 'StorageAdapter'\", () => {\n expect(<Name>StorageAdapter.name.endsWith(\"StorageAdapter\")).toBe(true);\n });\n\n test(\"should have 'bucket' field\", () => {\n expect(\"bucket\" in <Name>StorageAdapter.prototype || \"bucket\" in Object.getOwnPropertyNames(<Name>StorageAdapter.prototype)).toBe(true);\n });\n\n test(\"should have 'getOptions' method\", () => {\n expect(<Name>StorageAdapter.prototype.getOptions).toBeDefined();\n expect(typeof <Name>StorageAdapter.prototype.getOptions).toBe(\"function\");\n });\n});\n```\n\n### 5. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/storage/<Name>Storage.ts tests/storage/<Name>Storage.spec.ts\n```\n";var Qr="---\nname: make:vector-database\ndescription: Generate a new vector database class with its test file, then complete the generated code. Use when creating a new vector database that extends VectorDatabase from @ooneex/rag.\n---\n\n# Make Vector Database Class\n\nGenerate a new vector database class and its test file using the `make:vector-database` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the vector database class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:vector-database --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/databases/<Name>VectorDatabase.ts` - The vector database class file (or `modules/<module>/src/databases/<Name>VectorDatabase.ts` with `--module`)\n- `tests/databases/<Name>VectorDatabase.spec.ts` - The test file (or `modules/<module>/tests/databases/<Name>VectorDatabase.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the vector database class\n\nEdit `src/databases/<Name>VectorDatabase.ts` to complete the implementation:\n\n- Set the `getDatabaseUri()` return value to the actual LanceDB database path\n- Configure the embedding provider and model in `getEmbeddingModel()`\n- Define the custom data fields in `DataType` and map them in `getSchema()`\n- Import the appropriate Apache Arrow types for your schema fields\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { VectorDatabase, decorator } from \"@ooneex/rag\";\nimport type { EmbeddingModelType, EmbeddingProviderType, FieldValueType } from \"@ooneex/rag\";\nimport { Utf8 } from \"apache-arrow\";\n\ntype DataType = {\n name: string;\n};\n\n@decorator.vectorDatabase()\nexport class <Name>VectorDatabase extends VectorDatabase<DataType> {\n public getDatabaseUri(): string {\n return \"\";\n }\n\n public getEmbeddingModel(): { provider: EmbeddingProviderType; model: EmbeddingModelType[\"model\"] } {\n return { provider: \"openai\", model: \"text-embedding-ada-002\" };\n }\n\n public getSchema(): { [K in keyof DataType]: FieldValueType } {\n return {\n name: new Utf8(),\n };\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/databases/<Name>VectorDatabase.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, getDatabaseUri, getEmbeddingModel, getSchema methods)\n- Add tests relevant to the specific vector database class behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>VectorDatabase } from \"@/databases/<Name>VectorDatabase\";\n\ndescribe(\"<Name>VectorDatabase\", () => {\n test(\"should have class name ending with 'VectorDatabase'\", () => {\n expect(<Name>VectorDatabase.name.endsWith(\"VectorDatabase\")).toBe(true);\n });\n\n test(\"should have 'getDatabaseUri' method\", () => {\n expect(<Name>VectorDatabase.prototype.getDatabaseUri).toBeDefined();\n expect(typeof <Name>VectorDatabase.prototype.getDatabaseUri).toBe(\"function\");\n });\n\n test(\"should have 'getEmbeddingModel' method\", () => {\n expect(<Name>VectorDatabase.prototype.getEmbeddingModel).toBeDefined();\n expect(typeof <Name>VectorDatabase.prototype.getEmbeddingModel).toBe(\"function\");\n });\n\n test(\"should have 'getSchema' method\", () => {\n expect(<Name>VectorDatabase.prototype.getSchema).toBeDefined();\n expect(typeof <Name>VectorDatabase.prototype.getSchema).toBe(\"function\");\n });\n});\n```\n\n### 5. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/databases/<Name>VectorDatabase.ts tests/databases/<Name>VectorDatabase.spec.ts\n```\n";var Xr=`---
|
|
1804
|
+
`;var $o="---\nname: make:ai\ndescription: Generate a new AI class with its test file, then complete the generated code. Use when creating a new AI chat class that uses OpenAI via the @ooneex/ai package.\n---\n\n# Make AI Class\n\nGenerate a new AI class and its test file using the `make:ai` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the AI class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:ai --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/ai/<Name>Ai.ts` - The AI class file (or `modules/<module>/src/ai/<Name>Ai.ts` with `--module`)\n- `tests/ai/<Name>Ai.spec.ts` - The test file (or `modules/<module>/tests/ai/<Name>Ai.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the AI class\n\nEdit `src/ai/<Name>Ai.ts` to complete the implementation:\n\n- Update the prompt in the `run` method from `\"My prompt\"` to a meaningful prompt based on the class purpose\n- Update the prompt in the `runStream` method from `\"My prompt\"` to a meaningful prompt based on the class purpose\n- Add any additional configuration or methods relevant to the AI class purpose\n- Ensure proper typing for the `run<T>()` generic return type\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { decorator, type IAiChat, OpenAi, type OpenAiConfigType } from \"@ooneex/ai\";\nimport { inject } from \"@ooneex/container\";\n\n@decorator.ai()\nexport class <Name>Ai implements IAiChat<OpenAiConfigType> {\n constructor(@inject(OpenAi) private readonly ai: OpenAi) {}\n\n public async run<T>(prompt?: string, config?: Omit<OpenAiConfigType, \"prompt\">): Promise<T> {\n return this.ai.run<T>(prompt || \"My prompt\", config);\n }\n\n public async *runStream(\n prompt?: string,\n config?: Omit<OpenAiConfigType, \"prompt\" | \"output\">,\n ): AsyncGenerator<string, void, unknown> {\n yield* this.ai.runStream(prompt || \"My prompt\", config);\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/ai/<Name>Ai.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, run method, runStream method)\n- Add tests relevant to the specific AI class behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Ai } from \"@/ai/<Name>Ai\";\n\ndescribe(\"<Name>Ai\", () => {\n test(\"should have class name ending with 'Ai'\", () => {\n expect(<Name>Ai.name.endsWith(\"Ai\")).toBe(true);\n });\n\n test(\"should have 'run' method\", () => {\n expect(<Name>Ai.prototype.run).toBeDefined();\n expect(typeof <Name>Ai.prototype.run).toBe(\"function\");\n });\n\n test(\"should have 'runStream' method\", () => {\n expect(<Name>Ai.prototype.runStream).toBeDefined();\n expect(typeof <Name>Ai.prototype.runStream).toBe(\"function\");\n });\n});\n```\n\n### 5. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/ai/<Name>Ai.ts tests/ai/<Name>Ai.spec.ts\n```\n";var Wo="---\nname: make:analytics\ndescription: Generate a new analytics class with its test file, then complete the generated code. Use when creating a new analytics tracking class that uses the @ooneex/analytics package.\n---\n\n# Make Analytics Class\n\nGenerate a new analytics class and its test file using the `make:analytics` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the analytics class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:analytics --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/analytics/<Name>Analytics.ts` - The analytics class file (or `modules/<module>/src/analytics/<Name>Analytics.ts` with `--module`)\n- `tests/analytics/<Name>Analytics.spec.ts` - The test file (or `modules/<module>/tests/analytics/<Name>Analytics.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the analytics class\n\nEdit `src/analytics/<Name>Analytics.ts` to complete the implementation:\n\n- Implement the `capture` method with actual analytics tracking logic\n- Define a proper type for `CaptureOptionsType` instead of `Record<string, unknown>` based on the analytics purpose\n- Add any additional methods or properties relevant to the analytics class purpose\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { decorator } from \"@ooneex/analytics\";\nimport type { IAnalytics } from \"@ooneex/analytics\";\n\ntype CaptureOptionsType = Record<string, unknown>;\n\n@decorator.analytics()\nexport class <Name>Analytics<T extends CaptureOptionsType = CaptureOptionsType> implements IAnalytics<T> {\n public capture(options: T): void {\n // console.log(\"Analytics captured:\", options);\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/analytics/<Name>Analytics.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, capture method)\n- Add tests relevant to the specific analytics class behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Analytics } from \"@/analytics/<Name>Analytics\";\n\ndescribe(\"<Name>Analytics\", () => {\n test(\"should have class name ending with 'Analytics'\", () => {\n expect(<Name>Analytics.name.endsWith(\"Analytics\")).toBe(true);\n });\n\n test(\"should have 'capture' method\", () => {\n expect(<Name>Analytics.prototype.capture).toBeDefined();\n expect(typeof <Name>Analytics.prototype.capture).toBe(\"function\");\n });\n});\n```\n\n### 5. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/analytics/<Name>Analytics.ts tests/analytics/<Name>Analytics.spec.ts\n```\n";var qo="---\nname: make:cache\ndescription: Generate a new cache adapter class with its test file, then complete the generated code. Use when creating a new cache adapter that implements the ICache interface from @ooneex/cache.\n---\n\n# Make Cache Class\n\nGenerate a new cache class and its test file using the `make:cache` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the cache class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:cache --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/cache/<Name>Cache.ts` - The cache class file (or `modules/<module>/src/cache/<Name>Cache.ts` with `--module`)\n- `tests/cache/<Name>Cache.spec.ts` - The test file (or `modules/<module>/tests/cache/<Name>Cache.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the cache class\n\nEdit `src/cache/<Name>Cache.ts` to complete the implementation:\n\n- Implement the `get` method to retrieve cached values by key\n- Implement the `set` method to store values with optional TTL\n- Implement the `delete` method to remove cached entries\n- Implement the `has` method to check key existence\n- Replace the `CacheException` throws with actual cache logic\n- Inject any required dependencies (e.g., Redis client) via the constructor\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { CacheException, decorator } from \"@ooneex/cache\";\nimport type { ICache } from \"@ooneex/cache\";\n\n@decorator.cache()\nexport class <Name>Cache implements ICache {\n public async get<T = unknown>(key: string): Promise<T | undefined> {\n throw new CacheException(`Failed to get key \"${key}\": Not implemented`);\n }\n\n public async set<T = unknown>(key: string, value: T, ttl?: number): Promise<void> {\n throw new CacheException(`Failed to set key \"${key}\": Not implemented`);\n }\n\n public async delete(key: string): Promise<boolean> {\n throw new CacheException(`Failed to delete key \"${key}\": Not implemented`);\n }\n\n public async has(key: string): Promise<boolean> {\n throw new CacheException(`Failed to check if key \"${key}\" exists: Not implemented`);\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/cache/<Name>Cache.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, get, set, delete, has methods)\n- Add tests relevant to the specific cache class behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Cache } from \"@/cache/<Name>Cache\";\n\ndescribe(\"<Name>Cache\", () => {\n test(\"should have class name ending with 'Cache'\", () => {\n expect(<Name>Cache.name.endsWith(\"Cache\")).toBe(true);\n });\n\n test(\"should have 'get' method\", () => {\n expect(<Name>Cache.prototype.get).toBeDefined();\n expect(typeof <Name>Cache.prototype.get).toBe(\"function\");\n });\n\n test(\"should have 'set' method\", () => {\n expect(<Name>Cache.prototype.set).toBeDefined();\n expect(typeof <Name>Cache.prototype.set).toBe(\"function\");\n });\n\n test(\"should have 'delete' method\", () => {\n expect(<Name>Cache.prototype.delete).toBeDefined();\n expect(typeof <Name>Cache.prototype.delete).toBe(\"function\");\n });\n\n test(\"should have 'has' method\", () => {\n expect(<Name>Cache.prototype.has).toBeDefined();\n expect(typeof <Name>Cache.prototype.has).toBe(\"function\");\n });\n});\n```\n\n### 5. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/cache/<Name>Cache.ts tests/cache/<Name>Cache.spec.ts\n```\n";var Ko="---\nname: make:controller\ndescription: Generate a new controller class with route type and test file, then complete the generated code. Use when creating a new HTTP or WebSocket controller with routing, validation, and role-based access.\n---\n\n# Make Controller Class\n\nGenerate a new controller class, its route type, and test file using the `make:controller` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the controller class and related files:\n\n```bash\nbunx @ooneex/cli@latest make:controller --name <name> --module <module> --is-socket <true|false> --route.name <route.name> --route.path <route.path> --route.method <route.method>\n```\n\nWhere:\n- `<name>` is the controller name provided by the user\n- `--module` is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root\n- `--is-socket` determines HTTP vs WebSocket controller (defaults to `false`)\n- `--route.name` is the route name using dot notation: `<resource>.<action>` (e.g., `user.create`, `book.list`, `flashcard.delete`)\n- `--route.path` is the route path (e.g., `/api/users`)\n- `--route.method` is the HTTP method (e.g., `get`, `post`, `put`, `patch`, `delete`) \u2014 only for HTTP controllers\n\nThe command will generate (paths prefixed with `modules/<module>/` when `--module` is provided):\n- `src/controllers/<Name>Controller.ts` - The controller class file\n- `src/types/routes/<route.name>.ts` - The route type file\n- `tests/controllers/<Name>Controller.spec.ts` - The test file\n\n### 2. Read the generated files\n\nRead all three generated files to understand the scaffolded code.\n\n### 3. Complete the route type\n\nEdit `src/types/routes/<route.name>.ts` to define the route's type contract.\n\n**Add or remove `params`, `payload`, and `queries` based on context:**\n\n- **`params`** \u2014 Include only when the route path contains dynamic segments (e.g., `/api/users/:id`). Remove entirely for routes with no URL parameters (e.g., `/api/users`).\n- **`payload`** \u2014 Include only for methods that accept a request body (`post`, `put`, `patch`). Remove entirely for `get` and `delete` routes.\n- **`queries`** \u2014 Include only when the route supports query string filtering, pagination, or sorting (e.g., list/search endpoints). Remove entirely when not needed.\n- **`response`** \u2014 Always include.\n\nThe generated route type structure follows this pattern (remove unused sections):\n\n```typescript\n// Example: GET /api/users (list) \u2014 no params, no payload, has queries\nexport type <TypeName>RouteType = {\n queries: {\n\n },\n response: {\n\n },\n};\n\n// Example: POST /api/users (create) \u2014 no params, has payload, no queries\nexport type <TypeName>RouteType = {\n payload: {\n\n },\n response: {\n\n },\n};\n\n// Example: GET /api/users/:id (detail) \u2014 has params, no payload, no queries\nexport type <TypeName>RouteType = {\n params: {\n\n },\n response: {\n\n },\n};\n\n// Example: PUT /api/users/:id (update) \u2014 has params, has payload, no queries\nexport type <TypeName>RouteType = {\n params: {\n\n },\n payload: {\n\n },\n response: {\n\n },\n};\n```\n\n### 4. Complete the controller class\n\nEdit `src/controllers/<Name>Controller.ts` to complete the implementation:\n\n- Set appropriate `roles` for access control\n- Add a meaningful `description` for the route that explains what the endpoint does (e.g., `\"Create a new user account\"`, `\"List all books with pagination\"`)\n- Implement the `index` method with actual controller logic\n- Inject any required dependencies (repositories, services) via the constructor\n\n**Add or remove `params`, `payload`, and `queries` in the `@Route` decorator to match the route type (step 3):**\n\n- **`params`** \u2014 Include with `Assert()` validators only when the route has URL parameters. Remove the `params` key entirely otherwise.\n- **`payload`** \u2014 Include with `Assert({...})` only for `post`, `put`, `patch` methods. Remove the `payload` key entirely for `get` and `delete`.\n- **`queries`** \u2014 Include with `Assert({...})` only when query parameters are expected. Remove the `queries` key entirely otherwise.\n- **`response`** \u2014 Always include with `Assert({...})`.\n\n**HTTP controller** generated structure (remove `params`, `payload`, `queries` as needed \u2014 see rules above):\n\n```typescript\nimport type { ContextType } from \"@ooneex/controller\";\nimport { ERole } from \"@ooneex/role\";\nimport { Route } from \"@ooneex/routing\";\nimport { Assert } from \"@ooneex/validation\";\nimport type { <TypeName>RouteType } from \"../types/routes/<route.name>\";\n\n@Route.<method>(\"<route.path>\", {\n name: \"<route.name>\",\n version: 1,\n description: \"\",\n params: {\n // id: Assert(\"string\"),\n },\n payload: Assert({\n\n }),\n queries: Assert({\n\n }),\n response: Assert({\n\n }),\n roles: [ERole.USER],\n})\nexport class <Name>Controller {\n public async index(context: ContextType<<TypeName>RouteType>) {\n // const { id } = context.params;\n\n return context.response.json({\n\n });\n }\n}\n```\n\n**Socket controller** generated structure (remove `params`, `payload`, `queries` as needed \u2014 see rules above):\n\n```typescript\nimport type { ContextType } from \"@ooneex/socket\";\nimport { ERole } from \"@ooneex/role\";\nimport { Route } from \"@ooneex/routing\";\nimport { Assert } from \"@ooneex/validation\";\nimport type { <TypeName>RouteType } from \"../types/routes/<route.name>\";\n\n@Route.socket(\"<route.path>\", {\n name: \"<route.name>\",\n version: 1,\n description: \"\",\n params: {\n // id: Assert(\"string\"),\n },\n payload: Assert({\n\n }),\n queries: Assert({\n\n }),\n response: Assert({\n\n }),\n roles: [ERole.USER],\n})\nexport class <Name>Controller {\n public async index(context: ContextType<<TypeName>RouteType>) {\n // const { id } = context.params;\n\n return context.response.json({\n\n });\n }\n}\n```\n\n### 5. Complete the test file\n\nEdit `tests/controllers/<Name>Controller.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, index method)\n- Add tests relevant to the specific controller behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Controller } from \"@/controllers/<Name>Controller\";\n\ndescribe(\"<Name>Controller\", () => {\n test(\"should have class name ending with 'Controller'\", () => {\n expect(<Name>Controller.name.endsWith(\"Controller\")).toBe(true);\n });\n\n test(\"should have 'index' method\", () => {\n expect(<Name>Controller.prototype.index).toBeDefined();\n expect(typeof <Name>Controller.prototype.index).toBe(\"function\");\n });\n});\n```\n\n### 6. Register the controller in the module\n\nAdd the new controller to the module's `controllers` array in `src/<PascalModuleName>Module.ts` (e.g., `src/BookModule.ts` for the `book` module):\n\n```typescript\nimport type { ModuleType } from \"@ooneex/module\";\nimport { <Name>Controller } from \"./controllers/<Name>Controller\";\n\nexport const <PascalModuleName>Module: ModuleType = {\n controllers: [<Name>Controller],\n entities: [],\n permissions: [],\n middlewares: [],\n cronJobs: [],\n events: [],\n};\n```\n\nThe module file uses PascalCase naming: `<PascalModuleName>Module.ts` with export `<PascalModuleName>Module`.\n\nIf the module already has other controllers registered, append the new controller to the existing `controllers` array and add the import alongside existing imports.\n\n### 7. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/controllers/<Name>Controller.ts src/types/routes/<route.name>.ts tests/controllers/<Name>Controller.spec.ts\n```\n\n### 8. Create the service\n\nAfter the controller is created, generate a service class for the controller's business logic using the `make:service` skill:\n\n```\n/make:service --name <Name>\n```\n\nWhere `<Name>` matches the controller name (e.g., if the controller is `CreateUserController`, the service is `CreateUserService`).\n\n### 9. Create the pubsub event\n\nAfter the service is created, generate a pubsub event class for the controller's domain events using the `make:pubsub` skill:\n\n```\n/make:pubsub --name <Name> --channel <resource>.<action>\n```\n\nWhere:\n- `<Name>` matches the controller name (e.g., if the controller is `CreateUserController`, the event is `CreateUserEvent`)\n- `<resource>.<action>` follows the same dot notation as the route name (e.g., `user.create`, `book.delete`)\n\nOnce the event is created:\n- Inject the **service** into the **event** via the constructor, and call the service's `execute` method from the event's `handler` method.\n- Inject the **event** into the **controller** via the constructor, and publish the event from the controller's `index` method.\n";var Ho="---\nname: make:cron\ndescription: Generate a new cron job class with its test file, then complete the generated code. Use when creating a new scheduled task that extends the Cron base class from @ooneex/cron.\n---\n\n# Make Cron Class\n\nGenerate a new cron class and its test file using the `make:cron` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the cron class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:cron --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/cron/<Name>Cron.ts` - The cron class file (or `modules/<module>/src/cron/<Name>Cron.ts` with `--module`)\n- `tests/cron/<Name>Cron.spec.ts` - The test file (or `modules/<module>/tests/cron/<Name>Cron.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the cron class\n\nEdit `src/cron/<Name>Cron.ts` to complete the implementation:\n\n- Set the appropriate cron schedule in `getTime()` (e.g., `\"every 5 minutes\"`, `\"every 1 hours\"`, `\"every 30 seconds\"`)\n- Set the timezone in `getTimeZone()` if needed, or keep `null` for server timezone\n- Implement the `handler()` method with the actual cron job logic\n- Inject any required dependencies via the constructor\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport type { TimeZoneType } from \"@ooneex/country\";\nimport type { CronTimeType } from \"@ooneex/cron\";\nimport { Cron, decorator } from \"@ooneex/cron\";\n\n@decorator.cron()\nexport class <Name>Cron extends Cron {\n public getTime(): CronTimeType {\n // Examples: \"every 5 minutes\", \"every 1 hours\", \"every 30 seconds\"\n return \"every 1 hours\";\n }\n\n public getTimeZone(): TimeZoneType | null {\n // Return null to use server timezone, or specify a timezone like \"Europe/Paris\"\n return null;\n }\n\n public async handler(): Promise<void> {\n // Implement your cron handler logic here\n // console.log(\"<Name>Cron handler executed\");\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/cron/<Name>Cron.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, getTime, getTimeZone, handler methods)\n- Add tests relevant to the specific cron class behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Cron } from \"@/cron/<Name>Cron\";\n\ndescribe(\"<Name>Cron\", () => {\n test(\"should have class name ending with 'Cron'\", () => {\n expect(<Name>Cron.name.endsWith(\"Cron\")).toBe(true);\n });\n\n test(\"should have 'getTime' method\", () => {\n expect(<Name>Cron.prototype.getTime).toBeDefined();\n expect(typeof <Name>Cron.prototype.getTime).toBe(\"function\");\n });\n\n test(\"should have 'getTimeZone' method\", () => {\n expect(<Name>Cron.prototype.getTimeZone).toBeDefined();\n expect(typeof <Name>Cron.prototype.getTimeZone).toBe(\"function\");\n });\n\n test(\"should have 'handler' method\", () => {\n expect(<Name>Cron.prototype.handler).toBeDefined();\n expect(typeof <Name>Cron.prototype.handler).toBe(\"function\");\n });\n});\n```\n\n### 5. Register the cron job in the module\n\nAdd the new cron job to the module's `cronJobs` array in `src/<PascalModuleName>Module.ts` (e.g., `src/BookModule.ts` for the `book` module):\n\n```typescript\nimport type { ModuleType } from \"@ooneex/module\";\nimport { <Name>Cron } from \"./cron/<Name>Cron\";\n\nexport const <PascalModuleName>Module: ModuleType = {\n controllers: [],\n entities: [],\n permissions: [],\n middlewares: [],\n cronJobs: [<Name>Cron],\n events: [],\n};\n```\n\nThe module file uses PascalCase naming: `<PascalModuleName>Module.ts` with export `<PascalModuleName>Module`.\n\nIf the module already has other cron jobs registered, append the new cron job to the existing `cronJobs` array and add the import alongside existing imports.\n\n### 6. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/cron/<Name>Cron.ts tests/cron/<Name>Cron.spec.ts\n```\n";var Fo="---\nname: make:database\ndescription: Generate a new database class with its test file, then complete the generated code. Use when creating a new database adapter that extends TypeormDatabase from @ooneex/database.\n---\n\n# Make Database Class\n\nGenerate a new database class and its test file using the `make:database` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the database class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:database --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/databases/<Name>Database.ts` - The database class file (or `modules/<module>/src/databases/<Name>Database.ts` with `--module`)\n- `tests/databases/<Name>Database.spec.ts` - The test file (or `modules/<module>/tests/databases/<Name>Database.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the database class\n\nEdit `src/databases/<Name>Database.ts` to complete the implementation:\n\n- Add entity imports and register them in the `entities` array\n- Adjust the database path if needed (default is `\"var/db\"`)\n- Configure DataSource options as appropriate (type, synchronize, etc.)\n- Inject any required dependencies via the constructor\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { DataSource } from \"typeorm\";\nimport { TypeormDatabase, DatabaseException, decorator } from \"@ooneex/database\";\n\n@decorator.database()\nexport class <Name>Database extends TypeormDatabase {\n public getSource(database?: string): DataSource {\n database = database || \"var/db\";\n\n this.source = new DataSource({\n synchronize: false,\n entities: [\n // TODO: Load your entities here\n ],\n enableWAL: true,\n busyErrorRetry: 2000,\n busyTimeout: 30_000,\n database,\n type: \"sqlite\",\n });\n\n return this.source;\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/databases/<Name>Database.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, getSource method)\n- Add tests relevant to the specific database class behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Database } from \"@/databases/<Name>Database\";\n\ndescribe(\"<Name>Database\", () => {\n test(\"should have class name ending with 'Database'\", () => {\n expect(<Name>Database.name.endsWith(\"Database\")).toBe(true);\n });\n\n test(\"should have 'getSource' method\", () => {\n expect(<Name>Database.prototype.getSource).toBeDefined();\n expect(typeof <Name>Database.prototype.getSource).toBe(\"function\");\n });\n});\n```\n\n### 5. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/databases/<Name>Database.ts tests/databases/<Name>Database.spec.ts\n```\n";var Vo="---\nname: make:entity\ndescription: Generate a new TypeORM entity class with its test file, then complete the generated code. Use when creating a new database entity with columns, relations, and table mapping.\n---\n\n# Make Entity Class\n\nGenerate a new entity class and its test file using the `make:entity` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the entity class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:entity --name <name> --module <module> --table-name <table_name>\n```\n\nWhere `<name>` is the name provided by the user. The `--table-name` option is optional \u2014 if omitted, it defaults to the snake_case pluralized form of the name (e.g., `UserProfile` becomes `user_profiles`). The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/entities/<Name>Entity.ts` - The entity class file (or `modules/<module>/src/entities/<Name>Entity.ts` with `--module`)\n- `tests/entities/<Name>Entity.spec.ts` - The test file (or `modules/<module>/tests/entities/<Name>Entity.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the entity class\n\nEdit `src/entities/<Name>Entity.ts` to complete the implementation:\n\n- Add entity-specific columns with appropriate TypeORM decorators (`@Column`)\n- Add relations if needed (`@ManyToOne`, `@OneToMany`, `@ManyToMany`, etc.)\n- Remove any scaffolded columns that are not relevant to the entity\n- Adjust column types, lengths, and constraints as needed\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport type { LocaleType } from \"@ooneex/translation\";\nimport { random } from \"@ooneex/utils\";\nimport { Column, CreateDateColumn, DeleteDateColumn, PrimaryColumn, UpdateDateColumn } from \"typeorm\";\n\n@Entity({\n name: \"<table_name>\",\n})\nexport class <Name>Entity extends BaseEntity {\n @PrimaryColumn({ name: \"id\", type: \"varchar\", length: 25 })\n id: string = random.nanoid(25);\n\n @Column({\n name: \"is_locked\",\n type: \"boolean\",\n default: false,\n nullable: true,\n })\n isLocked?: boolean;\n\n @Column({ name: \"locked_at\", type: \"timestamptz\", nullable: true })\n lockedAt?: Date;\n\n @Column({\n name: \"is_blocked\",\n type: \"boolean\",\n default: false,\n nullable: true,\n })\n isBlocked?: boolean;\n\n @Column({ name: \"blocked_at\", type: \"timestamptz\", nullable: true })\n blockedAt?: Date;\n\n @Column({ name: \"block_reason\", type: \"text\", nullable: true })\n blockReason?: string;\n\n @Column({ name: \"is_public\", type: \"boolean\", default: true, nullable: true })\n isPublic?: boolean;\n\n @Column({ name: \"lang\", type: \"varchar\", length: 10, nullable: true })\n lang?: LocaleType;\n\n @CreateDateColumn({ name: \"created_at\" })\n createdAt?: Date;\n\n @UpdateDateColumn({ name: \"updated_at\" })\n updatedAt?: Date;\n\n @DeleteDateColumn({ name: \"deleted_at\" })\n deletedAt?: Date;\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/entities/<Name>Entity.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, id, default columns)\n- Add tests for any new entity-specific columns and relations\n- Update tests if scaffolded columns were removed\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Entity } from \"@/entities/<Name>Entity\";\n\ndescribe(\"<Name>Entity\", () => {\n test(\"should have class name ending with 'Entity'\", () => {\n expect(<Name>Entity.name.endsWith(\"Entity\")).toBe(true);\n });\n\n test(\"should have 'id' property with default nanoid\", () => {\n const entity = new <Name>Entity();\n expect(entity.id).toBeDefined();\n expect(typeof entity.id).toBe(\"string\");\n expect(entity.id.length).toBe(25);\n });\n\n test(\"should have 'isLocked' property\", () => {\n const entity = new <Name>Entity();\n expect(\"isLocked\" in entity).toBe(true);\n });\n\n // ... additional property tests\n});\n```\n\n### 5. Register the entity in the module\n\nAdd the new entity to the module's `entities` array in `src/<PascalModuleName>Module.ts` (e.g., `src/BookModule.ts` for the `book` module):\n\n```typescript\nimport type { ModuleType } from \"@ooneex/module\";\nimport { <Name>Entity } from \"./entities/<Name>Entity\";\n\nexport const <PascalModuleName>Module: ModuleType = {\n controllers: [],\n entities: [<Name>Entity],\n permissions: [],\n middlewares: [],\n cronJobs: [],\n events: [],\n};\n```\n\nThe module file uses PascalCase naming: `<PascalModuleName>Module.ts` with export `<PascalModuleName>Module`.\n\nIf the module already has other entities registered, append the new entity to the existing `entities` array and add the import alongside existing imports.\n\n### 6. Create a migration for the entity\n\nAfter creating or updating an entity, generate a migration to apply the corresponding schema changes to the database.\n\nRun the generator:\n\n```bash\nbunx @ooneex/cli@latest make:migration\n```\n\nThen read the generated migration file in `src/migrations/` and complete it:\n\n- In the `up` method, write the SQL to create the table (or alter it if updating an existing entity). Include all columns, types, constraints, defaults, and indexes matching the entity definition.\n- In the `down` method, write the reverse SQL to undo the changes (e.g., `DROP TABLE` or `ALTER TABLE DROP COLUMN`).\n- If the migration depends on another migration (e.g., a foreign key referencing another table), add that migration class to the `getDependencies()` return array.\n\nExample `up` method for a new entity:\n\n```typescript\npublic async up(tx: TransactionSQL): Promise<void> {\n await tx`\n CREATE TABLE IF NOT EXISTS <table_name> (\n id VARCHAR(25) PRIMARY KEY,\n is_locked BOOLEAN DEFAULT false,\n locked_at TIMESTAMPTZ,\n is_blocked BOOLEAN DEFAULT false,\n blocked_at TIMESTAMPTZ,\n block_reason TEXT,\n is_public BOOLEAN DEFAULT true,\n lang VARCHAR(10),\n created_at TIMESTAMPTZ DEFAULT NOW(),\n updated_at TIMESTAMPTZ DEFAULT NOW(),\n deleted_at TIMESTAMPTZ\n )\n `;\n}\n```\n\n### 7. Create a repository for the entity\n\nAfter creating the entity, generate a repository to handle database operations for it.\n\nRun the generator:\n\n```bash\nbunx @ooneex/cli@latest make:repository --name <name>\n```\n\nWhere `<name>` is the same name used for the entity. The command will generate:\n- `src/repositories/<Name>Repository.ts` - The repository class\n- `tests/repositories/<Name>Repository.spec.ts` - The test file\n\nThen read the generated files and complete the repository implementation:\n\n- Adjust search fields in the `find()` method to match the entity's searchable columns\n- Customize relations loading in `findOne`/`findOneBy` if the entity has relations\n- Add any domain-specific methods relevant to the entity\n- Remove methods that don't apply to the entity\n- Update tests to match the final repository methods\n\n### 8. Lint and format\n\nRun linting and formatting on all generated files:\n\n```bash\nbunx biome check --fix src/entities/<Name>Entity.ts tests/entities/<Name>Entity.spec.ts src/repositories/<Name>Repository.ts tests/repositories/<Name>Repository.spec.ts src/migrations/\n```\n";var Yo="---\nname: make:logger\ndescription: Generate a new logger class with its test file, then complete the generated code. Use when creating a new logger that implements the ILogger interface from @ooneex/logger.\n---\n\n# Make Logger Class\n\nGenerate a new logger class and its test file using the `make:logger` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the logger class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:logger --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/loggers/<Name>Logger.ts` - The logger class file (or `modules/<module>/src/loggers/<Name>Logger.ts` with `--module`)\n- `tests/loggers/<Name>Logger.spec.ts` - The test file (or `modules/<module>/tests/loggers/<Name>Logger.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the logger class\n\nEdit `src/loggers/<Name>Logger.ts` to complete the implementation:\n\n- Implement the `init()` method to set up the logger (e.g., open file handles, configure transports)\n- Implement `log`, `debug`, `info`, `success`, `warn`, and `error` methods with actual logging logic\n- Inject any required dependencies via the constructor\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport type { IException } from \"@ooneex/exception\";\nimport type { ILogger } from \"@ooneex/logger\";\nimport type { ScalarType } from \"@ooneex/types\";\nimport { decorator } from \"@ooneex/logger\";\n\n@decorator.logger()\nexport class <Name>Logger implements ILogger {\n public async init(): Promise<void> {\n // Initialize your logger here\n }\n\n public log(message: string, data?: Record<string, ScalarType>): void {\n // Handle general logging\n }\n\n public debug(message: string, data?: Record<string, ScalarType>): void {\n // Handle debug logging\n }\n\n public info(message: string, data?: Record<string, ScalarType>): void {\n // Handle info logging\n }\n\n public success(message: string, data?: Record<string, ScalarType>): void {\n // Handle success logging\n }\n\n public warn(message: string, data?: Record<string, ScalarType>): void {\n // Handle warning logging\n }\n\n public error(message: string | IException, data?: Record<string, ScalarType>): void {\n // Handle error logging\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/loggers/<Name>Logger.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, init, log, debug, info, success, warn, error methods)\n- Add tests relevant to the specific logger class behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Logger } from \"@/loggers/<Name>Logger\";\n\ndescribe(\"<Name>Logger\", () => {\n test(\"should have class name ending with 'Logger'\", () => {\n expect(<Name>Logger.name.endsWith(\"Logger\")).toBe(true);\n });\n\n test(\"should have 'init' method\", () => {\n expect(<Name>Logger.prototype.init).toBeDefined();\n expect(typeof <Name>Logger.prototype.init).toBe(\"function\");\n });\n\n test(\"should have 'log' method\", () => {\n expect(<Name>Logger.prototype.log).toBeDefined();\n expect(typeof <Name>Logger.prototype.log).toBe(\"function\");\n });\n\n test(\"should have 'debug' method\", () => {\n expect(<Name>Logger.prototype.debug).toBeDefined();\n expect(typeof <Name>Logger.prototype.debug).toBe(\"function\");\n });\n\n test(\"should have 'info' method\", () => {\n expect(<Name>Logger.prototype.info).toBeDefined();\n expect(typeof <Name>Logger.prototype.info).toBe(\"function\");\n });\n\n test(\"should have 'success' method\", () => {\n expect(<Name>Logger.prototype.success).toBeDefined();\n expect(typeof <Name>Logger.prototype.success).toBe(\"function\");\n });\n\n test(\"should have 'warn' method\", () => {\n expect(<Name>Logger.prototype.warn).toBeDefined();\n expect(typeof <Name>Logger.prototype.warn).toBe(\"function\");\n });\n\n test(\"should have 'error' method\", () => {\n expect(<Name>Logger.prototype.error).toBeDefined();\n expect(typeof <Name>Logger.prototype.error).toBe(\"function\");\n });\n});\n```\n\n### 5. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/loggers/<Name>Logger.ts tests/loggers/<Name>Logger.spec.ts\n```\n";var zo="---\nname: make:mailer\ndescription: Generate a new mailer class with its template and test files, then complete the generated code. Use when creating a new email sender with JSX template using @ooneex/mailer.\n---\n\n# Make Mailer Class\n\nGenerate a new mailer class, its JSX template, and test files using the `make:mailer` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the mailer class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:mailer --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate (paths prefixed with `modules/<module>/` when `--module` is provided):\n- `src/mailers/<Name>Mailer.ts` - The mailer class file\n- `src/mailers/<Name>MailerTemplate.tsx` - The JSX email template\n- `tests/mailers/<Name>Mailer.spec.ts` - The mailer test file\n- `tests/mailers/<Name>MailerTemplate.spec.ts` - The template test file\n\n### 2. Read the generated files\n\nRead all four generated files to understand the scaffolded code.\n\n### 3. Complete the mailer class\n\nEdit `src/mailers/<Name>Mailer.ts` to complete the implementation:\n\n- Adjust the `send` method config type if additional parameters are needed\n- Add any pre-send logic (validation, data transformation, etc.)\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { inject } from \"@ooneex/container\";\nimport type { IMailer } from \"@ooneex/mailer\";\nimport { type <Name>MailerPropsType, <Name>MailerTemplate } from \"./<Name>MailerTemplate\";\n\nexport class <Name>Mailer implements IMailer {\n constructor(\n @inject(\"mailer\")\n private readonly mailer: IMailer,\n ) {}\n\n public send = async (config: {\n to: string[];\n subject: string;\n from?: { name: string; address: string };\n data?: <Name>MailerPropsType;\n }): Promise<void> => {\n const { data, ...rest } = config;\n\n await this.mailer.send({\n ...rest,\n content: <Name>MailerTemplate(data),\n });\n };\n}\n```\n\n### 4. Complete the mailer template\n\nEdit `src/mailers/<Name>MailerTemplate.tsx` to complete the implementation:\n\n- Update `<Name>MailerPropsType` with the actual props needed for the email\n- Build the email body using `MailerLayout` components (Header, Body, Footer)\n- Add email content, styling, and dynamic data rendering\n\nThe generated template structure follows this pattern:\n\n```tsx\nimport { MailerLayout } from \"@ooneex/mailer\";\n\nexport type <Name>MailerPropsType = {\n link: string;\n};\n\nexport const <Name>MailerTemplate = (props?: <Name>MailerPropsType) => (\n <MailerLayout>\n <MailerLayout.Header />\n <MailerLayout.Body>\n <a href={props?.link}>Login</a>\n </MailerLayout.Body>\n <MailerLayout.Footer />\n </MailerLayout>\n);\n```\n\n### 5. Complete the test files\n\nEdit `tests/mailers/<Name>Mailer.spec.ts` and `tests/mailers/<Name>MailerTemplate.spec.ts` to add meaningful tests beyond the scaffolded ones.\n\n### 6. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/mailers/<Name>Mailer.ts src/mailers/<Name>MailerTemplate.tsx tests/mailers/<Name>Mailer.spec.ts tests/mailers/<Name>MailerTemplate.spec.ts\n```\n";var Zo="---\nname: make:middleware\ndescription: Generate a new middleware class with its test file, then complete the generated code. Use when creating a new HTTP or WebSocket middleware that implements IMiddleware from @ooneex/middleware.\n---\n\n# Make Middleware Class\n\nGenerate a new middleware class and its test file using the `make:middleware` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the middleware class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:middleware --name <name> --module <module> --is-socket <true|false>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The `--is-socket` option determines whether to generate an HTTP middleware or a WebSocket middleware (defaults to `false` if omitted). The command will generate:\n- `src/middlewares/<Name>Middleware.ts` - The middleware class file (or `modules/<module>/src/middlewares/<Name>Middleware.ts` with `--module`)\n- `tests/middlewares/<Name>Middleware.spec.ts` - The test file (or `modules/<module>/tests/middlewares/<Name>Middleware.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the middleware class\n\nEdit `src/middlewares/<Name>Middleware.ts` to complete the implementation:\n\n- Implement the `handler` method with actual middleware logic\n- Add request/response transformations, authentication checks, logging, etc.\n- Inject any required dependencies via the constructor\n\n**HTTP middleware** generated structure:\n\n```typescript\nimport type { ContextType } from \"@ooneex/controller\";\nimport { decorator, type IMiddleware } from \"@ooneex/middleware\";\n\n@decorator.middleware()\nexport class <Name>Middleware implements IMiddleware {\n public async handler(context: ContextType): Promise<ContextType> {\n // Example: Add custom header\n // context.response.header(\"X-Custom-Header\", \"value\");\n\n return context\n }\n}\n```\n\n**Socket middleware** generated structure:\n\n```typescript\nimport type { ContextType } from \"@ooneex/socket\";\nimport { decorator, type IMiddleware } from \"@ooneex/middleware\";\n\n@decorator.middleware()\nexport class <Name>Middleware implements IMiddleware {\n public async handler(context: ContextType): Promise<ContextType> {\n // Example: Add custom header\n // context.response.header(\"X-Custom-Header\", \"value\");\n\n return context\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/middlewares/<Name>Middleware.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, handler method)\n- Add tests relevant to the specific middleware behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Middleware } from \"@/middlewares/<Name>Middleware\";\n\ndescribe(\"<Name>Middleware\", () => {\n test(\"should have class name ending with 'Middleware'\", () => {\n expect(<Name>Middleware.name.endsWith(\"Middleware\")).toBe(true);\n });\n\n test(\"should have 'handler' method\", () => {\n expect(<Name>Middleware.prototype.handler).toBeDefined();\n expect(typeof <Name>Middleware.prototype.handler).toBe(\"function\");\n });\n});\n```\n\n### 5. Register the middleware in the module\n\nAdd the new middleware to the module's `middlewares` array in `src/<PascalModuleName>Module.ts` (e.g., `src/BookModule.ts` for the `book` module):\n\n```typescript\nimport type { ModuleType } from \"@ooneex/module\";\nimport { <Name>Middleware } from \"./middlewares/<Name>Middleware\";\n\nexport const <PascalModuleName>Module: ModuleType = {\n controllers: [],\n entities: [],\n permissions: [],\n middlewares: [<Name>Middleware],\n cronJobs: [],\n events: [],\n};\n```\n\nThe module file uses PascalCase naming: `<PascalModuleName>Module.ts` with export `<PascalModuleName>Module`.\n\nIf the module already has other middlewares registered, append the new middleware to the existing `middlewares` array and add the import alongside existing imports.\n\n### 6. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/middlewares/<Name>Middleware.ts tests/middlewares/<Name>Middleware.spec.ts\n```\n";var Qo="---\nname: make:migration\ndescription: Generate a new database migration file, then complete the generated code. Use when creating a new database migration for schema changes using @ooneex/migrations.\n---\n\n# Make Migration\n\nGenerate a new migration file using the `make:migration` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the migration file:\n\n```bash\nbunx @ooneex/cli@latest make:migration --module <module>\n```\n\nThe `--module` option is optional \u2014 if provided, the migration file is generated under `modules/<module>/src/migrations/` instead of `src/migrations/`. The command will:\n- Generate a timestamped migration file in `src/migrations/` (or `modules/<module>/src/migrations/` with `--module`)\n- Add a `migration:up` script to `package.json` if not already present\n\n### 2. Read the generated file\n\nRead the generated migration file in `src/migrations/` to understand the scaffolded code.\n\n### 3. Complete the migration\n\nEdit the generated migration file to implement:\n\n- The `up` method with the schema changes (create tables, add columns, create indexes, etc.)\n- The `down` method with the reverse operations to undo the migration\n\n### 4. Lint and format\n\nRun linting and formatting on the generated file:\n\n```bash\nbunx biome check --fix src/migrations/\n```\n";var Xo="---\nname: make:permission\ndescription: Generate a new permission class with its test file, then complete the generated code. Use when creating a new permission that extends Permission from @ooneex/permission.\n---\n\n# Make Permission Class\n\nGenerate a new permission class and its test file using the `make:permission` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the permission class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:permission --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/permissions/<Name>Permission.ts` - The permission class file (or `modules/<module>/src/permissions/<Name>Permission.ts` with `--module`)\n- `tests/permissions/<Name>Permission.spec.ts` - The test file (or `modules/<module>/tests/permissions/<Name>Permission.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the permission class\n\nEdit `src/permissions/<Name>Permission.ts` to complete the implementation:\n\n- Implement the `allow()` method with permission rules using `this.ability.can()`\n- Implement the `setUserPermissions()` method with role-based permission logic\n- Define which actions (read, create, update, delete, manage) are allowed on which entities\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { decorator, Permission } from \"@ooneex/permission\";\nimport type { IUser } from \"@ooneex/user\";\n\n@decorator.permission()\nexport class <Name>Permission extends Permission {\n public allow(): this {\n // Example: Add permissions using this.ability.can()\n // this.ability.can(\"read\", \"YourEntity\");\n // this.ability.can([\"read\", \"update\"], \"YourEntity\", { userId: user.id });\n\n return this;\n }\n\n public setUserPermissions(user: IUser | null): this {\n if (!user) {\n return this;\n }\n\n // Example: Grant full access to admins\n // const { roles } = user;\n // if (roles.includes(ERole.ADMIN)) {\n // this.ability.can(\"manage\", \"all\");\n // return this;\n // }\n\n // Example: Grant specific permissions based on roles\n // for (const role of roles) {\n // if (role === ERole.USER) {\n // this.ability.can([\"read\", \"update\"], \"YourEntity\", { userId: user.id });\n // }\n //\n // if (role === ERole.GUEST) {\n // this.ability.can(\"read\", \"YourEntity\", { public: true });\n // }\n // }\n\n return this;\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/permissions/<Name>Permission.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, extends Permission, allow, setUserPermissions methods)\n- Add tests relevant to the specific permission rules\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { Permission } from \"@ooneex/permission\";\nimport { <Name>Permission } from \"@/permissions/<Name>Permission\";\n\ndescribe(\"<Name>Permission\", () => {\n test(\"should have class name ending with 'Permission'\", () => {\n expect(<Name>Permission.name.endsWith(\"Permission\")).toBe(true);\n });\n\n test(\"should extend Permission\", () => {\n const permission = new <Name>Permission();\n expect(permission).toBeInstanceOf(Permission);\n });\n\n test(\"should have 'allow' method\", () => {\n expect(<Name>Permission.prototype.allow).toBeDefined();\n expect(typeof <Name>Permission.prototype.allow).toBe(\"function\");\n });\n\n test(\"should have 'setUserPermissions' method\", () => {\n expect(<Name>Permission.prototype.setUserPermissions).toBeDefined();\n expect(typeof <Name>Permission.prototype.setUserPermissions).toBe(\"function\");\n });\n});\n```\n\n### 5. Register the permission in the module\n\nAdd the new permission to the module's `permissions` array in `src/<PascalModuleName>Module.ts` (e.g., `src/BookModule.ts` for the `book` module):\n\n```typescript\nimport type { ModuleType } from \"@ooneex/module\";\nimport { <Name>Permission } from \"./permissions/<Name>Permission\";\n\nexport const <PascalModuleName>Module: ModuleType = {\n controllers: [],\n entities: [],\n permissions: [<Name>Permission],\n middlewares: [],\n cronJobs: [],\n events: [],\n};\n```\n\nThe module file uses PascalCase naming: `<PascalModuleName>Module.ts` with export `<PascalModuleName>Module`.\n\nIf the module already has other permissions registered, append the new permission to the existing `permissions` array and add the import alongside existing imports.\n\n### 6. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/permissions/<Name>Permission.ts tests/permissions/<Name>Permission.spec.ts\n```\n";var Jo="---\nname: make:pubsub\ndescription: Generate a new PubSub event class with its test file, then complete the generated code. Use when creating a new publish/subscribe event that extends PubSub from @ooneex/pub-sub.\n---\n\n# Make PubSub Event Class\n\nGenerate a new PubSub event class and its test file using the `make:pubsub` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the PubSub event class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:pubsub --name <name> --module <module> --channel <channel>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The `--channel` option is optional \u2014 if omitted, it defaults to the kebab-case form of the name (e.g., `UserCreated` becomes `user-created`). The command will generate:\n- `src/events/<Name>Event.ts` - The event class file (or `modules/<module>/src/events/<Name>Event.ts` with `--module`)\n- `tests/events/<Name>Event.spec.ts` - The test file (or `modules/<module>/tests/events/<Name>Event.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the PubSub event class\n\nEdit `src/events/<Name>Event.ts` to complete the implementation:\n\n- Define a proper data type instead of `Record<string, ScalarType>` for the event payload\n- Implement the `handler()` method with actual event handling logic\n- Set the appropriate channel name in `getChannel()`\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { inject } from \"@ooneex/container\";\nimport type { ScalarType } from \"@ooneex/types\";\nimport { decorator, PubSub, RedisPubSub } from \"@ooneex/pub-sub\";\n\n@decorator.pubSub()\nexport class <Name>Event<Data extends Record<string, ScalarType> = Record<string, ScalarType>> extends PubSub<Data> {\n constructor(\n @inject(RedisPubSub)\n client: RedisPubSub<Data>,\n ) {\n super(client);\n }\n\n public getChannel(): string {\n return \"<channel>\";\n }\n\n public async handler(context: { data: Data; channel: string }): Promise<void> {\n console.log(context);\n // TODO: Implement handler logic here\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/events/<Name>Event.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, getChannel, handler, publish, subscribe, unsubscribe, unsubscribeAll methods)\n- Add tests relevant to the specific event behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>PubSub } from \"@/pubsub/<Name>PubSub\";\n\ndescribe(\"<Name>PubSub\", () => {\n test(\"should have class name ending with 'PubSub'\", () => {\n expect(<Name>PubSub.name.endsWith(\"PubSub\")).toBe(true);\n });\n\n test(\"should have 'getChannel' method\", () => {\n expect(<Name>PubSub.prototype.getChannel).toBeDefined();\n expect(typeof <Name>PubSub.prototype.getChannel).toBe(\"function\");\n });\n\n test(\"should have 'handler' method\", () => {\n expect(<Name>PubSub.prototype.handler).toBeDefined();\n expect(typeof <Name>PubSub.prototype.handler).toBe(\"function\");\n });\n\n test(\"should have 'publish' method\", () => {\n expect(<Name>PubSub.prototype.publish).toBeDefined();\n expect(typeof <Name>PubSub.prototype.publish).toBe(\"function\");\n });\n\n test(\"should have 'subscribe' method\", () => {\n expect(<Name>PubSub.prototype.subscribe).toBeDefined();\n expect(typeof <Name>PubSub.prototype.subscribe).toBe(\"function\");\n });\n\n test(\"should have 'unsubscribe' method\", () => {\n expect(<Name>PubSub.prototype.unsubscribe).toBeDefined();\n expect(typeof <Name>PubSub.prototype.unsubscribe).toBe(\"function\");\n });\n\n test(\"should have 'unsubscribeAll' method\", () => {\n expect(<Name>PubSub.prototype.unsubscribeAll).toBeDefined();\n expect(typeof <Name>PubSub.prototype.unsubscribeAll).toBe(\"function\");\n });\n});\n```\n\n### 5. Register the event in the module\n\nAdd the new event to the module's `events` array in `src/<PascalModuleName>Module.ts` (e.g., `src/BookModule.ts` for the `book` module):\n\n```typescript\nimport type { ModuleType } from \"@ooneex/module\";\nimport { <Name>Event } from \"./events/<Name>Event\";\n\nexport const <PascalModuleName>Module: ModuleType = {\n controllers: [],\n entities: [],\n permissions: [],\n middlewares: [],\n cronJobs: [],\n events: [<Name>Event],\n};\n```\n\nThe module file uses PascalCase naming: `<PascalModuleName>Module.ts` with export `<PascalModuleName>Module`.\n\nIf the module already has other events registered, append the new event to the existing `events` array and add the import alongside existing imports.\n\n### 6. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/events/<Name>Event.ts tests/events/<Name>Event.spec.ts\n```\n";var jo="---\nname: make:repository\ndescription: Generate a new repository class with its test file, then complete the generated code. Use when creating a new TypeORM repository for database operations on an entity.\n---\n\n# Make Repository Class\n\nGenerate a new repository class and its test file using the `make:repository` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the repository class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:repository --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/repositories/<Name>Repository.ts` - The repository class file (or `modules/<module>/src/repositories/<Name>Repository.ts` with `--module`)\n- `tests/repositories/<Name>Repository.spec.ts` - The test file (or `modules/<module>/tests/repositories/<Name>Repository.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the repository class\n\nEdit `src/repositories/<Name>Repository.ts` to complete the implementation:\n\n- Verify the entity import path matches the actual entity location\n- Adjust the `find` method's search fields (default searches `name` with `ILike`)\n- Customize relations loading in `findOne`/`findOneBy` if needed\n\n#### Adding methods\n\nLook at the entity's fields, relations, and business context to determine if custom domain-specific methods are needed. For example:\n- A `SessionRepository` might need `revokeSession(sessionId: string)` and `revokeAllUserSessions(userId: string)`\n- A `NotificationRepository` might need `markAsRead(id: string)` and `markAllAsRead(userId: string)`\n- Entities with status fields may need methods like `archive(id: string)` or `activate(id: string)`\n\nRead related entities, services, or actions in the module to understand what operations the repository should support, then add the appropriate methods.\n\n#### Removing methods\n\nRemove scaffolded methods that don't make sense for the entity's context:\n- Remove `createMany`/`updateMany` if the entity is always managed individually (e.g., user profiles, settings)\n- Remove `delete` if the entity uses soft deletes only (use a custom `softDelete` or `archive` method instead)\n- Remove `find` if the entity is only ever accessed by ID or specific criteria (e.g., singleton config entities)\n- Remove `count` if there's no use case for counting records of this entity\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { inject } from \"@ooneex/container\";\nimport type { ITypeormDatabase } from \"@ooneex/database\";\nimport { decorator } from \"@ooneex/repository\";\nimport type { FilterResultType } from \"@ooneex/types\";\nimport type { FindManyOptions, FindOptionsWhere, Repository, SaveOptions, UpdateResult } from \"typeorm\";\nimport { ILike } from \"typeorm\";\nimport { <Name>Entity } from \"../entities/<Name>Entity\";\n\n@decorator.repository()\nexport class <Name>Repository {\n constructor(\n @inject(\"database\")\n private readonly database: ITypeormDatabase,\n ) {}\n\n public async open(): Promise<Repository<<Name>Entity>> {\n return await this.database.open(<Name>Entity);\n }\n\n public async close(): Promise<void> {\n await this.database.close();\n }\n\n public async find(\n criteria: FindManyOptions<<Name>Entity> & { page?: number; limit?: number; q?: string },\n ): Promise<FilterResultType<<Name>Entity>> {\n // ... pagination and search logic\n }\n\n public async findOne(id: string): Promise<<Name>Entity | null> { ... }\n public async findOneBy(criteria: FindOptionsWhere<<Name>Entity>): Promise<<Name>Entity | null> { ... }\n public async create(entity: <Name>Entity, options?: SaveOptions): Promise<<Name>Entity> { ... }\n public async createMany(entities: <Name>Entity[], options?: SaveOptions): Promise<<Name>Entity[]> { ... }\n public async update(entity: <Name>Entity, options?: SaveOptions): Promise<<Name>Entity> { ... }\n public async updateMany(entities: <Name>Entity[], options?: SaveOptions): Promise<<Name>Entity[]> { ... }\n public async delete(criteria: FindOptionsWhere<<Name>Entity> | FindOptionsWhere<<Name>Entity>[]): Promise<UpdateResult> { ... }\n public async count(criteria?: FindOptionsWhere<<Name>Entity> | FindOptionsWhere<<Name>Entity>[]): Promise<number> { ... }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/repositories/<Name>Repository.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep scaffolded tests for methods that remain in the repository (remove tests for methods that were removed)\n- Add tests for any custom domain-specific methods added to the repository\n- Add tests relevant to the specific repository behavior\n\n### 5. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/repositories/<Name>Repository.ts tests/repositories/<Name>Repository.spec.ts\n```\n";var ei="---\nname: make:seed\ndescription: Generate a new database seed file, then complete the generated code. Use when creating seed data for populating the database using @ooneex/seeds.\n---\n\n# Make Seed\n\nGenerate a new seed file using the `make:seed` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the seed file:\n\n```bash\nbunx @ooneex/cli@latest make:seed --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, the seed file is generated under `modules/<module>/src/seeds/` instead of `src/seeds/`. The command will:\n- Generate a seed file in `src/seeds/` (or `modules/<module>/src/seeds/` with `--module`)\n- Add a `seed:run` script to `package.json` if not already present\n\n### 2. Read the generated file\n\nRead the generated seed file in `src/seeds/` to understand the scaffolded code.\n\n### 3. Complete the seed\n\nEdit the generated seed file to implement:\n\n- Import the relevant entity classes\n- Create seed data with hardcoded nanoid values for `id` fields (generate via `bun -e \"import { random } from '@ooneex/utils'; console.log(random.nanoid())\"`)\n- Do NOT use sequential IDs like `\"item-1\"`, `\"item-2\"`\n- Ensure the same entity uses the same ID everywhere it appears\n\n### 4. Lint and format\n\nRun linting and formatting on the generated file:\n\n```bash\nbunx biome check --fix src/seeds/\n```\n";var ti="---\nname: make:service\ndescription: Generate a new service class with its test file, then complete the generated code. Use when creating a new business logic service that implements IService from @ooneex/service.\n---\n\n# Make Service Class\n\nGenerate a new service class and its test file using the `make:service` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the service class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:service --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/services/<Name>Service.ts` - The service class file (or `modules/<module>/src/services/<Name>Service.ts` with `--module`)\n- `tests/services/<Name>Service.spec.ts` - The test file (or `modules/<module>/tests/services/<Name>Service.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the service class\n\nEdit `src/services/<Name>Service.ts` to complete the implementation:\n\n- Define a proper type for `ServiceDataType` instead of `Record<string, unknown>`\n- Implement the `execute()` method with actual business logic\n- Inject any required dependencies (repositories, other services, etc.) via the constructor\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { decorator } from \"@ooneex/service\";\nimport type { IService } from \"@ooneex/service\";\n\ntype ServiceDataType = Record<string, unknown>;\n\n@decorator.service()\nexport class <Name>Service<T extends ServiceDataType = ServiceDataType> implements IService<T> {\n public async execute(data?: T): Promise<void> {\n // TODO: Implement service logic\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/services/<Name>Service.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, execute method)\n- Add tests relevant to the specific service behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>Service } from \"@/services/<Name>Service\";\n\ndescribe(\"<Name>Service\", () => {\n test(\"should have class name ending with 'Service'\", () => {\n expect(<Name>Service.name.endsWith(\"Service\")).toBe(true);\n });\n\n test(\"should have 'execute' method\", () => {\n expect(<Name>Service.prototype.execute).toBeDefined();\n expect(typeof <Name>Service.prototype.execute).toBe(\"function\");\n });\n});\n```\n\n### 5. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/services/<Name>Service.ts tests/services/<Name>Service.spec.ts\n```\n";var si="---\nname: make:storage\ndescription: Generate a new storage class with its test file, then complete the generated code. Use when creating a new S3-compatible storage adapter that extends Storage from @ooneex/storage.\n---\n\n# Make Storage Class\n\nGenerate a new storage class and its test file using the `make:storage` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the storage class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:storage --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/storage/<Name>Storage.ts` - The storage class file (or `modules/<module>/src/storage/<Name>Storage.ts` with `--module`)\n- `tests/storage/<Name>Storage.spec.ts` - The test file (or `modules/<module>/tests/storage/<Name>Storage.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the storage class\n\nEdit `src/storage/<Name>Storage.ts` to complete the implementation:\n\n- Set the `bucket` property to the appropriate bucket name\n- Verify the environment variable names match the project configuration (`STORAGE_<NAME_UPPER>_ACCESS_KEY`, `STORAGE_<NAME_UPPER>_SECRET_KEY`, `STORAGE_<NAME_UPPER>_ENDPOINT`, `STORAGE_<NAME_UPPER>_REGION`)\n- Add any additional storage-specific methods if needed\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { Storage, decorator, StorageException } from \"@ooneex/storage\";\nimport type { S3Options } from \"bun\";\n\n@decorator.storage()\nexport class <Name>Storage extends Storage {\n protected bucket: string;\n private readonly accessKey: string;\n private readonly secretKey: string;\n private readonly endpoint: string;\n private readonly region: string;\n\n constructor(options?: {\n accessKey?: string;\n secretKey?: string;\n endpoint?: string;\n region?: string;\n }) {\n super();\n\n const accessKey = options?.accessKey || Bun.env.STORAGE_<NAME_UPPER>_ACCESS_KEY;\n const secretKey = options?.secretKey || Bun.env.STORAGE_<NAME_UPPER>_SECRET_KEY;\n const endpoint = options?.endpoint || Bun.env.STORAGE_<NAME_UPPER>_ENDPOINT;\n\n // ... validation throws StorageException if missing ...\n\n this.accessKey = accessKey;\n this.secretKey = secretKey;\n this.endpoint = endpoint;\n this.region = options?.region || Bun.env.STORAGE_<NAME_UPPER>_REGION || \"auto\";\n }\n\n public getOptions(): S3Options {\n return {\n accessKeyId: this.accessKey,\n secretAccessKey: this.secretKey,\n endpoint: this.endpoint,\n bucket: this.bucket,\n region: this.region,\n };\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/storage/<Name>Storage.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, bucket field, getOptions method)\n- Add tests relevant to the specific storage class behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>StorageAdapter } from \"@/storage/<Name>StorageAdapter\";\n\ndescribe(\"<Name>StorageAdapter\", () => {\n test(\"should have class name ending with 'StorageAdapter'\", () => {\n expect(<Name>StorageAdapter.name.endsWith(\"StorageAdapter\")).toBe(true);\n });\n\n test(\"should have 'bucket' field\", () => {\n expect(\"bucket\" in <Name>StorageAdapter.prototype || \"bucket\" in Object.getOwnPropertyNames(<Name>StorageAdapter.prototype)).toBe(true);\n });\n\n test(\"should have 'getOptions' method\", () => {\n expect(<Name>StorageAdapter.prototype.getOptions).toBeDefined();\n expect(typeof <Name>StorageAdapter.prototype.getOptions).toBe(\"function\");\n });\n});\n```\n\n### 5. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/storage/<Name>Storage.ts tests/storage/<Name>Storage.spec.ts\n```\n";var ri="---\nname: make:vector-database\ndescription: Generate a new vector database class with its test file, then complete the generated code. Use when creating a new vector database that extends VectorDatabase from @ooneex/rag.\n---\n\n# Make Vector Database Class\n\nGenerate a new vector database class and its test file using the `make:vector-database` CLI command, then complete the generated code with proper implementation.\n\n## Coding Conventions\n\n- Always explicitly show visibility on class methods and properties (`private`, `public`, `protected`)\n- Always use arrow functions when possible, but NOT for class methods (class methods use regular method syntax)\n- End type names with the `Type` suffix (e.g., `ExceptionStackFrameType`, `ServiceDataType`)\n- Start interface names with the `I` prefix (e.g., `IException`, `IService`, `IAiChat`)\n\n## Steps\n\n### 1. Run the generator\n\nRun the following command to scaffold the vector database class and test files:\n\n```bash\nbunx @ooneex/cli@latest make:vector-database --name <name> --module <module>\n```\n\nWhere `<name>` is the name provided by the user. The `--module` option is optional \u2014 if provided, files are generated under `modules/<module>/` instead of the project root. The command will generate:\n- `src/databases/<Name>VectorDatabase.ts` - The vector database class file (or `modules/<module>/src/databases/<Name>VectorDatabase.ts` with `--module`)\n- `tests/databases/<Name>VectorDatabase.spec.ts` - The test file (or `modules/<module>/tests/databases/<Name>VectorDatabase.spec.ts` with `--module`)\n\n### 2. Read the generated files\n\nRead both generated files to understand the scaffolded code.\n\n### 3. Complete the vector database class\n\nEdit `src/databases/<Name>VectorDatabase.ts` to complete the implementation:\n\n- Set the `getDatabaseUri()` return value to the actual LanceDB database path\n- Configure the embedding provider and model in `getEmbeddingModel()`\n- Define the custom data fields in `DataType` and map them in `getSchema()`\n- Import the appropriate Apache Arrow types for your schema fields\n\nThe generated class structure follows this pattern:\n\n```typescript\nimport { VectorDatabase, decorator } from \"@ooneex/rag\";\nimport type { EmbeddingModelType, EmbeddingProviderType, FieldValueType } from \"@ooneex/rag\";\nimport { Utf8 } from \"apache-arrow\";\n\ntype DataType = {\n name: string;\n};\n\n@decorator.vectorDatabase()\nexport class <Name>VectorDatabase extends VectorDatabase<DataType> {\n public getDatabaseUri(): string {\n return \"\";\n }\n\n public getEmbeddingModel(): { provider: EmbeddingProviderType; model: EmbeddingModelType[\"model\"] } {\n return { provider: \"openai\", model: \"text-embedding-ada-002\" };\n }\n\n public getSchema(): { [K in keyof DataType]: FieldValueType } {\n return {\n name: new Utf8(),\n };\n }\n}\n```\n\n### 4. Complete the test file\n\nEdit `tests/databases/<Name>VectorDatabase.spec.ts` to add meaningful tests beyond the scaffolded ones:\n\n- Keep the existing scaffolded tests (class name, getDatabaseUri, getEmbeddingModel, getSchema methods)\n- Add tests relevant to the specific vector database class behavior\n\nThe generated test structure follows this pattern:\n\n```typescript\nimport { describe, expect, test } from \"bun:test\";\nimport { <Name>VectorDatabase } from \"@/databases/<Name>VectorDatabase\";\n\ndescribe(\"<Name>VectorDatabase\", () => {\n test(\"should have class name ending with 'VectorDatabase'\", () => {\n expect(<Name>VectorDatabase.name.endsWith(\"VectorDatabase\")).toBe(true);\n });\n\n test(\"should have 'getDatabaseUri' method\", () => {\n expect(<Name>VectorDatabase.prototype.getDatabaseUri).toBeDefined();\n expect(typeof <Name>VectorDatabase.prototype.getDatabaseUri).toBe(\"function\");\n });\n\n test(\"should have 'getEmbeddingModel' method\", () => {\n expect(<Name>VectorDatabase.prototype.getEmbeddingModel).toBeDefined();\n expect(typeof <Name>VectorDatabase.prototype.getEmbeddingModel).toBe(\"function\");\n });\n\n test(\"should have 'getSchema' method\", () => {\n expect(<Name>VectorDatabase.prototype.getSchema).toBeDefined();\n expect(typeof <Name>VectorDatabase.prototype.getSchema).toBe(\"function\");\n });\n});\n```\n\n### 5. Lint and format\n\nRun linting and formatting on the generated files:\n\n```bash\nbunx biome check --fix src/databases/<Name>VectorDatabase.ts tests/databases/<Name>VectorDatabase.spec.ts\n```\n";var oi=`---
|
|
1753
1805
|
name: optimize
|
|
1754
1806
|
description: Optimize a module's codebase for quality, performance, and clean conventions. Enforces arrow functions (except class methods), type/interface naming, removes duplication, and ensures only important tests remain.
|
|
1755
1807
|
---
|
|
@@ -1843,7 +1895,7 @@ bun test <module test directory>
|
|
|
1843
1895
|
\`\`\`
|
|
1844
1896
|
|
|
1845
1897
|
If any test fails, fix the issue and re-run until all tests pass.
|
|
1846
|
-
`;var
|
|
1898
|
+
`;var zl={"make.ai":$o,"make.analytics":Wo,"make.cache":qo,"make.controller":Ko,"make.cron":Ho,"make.database":Fo,"make.entity":Vo,"make.logger":Yo,"make.mailer":zo,"make.middleware":Zo,"make.migration":Qo,"make.permission":Xo,"make.pubsub":Jo,"make.repository":jo,"make.seed":ei,"make.service":ti,"make.storage":si,"make.vector-database":ri,commit:ko,optimize:oi};class qe{getName(){return"make:claude:skill"}getDescription(){return"Generate Claude skills from templates"}async run(){let e=We(".claude","skills"),t=We(process.cwd(),e),s=new Yl;for(let[r,o]of Object.entries(zl)){let i=r.replace(/\./g,"-"),a=We(t,i,"SKILL.md");await Bun.write(a,o),s.success(`${We(e,i,"SKILL.md")} created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0})}}}qe=b([x.command()],qe);import{basename as Xl,join as G}from"path";import{TerminalLogger as Jl}from"@ooneex/logger";import{toPascalCase as Lt}from"@ooneex/utils";var ii=`import { describe, expect, test } from "bun:test";
|
|
1847
1899
|
import { {{NAME}}Cron } from "@/cron/{{NAME}}Cron";
|
|
1848
1900
|
|
|
1849
1901
|
describe("{{NAME}}Cron", () => {
|
|
@@ -1866,7 +1918,7 @@ describe("{{NAME}}Cron", () => {
|
|
|
1866
1918
|
expect(typeof {{NAME}}Cron.prototype.handler).toBe("function");
|
|
1867
1919
|
});
|
|
1868
1920
|
});
|
|
1869
|
-
`;var
|
|
1921
|
+
`;var ai=`import type { TimeZoneType } from "@ooneex/country";
|
|
1870
1922
|
import type { CronTimeType } from "@ooneex/cron";
|
|
1871
1923
|
import { Cron, decorator } from "@ooneex/cron";
|
|
1872
1924
|
|
|
@@ -1887,9 +1939,9 @@ export class {{NAME}}Cron extends Cron {
|
|
|
1887
1939
|
// console.log("{{NAME}}Cron handler executed");
|
|
1888
1940
|
}
|
|
1889
1941
|
}
|
|
1890
|
-
`;class
|
|
1891
|
-
`,
|
|
1892
|
-
`,
|
|
1942
|
+
`;class Ke{getName(){return"make:cron"}getDescription(){return"Generate a new cron class"}async addToModule(e,t){let s=await Bun.file(e).text(),r=`${t}Cron`,o=`import { ${r} } from "./cron/${r}";
|
|
1943
|
+
`,i=s.lastIndexOf("import "),a=s.indexOf(`
|
|
1944
|
+
`,i);s=`${s.slice(0,a+1)}${o}${s.slice(a+1)}`;let n=/(cronJobs:\s*\[)([^\]]*)/s,d=s.match(n);if(d){let l=d[2]?.trim(),c=l?`${l}, ${r}`:r;s=s.replace(n,`$1${c}`)}await Bun.write(e,s)}async run(e){let{name:t,module:s}=e;if(!t)t=await v({message:"Enter cron name"});t=Lt(t).replace(/Cron$/,"");let r=ai.replace(/{{NAME}}/g,t),o=s?G("modules",s):".",i=G(o,"src","cron"),a=G(process.cwd(),i),n=G(a,`${t}Cron.ts`);await Bun.write(n,r);let d=ii.replace(/{{NAME}}/g,t),l=G(o,"tests","cron"),c=G(process.cwd(),l),u=G(c,`${t}Cron.spec.ts`);await Bun.write(u,d);let p=s?Lt(s):Lt(Xl(process.cwd())),m=G(process.cwd(),o,"src",`${p}Module.ts`);if(await Bun.file(m).exists())await this.addToModule(m,t);let h=new Jl;h.success(`${G(i,t)}Cron.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),h.success(`${G(l,t)}Cron.spec.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),await Bun.spawn(["bun","add","@ooneex/cron"],{cwd:process.cwd(),stdout:"inherit",stderr:"inherit"}).exited}}Ke=b([x.command()],Ke);import{join as Y}from"path";import{TerminalLogger as tc}from"@ooneex/logger";import{toPascalCase as sc}from"@ooneex/utils";var ni=`import { describe, expect, test } from "bun:test";
|
|
1893
1945
|
import { {{NAME}}Database } from "@/databases/{{NAME}}Database";
|
|
1894
1946
|
|
|
1895
1947
|
describe("{{NAME}}Database", () => {
|
|
@@ -1902,7 +1954,7 @@ describe("{{NAME}}Database", () => {
|
|
|
1902
1954
|
expect(typeof {{NAME}}Database.prototype.getSource).toBe("function");
|
|
1903
1955
|
});
|
|
1904
1956
|
});
|
|
1905
|
-
`;var
|
|
1957
|
+
`;var di=`import { DataSource } from "typeorm";
|
|
1906
1958
|
import { TypeormDatabase, DatabaseException, decorator } from "@ooneex/database";
|
|
1907
1959
|
|
|
1908
1960
|
@decorator.database()
|
|
@@ -1925,7 +1977,7 @@ export class {{NAME}}Database extends TypeormDatabase {
|
|
|
1925
1977
|
return this.source;
|
|
1926
1978
|
}
|
|
1927
1979
|
}
|
|
1928
|
-
`;class
|
|
1980
|
+
`;class He{getName(){return"make:database"}getDescription(){return"Generate a new database class"}async run(e){let{name:t,module:s}=e;if(!t)t=await v({message:"Enter database name"});t=sc(t).replace(/DatabaseAdapter$/,"").replace(/Database$/,"");let r=di.replace(/{{NAME}}/g,t),o=s?Y("modules",s):".",i=Y(o,"src","databases"),a=Y(process.cwd(),i),n=Y(a,`${t}Database.ts`);await Bun.write(n,r);let d=ni.replace(/{{NAME}}/g,t),l=Y(o,"tests","databases"),c=Y(process.cwd(),l),u=Y(c,`${t}Database.spec.ts`);await Bun.write(u,d);let p=new tc;p.success(`${Y(i,t)}Database.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),p.success(`${Y(l,t)}Database.spec.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),await Bun.spawn(["bun","add","@ooneex/database"],{cwd:process.cwd(),stdout:"inherit",stderr:"inherit"}).exited}}He=b([x.command()],He);import{join as Oi}from"path";import{TerminalLogger as Ac}from"@ooneex/logger";var{YAML:Di}=globalThis.Bun;var ci=te(ae(),1),li=["clickhouse","elasticsearch","grafana","jaeger","keycloak","libretranslate","maildev","memcached","minio","mongodb","mysql","nats","postgres","prometheus","rabbitmq","redis","temporal","vault"],mi=async(e)=>{return(await ci.prompt({type:"autocomplete",name:"service",message:e.message,initial:e.initial,choices:li.map((s)=>s),validate:(s)=>{if(!li.includes(s))return"Docker service is invalid";return!0}})).service};var pi=`services:
|
|
1929
1981
|
# ClickHouse - Column-oriented OLAP database for analytics
|
|
1930
1982
|
# Docs: https://clickhouse.com/docs
|
|
1931
1983
|
# HTTP API: http://localhost:8123
|
|
@@ -1946,7 +1998,7 @@ export class {{NAME}}Database extends TypeormDatabase {
|
|
|
1946
1998
|
|
|
1947
1999
|
volumes:
|
|
1948
2000
|
clickhouse_data:
|
|
1949
|
-
`;var
|
|
2001
|
+
`;var ui=`services:
|
|
1950
2002
|
# Elasticsearch - Full-text search and analytics engine
|
|
1951
2003
|
# Docs: https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
|
|
1952
2004
|
# HTTP API: http://localhost:9200
|
|
@@ -1967,7 +2019,7 @@ volumes:
|
|
|
1967
2019
|
|
|
1968
2020
|
volumes:
|
|
1969
2021
|
elasticsearch_data:
|
|
1970
|
-
`;var
|
|
2022
|
+
`;var hi=`services:
|
|
1971
2023
|
# Grafana - Metrics visualization and dashboards
|
|
1972
2024
|
# Docs: https://grafana.com/docs/grafana/latest/
|
|
1973
2025
|
# Web UI: http://localhost:3000 (ooneex/ooneex)
|
|
@@ -1985,7 +2037,7 @@ volumes:
|
|
|
1985
2037
|
|
|
1986
2038
|
volumes:
|
|
1987
2039
|
grafana_data:
|
|
1988
|
-
`;var
|
|
2040
|
+
`;var fi=`services:
|
|
1989
2041
|
# Jaeger - Distributed tracing system
|
|
1990
2042
|
# Docs: https://www.jaegertracing.io/docs/
|
|
1991
2043
|
# Web UI: http://localhost:16686
|
|
@@ -1999,7 +2051,7 @@ volumes:
|
|
|
1999
2051
|
- "16686:16686"
|
|
2000
2052
|
- "6831:6831/udp"
|
|
2001
2053
|
- "14268:14268"
|
|
2002
|
-
`;var
|
|
2054
|
+
`;var yi=`services:
|
|
2003
2055
|
# Keycloak - Identity and access management
|
|
2004
2056
|
# Docs: https://www.keycloak.org/documentation
|
|
2005
2057
|
# Admin Console: http://localhost:8080 (ooneex/ooneex)
|
|
@@ -2013,7 +2065,7 @@ volumes:
|
|
|
2013
2065
|
- KEYCLOAK_ADMIN=ooneex
|
|
2014
2066
|
- KEYCLOAK_ADMIN_PASSWORD=ooneex
|
|
2015
2067
|
command: start-dev
|
|
2016
|
-
`;var
|
|
2068
|
+
`;var gi=`services:
|
|
2017
2069
|
# LibreTranslate - Self-hosted machine translation API
|
|
2018
2070
|
# Docs: https://libretranslate.com/docs/
|
|
2019
2071
|
# API: http://localhost:4000
|
|
@@ -2040,7 +2092,7 @@ volumes:
|
|
|
2040
2092
|
|
|
2041
2093
|
volumes:
|
|
2042
2094
|
libretranslate_models:
|
|
2043
|
-
`;var
|
|
2095
|
+
`;var bi=`services:
|
|
2044
2096
|
# MailDev - Email testing tool with web UI
|
|
2045
2097
|
# Docs: https://github.com/maildev/maildev
|
|
2046
2098
|
# Web UI: http://localhost:1080
|
|
@@ -2051,7 +2103,7 @@ volumes:
|
|
|
2051
2103
|
ports:
|
|
2052
2104
|
- "1080:1080"
|
|
2053
2105
|
- "1025:1025"
|
|
2054
|
-
`;var
|
|
2106
|
+
`;var xi=`services:
|
|
2055
2107
|
# Memcached - Distributed memory caching system
|
|
2056
2108
|
# Docs: https://memcached.org/
|
|
2057
2109
|
# Connection: localhost:11211
|
|
@@ -2061,7 +2113,7 @@ volumes:
|
|
|
2061
2113
|
restart: "on-failure"
|
|
2062
2114
|
ports:
|
|
2063
2115
|
- "11211:11211"
|
|
2064
|
-
`;var
|
|
2116
|
+
`;var wi=`services:
|
|
2065
2117
|
# MinIO - S3-compatible object storage
|
|
2066
2118
|
# Docs: https://min.io/docs/minio/container/index.html
|
|
2067
2119
|
# API: http://localhost:9000
|
|
@@ -2082,7 +2134,7 @@ volumes:
|
|
|
2082
2134
|
|
|
2083
2135
|
volumes:
|
|
2084
2136
|
minio_data:
|
|
2085
|
-
`;var
|
|
2137
|
+
`;var Ei=`services:
|
|
2086
2138
|
# MongoDB - NoSQL document database
|
|
2087
2139
|
# Docs: https://www.mongodb.com/docs/
|
|
2088
2140
|
# Connection: mongodb://ooneex:ooneex@localhost:27017/ooneex
|
|
@@ -2101,7 +2153,7 @@ volumes:
|
|
|
2101
2153
|
|
|
2102
2154
|
volumes:
|
|
2103
2155
|
mongodb_data:
|
|
2104
|
-
`;var
|
|
2156
|
+
`;var Ai=`services:
|
|
2105
2157
|
# MySQL - Alternative relational database
|
|
2106
2158
|
# Docs: https://dev.mysql.com/doc/
|
|
2107
2159
|
# Connection: mysql://ooneex:ooneex@localhost:3306/ooneex
|
|
@@ -2121,7 +2173,7 @@ volumes:
|
|
|
2121
2173
|
|
|
2122
2174
|
volumes:
|
|
2123
2175
|
mysql_db:
|
|
2124
|
-
`;var
|
|
2176
|
+
`;var vi=`services:
|
|
2125
2177
|
# NATS - High-performance messaging system with JetStream
|
|
2126
2178
|
# Docs: https://docs.nats.io/
|
|
2127
2179
|
# Client: localhost:4222
|
|
@@ -2134,7 +2186,7 @@ volumes:
|
|
|
2134
2186
|
- "4222:4222"
|
|
2135
2187
|
- "8222:8222"
|
|
2136
2188
|
command: "--jetstream --http_port 8222"
|
|
2137
|
-
`;var
|
|
2189
|
+
`;var Ni=`services:
|
|
2138
2190
|
# Jade - FastAPI REST API to fetch YouTube metadata and download videos or audio via Dockerized microservice.
|
|
2139
2191
|
# API: http://localhost:8000
|
|
2140
2192
|
# Docs: http://localhost:8000/docs
|
|
@@ -2152,7 +2204,7 @@ volumes:
|
|
|
2152
2204
|
|
|
2153
2205
|
volumes:
|
|
2154
2206
|
jade_data:
|
|
2155
|
-
`;var
|
|
2207
|
+
`;var Si=`services:
|
|
2156
2208
|
# PostgreSQL - Primary relational database
|
|
2157
2209
|
# Docs: https://www.postgresql.org/docs/
|
|
2158
2210
|
# Connection: postgresql://ooneex:ooneex@localhost:5432/ooneex
|
|
@@ -2173,7 +2225,7 @@ volumes:
|
|
|
2173
2225
|
|
|
2174
2226
|
volumes:
|
|
2175
2227
|
postgres_db:
|
|
2176
|
-
`;var
|
|
2228
|
+
`;var Ti=`services:
|
|
2177
2229
|
# Prometheus - Metrics collection and monitoring
|
|
2178
2230
|
# Docs: https://prometheus.io/docs/
|
|
2179
2231
|
# Web UI: http://localhost:9090
|
|
@@ -2188,7 +2240,7 @@ volumes:
|
|
|
2188
2240
|
|
|
2189
2241
|
volumes:
|
|
2190
2242
|
prometheus_data:
|
|
2191
|
-
`;var
|
|
2243
|
+
`;var Ri=`services:
|
|
2192
2244
|
# RabbitMQ - Message broker for async processing
|
|
2193
2245
|
# Docs: https://www.rabbitmq.com/docs
|
|
2194
2246
|
# AMQP: amqp://ooneex:ooneex@localhost:5672/ooneex
|
|
@@ -2210,7 +2262,7 @@ volumes:
|
|
|
2210
2262
|
|
|
2211
2263
|
volumes:
|
|
2212
2264
|
rabbitmq_data:
|
|
2213
|
-
`;var
|
|
2265
|
+
`;var Mi=`services:
|
|
2214
2266
|
# Redis - In-memory data store for caching and sessions
|
|
2215
2267
|
# Docs: https://redis.io/docs/
|
|
2216
2268
|
# Connection: redis://localhost:6379
|
|
@@ -2225,7 +2277,7 @@ volumes:
|
|
|
2225
2277
|
|
|
2226
2278
|
volumes:
|
|
2227
2279
|
redis_data:
|
|
2228
|
-
`;var
|
|
2280
|
+
`;var Ci=`services:
|
|
2229
2281
|
# Temporal - Workflow orchestration engine
|
|
2230
2282
|
# Docs: https://docs.temporal.io/
|
|
2231
2283
|
# gRPC: localhost:7233
|
|
@@ -2242,7 +2294,7 @@ volumes:
|
|
|
2242
2294
|
- POSTGRES_USER=ooneex
|
|
2243
2295
|
- POSTGRES_PWD=ooneex
|
|
2244
2296
|
- POSTGRES_SEEDS=postgres
|
|
2245
|
-
`;var
|
|
2297
|
+
`;var _i=`services:
|
|
2246
2298
|
# Vault - Secrets management and encryption
|
|
2247
2299
|
# Docs: https://developer.hashicorp.com/vault/docs
|
|
2248
2300
|
# Web UI: http://localhost:8200 (token: ooneex)
|
|
@@ -2257,20 +2309,20 @@ volumes:
|
|
|
2257
2309
|
- VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200
|
|
2258
2310
|
cap_add:
|
|
2259
2311
|
- IPC_LOCK
|
|
2260
|
-
`;var
|
|
2261
|
-
`),s=[],
|
|
2262
|
-
`)}function
|
|
2263
|
-
volumes:`),
|
|
2264
|
-
networks:`),f=-1;if(
|
|
2265
|
-
${
|
|
2266
|
-
${
|
|
2267
|
-
volumes:`)){let
|
|
2268
|
-
volumes:`),E=
|
|
2269
|
-
${
|
|
2312
|
+
`;var Ii={clickhouse:pi,elasticsearch:ui,grafana:hi,"ooneex-jade":Ni,jaeger:fi,keycloak:yi,libretranslate:gi,maildev:bi,memcached:xi,minio:wi,mongodb:Ei,mysql:Ai,nats:vi,postgres:Si,prometheus:Ti,rabbitmq:Ri,redis:Mi,temporal:Ci,vault:_i};function vc(e){let t=e.split(`
|
|
2313
|
+
`),s=[],r=!1;for(let o of t){if(o.startsWith("services:")){r=!0;continue}if(r){if(o.startsWith("volumes:")||o.startsWith("networks:"))break;s.push(o)}}return s.join(`
|
|
2314
|
+
`)}function Nc(e){let t=Di.parse(e);return t.volumes?Object.keys(t.volumes):[]}class Fe{getName(){return"make:docker"}getDescription(){return"Add a docker service to docker-compose.yml"}async run(e){let{name:t}=e;if(!t)t=await mi({message:"Select docker service"});let s=Ii[t],r=Oi(process.cwd(),"docker-compose.yml"),o=new Ac,i=Bun.file(r);if(await i.exists()){let d=await i.text(),l=Di.parse(d);if(l.services&&t in l.services){o.warn(`Service "${t}" already exists in docker-compose.yml`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0});return}let c=vc(s),u=Nc(s),p=d,m=p.indexOf(`
|
|
2315
|
+
volumes:`),h=p.indexOf(`
|
|
2316
|
+
networks:`),f=-1;if(m!==-1&&h!==-1)f=Math.min(m,h);else if(m!==-1)f=m;else if(h!==-1)f=h;if(f!==-1)p=`${p.slice(0,f)}
|
|
2317
|
+
${c}${p.slice(f)}`;else p=`${p.trimEnd()}
|
|
2318
|
+
${c}`;for(let g of u)if(!p.includes(` ${g}:`))if(p.includes(`
|
|
2319
|
+
volumes:`)){let y=p.indexOf(`
|
|
2320
|
+
volumes:`),E=p.slice(y+9);p=`${p.slice(0,y+9)}
|
|
2321
|
+
${g}:${E}`}else p=`${p.trimEnd()}
|
|
2270
2322
|
|
|
2271
2323
|
volumes:
|
|
2272
|
-
${
|
|
2273
|
-
`;await Bun.write(
|
|
2324
|
+
${g}:
|
|
2325
|
+
`;await Bun.write(r,p)}else await Bun.write(r,s);let a=Oi(process.cwd(),"package.json"),n=Bun.file(a);if(await n.exists()){let d=await n.json();d.scripts=d.scripts||{},d.scripts.docker="docker compose up -d",await Bun.write(a,JSON.stringify(d,null,2))}o.success(`Service "${t}" added to docker-compose.yml`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),o.info("Run 'bun run docker' to start docker containers",void 0,{showTimestamp:!1,showArrow:!0,showLevel:!1})}}Fe=b([x.command()],Fe);var Ui=te(Bi(),1);import{basename as Rc,join as k}from"path";import{TerminalLogger as Mc}from"@ooneex/logger";import{toPascalCase as kt,toSnakeCase as Cc}from"@ooneex/utils";var Pi=`import { describe, expect, test } from "bun:test";
|
|
2274
2326
|
import { {{NAME}}Entity } from "@/entities/{{NAME}}Entity";
|
|
2275
2327
|
|
|
2276
2328
|
describe("{{NAME}}Entity", () => {
|
|
@@ -2335,7 +2387,7 @@ describe("{{NAME}}Entity", () => {
|
|
|
2335
2387
|
expect("deletedAt" in entity).toBe(true);
|
|
2336
2388
|
});
|
|
2337
2389
|
});
|
|
2338
|
-
`;var
|
|
2390
|
+
`;var Li=`import type { LocaleType } from "@ooneex/translation";
|
|
2339
2391
|
import { random } from "@ooneex/utils";
|
|
2340
2392
|
import { Column, CreateDateColumn, DeleteDateColumn, PrimaryColumn, UpdateDateColumn } from "typeorm";
|
|
2341
2393
|
|
|
@@ -2386,9 +2438,9 @@ export class {{NAME}}Entity extends BaseEntity {
|
|
|
2386
2438
|
@DeleteDateColumn({ name: "deleted_at" })
|
|
2387
2439
|
deletedAt?: Date;
|
|
2388
2440
|
}
|
|
2389
|
-
`;class
|
|
2390
|
-
`,
|
|
2391
|
-
`,
|
|
2441
|
+
`;class Ve{getName(){return"make:entity"}getDescription(){return"Generate a new entity class"}async addToModule(e,t){let s=await Bun.file(e).text(),r=`${t}Entity`,o=`import { ${r} } from "./entities/${r}";
|
|
2442
|
+
`,i=s.lastIndexOf("import "),a=s.indexOf(`
|
|
2443
|
+
`,i);s=`${s.slice(0,a+1)}${o}${s.slice(a+1)}`;let n=/(entities:\s*\[)([^\]]*)/s,d=s.match(n);if(d){let l=d[2]?.trim(),c=l?`${l}, ${r}`:r;s=s.replace(n,`$1${c}`)}await Bun.write(e,s)}async run(e){let{name:t,module:s,tableName:r}=e;if(!t)t=await v({message:"Enter entity name"});if(t=kt(t).replace(/Entity$/,""),!r)r=Cc(Ui.default(t));let o=Li.replace(/{{NAME}}/g,t).replace(/{{TABLE_NAME}}/g,r),i=s?k("modules",s):".",a=k(i,"src","entities"),n=k(process.cwd(),a),d=k(n,`${t}Entity.ts`);await Bun.write(d,o);let l=Pi.replace(/{{NAME}}/g,t),c=k(i,"tests","entities"),u=k(process.cwd(),c),p=k(u,`${t}Entity.spec.ts`);await Bun.write(p,l);let m=s?kt(s):kt(Rc(process.cwd())),h=k(process.cwd(),i,"src",`${m}Module.ts`);if(await Bun.file(h).exists())await this.addToModule(h,t);let f=new Mc;f.success(`${k(a,t)}Entity.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),f.success(`${k(c,t)}Entity.spec.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0})}}Ve=b([x.command()],Ve);import{join as z}from"path";import{TerminalLogger as Oc}from"@ooneex/logger";import{toPascalCase as Dc}from"@ooneex/utils";var Gi=`import { describe, expect, test } from "bun:test";
|
|
2392
2444
|
import { {{NAME}}Logger } from "@/loggers/{{NAME}}Logger";
|
|
2393
2445
|
|
|
2394
2446
|
describe("{{NAME}}Logger", () => {
|
|
@@ -2431,7 +2483,7 @@ describe("{{NAME}}Logger", () => {
|
|
|
2431
2483
|
expect(typeof {{NAME}}Logger.prototype.error).toBe("function");
|
|
2432
2484
|
});
|
|
2433
2485
|
});
|
|
2434
|
-
`;var
|
|
2486
|
+
`;var ki=`import type { IException } from "@ooneex/exception";
|
|
2435
2487
|
import type { ILogger } from "@ooneex/logger";
|
|
2436
2488
|
import type { ScalarType } from "@ooneex/types";
|
|
2437
2489
|
import { decorator } from "@ooneex/logger";
|
|
@@ -2466,7 +2518,7 @@ export class {{NAME}}Logger implements ILogger {
|
|
|
2466
2518
|
// Handle error logging
|
|
2467
2519
|
}
|
|
2468
2520
|
}
|
|
2469
|
-
`;class
|
|
2521
|
+
`;class Ye{getName(){return"make:logger"}getDescription(){return"Generate a new logger class"}async run(e){let{name:t,module:s}=e;if(!t)t=await v({message:"Enter logger name"});t=Dc(t).replace(/Logger$/,"");let r=ki.replace(/{{NAME}}/g,t),o=s?z("modules",s):".",i=z(o,"src","loggers"),a=z(process.cwd(),i),n=z(a,`${t}Logger.ts`);await Bun.write(n,r);let d=Gi.replace(/{{NAME}}/g,t),l=z(o,"tests","loggers"),c=z(process.cwd(),l),u=z(c,`${t}Logger.spec.ts`);await Bun.write(u,d);let p=new Oc;p.success(`${z(i,t)}Logger.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),p.success(`${z(l,t)}Logger.spec.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),await Bun.spawn(["bun","add","@ooneex/logger"],{cwd:process.cwd(),stdout:"inherit",stderr:"inherit"}).exited}}Ye=b([x.command()],Ye);import{join as D}from"path";import{TerminalLogger as Gc}from"@ooneex/logger";import{toPascalCase as kc}from"@ooneex/utils";var $i=`import { describe, expect, test } from "bun:test";
|
|
2470
2522
|
import { {{NAME}}Mailer } from "@/mailers/{{NAME}}Mailer";
|
|
2471
2523
|
|
|
2472
2524
|
describe("{{NAME}}Mailer", () => {
|
|
@@ -2479,7 +2531,7 @@ describe("{{NAME}}Mailer", () => {
|
|
|
2479
2531
|
expect(typeof {{NAME}}Mailer.prototype.send).toBe("function");
|
|
2480
2532
|
});
|
|
2481
2533
|
});
|
|
2482
|
-
`;var
|
|
2534
|
+
`;var Wi=`import { inject } from "@ooneex/container";
|
|
2483
2535
|
import type { IMailer } from "@ooneex/mailer";
|
|
2484
2536
|
import { type {{NAME}}MailerPropsType, {{NAME}}MailerTemplate } from "./{{NAME}}MailerTemplate";
|
|
2485
2537
|
|
|
@@ -2503,7 +2555,7 @@ export class {{NAME}}Mailer implements IMailer {
|
|
|
2503
2555
|
});
|
|
2504
2556
|
}
|
|
2505
2557
|
}
|
|
2506
|
-
`;var
|
|
2558
|
+
`;var qi=`import { describe, expect, test } from "bun:test";
|
|
2507
2559
|
import { {{NAME}}MailerTemplate } from "@/mailers/{{NAME}}MailerTemplate";
|
|
2508
2560
|
|
|
2509
2561
|
describe("{{NAME}}MailerTemplate", () => {
|
|
@@ -2515,7 +2567,7 @@ describe("{{NAME}}MailerTemplate", () => {
|
|
|
2515
2567
|
expect(typeof {{NAME}}MailerTemplate).toBe("function");
|
|
2516
2568
|
});
|
|
2517
2569
|
});
|
|
2518
|
-
`;var
|
|
2570
|
+
`;var Ki=`import { MailerLayout } from "@ooneex/mailer";
|
|
2519
2571
|
|
|
2520
2572
|
export type {{NAME}}MailerPropsType = {
|
|
2521
2573
|
link: string;
|
|
@@ -2530,7 +2582,7 @@ export const {{NAME}}MailerTemplate = (props?: {{NAME}}MailerPropsType) => (
|
|
|
2530
2582
|
<MailerLayout.Footer />
|
|
2531
2583
|
</MailerLayout>
|
|
2532
2584
|
);
|
|
2533
|
-
`;class
|
|
2585
|
+
`;class ze{getName(){return"make:mailer"}getDescription(){return"Generate a new mailer class"}async run(e){let{name:t,module:s}=e;if(!t)t=await v({message:"Enter mailer name"});t=kc(t).replace(/Mailer$/,"");let r=Wi.replace(/{{NAME}}/g,t),o=Ki.replace(/{{NAME}}/g,t),i=s?D("modules",s):".",a=D(i,"src","mailers"),n=D(process.cwd(),a),d=D(n,`${t}Mailer.ts`),l=D(n,`${t}MailerTemplate.tsx`);await Bun.write(d,r),await Bun.write(l,o);let c=$i.replace(/{{NAME}}/g,t),u=qi.replace(/{{NAME}}/g,t),p=D(i,"tests","mailers"),m=D(process.cwd(),p),h=D(m,`${t}Mailer.spec.ts`),f=D(m,`${t}MailerTemplate.spec.ts`);await Bun.write(h,c),await Bun.write(f,u);let g=new Gc;g.success(`${D(a,t)}Mailer.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),g.success(`${D(a,t)}MailerTemplate.tsx created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),g.success(`${D(p,t)}Mailer.spec.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),g.success(`${D(p,t)}MailerTemplate.spec.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),await Bun.spawn(["bun","add","@ooneex/mailer"],{cwd:process.cwd(),stdout:"inherit",stderr:"inherit"}).exited}}ze=b([x.command()],ze);import{basename as Kc,join as $}from"path";import{TerminalLogger as Hc}from"@ooneex/logger";import{toPascalCase as $t}from"@ooneex/utils";var Hi=`import type { ContextType } from "@ooneex/socket";
|
|
2534
2586
|
import { decorator, type IMiddleware } from "@ooneex/middleware";
|
|
2535
2587
|
|
|
2536
2588
|
@decorator.middleware()
|
|
@@ -2542,7 +2594,7 @@ export class {{NAME}}Middleware implements IMiddleware {
|
|
|
2542
2594
|
return context
|
|
2543
2595
|
}
|
|
2544
2596
|
}
|
|
2545
|
-
`;var
|
|
2597
|
+
`;var Fi=`import { describe, expect, test } from "bun:test";
|
|
2546
2598
|
import { {{NAME}}Middleware } from "@/middlewares/{{NAME}}Middleware";
|
|
2547
2599
|
|
|
2548
2600
|
describe("{{NAME}}Middleware", () => {
|
|
@@ -2555,7 +2607,7 @@ describe("{{NAME}}Middleware", () => {
|
|
|
2555
2607
|
expect(typeof {{NAME}}Middleware.prototype.handler).toBe("function");
|
|
2556
2608
|
});
|
|
2557
2609
|
});
|
|
2558
|
-
`;var
|
|
2610
|
+
`;var Vi=`import type { ContextType } from "@ooneex/controller";
|
|
2559
2611
|
import { decorator, type IMiddleware } from "@ooneex/middleware";
|
|
2560
2612
|
|
|
2561
2613
|
@decorator.middleware()
|
|
@@ -2567,9 +2619,9 @@ export class {{NAME}}Middleware implements IMiddleware {
|
|
|
2567
2619
|
return context
|
|
2568
2620
|
}
|
|
2569
2621
|
}
|
|
2570
|
-
`;class
|
|
2571
|
-
`,
|
|
2572
|
-
`,
|
|
2622
|
+
`;class Ze{getName(){return"make:middleware"}getDescription(){return"Generate a new middleware class"}async addToModule(e,t){let s=await Bun.file(e).text(),r=`${t}Middleware`,o=`import { ${r} } from "./middlewares/${r}";
|
|
2623
|
+
`,i=s.lastIndexOf("import "),a=s.indexOf(`
|
|
2624
|
+
`,i);s=`${s.slice(0,a+1)}${o}${s.slice(a+1)}`;let n=/(middlewares:\s*\[)([^\]]*)/s,d=s.match(n);if(d){let l=d[2]?.trim(),c=l?`${l}, ${r}`:r;s=s.replace(n,`$1${c}`)}await Bun.write(e,s)}async run(e){let{name:t,module:s,isSocket:r}=e;if(!t)t=await v({message:"Enter middleware name"});if(r===void 0)r=await fe({message:"Is this a socket middleware?"});t=$t(t).replace(/Middleware$/,"");let i=(r?Hi:Vi).replace(/{{NAME}}/g,t),a=s?$("modules",s):".",n=$(a,"src","middlewares"),d=$(process.cwd(),n),l=$(d,`${t}Middleware.ts`);await Bun.write(l,i);let c=Fi.replace(/{{NAME}}/g,t),u=$(a,"tests","middlewares"),p=$(process.cwd(),u),m=$(p,`${t}Middleware.spec.ts`);await Bun.write(m,c);let h=s?$t(s):$t(Kc(process.cwd())),f=$(process.cwd(),a,"src",`${h}Module.ts`);if(await Bun.file(f).exists())await this.addToModule(f,t);let g=new Hc;g.success(`${$(n,t)}Middleware.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),g.success(`${$(u,t)}Middleware.spec.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),await Bun.spawn(["bun","add","@ooneex/middleware"],{cwd:process.cwd(),stdout:"inherit",stderr:"inherit"}).exited}}Ze=b([x.command()],Ze);import{join as Qe}from"path";import{TerminalLogger as Vc}from"@ooneex/logger";import{migrationCreate as Yc}from"@ooneex/migrations";var Yi=`#!/usr/bin/env bun
|
|
2573
2625
|
|
|
2574
2626
|
import { migrationUp } from "@ooneex/migrations";
|
|
2575
2627
|
import "@/migrations/migrations";
|
|
@@ -2578,7 +2630,7 @@ await migrationUp({
|
|
|
2578
2630
|
databaseUrl: Bun.env.DATABASE_URL || ":memory:",
|
|
2579
2631
|
tableName: "migrations",
|
|
2580
2632
|
});
|
|
2581
|
-
`;class
|
|
2633
|
+
`;class Xe{getName(){return"make:migration"}getDescription(){return"Generate a new migration file"}async run(e){let{module:t}=e,s=t?Qe("modules",t):".",r=await Yc({dir:Qe(s,"src/migrations")}),o=Qe(process.cwd(),s,"bin","migration","up.ts");if(!await Bun.file(o).exists())await Bun.write(o,Yi);let a=Qe(process.cwd(),"package.json"),n=Bun.file(a);if(await n.exists()){let c=await n.json();c.scripts=c.scripts||{},c.scripts["migration:up"]="bun ./bin/migration/up.ts",await Bun.write(a,JSON.stringify(c,null,2))}let d=new Vc;d.success(`${r} created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),d.info("Run 'bun run migration:up' to execute migrations",void 0,{showTimestamp:!1,showArrow:!0,showLevel:!1}),await Bun.spawn(["bun","add","--dev","@ooneex/migrations"],{cwd:process.cwd(),stdout:"inherit",stderr:"inherit"}).exited}}Xe=b([x.command()],Xe);import{join as Z}from"path";import{TerminalLogger as Qc}from"@ooneex/logger";import{toPascalCase as Xc}from"@ooneex/utils";var zi=`import { describe, expect, test } from "bun:test";
|
|
2582
2634
|
import { Permission } from "@ooneex/permission";
|
|
2583
2635
|
import { {{NAME}}Permission } from "@/permissions/{{NAME}}Permission";
|
|
2584
2636
|
|
|
@@ -2603,7 +2655,7 @@ describe("{{NAME}}Permission", () => {
|
|
|
2603
2655
|
});
|
|
2604
2656
|
|
|
2605
2657
|
});
|
|
2606
|
-
`;var
|
|
2658
|
+
`;var Zi=`import { decorator, Permission } from "@ooneex/permission";
|
|
2607
2659
|
import type { IUser } from "@ooneex/user";
|
|
2608
2660
|
|
|
2609
2661
|
@decorator.permission()
|
|
@@ -2642,9 +2694,7 @@ export class {{NAME}}Permission extends Permission {
|
|
|
2642
2694
|
return this;
|
|
2643
2695
|
}
|
|
2644
2696
|
}
|
|
2645
|
-
`;class
|
|
2646
|
-
`,a=s.lastIndexOf("import "),i=s.indexOf(`
|
|
2647
|
-
`,a);s=`${s.slice(0,i+1)}${r}${s.slice(i+1)}`;let n=/(permissions:\s*\[)([^\]]*)/s,l=s.match(n);if(l){let d=l[2]?.trim(),m=d?`${d}, ${o}`:o;s=s.replace(n,`$1${m}`)}await Bun.write(e,s)}async run(e){let{name:t,module:s}=e;if(!t)t=await v({message:"Enter permission name"});t=Ya(t).replace(/Permission$/,"");let o=Va.replace(/{{NAME}}/g,t),r=s?W("modules",s):".",a=W(r,"src","permissions"),i=W(process.cwd(),a),n=W(i,`${t}Permission.ts`);await Bun.write(n,o);let l=Ha.replace(/{{NAME}}/g,t),d=W(r,"tests","permissions"),m=W(process.cwd(),d),h=W(m,`${t}Permission.spec.ts`);await Bun.write(h,l);let c=Ya(zm(process.cwd())),p=W(process.cwd(),"src",`${c}Module.ts`);if(await Bun.file(p).exists())await this.addToModule(p,t);let u=new Zm;u.success(`${W(a,t)}Permission.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),u.success(`${W(d,t)}Permission.spec.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0})}}Qe=b([w.command()],Qe);import{basename as Jm,join as q}from"path";import{TerminalLogger as ec}from"@ooneex/logger";import{toKebabCase as tc,toPascalCase as Za}from"@ooneex/utils";var ja=`import { describe, expect, test } from "bun:test";
|
|
2697
|
+
`;class Je{getName(){return"make:permission"}getDescription(){return"Generate a new permission class"}async run(e){let{name:t,module:s}=e;if(!t)t=await v({message:"Enter permission name"});t=Xc(t).replace(/Permission$/,"");let r=Zi.replace(/{{NAME}}/g,t),o=s?Z("modules",s):".",i=Z(o,"src","permissions"),a=Z(process.cwd(),i),n=Z(a,`${t}Permission.ts`);await Bun.write(n,r);let d=zi.replace(/{{NAME}}/g,t),l=Z(o,"tests","permissions"),c=Z(process.cwd(),l),u=Z(c,`${t}Permission.spec.ts`);await Bun.write(u,d);let p=new Qc;p.success(`${Z(i,t)}Permission.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),p.success(`${Z(l,t)}Permission.spec.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),await Bun.spawn(["bun","add","@ooneex/permission"],{cwd:process.cwd(),stdout:"inherit",stderr:"inherit"}).exited}}Je=b([x.command()],Je);import{basename as em,join as W}from"path";import{TerminalLogger as tm}from"@ooneex/logger";import{toKebabCase as sm,toPascalCase as Wt}from"@ooneex/utils";var Qi=`import { describe, expect, test } from "bun:test";
|
|
2648
2698
|
import { {{NAME}}PubSub } from "@/pubsub/{{NAME}}PubSub";
|
|
2649
2699
|
|
|
2650
2700
|
describe("{{NAME}}PubSub", () => {
|
|
@@ -2682,7 +2732,7 @@ describe("{{NAME}}PubSub", () => {
|
|
|
2682
2732
|
expect(typeof {{NAME}}PubSub.prototype.unsubscribeAll).toBe("function");
|
|
2683
2733
|
});
|
|
2684
2734
|
});
|
|
2685
|
-
`;var
|
|
2735
|
+
`;var Xi=`import { inject } from "@ooneex/container";
|
|
2686
2736
|
import type { ScalarType } from "@ooneex/types";
|
|
2687
2737
|
import { decorator, PubSub, RedisPubSub } from "@ooneex/pub-sub";
|
|
2688
2738
|
|
|
@@ -2704,27 +2754,27 @@ export class {{NAME}}Event<Data extends Record<string, ScalarType> = Record<stri
|
|
|
2704
2754
|
// TODO: Implement handler logic here
|
|
2705
2755
|
}
|
|
2706
2756
|
}
|
|
2707
|
-
`;class
|
|
2708
|
-
`,
|
|
2709
|
-
`,
|
|
2710
|
-
`),await this.updateChangelog(n,
|
|
2711
|
-
`,void 0,{showArrow:!1,showTimestamp:!1,showLevel:!1,useSymbol:!1});return}if(e.success(`${
|
|
2712
|
-
`)[0]??null}catch{return null}}async getCommitsSinceTag(e,t){let s=e?`${e}..HEAD`:"HEAD",
|
|
2713
|
-
`)){let[
|
|
2714
|
-
`;for(let
|
|
2715
|
-
### ${
|
|
2716
|
-
|
|
2717
|
-
`;for(let
|
|
2718
|
-
`}}let
|
|
2719
|
-
${
|
|
2720
|
-
${
|
|
2721
|
-
${
|
|
2722
|
-
|
|
2723
|
-
${
|
|
2724
|
-
`}else
|
|
2725
|
-
|
|
2726
|
-
${
|
|
2727
|
-
`;await Bun.write(
|
|
2757
|
+
`;class je{getName(){return"make:pubsub"}getDescription(){return"Generate a new PubSub event class"}async addToModule(e,t){let s=await Bun.file(e).text(),r=`${t}Event`,o=`import { ${r} } from "./events/${r}";
|
|
2758
|
+
`,i=s.lastIndexOf("import "),a=s.indexOf(`
|
|
2759
|
+
`,i);s=`${s.slice(0,a+1)}${o}${s.slice(a+1)}`;let n=/(events:\s*\[)([^\]]*)/s,d=s.match(n);if(d){let l=d[2]?.trim(),c=l?`${l}, ${r}`:r;s=s.replace(n,`$1${c}`)}await Bun.write(e,s)}async run(e){let{name:t,module:s,channel:r}=e;if(!t)t=await v({message:"Enter name"});if(t=Wt(t).replace(/PubSub$/,""),!r)r=sm(t);let o=Xi.replace(/{{NAME}}/g,t).replace(/{{CHANNEL}}/g,r),i=s?W("modules",s):".",a=W(i,"src","events"),n=W(process.cwd(),a),d=W(n,`${t}Event.ts`);await Bun.write(d,o);let l=Qi.replace(/{{NAME}}/g,t),c=W(i,"tests","events"),u=W(process.cwd(),c),p=W(u,`${t}Event.spec.ts`);await Bun.write(p,l);let m=s?Wt(s):Wt(em(process.cwd())),h=W(process.cwd(),i,"src",`${m}Module.ts`);if(await Bun.file(h).exists())await this.addToModule(h,t);let f=new tm;f.success(`${W(a,t)}Event.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),f.success(`${W(c,t)}Event.spec.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),await Bun.spawn(["bun","add","@ooneex/pub-sub"],{cwd:process.cwd(),stdout:"inherit",stderr:"inherit"}).exited}}je=b([x.command()],je);import{readdir as rm}from"fs/promises";import{join as ce}from"path";import{TerminalLogger as om}from"@ooneex/logger";var{$:me}=globalThis.Bun;var im={feat:"Added",fix:"Fixed",refactor:"Changed",perf:"Changed",style:"Changed",docs:"Changed",build:"Changed",ci:"Changed",chore:"Changed",revert:"Removed"};class et{getName(){return"make:release"}getDescription(){return"Release packages with version bump, changelog, and git tag"}async run(){let e=new om,t=process.cwd(),s=[];for(let{name:a,type:n}of[{name:"packages",type:"package"},{name:"modules",type:"module"}])try{let d=await rm(ce(t,a),{withFileTypes:!0});s.push(...d.filter((l)=>l.isDirectory()).map((l)=>({base:ce(a,l.name),type:n})))}catch{}let r={showTimestamp:!1,showArrow:!1,useSymbol:!0};if(s.length===0){e.error("No packages or modules found",void 0,r);return}let o=0;for(let a of s){let n=ce(t,a.base),d=ce(n,"package.json"),l=Bun.file(d);if(!await l.exists())continue;let c=await l.json(),u=await this.getLastTag(c.name),p=await this.getCommitsSinceTag(u,a.base);if(p.length===0)continue;let m=this.determineBumpType(p),h=this.bumpVersion(c.version,m);c.version=h;let f=`${c.name}@${h}`;await Bun.write(d,`${JSON.stringify(c,null,2)}
|
|
2760
|
+
`),await this.updateChangelog(n,h,f,p),await this.gitAdd(ce(a.base,"package.json"),ce(a.base,"CHANGELOG.md")),await this.gitCommit(`chore(release): ${c.name}@${h}`),await this.gitTag(f,`chore(release): ${c.name}@${h}`),e.success(`${c.name}@${h} released (${m} bump, ${p.length} commit(s))`,void 0,r),o++}if(o===0){e.info(`No packages have unreleased commits
|
|
2761
|
+
`,void 0,{showArrow:!1,showTimestamp:!1,showLevel:!1,useSymbol:!1});return}if(e.success(`${o} package(s) released`,void 0,r),await fe({message:"Push commits and tags to remote?"}))try{await me`git push && git push --tags`,e.success("Pushed commits and tags to remote",void 0,r)}catch{e.error("Failed to push to remote",void 0,r)}}async getLastTag(e){try{let s=(await me`git --no-pager tag --list "${e}@*" --sort=-v:refname`.quiet()).text().trim();if(!s)return null;return s.split(`
|
|
2762
|
+
`)[0]??null}catch{return null}}async getCommitsSinceTag(e,t){let s=e?`${e}..HEAD`:"HEAD",r="%H|%an|%s";try{let i=(await me`git --no-pager log ${s} --format=${"%H|%an|%s"} -- ${t}`.quiet()).text().trim();if(!i)return[];let a=[],n=/^([a-z]+)\(([^)]+)\):\s*(.+)$/;for(let d of i.split(`
|
|
2763
|
+
`)){let[l,c,...u]=d.split("|"),p=u.join("|");if(!l||!c||!p)continue;let m=p.match(n);if(m){let[,h,f,g]=m;if(h&&f&&g)a.push({hash:l.substring(0,8),type:h,scope:f,subject:g,author:c})}}return a}catch{return[]}}determineBumpType(e){for(let t of e)if(t.type==="feat")return"minor";return"patch"}bumpVersion(e,t){let s=e.split(".").map(Number),[r=0,o=0,i=0]=s;if(t==="minor")return`${r}.${o+1}.0`;return`${r}.${o}.${i+1}`}async getRepoUrl(){try{return(await me`git --no-pager remote get-url origin`.quiet()).text().trim().replace(/\.git$/,"").replace(/^git@([^:]+):/,"https://$1/")}catch{return null}}async updateChangelog(e,t,s,r){let o=ce(e,"CHANGELOG.md"),i=new Date().toISOString().split("T")[0],a=await this.getRepoUrl(),n=new Map;for(let h of r){let f=im[h.type]??"Changed",g=n.get(f)??[];g.push(h),n.set(f,g)}let d=["Added","Changed","Deprecated","Removed","Fixed","Security"],c=`## ${a?`[${t}](${a}/releases/tag/${s})`:`[${t}]`} - ${i}
|
|
2764
|
+
`;for(let h of d){let f=n.get(h);if(!f||f.length===0)continue;c+=`
|
|
2765
|
+
### ${h}
|
|
2766
|
+
|
|
2767
|
+
`;for(let g of f){let y=a?` ([${g.hash}](${a}/commit/${g.hash}))`:"";c+=`- ${g.subject} \u2014 ${g.author}${y}
|
|
2768
|
+
`}}let u=Bun.file(o),p="";if(await u.exists())p=await u.text();let m;if(p){let h=p.match(/## \[Unreleased\][^\n]*\n/),f=p.match(/## \[\d+\.\d+\.\d+\]/);if(h){let g=(h.index??0)+h[0].length;m=`${p.slice(0,g)}
|
|
2769
|
+
${c}
|
|
2770
|
+
${p.slice(g)}`}else if(f&&f.index!==void 0)m=`${p.slice(0,f.index)}${c}
|
|
2771
|
+
${p.slice(f.index)}`;else m=`${p.trimEnd()}
|
|
2772
|
+
|
|
2773
|
+
${c}
|
|
2774
|
+
`}else m=`# Changelog
|
|
2775
|
+
|
|
2776
|
+
${c}
|
|
2777
|
+
`;await Bun.write(o,m)}async gitAdd(...e){await me`git add ${e}`}async gitCommit(e){await me`git commit --no-verify -m ${e}`}async gitTag(e,t){await me`git tag -a ${e} -m ${t}`}}et=b([x.command()],et);import{join as Q}from"path";import{TerminalLogger as dm}from"@ooneex/logger";import{toPascalCase as lm}from"@ooneex/utils";var Ji=`import { describe, expect, test } from "bun:test";
|
|
2728
2778
|
import { {{NAME}}Repository } from "@/repositories/{{NAME}}Repository";
|
|
2729
2779
|
|
|
2730
2780
|
describe("{{NAME}}Repository", () => {
|
|
@@ -2787,7 +2837,7 @@ describe("{{NAME}}Repository", () => {
|
|
|
2787
2837
|
expect(typeof {{NAME}}Repository.prototype.count).toBe("function");
|
|
2788
2838
|
});
|
|
2789
2839
|
});
|
|
2790
|
-
`;var
|
|
2840
|
+
`;var ji=`import { inject } from "@ooneex/container";
|
|
2791
2841
|
import type { ITypeormDatabase } from "@ooneex/database";
|
|
2792
2842
|
import { decorator } from "@ooneex/repository";
|
|
2793
2843
|
import type { FilterResultType } from "@ooneex/types";
|
|
@@ -2909,13 +2959,13 @@ export class {{NAME}}Repository {
|
|
|
2909
2959
|
return await repository.count(criteria ? { where: criteria } : {});
|
|
2910
2960
|
}
|
|
2911
2961
|
}
|
|
2912
|
-
`;class
|
|
2962
|
+
`;class tt{getName(){return"make:repository"}getDescription(){return"Generate a new repository class"}async run(e){let{name:t,module:s}=e;if(!t)t=await v({message:"Enter repository name"});t=lm(t).replace(/Repository$/,"");let r=ji.replace(/{{NAME}}/g,t),o=s?Q("modules",s):".",i=Q(o,"src","repositories"),a=Q(process.cwd(),i),n=Q(a,`${t}Repository.ts`);await Bun.write(n,r);let d=Ji.replace(/{{NAME}}/g,t),l=Q(o,"tests","repositories"),c=Q(process.cwd(),l),u=Q(c,`${t}Repository.spec.ts`);await Bun.write(u,d);let p=new dm;p.success(`${Q(i,t)}Repository.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),p.success(`${Q(l,t)}Repository.spec.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),await Bun.spawn(["bun","add","@ooneex/repository"],{cwd:process.cwd(),stdout:"inherit",stderr:"inherit"}).exited}}tt=b([x.command()],tt);import{join as st}from"path";import{TerminalLogger as mm}from"@ooneex/logger";import{seedCreate as pm}from"@ooneex/seeds";var ea=`#!/usr/bin/env bun
|
|
2913
2963
|
|
|
2914
2964
|
import { seedRun } from "@ooneex/seeds";
|
|
2915
2965
|
import "@/seeds/seeds";
|
|
2916
2966
|
|
|
2917
2967
|
await seedRun();
|
|
2918
|
-
`;class
|
|
2968
|
+
`;class rt{getName(){return"make:seed"}getDescription(){return"Generate a new seed file"}async run(e){let{name:t,module:s}=e;if(!t)t=await v({message:"Enter seed name"});let r=s?st("modules",s):".",o=await pm({name:t,dir:st(r,"src/seeds")}),i=st(process.cwd(),r,"bin","seed","run.ts");if(!await Bun.file(i).exists())await Bun.write(i,ea);let n=st(process.cwd(),"package.json"),d=Bun.file(n);if(await d.exists()){let u=await d.json();u.scripts=u.scripts||{},u.scripts["seed:run"]="bun ./bin/seed/run.ts",await Bun.write(n,JSON.stringify(u,null,2))}let l=new mm;l.success(`${o} created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),l.info("Run 'bun run seed:run' to execute seeds",void 0,{showTimestamp:!1,showArrow:!0,showLevel:!1}),await Bun.spawn(["bun","add","--dev","@ooneex/seeds"],{cwd:process.cwd(),stdout:"inherit",stderr:"inherit"}).exited}}rt=b([x.command()],rt);import{join as X}from"path";import{TerminalLogger as fm}from"@ooneex/logger";import{toPascalCase as ym}from"@ooneex/utils";var ta=`import { describe, expect, test } from "bun:test";
|
|
2919
2969
|
import { {{NAME}}Service } from "@/services/{{NAME}}Service";
|
|
2920
2970
|
|
|
2921
2971
|
describe("{{NAME}}Service", () => {
|
|
@@ -2928,7 +2978,7 @@ describe("{{NAME}}Service", () => {
|
|
|
2928
2978
|
expect(typeof {{NAME}}Service.prototype.execute).toBe("function");
|
|
2929
2979
|
});
|
|
2930
2980
|
});
|
|
2931
|
-
`;var
|
|
2981
|
+
`;var sa=`import { decorator } from "@ooneex/service";
|
|
2932
2982
|
import type { IService } from "@ooneex/service";
|
|
2933
2983
|
|
|
2934
2984
|
type ServiceDataType = Record<string, unknown>;
|
|
@@ -2939,7 +2989,7 @@ export class {{NAME}}Service<T extends ServiceDataType = ServiceDataType> implem
|
|
|
2939
2989
|
// TODO: Implement service logic
|
|
2940
2990
|
}
|
|
2941
2991
|
}
|
|
2942
|
-
`;class ot{getName(){return"make:service"}getDescription(){return"Generate a new service class"}async run(e){let{name:t,module:s}=e;if(!t)t=await v({message:"Enter service name"});t=
|
|
2992
|
+
`;class ot{getName(){return"make:service"}getDescription(){return"Generate a new service class"}async run(e){let{name:t,module:s}=e;if(!t)t=await v({message:"Enter service name"});t=ym(t).replace(/Service$/,"");let r=sa.replace(/{{NAME}}/g,t),o=s?X("modules",s):".",i=X(o,"src","services"),a=X(process.cwd(),i),n=X(a,`${t}Service.ts`);await Bun.write(n,r);let d=ta.replace(/{{NAME}}/g,t),l=X(o,"tests","services"),c=X(process.cwd(),l),u=X(c,`${t}Service.spec.ts`);await Bun.write(u,d);let p=new fm;p.success(`${X(i,t)}Service.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),p.success(`${X(l,t)}Service.spec.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),await Bun.spawn(["bun","add","@ooneex/service"],{cwd:process.cwd(),stdout:"inherit",stderr:"inherit"}).exited}}ot=b([x.command()],ot);import{join as J}from"path";import{TerminalLogger as xm}from"@ooneex/logger";import{toPascalCase as wm,toSnakeCase as Em}from"@ooneex/utils";var ra=`import { describe, expect, test } from "bun:test";
|
|
2943
2993
|
import { {{NAME}}StorageAdapter } from "@/storage/{{NAME}}StorageAdapter";
|
|
2944
2994
|
|
|
2945
2995
|
describe("{{NAME}}StorageAdapter", () => {
|
|
@@ -2956,7 +3006,7 @@ describe("{{NAME}}StorageAdapter", () => {
|
|
|
2956
3006
|
expect(typeof {{NAME}}StorageAdapter.prototype.getOptions).toBe("function");
|
|
2957
3007
|
});
|
|
2958
3008
|
});
|
|
2959
|
-
`;var
|
|
3009
|
+
`;var oa=`import { Storage, decorator, StorageException } from "@ooneex/storage";
|
|
2960
3010
|
import type { S3Options } from "bun";
|
|
2961
3011
|
|
|
2962
3012
|
@decorator.storage()
|
|
@@ -3011,7 +3061,7 @@ export class {{NAME}}Storage extends Storage {
|
|
|
3011
3061
|
};
|
|
3012
3062
|
}
|
|
3013
3063
|
}
|
|
3014
|
-
`;class
|
|
3064
|
+
`;class it{getName(){return"make:storage"}getDescription(){return"Generate a new storage class"}async run(e){let{name:t,module:s}=e;if(!t)t=await v({message:"Enter storage name"});t=wm(t).replace(/Storage$/,"");let r=Em(t).toUpperCase(),o=oa.replace(/{{NAME}}/g,t).replace(/{{NAME_UPPER}}/g,r),i=s?J("modules",s):".",a=J(i,"src","storage"),n=J(process.cwd(),a),d=J(n,`${t}Storage.ts`);await Bun.write(d,o);let l=ra.replace(/{{NAME}}/g,t),c=J(i,"tests","storage"),u=J(process.cwd(),c),p=J(u,`${t}Storage.spec.ts`);await Bun.write(p,l);let m=new xm;m.success(`${J(a,t)}Storage.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),m.success(`${J(c,t)}Storage.spec.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),await Bun.spawn(["bun","add","@ooneex/storage"],{cwd:process.cwd(),stdout:"inherit",stderr:"inherit"}).exited}}it=b([x.command()],it);import{join as j}from"path";import{TerminalLogger as Nm}from"@ooneex/logger";import{toPascalCase as Sm}from"@ooneex/utils";var ia=`import { describe, expect, test } from "bun:test";
|
|
3015
3065
|
import { {{NAME}}VectorDatabase } from "@/databases/{{NAME}}VectorDatabase";
|
|
3016
3066
|
|
|
3017
3067
|
describe("{{NAME}}VectorDatabase", () => {
|
|
@@ -3034,7 +3084,7 @@ describe("{{NAME}}VectorDatabase", () => {
|
|
|
3034
3084
|
expect(typeof {{NAME}}VectorDatabase.prototype.getSchema).toBe("function");
|
|
3035
3085
|
});
|
|
3036
3086
|
});
|
|
3037
|
-
`;var
|
|
3087
|
+
`;var aa=`import { VectorDatabase, decorator } from "@ooneex/rag";
|
|
3038
3088
|
import type { EmbeddingModelType, EmbeddingProviderType, FieldValueType } from "@ooneex/rag";
|
|
3039
3089
|
import { Utf8 } from "apache-arrow";
|
|
3040
3090
|
|
|
@@ -3058,8 +3108,8 @@ export class {{NAME}}VectorDatabase extends VectorDatabase<DataType> {
|
|
|
3058
3108
|
};
|
|
3059
3109
|
}
|
|
3060
3110
|
}
|
|
3061
|
-
`;class at{getName(){return"make:vector-database"}getDescription(){return"Generate a new vector database class"}async run(e){let{name:t,module:s}=e;if(!t)t=await v({message:"Enter vector database name"});t=
|
|
3062
|
-
`),process.exit(1);var
|
|
3063
|
-
`),process.exit(1);var
|
|
3111
|
+
`;class at{getName(){return"make:vector-database"}getDescription(){return"Generate a new vector database class"}async run(e){let{name:t,module:s}=e;if(!t)t=await v({message:"Enter vector database name"});t=Sm(t).replace(/VectorDatabase$/,"").replace(/Database$/,"");let r=aa.replace(/{{NAME}}/g,t),o=s?j("modules",s):".",i=j(o,"src","databases"),a=j(process.cwd(),i),n=j(a,`${t}VectorDatabase.ts`);await Bun.write(n,r);let d=ia.replace(/{{NAME}}/g,t),l=j(o,"tests","databases"),c=j(process.cwd(),l),u=j(c,`${t}VectorDatabase.spec.ts`);await Bun.write(u,d);let p=new Nm;p.success(`${j(i,t)}VectorDatabase.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),p.success(`${j(l,t)}VectorDatabase.spec.ts created successfully`,void 0,{showTimestamp:!1,showArrow:!1,useSymbol:!0}),await Bun.spawn(["bun","add","@ooneex/rag"],{cwd:process.cwd(),stdout:"inherit",stderr:"inherit"}).exited}}at=b([x.command()],at);var{values:q,positionals:Mm}=Tm({args:Bun.argv,options:{name:{type:"string"},"route-name":{type:"string"},"route-path":{type:"string"},"route-method":{type:"string"},"is-socket":{type:"boolean"},dir:{type:"string"},channel:{type:"string"},"table-name":{type:"string"},module:{type:"string"},destination:{type:"string"}},strict:!1,allowPositionals:!0}),qt=new Rm,da=Mm[2];if(!da)qt.error(`Command name is required
|
|
3112
|
+
`),process.exit(1);var la=Ft(da);if(!la)qt.info(`No commands found
|
|
3113
|
+
`),process.exit(1);var Cm={name:q.name,dir:q.dir,channel:q.channel,isSocket:q["is-socket"],tableName:q["table-name"],module:q.module,destination:q.destination,route:{name:q["route-name"],path:q["route-path"],method:q["route-method"]}};try{await la.run(Cm)}catch(e){let t=e instanceof na?e:new na(e instanceof Error?e:String(e));qt.error(t,void 0,{showArrow:!1,showTimestamp:!1,showLevel:!1}),process.exit(1)}
|
|
3064
3114
|
|
|
3065
|
-
//# debugId=
|
|
3115
|
+
//# debugId=9AEDA1AEBE5609AA64756E2164756E21
|