@ahmadjavaiddev/aura 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +59 -0
  2. package/dist/index.js +1123 -0
  3. package/package.json +29 -0
package/README.md ADDED
@@ -0,0 +1,59 @@
1
+ # custom-structure scaffolder
2
+
3
+ A flexible, interactive CLI scaffolder to generate modern Express.js backends. Pick and choose only the features you need, and all framework code is cleanly abstracted into an `internals/` directory.
4
+
5
+ ## Features you can choose:
6
+ - **Core** (Included): Express, Zod validation, TS routing, centralized error handling.
7
+ - **Redis**: Caching middleware and redis connection utilities.
8
+ - **OpenTelemetry Logger**: PostHog integration and request logging.
9
+ - **Prisma**: PostgreSQL database setup.
10
+ - **Rate Limiting**: Route-specific rate limits.
11
+ - **Auth Middleware**: Skeleton role-based authentication.
12
+ - **Pagination**: Zod schemas and paging helpers.
13
+
14
+ ## Installation / Usage
15
+
16
+ Run the CLI tool using bun:
17
+
18
+ ```bash
19
+ bun create-custom-api my-new-project
20
+ ```
21
+
22
+ Or run directly from the source:
23
+
24
+ ```bash
25
+ bun run src/cli.ts my-new-project
26
+ ```
27
+
28
+ Follow the interactive prompts to select your features:
29
+
30
+ ```text
31
+ ? Select features to include in your project:
32
+ ◻ Redis Caching (Adds redis config and caching utilities)
33
+ ◻ OpenTelemetry Logger (PostHog logging & request middleware)
34
+ ◻ Prisma ORM (Database setup with Postgres)
35
+ ◻ Rate Limiting (Express rate limit middleware)
36
+ ◻ Auth Middleware (Role-based auth middleware skeleton)
37
+ ◻ Pagination (Zod pagination helpers)
38
+ ```
39
+
40
+ ## Generated Project Structure
41
+
42
+ The scaffolder abstracts away framework boilerplate. Your generated project will look like:
43
+
44
+ ```
45
+ my-new-project/
46
+ ├── .env
47
+ ├── package.json
48
+ └── src/
49
+ ├── app.ts # Clean entry point
50
+ ├── routes/
51
+ │ └── health-route.ts # Your routing logic goes here
52
+ └── internals/ # DO NOT TOUCH: Framework boilerplate
53
+ ├── index.ts
54
+ ├── define-route.ts
55
+ ├── route-registry.ts
56
+ └── ...
57
+ ```
58
+
59
+ To create new routes, use `defineRoute` imported from `../internals` in your generated project!
package/dist/index.js ADDED
@@ -0,0 +1,1123 @@
1
+ #!/usr/bin/env node
2
+ var gr=Object.create;var{getPrototypeOf:Ar,defineProperty:F,getOwnPropertyNames:Tr}=Object;var Or=Object.prototype.hasOwnProperty;var j=(r,t,o)=>{o=r!=null?gr(Ar(r)):{};let i=t||!r||!r.__esModule?F(o,"default",{value:r,enumerable:!0}):o;for(let n of Tr(r))if(!Or.call(i,n))F(i,n,{get:()=>r[n],enumerable:!0});return i};var D=(r,t)=>()=>(t||r((t={exports:{}}).exports,t),t.exports);var q=D((Rt,ee)=>{var z={to(r,t){if(!t)return`\x1B[${r+1}G`;return`\x1B[${t+1};${r+1}H`},move(r,t){let o="";if(r<0)o+=`\x1B[${-r}D`;else if(r>0)o+=`\x1B[${r}C`;if(t<0)o+=`\x1B[${-t}A`;else if(t>0)o+=`\x1B[${t}B`;return o},up:(r=1)=>`\x1B[${r}A`,down:(r=1)=>`\x1B[${r}B`,forward:(r=1)=>`\x1B[${r}C`,backward:(r=1)=>`\x1B[${r}D`,nextLine:(r=1)=>"\x1B[E".repeat(r),prevLine:(r=1)=>"\x1B[F".repeat(r),left:"\x1B[G",hide:"\x1B[?25l",show:"\x1B[?25h",save:"\x1B7",restore:"\x1B8"},Cr={up:(r=1)=>"\x1B[S".repeat(r),down:(r=1)=>"\x1B[T".repeat(r)},jr={screen:"\x1B[2J",up:(r=1)=>"\x1B[1J".repeat(r),down:(r=1)=>"\x1B[J".repeat(r),line:"\x1B[2K",lineEnd:"\x1B[K",lineStart:"\x1B[1K",lines(r){let t="";for(let o=0;o<r;o++)t+=this.line+(o<r-1?z.up():"");if(r)t+=z.left;return t}};ee.exports={cursor:z,scroll:Cr,erase:jr,beep:"\x07"}});var H=D((It,U)=>{var P=process||{},re=P.argv||[],L=P.env||{},Lr=!(!!L.NO_COLOR||re.includes("--no-color"))&&(!!L.FORCE_COLOR||re.includes("--color")||P.platform==="win32"||(P.stdout||{}).isTTY&&L.TERM!=="dumb"||!!L.CI),Pr=(r,t,o=r)=>(i)=>{let n=""+i,s=n.indexOf(t,r.length);return~s?r+Mr(n,t,o,s)+t:r+n+t},Mr=(r,t,o,i)=>{let n="",s=0;do n+=r.substring(s,i)+o,s=i+t.length,i=r.indexOf(t,s);while(~i);return n+r.substring(s)},te=(r=Lr)=>{let t=r?Pr:()=>String;return{isColorSupported:r,reset:t("\x1B[0m","\x1B[0m"),bold:t("\x1B[1m","\x1B[22m","\x1B[22m\x1B[1m"),dim:t("\x1B[2m","\x1B[22m","\x1B[22m\x1B[2m"),italic:t("\x1B[3m","\x1B[23m"),underline:t("\x1B[4m","\x1B[24m"),inverse:t("\x1B[7m","\x1B[27m"),hidden:t("\x1B[8m","\x1B[28m"),strikethrough:t("\x1B[9m","\x1B[29m"),black:t("\x1B[30m","\x1B[39m"),red:t("\x1B[31m","\x1B[39m"),green:t("\x1B[32m","\x1B[39m"),yellow:t("\x1B[33m","\x1B[39m"),blue:t("\x1B[34m","\x1B[39m"),magenta:t("\x1B[35m","\x1B[39m"),cyan:t("\x1B[36m","\x1B[39m"),white:t("\x1B[37m","\x1B[39m"),gray:t("\x1B[90m","\x1B[39m"),bgBlack:t("\x1B[40m","\x1B[49m"),bgRed:t("\x1B[41m","\x1B[49m"),bgGreen:t("\x1B[42m","\x1B[49m"),bgYellow:t("\x1B[43m","\x1B[49m"),bgBlue:t("\x1B[44m","\x1B[49m"),bgMagenta:t("\x1B[45m","\x1B[49m"),bgCyan:t("\x1B[46m","\x1B[49m"),bgWhite:t("\x1B[47m","\x1B[49m"),blackBright:t("\x1B[90m","\x1B[39m"),redBright:t("\x1B[91m","\x1B[39m"),greenBright:t("\x1B[92m","\x1B[39m"),yellowBright:t("\x1B[93m","\x1B[39m"),blueBright:t("\x1B[94m","\x1B[39m"),magentaBright:t("\x1B[95m","\x1B[39m"),cyanBright:t("\x1B[96m","\x1B[39m"),whiteBright:t("\x1B[97m","\x1B[39m"),bgBlackBright:t("\x1B[100m","\x1B[49m"),bgRedBright:t("\x1B[101m","\x1B[49m"),bgGreenBright:t("\x1B[102m","\x1B[49m"),bgYellowBright:t("\x1B[103m","\x1B[49m"),bgBlueBright:t("\x1B[104m","\x1B[49m"),bgMagentaBright:t("\x1B[105m","\x1B[49m"),bgCyanBright:t("\x1B[106m","\x1B[49m"),bgWhiteBright:t("\x1B[107m","\x1B[49m")}};U.exports=te();U.exports.createColors=te});var w=j(q(),1),G=j(H(),1);import{stdin as be,stdout as xe}from"node:process";import*as N from"node:readline";import oe from"node:readline";import{WriteStream as Gr}from"node:tty";function kr({onlyFirst:r=!1}={}){let t=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"].join("|");return new RegExp(t,r?void 0:"g")}var fr=kr();function Ee(r){if(typeof r!="string")throw TypeError(`Expected a \`string\`, got \`${typeof r}\``);return r.replace(fr,"")}function ue(r){return r&&r.__esModule&&Object.prototype.hasOwnProperty.call(r,"default")?r.default:r}var ve={exports:{}};(function(r){var t={};r.exports=t,t.eastAsianWidth=function(i){var n=i.charCodeAt(0),s=i.length==2?i.charCodeAt(1):0,e=n;return 55296<=n&&n<=56319&&56320<=s&&s<=57343&&(n&=1023,s&=1023,e=n<<10|s,e+=65536),e==12288||65281<=e&&e<=65376||65504<=e&&e<=65510?"F":e==8361||65377<=e&&e<=65470||65474<=e&&e<=65479||65482<=e&&e<=65487||65490<=e&&e<=65495||65498<=e&&e<=65500||65512<=e&&e<=65518?"H":4352<=e&&e<=4447||4515<=e&&e<=4519||4602<=e&&e<=4607||9001<=e&&e<=9002||11904<=e&&e<=11929||11931<=e&&e<=12019||12032<=e&&e<=12245||12272<=e&&e<=12283||12289<=e&&e<=12350||12353<=e&&e<=12438||12441<=e&&e<=12543||12549<=e&&e<=12589||12593<=e&&e<=12686||12688<=e&&e<=12730||12736<=e&&e<=12771||12784<=e&&e<=12830||12832<=e&&e<=12871||12880<=e&&e<=13054||13056<=e&&e<=19903||19968<=e&&e<=42124||42128<=e&&e<=42182||43360<=e&&e<=43388||44032<=e&&e<=55203||55216<=e&&e<=55238||55243<=e&&e<=55291||63744<=e&&e<=64255||65040<=e&&e<=65049||65072<=e&&e<=65106||65108<=e&&e<=65126||65128<=e&&e<=65131||110592<=e&&e<=110593||127488<=e&&e<=127490||127504<=e&&e<=127546||127552<=e&&e<=127560||127568<=e&&e<=127569||131072<=e&&e<=194367||177984<=e&&e<=196605||196608<=e&&e<=262141?"W":32<=e&&e<=126||162<=e&&e<=163||165<=e&&e<=166||e==172||e==175||10214<=e&&e<=10221||10629<=e&&e<=10630?"Na":e==161||e==164||167<=e&&e<=168||e==170||173<=e&&e<=174||176<=e&&e<=180||182<=e&&e<=186||188<=e&&e<=191||e==198||e==208||215<=e&&e<=216||222<=e&&e<=225||e==230||232<=e&&e<=234||236<=e&&e<=237||e==240||242<=e&&e<=243||247<=e&&e<=250||e==252||e==254||e==257||e==273||e==275||e==283||294<=e&&e<=295||e==299||305<=e&&e<=307||e==312||319<=e&&e<=322||e==324||328<=e&&e<=331||e==333||338<=e&&e<=339||358<=e&&e<=359||e==363||e==462||e==464||e==466||e==468||e==470||e==472||e==474||e==476||e==593||e==609||e==708||e==711||713<=e&&e<=715||e==717||e==720||728<=e&&e<=731||e==733||e==735||768<=e&&e<=879||913<=e&&e<=929||931<=e&&e<=937||945<=e&&e<=961||963<=e&&e<=969||e==1025||1040<=e&&e<=1103||e==1105||e==8208||8211<=e&&e<=8214||8216<=e&&e<=8217||8220<=e&&e<=8221||8224<=e&&e<=8226||8228<=e&&e<=8231||e==8240||8242<=e&&e<=8243||e==8245||e==8251||e==8254||e==8308||e==8319||8321<=e&&e<=8324||e==8364||e==8451||e==8453||e==8457||e==8467||e==8470||8481<=e&&e<=8482||e==8486||e==8491||8531<=e&&e<=8532||8539<=e&&e<=8542||8544<=e&&e<=8555||8560<=e&&e<=8569||e==8585||8592<=e&&e<=8601||8632<=e&&e<=8633||e==8658||e==8660||e==8679||e==8704||8706<=e&&e<=8707||8711<=e&&e<=8712||e==8715||e==8719||e==8721||e==8725||e==8730||8733<=e&&e<=8736||e==8739||e==8741||8743<=e&&e<=8748||e==8750||8756<=e&&e<=8759||8764<=e&&e<=8765||e==8776||e==8780||e==8786||8800<=e&&e<=8801||8804<=e&&e<=8807||8810<=e&&e<=8811||8814<=e&&e<=8815||8834<=e&&e<=8835||8838<=e&&e<=8839||e==8853||e==8857||e==8869||e==8895||e==8978||9312<=e&&e<=9449||9451<=e&&e<=9547||9552<=e&&e<=9587||9600<=e&&e<=9615||9618<=e&&e<=9621||9632<=e&&e<=9633||9635<=e&&e<=9641||9650<=e&&e<=9651||9654<=e&&e<=9655||9660<=e&&e<=9661||9664<=e&&e<=9665||9670<=e&&e<=9672||e==9675||9678<=e&&e<=9681||9698<=e&&e<=9701||e==9711||9733<=e&&e<=9734||e==9737||9742<=e&&e<=9743||9748<=e&&e<=9749||e==9756||e==9758||e==9792||e==9794||9824<=e&&e<=9825||9827<=e&&e<=9829||9831<=e&&e<=9834||9836<=e&&e<=9837||e==9839||9886<=e&&e<=9887||9918<=e&&e<=9919||9924<=e&&e<=9933||9935<=e&&e<=9953||e==9955||9960<=e&&e<=9983||e==10045||e==10071||10102<=e&&e<=10111||11093<=e&&e<=11097||12872<=e&&e<=12879||57344<=e&&e<=63743||65024<=e&&e<=65039||e==65533||127232<=e&&e<=127242||127248<=e&&e<=127277||127280<=e&&e<=127337||127344<=e&&e<=127386||917760<=e&&e<=917999||983040<=e&&e<=1048573||1048576<=e&&e<=1114109?"A":"N"},t.characterLength=function(i){var n=this.eastAsianWidth(i);return n=="F"||n=="W"||n=="A"?2:1};function o(i){return i.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\uD800-\uDFFF]/g)||[]}t.length=function(i){for(var n=o(i),s=0,e=0;e<n.length;e++)s=s+this.characterLength(n[e]);return s},t.slice=function(i,n,s){textLen=t.length(i),n=n||0,s=s||1,n<0&&(n=textLen+n),s<0&&(s=textLen+s);for(var e="",c=0,d=o(i),l=0;l<d.length;l++){var u=d[l],x=t.length(u);if(c>=n-(x==2?1:0))if(c+x<=s)e+=u;else break;c+=x}return e}})(ve);var Br=ve.exports,zr=ue(Br),qr=function(){return/\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67)\uDB40\uDC7F|(?:\uD83E\uDDD1\uD83C\uDFFF\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFC-\uDFFF])|\uD83D\uDC68(?:\uD83C\uDFFB(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))?|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])\uFE0F|\u200D(?:(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D[\uDC66\uDC67])|\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC)?|(?:\uD83D\uDC69(?:\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69]))|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC69(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83E\uDDD1(?:\u200D(?:\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDE36\u200D\uD83C\uDF2B|\uD83C\uDFF3\uFE0F\u200D\u26A7|\uD83D\uDC3B\u200D\u2744|(?:(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\uD83C\uDFF4\u200D\u2620|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])\u200D[\u2640\u2642]|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u2600-\u2604\u260E\u2611\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26B0\u26B1\u26C8\u26CF\u26D1\u26D3\u26E9\u26F0\u26F1\u26F4\u26F7\u26F8\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u3030\u303D\u3297\u3299]|\uD83C[\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]|\uD83D[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3])\uFE0F|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDE35\u200D\uD83D\uDCAB|\uD83D\uDE2E\u200D\uD83D\uDCA8|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83E\uDDD1(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83D\uDC69(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF6\uD83C\uDDE6|\uD83C\uDDF4\uD83C\uDDF2|\uD83D\uDC08\u200D\u2B1B|\u2764\uFE0F\u200D(?:\uD83D\uDD25|\uD83E\uDE79)|\uD83D\uDC41\uFE0F|\uD83C\uDFF3\uFE0F|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|[#\*0-9]\uFE0F\u20E3|\u2764\uFE0F|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|\uD83C\uDFF4|(?:[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270C\u270D]|\uD83D[\uDD74\uDD90])(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC08\uDC15\uDC3B\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE2E\uDE35\uDE36\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5]|\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD]|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF]|[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0D\uDD0E\uDD10-\uDD17\uDD1D\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78\uDD7A-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCB\uDDD0\uDDE0-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6]|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26A7\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5-\uDED7\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDD77\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g},Ur=ue(qr);function O(r,t={}){if(typeof r!="string"||r.length===0||(t={ambiguousIsNarrow:!0,...t},r=Ee(r),r.length===0))return 0;r=r.replace(Ur()," ");let o=t.ambiguousIsNarrow?1:2,i=0;for(let n of r){let s=n.codePointAt(0);if(s<=31||s>=127&&s<=159||s>=768&&s<=879)continue;switch(zr.eastAsianWidth(n)){case"F":case"W":i+=2;break;case"A":i+=o;break;default:i+=1}}return i}var $=10,ne=(r=0)=>(t)=>`\x1B[${t+r}m`,ie=(r=0)=>(t)=>`\x1B[${38+r};5;${t}m`,se=(r=0)=>(t,o,i)=>`\x1B[${38+r};2;${t};${o};${i}m`,b={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],overline:[53,55],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],gray:[90,39],grey:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgGray:[100,49],bgGrey:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};Object.keys(b.modifier);var Hr=Object.keys(b.color),$r=Object.keys(b.bgColor);[...Hr,...$r];function Wr(){let r=new Map;for(let[t,o]of Object.entries(b)){for(let[i,n]of Object.entries(o))b[i]={open:`\x1B[${n[0]}m`,close:`\x1B[${n[1]}m`},o[i]=b[i],r.set(n[0],n[1]);Object.defineProperty(b,t,{value:o,enumerable:!1})}return Object.defineProperty(b,"codes",{value:r,enumerable:!1}),b.color.close="\x1B[39m",b.bgColor.close="\x1B[49m",b.color.ansi=ne(),b.color.ansi256=ie(),b.color.ansi16m=se(),b.bgColor.ansi=ne($),b.bgColor.ansi256=ie($),b.bgColor.ansi16m=se($),Object.defineProperties(b,{rgbToAnsi256:{value:(t,o,i)=>t===o&&o===i?t<8?16:t>248?231:Math.round((t-8)/247*24)+232:16+36*Math.round(t/255*5)+6*Math.round(o/255*5)+Math.round(i/255*5),enumerable:!1},hexToRgb:{value:(t)=>{let o=/[a-f\d]{6}|[a-f\d]{3}/i.exec(t.toString(16));if(!o)return[0,0,0];let[i]=o;i.length===3&&(i=[...i].map((s)=>s+s).join(""));let n=Number.parseInt(i,16);return[n>>16&255,n>>8&255,n&255]},enumerable:!1},hexToAnsi256:{value:(t)=>b.rgbToAnsi256(...b.hexToRgb(t)),enumerable:!1},ansi256ToAnsi:{value:(t)=>{if(t<8)return 30+t;if(t<16)return 90+(t-8);let o,i,n;if(t>=232)o=((t-232)*10+8)/255,i=o,n=o;else{t-=16;let c=t%36;o=Math.floor(t/36)/5,i=Math.floor(c/6)/5,n=c%6/5}let s=Math.max(o,i,n)*2;if(s===0)return 30;let e=30+(Math.round(n)<<2|Math.round(i)<<1|Math.round(o));return s===2&&(e+=60),e},enumerable:!1},rgbToAnsi:{value:(t,o,i)=>b.ansi256ToAnsi(b.rgbToAnsi256(t,o,i)),enumerable:!1},hexToAnsi:{value:(t)=>b.ansi256ToAnsi(b.hexToAnsi256(t)),enumerable:!1}}),b}var Jr=Wr(),k=new Set(["\x1B","›"]),Zr=39,J="\x07",he="[",Vr="]",we="m",Z=`${Vr}8;;`,me=(r)=>`${k.values().next().value}${he}${r}${we}`,ae=(r)=>`${k.values().next().value}${Z}${r}${J}`,Kr=(r)=>r.split(" ").map((t)=>O(t)),W=(r,t,o)=>{let i=[...t],n=!1,s=!1,e=O(Ee(r[r.length-1]));for(let[c,d]of i.entries()){let l=O(d);if(e+l<=o?r[r.length-1]+=d:(r.push(d),e=0),k.has(d)&&(n=!0,s=i.slice(c+1).join("").startsWith(Z)),n){s?d===J&&(n=!1,s=!1):d===we&&(n=!1);continue}e+=l,e===o&&c<i.length-1&&(r.push(""),e=0)}!e&&r[r.length-1].length>0&&r.length>1&&(r[r.length-2]+=r.pop())},Yr=(r)=>{let t=r.split(" "),o=t.length;for(;o>0&&!(O(t[o-1])>0);)o--;return o===t.length?r:t.slice(0,o).join(" ")+t.slice(o).join("")},Xr=(r,t,o={})=>{if(o.trim!==!1&&r.trim()==="")return"";let i="",n,s,e=Kr(r),c=[""];for(let[l,u]of r.split(" ").entries()){o.trim!==!1&&(c[c.length-1]=c[c.length-1].trimStart());let x=O(c[c.length-1]);if(l!==0&&(x>=t&&(o.wordWrap===!1||o.trim===!1)&&(c.push(""),x=0),(x>0||o.trim===!1)&&(c[c.length-1]+=" ",x++)),o.hard&&e[l]>t){let S=t-x,h=1+Math.floor((e[l]-S-1)/t);Math.floor((e[l]-1)/t)<h&&c.push(""),W(c,u,t);continue}if(x+e[l]>t&&x>0&&e[l]>0){if(o.wordWrap===!1&&x<t){W(c,u,t);continue}c.push("")}if(x+e[l]>t&&o.wordWrap===!1){W(c,u,t);continue}c[c.length-1]+=u}o.trim!==!1&&(c=c.map((l)=>Yr(l)));let d=[...c.join(`
3
+ `)];for(let[l,u]of d.entries()){if(i+=u,k.has(u)){let{groups:S}=new RegExp(`(?:\\${he}(?<code>\\d+)m|\\${Z}(?<uri>.*)${J})`).exec(d.slice(l).join(""))||{groups:{}};if(S.code!==void 0){let h=Number.parseFloat(S.code);n=h===Zr?void 0:h}else S.uri!==void 0&&(s=S.uri.length===0?void 0:S.uri)}let x=Jr.codes.get(Number(n));d[l+1]===`
4
+ `?(s&&(i+=ae("")),n&&x&&(i+=me(x))):u===`
5
+ `&&(n&&x&&(i+=me(n)),s&&(i+=ae(s)))}return i};function ce(r,t,o){return String(r).normalize().replace(/\r\n/g,`
6
+ `).split(`
7
+ `).map((i)=>Xr(i,t,o)).join(`
8
+ `)}var Qr=Object.defineProperty,Fr=(r,t,o)=>(t in r)?Qr(r,t,{enumerable:!0,configurable:!0,writable:!0,value:o}):r[t]=o,y=(r,t,o)=>(Fr(r,typeof t!="symbol"?t+"":t,o),o);function Dr(r,t){if(r===t)return;let o=r.split(`
9
+ `),i=t.split(`
10
+ `),n=[];for(let s=0;s<Math.max(o.length,i.length);s++)o[s]!==i[s]&&n.push(s);return n}var Se=Symbol("clack:cancel");function C(r){return r===Se}function M(r,t){r.isTTY&&r.setRawMode(t)}var pe=new Map([["k","up"],["j","down"],["h","left"],["l","right"]]),et=new Set(["up","down","left","right","space","enter"]);class f{constructor({render:r,input:t=be,output:o=xe,...i},n=!0){y(this,"input"),y(this,"output"),y(this,"rl"),y(this,"opts"),y(this,"_track",!1),y(this,"_render"),y(this,"_cursor",0),y(this,"state","initial"),y(this,"value"),y(this,"error",""),y(this,"subscribers",new Map),y(this,"_prevFrame",""),this.opts=i,this.onKeypress=this.onKeypress.bind(this),this.close=this.close.bind(this),this.render=this.render.bind(this),this._render=r.bind(this),this._track=n,this.input=t,this.output=o}prompt(){let r=new Gr(0);return r._write=(t,o,i)=>{this._track&&(this.value=this.rl.line.replace(/\t/g,""),this._cursor=this.rl.cursor,this.emit("value",this.value)),i()},this.input.pipe(r),this.rl=oe.createInterface({input:this.input,output:r,tabSize:2,prompt:"",escapeCodeTimeout:50}),oe.emitKeypressEvents(this.input,this.rl),this.rl.prompt(),this.opts.initialValue!==void 0&&this._track&&this.rl.write(this.opts.initialValue),this.input.on("keypress",this.onKeypress),M(this.input,!0),this.output.on("resize",this.render),this.render(),new Promise((t,o)=>{this.once("submit",()=>{this.output.write(w.cursor.show),this.output.off("resize",this.render),M(this.input,!1),t(this.value)}),this.once("cancel",()=>{this.output.write(w.cursor.show),this.output.off("resize",this.render),M(this.input,!1),t(Se)})})}on(r,t){let o=this.subscribers.get(r)??[];o.push({cb:t}),this.subscribers.set(r,o)}once(r,t){let o=this.subscribers.get(r)??[];o.push({cb:t,once:!0}),this.subscribers.set(r,o)}emit(r,...t){let o=this.subscribers.get(r)??[],i=[];for(let n of o)n.cb(...t),n.once&&i.push(()=>o.splice(o.indexOf(n),1));for(let n of i)n()}unsubscribe(){this.subscribers.clear()}onKeypress(r,t){if(this.state==="error"&&(this.state="active"),t?.name&&!this._track&&pe.has(t.name)&&this.emit("cursor",pe.get(t.name)),t?.name&&et.has(t.name)&&this.emit("cursor",t.name),r&&(r.toLowerCase()==="y"||r.toLowerCase()==="n")&&this.emit("confirm",r.toLowerCase()==="y"),r==="\t"&&this.opts.placeholder&&(this.value||(this.rl.write(this.opts.placeholder),this.emit("value",this.opts.placeholder))),r&&this.emit("key",r.toLowerCase()),t?.name==="return"){if(this.opts.validate){let o=this.opts.validate(this.value);o&&(this.error=o,this.state="error",this.rl.write(this.value))}this.state!=="error"&&(this.state="submit")}r==="\x03"&&(this.state="cancel"),(this.state==="submit"||this.state==="cancel")&&this.emit("finalize"),this.render(),(this.state==="submit"||this.state==="cancel")&&this.close()}close(){this.input.unpipe(),this.input.removeListener("keypress",this.onKeypress),this.output.write(`
11
+ `),M(this.input,!1),this.rl.close(),this.emit(`${this.state}`,this.value),this.unsubscribe()}restoreCursor(){let r=ce(this._prevFrame,process.stdout.columns,{hard:!0}).split(`
12
+ `).length-1;this.output.write(w.cursor.move(-999,r*-1))}render(){let r=ce(this._render(this)??"",process.stdout.columns,{hard:!0});if(r!==this._prevFrame){if(this.state==="initial")this.output.write(w.cursor.hide);else{let t=Dr(this._prevFrame,r);if(this.restoreCursor(),t&&t?.length===1){let o=t[0];this.output.write(w.cursor.move(0,o)),this.output.write(w.erase.lines(1));let i=r.split(`
13
+ `);this.output.write(i[o]),this._prevFrame=r,this.output.write(w.cursor.move(0,i.length-o-1));return}else if(t&&t?.length>1){let o=t[0];this.output.write(w.cursor.move(0,o)),this.output.write(w.erase.down());let i=r.split(`
14
+ `).slice(o);this.output.write(i.join(`
15
+ `)),this._prevFrame=r;return}this.output.write(w.erase.down())}this.output.write(r),this.state==="initial"&&(this.state="active"),this._prevFrame=r}}}var rt=Object.defineProperty,tt=(r,t,o)=>(t in r)?rt(r,t,{enumerable:!0,configurable:!0,writable:!0,value:o}):r[t]=o,le=(r,t,o)=>(tt(r,typeof t!="symbol"?t+"":t,o),o),ye=class extends f{constructor(r){super(r,!1),le(this,"options"),le(this,"cursor",0),this.options=r.options,this.value=[...r.initialValues??[]],this.cursor=Math.max(this.options.findIndex(({value:t})=>t===r.cursorAt),0),this.on("key",(t)=>{t==="a"&&this.toggleAll()}),this.on("cursor",(t)=>{switch(t){case"left":case"up":this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;break;case"down":case"right":this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;break;case"space":this.toggleValue();break}})}get _value(){return this.options[this.cursor].value}toggleAll(){let r=this.value.length===this.options.length;this.value=r?[]:this.options.map((t)=>t.value)}toggleValue(){let r=this.value.includes(this._value);this.value=r?this.value.filter((t)=>t!==this._value):[...this.value,this._value]}};var ot=Object.defineProperty,nt=(r,t,o)=>(t in r)?ot(r,t,{enumerable:!0,configurable:!0,writable:!0,value:o}):r[t]=o,de=(r,t,o)=>(nt(r,typeof t!="symbol"?t+"":t,o),o),Re=class extends f{constructor(r){super(r,!1),de(this,"options"),de(this,"cursor",0),this.options=r.options,this.cursor=this.options.findIndex(({value:t})=>t===r.initialValue),this.cursor===-1&&(this.cursor=0),this.changeValue(),this.on("cursor",(t)=>{switch(t){case"left":case"up":this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;break;case"down":case"right":this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;break}this.changeValue()})}get _value(){return this.options[this.cursor]}changeValue(){this.value=this._value.value}};var it=Object.defineProperty,st=(r,t,o)=>(t in r)?it(r,t,{enumerable:!0,configurable:!0,writable:!0,value:o}):r[t]=o,mt=(r,t,o)=>(st(r,typeof t!="symbol"?t+"":t,o),o);class V extends f{constructor(r){super(r),mt(this,"valueWithCursor",""),this.on("finalize",()=>{this.value||(this.value=r.defaultValue),this.valueWithCursor=this.value}),this.on("value",()=>{if(this.cursor>=this.value.length)this.valueWithCursor=`${this.value}${G.default.inverse(G.default.hidden("_"))}`;else{let t=this.value.slice(0,this.cursor),o=this.value.slice(this.cursor);this.valueWithCursor=`${t}${G.default.inverse(o[0])}${o.slice(1)}`}})}get cursor(){return this._cursor}}var at=globalThis.process.platform.startsWith("win");function Ie({input:r=be,output:t=xe,overwrite:o=!0,hideCursor:i=!0}={}){let n=N.createInterface({input:r,output:t,prompt:"",tabSize:1});N.emitKeypressEvents(r,n),r.isTTY&&r.setRawMode(!0);let s=(e,{name:c})=>{if(String(e)==="\x03"){i&&t.write(w.cursor.show),process.exit(0);return}if(!o)return;N.moveCursor(t,c==="return"?0:-1,c==="return"?-1:0,()=>{N.clearLine(t,1,()=>{r.once("keypress",s)})})};return i&&t.write(w.cursor.hide),r.once("keypress",s),()=>{r.off("keypress",s),i&&t.write(w.cursor.show),r.isTTY&&!at&&r.setRawMode(!1),n.terminal=!1,n.close()}}var m=j(H(),1),T=j(q(),1);import I from"node:process";function ct(){return I.platform!=="win32"?I.env.TERM!=="linux":!!I.env.CI||!!I.env.WT_SESSION||!!I.env.TERMINUS_SUBLIME||I.env.ConEmuTask==="{cmd::Cmder}"||I.env.TERM_PROGRAM==="Terminus-Sublime"||I.env.TERM_PROGRAM==="vscode"||I.env.TERM==="xterm-256color"||I.env.TERM==="alacritty"||I.env.TERMINAL_EMULATOR==="JetBrains-JediTerm"}var K=ct(),v=(r,t)=>K?r:t,pt=v("◆","*"),Ne=v("■","x"),ge=v("▲","x"),Ae=v("◇","o"),lt=v("┌","T"),E=v("│","|"),g=v("└","—"),dt=v("●",">"),bt=v("○"," "),xt=v("◻","[•]"),_e=v("◼","[+]"),Et=v("◻","[ ]"),kt=v("▪","•"),ft=v("─","-"),Bt=v("╮","+"),zt=v("├","+"),qt=v("╯","+"),Ut=v("●","•"),Ht=v("◆","*"),$t=v("▲","!"),Wt=v("■","x"),X=(r)=>{switch(r){case"initial":case"active":return m.default.cyan(pt);case"cancel":return m.default.red(Ne);case"error":return m.default.yellow(ge);case"submit":return m.default.green(Ae)}},Y=(r)=>{let{cursor:t,options:o,style:i}=r,n=r.maxItems??1/0,s=Math.max(process.stdout.rows-4,0),e=Math.min(s,Math.max(n,5)),c=0;t>=c+e-3?c=Math.max(Math.min(t-e+3,o.length-e),0):t<c+2&&(c=Math.max(t-2,0));let d=e<o.length&&c>0,l=e<o.length&&c+e<o.length;return o.slice(c,c+e).map((u,x,S)=>{let h=x===0&&d,R=x===S.length-1&&l;return h||R?m.default.dim("..."):i(u,x+c===t)})},Te=(r)=>new V({validate:r.validate,placeholder:r.placeholder,defaultValue:r.defaultValue,initialValue:r.initialValue,render(){let t=`${m.default.gray(E)}
16
+ ${X(this.state)} ${r.message}
17
+ `,o=r.placeholder?m.default.inverse(r.placeholder[0])+m.default.dim(r.placeholder.slice(1)):m.default.inverse(m.default.hidden("_")),i=this.value?this.valueWithCursor:o;switch(this.state){case"error":return`${t.trim()}
18
+ ${m.default.yellow(E)} ${i}
19
+ ${m.default.yellow(g)} ${m.default.yellow(this.error)}
20
+ `;case"submit":return`${t}${m.default.gray(E)} ${m.default.dim(this.value||r.placeholder)}`;case"cancel":return`${t}${m.default.gray(E)} ${m.default.strikethrough(m.default.dim(this.value??""))}${this.value?.trim()?`
21
+ `+m.default.gray(E):""}`;default:return`${t}${m.default.cyan(E)} ${i}
22
+ ${m.default.cyan(g)}
23
+ `}}}).prompt();var _=(r)=>{let t=(o,i)=>{let n=o.label??String(o.value);switch(i){case"selected":return`${m.default.dim(n)}`;case"active":return`${m.default.green(dt)} ${n} ${o.hint?m.default.dim(`(${o.hint})`):""}`;case"cancelled":return`${m.default.strikethrough(m.default.dim(n))}`;default:return`${m.default.dim(bt)} ${m.default.dim(n)}`}};return new Re({options:r.options,initialValue:r.initialValue,render(){let o=`${m.default.gray(E)}
24
+ ${X(this.state)} ${r.message}
25
+ `;switch(this.state){case"submit":return`${o}${m.default.gray(E)} ${t(this.options[this.cursor],"selected")}`;case"cancel":return`${o}${m.default.gray(E)} ${t(this.options[this.cursor],"cancelled")}
26
+ ${m.default.gray(E)}`;default:return`${o}${m.default.cyan(E)} ${Y({cursor:this.cursor,options:this.options,maxItems:r.maxItems,style:(i,n)=>t(i,n?"active":"inactive")}).join(`
27
+ ${m.default.cyan(E)} `)}
28
+ ${m.default.cyan(g)}
29
+ `}}}).prompt()};var Oe=(r)=>{let t=(o,i)=>{let n=o.label??String(o.value);return i==="active"?`${m.default.cyan(xt)} ${n} ${o.hint?m.default.dim(`(${o.hint})`):""}`:i==="selected"?`${m.default.green(_e)} ${m.default.dim(n)}`:i==="cancelled"?`${m.default.strikethrough(m.default.dim(n))}`:i==="active-selected"?`${m.default.green(_e)} ${n} ${o.hint?m.default.dim(`(${o.hint})`):""}`:i==="submitted"?`${m.default.dim(n)}`:`${m.default.dim(Et)} ${m.default.dim(n)}`};return new ye({options:r.options,initialValues:r.initialValues,required:r.required??!0,cursorAt:r.cursorAt,validate(o){if(this.required&&o.length===0)return`Please select at least one option.
30
+ ${m.default.reset(m.default.dim(`Press ${m.default.gray(m.default.bgWhite(m.default.inverse(" space ")))} to select, ${m.default.gray(m.default.bgWhite(m.default.inverse(" enter ")))} to submit`))}`},render(){let o=`${m.default.gray(E)}
31
+ ${X(this.state)} ${r.message}
32
+ `,i=(n,s)=>{let e=this.value.includes(n.value);return s&&e?t(n,"active-selected"):e?t(n,"selected"):t(n,s?"active":"inactive")};switch(this.state){case"submit":return`${o}${m.default.gray(E)} ${this.options.filter(({value:n})=>this.value.includes(n)).map((n)=>t(n,"submitted")).join(m.default.dim(", "))||m.default.dim("none")}`;case"cancel":{let n=this.options.filter(({value:s})=>this.value.includes(s)).map((s)=>t(s,"cancelled")).join(m.default.dim(", "));return`${o}${m.default.gray(E)} ${n.trim()?`${n}
33
+ ${m.default.gray(E)}`:""}`}case"error":{let n=this.error.split(`
34
+ `).map((s,e)=>e===0?`${m.default.yellow(g)} ${m.default.yellow(s)}`:` ${s}`).join(`
35
+ `);return o+m.default.yellow(E)+" "+Y({options:this.options,cursor:this.cursor,maxItems:r.maxItems,style:i}).join(`
36
+ ${m.default.yellow(E)} `)+`
37
+ `+n+`
38
+ `}default:return`${o}${m.default.cyan(E)} ${Y({options:this.options,cursor:this.cursor,maxItems:r.maxItems,style:i}).join(`
39
+ ${m.default.cyan(E)} `)}
40
+ ${m.default.cyan(g)}
41
+ `}}}).prompt()};var B=(r="")=>{process.stdout.write(`${m.default.gray(g)} ${m.default.red(r)}
42
+
43
+ `)},Ce=(r="")=>{process.stdout.write(`${m.default.gray(lt)} ${r}
44
+ `)},je=(r="")=>{process.stdout.write(`${m.default.gray(E)}
45
+ ${m.default.gray(g)} ${r}
46
+
47
+ `)};var Le=()=>{let r=K?["◒","◐","◓","◑"]:["•","o","O","0"],t=K?80:120,o,i,n=!1,s="",e=(h)=>{let R=h>1?"Something went wrong":"Canceled";n&&S(R,h)},c=()=>e(2),d=()=>e(1),l=()=>{process.on("uncaughtExceptionMonitor",c),process.on("unhandledRejection",c),process.on("SIGINT",d),process.on("SIGTERM",d),process.on("exit",e)},u=()=>{process.removeListener("uncaughtExceptionMonitor",c),process.removeListener("unhandledRejection",c),process.removeListener("SIGINT",d),process.removeListener("SIGTERM",d),process.removeListener("exit",e)},x=(h="")=>{n=!0,o=Ie(),s=h.replace(/\.+$/,""),process.stdout.write(`${m.default.gray(E)}
48
+ `);let R=0,A=0;l(),i=setInterval(()=>{let _r=m.default.magenta(r[R]),Nr=".".repeat(Math.floor(A)).slice(0,3);process.stdout.write(T.cursor.move(-999,0)),process.stdout.write(T.erase.down(1)),process.stdout.write(`${_r} ${s}${Nr}`),R=R+1<r.length?R+1:0,A=A<r.length?A+0.125:0},t)},S=(h="",R=0)=>{s=h??s,n=!1,clearInterval(i);let A=R===0?m.default.green(Ae):R===1?m.default.red(Ne):m.default.red(ge);process.stdout.write(T.cursor.move(-999,0)),process.stdout.write(T.erase.down(1)),process.stdout.write(`${A} ${s}
49
+ `),u(),o()};return{start:x,stop:S,message:(h="")=>{s=h??s}}};var Pe=async(r,t)=>{let o={},i=Object.keys(r);for(let n of i){let s=r[n],e=await s({results:o})?.catch((c)=>{throw c});if(typeof t?.onCancel=="function"&&C(e)){o[n]="canceled",t.onCancel({results:o});continue}o[n]=e}return o};async function Me(){let r=await Pe({caching:()=>_({message:"Select Caching strategy:",options:[{value:"none",label:"None"},{value:"memory",label:"In-memory (Local caching)"},{value:"redis",label:"Redis (Distributed caching)"}]}),logger:()=>_({message:"Select Logging strategy:",options:[{value:"none",label:"None"},{value:"console",label:"Console (Basic terminal logs)"},{value:"otel",label:"OpenTelemetry (Advanced logging + PostHog)"}]}),orm:()=>_({message:"Select a Database ORM:",options:[{value:"prisma",label:"Prisma (PostgreSQL + Typed schemas)"},{value:"drizzle",label:"Drizzle (PostgreSQL + Lightweight SQL)"},{value:"mongoose",label:"Mongoose (MongoDB)"},{value:"none",label:"None"}]}),auth:()=>_({message:"Select an Authentication provider:",options:[{value:"clerk",label:"Clerk (Hosted Auth)"},{value:"betterauth",label:"Better-Auth (Self-hosted)"},{value:"custom",label:"Custom JWT Middleware (Starter)"},{value:"none",label:"None"}]}),rateLimit:()=>_({message:"Select Rate Limiting strategy:",options:[{value:"none",label:"None"},{value:"basic",label:"Basic (Memory-based)"},{value:"redis",label:"Redis-based (Distributed)"}]}),inngest:()=>_({message:"Select Inngest support:",options:[{value:"none",label:"None"},{value:"basic",label:"Basic (Event-driven background functions)"}]}),email:()=>_({message:"Select an Email provider:",options:[{value:"resend",label:"Resend (Modern API)"},{value:"nodemailer",label:"Nodemailer (Traditional SMTP)"},{value:"none",label:"None"}]}),features:()=>Oe({message:"Extra features:",options:[{value:"pagination",label:"Pagination",hint:"Zod pagination helpers"}],required:!1}),formatter:()=>_({message:"Select a formatter/linter:",options:[{value:"biome",label:"Biome (Recommended: Fast formatter & linter)"},{value:"prettier",label:"Prettier + ESLint"},{value:"none",label:"None"}]})},{onCancel:()=>{B("Operation cancelled."),process.exit(0)}}),t=r.features;return{caching:r.caching,logger:r.logger,orm:r.orm,rateLimit:r.rateLimit,auth:r.auth,email:r.email,pagination:t.includes("pagination"),formatter:r.formatter,inngest:r.inngest}}import p from"fs/promises";import a from"path";import{exec as ut}from"child_process";import{promisify as vt}from"util";var Ge=`{
50
+ "compilerOptions": {
51
+ "lib": ["ESNext"],
52
+ "target": "ESNext",
53
+ "module": "Preserve",
54
+ "moduleDetection": "force",
55
+ "jsx": "react-jsx",
56
+ "allowJs": true,
57
+
58
+ "moduleResolution": "bundler",
59
+ "allowImportingTsExtensions": true,
60
+ "verbatimModuleSyntax": true,
61
+ "noEmit": true,
62
+
63
+ "strict": true,
64
+ "skipLibCheck": true,
65
+ "noFallthroughCasesInSwitch": true,
66
+ "noUncheckedIndexedAccess": true,
67
+ "noImplicitOverride": true,
68
+
69
+ "noUnusedLocals": false,
70
+ "noUnusedParameters": false,
71
+ "noPropertyAccessFromIndexSignature": false
72
+ }
73
+ }
74
+ `,ke=`# dependencies (bun install)
75
+ node_modules
76
+ generated
77
+
78
+ # output
79
+ out
80
+ dist
81
+ *.tgz
82
+
83
+ # code coverage
84
+ coverage
85
+ *.lcov
86
+
87
+ # logs
88
+ logs
89
+ *.log
90
+ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
91
+
92
+ # dotenv environment variable files
93
+ .env
94
+ .env.development.local
95
+ .env.test.local
96
+ .env.production.local
97
+ .env.local
98
+
99
+ # caches
100
+ .eslintcache
101
+ .cache
102
+ *.tsbuildinfo
103
+
104
+ # Test output matrix folders
105
+ tests_output_matrix_v*
106
+
107
+ # IDE settings
108
+ .idea
109
+ .vscode/
110
+
111
+ # MacOS files
112
+ .DS_Store
113
+ `,fe=`export class AppError extends Error {
114
+ constructor(
115
+ public statusCode: number,
116
+ message: string,
117
+ ) {
118
+ super(message);
119
+ this.name = "AppError";
120
+ }
121
+ }
122
+ `,Be=`import { join } from "path";
123
+ import type { RouteConfig } from "./define-route";
124
+
125
+ const ROUTES_DIR = join(import.meta.dir, "../routes");
126
+
127
+ function isRouteConfig(
128
+ value: unknown,
129
+ ): value is RouteConfig<any, any, any, any> {
130
+ if (!value || typeof value !== "object") return false;
131
+ const v = value as Record<string, unknown>;
132
+ return (
133
+ typeof v.method === "string" &&
134
+ typeof v.path === "string" &&
135
+ typeof v.handler === "function" &&
136
+ v.output !== undefined
137
+ );
138
+ }
139
+
140
+ export async function loadRoutes(): Promise<RouteConfig<any, any, any, any>[]> {
141
+ const glob = new Bun.Glob("**/*.ts");
142
+ const routes: RouteConfig<any, any, any, any>[] = [];
143
+
144
+ for await (const filePath of glob.scan({
145
+ cwd: ROUTES_DIR,
146
+ absolute: false,
147
+ })) {
148
+ const fullPath = join(ROUTES_DIR, filePath);
149
+ const mod = await import(fullPath);
150
+
151
+ for (const [exportName, exportValue] of Object.entries(mod)) {
152
+ if (isRouteConfig(exportValue)) {
153
+ routes.push(exportValue);
154
+ }
155
+ }
156
+ }
157
+
158
+ return routes;
159
+ }
160
+ `,ze=`{
161
+ "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
162
+ "organizeImports": {
163
+ "enabled": true
164
+ },
165
+ "linter": {
166
+ "enabled": true,
167
+ "rules": {
168
+ "recommended": true
169
+ }
170
+ },
171
+ "formatter": {
172
+ "enabled": true,
173
+ "indentStyle": "space",
174
+ "indentWidth": 2
175
+ }
176
+ }
177
+ `,qe=`{
178
+ "semi": true,
179
+ "singleQuote": false,
180
+ "tabWidth": 2,
181
+ "trailingComma": "all"
182
+ }
183
+ `,Ue=`import tseslint from 'typescript-eslint';
184
+
185
+ export default tseslint.config(
186
+ ...tseslint.configs.recommended,
187
+ {
188
+ ignores: ['generated/', 'dist/', 'out/', 'node_modules/']
189
+ }
190
+ );
191
+ `;var He=`import { createClient } from "redis";
192
+ import { env } from "./env";
193
+
194
+ export const redisClient = createClient({
195
+ url: env.REDIS_URL,
196
+ });
197
+
198
+ if (env.IS_CACHE_ENABLED) {
199
+ redisClient.on("error", (err) =>
200
+ console.error("Redis client error", { error: err.message }),
201
+ );
202
+ redisClient.on("connect", () => console.log("Redis connected"));
203
+ redisClient.on("reconnecting", () => console.log("Redis reconnecting"));
204
+ }
205
+
206
+ export async function connectRedis() {
207
+ if (env.IS_CACHE_ENABLED) {
208
+ await redisClient.connect();
209
+ } else {
210
+ console.log("Caching is disabled. Redis will not connect.");
211
+ }
212
+ }
213
+ `,$e=`import { redisClient } from "../config/redis";
214
+ import { env } from "../config/env";
215
+
216
+ interface CacheOptions {
217
+ ttl: number;
218
+ }
219
+
220
+ export const cache = {
221
+ async get<T>(key: string): Promise<T | null> {
222
+ if (!env.IS_CACHE_ENABLED) return null;
223
+ const value = await redisClient.get(key);
224
+ if (!value) return null;
225
+ return JSON.parse(value) as T;
226
+ },
227
+
228
+ async set<T>(key: string, value: T, options: CacheOptions): Promise<void> {
229
+ if (!env.IS_CACHE_ENABLED) return;
230
+ await redisClient.set(key, JSON.stringify(value), { EX: options.ttl });
231
+ },
232
+
233
+ async del(key: string): Promise<void> {
234
+ if (!env.IS_CACHE_ENABLED) return;
235
+ await redisClient.del(key);
236
+ },
237
+
238
+ async delPattern(pattern: string): Promise<void> {
239
+ if (!env.IS_CACHE_ENABLED) return;
240
+ const keys = await redisClient.keys(pattern);
241
+ if (keys.length > 0) {
242
+ await redisClient.del(keys);
243
+ }
244
+ },
245
+ };
246
+ `,We=`import { env } from "../config/env";
247
+
248
+ interface CacheOptions {
249
+ ttl: number;
250
+ }
251
+
252
+ const store = new Map<string, { value: any; expiresAt: number }>();
253
+
254
+ export const cache = {
255
+ async get<T>(key: string): Promise<T | null> {
256
+ if (!env.IS_CACHE_ENABLED) return null;
257
+ const item = store.get(key);
258
+ if (!item) return null;
259
+ if (Date.now() > item.expiresAt) {
260
+ store.delete(key);
261
+ return null;
262
+ }
263
+ return item.value as T;
264
+ },
265
+
266
+ async set<T>(key: string, value: T, options: CacheOptions): Promise<void> {
267
+ if (!env.IS_CACHE_ENABLED) return;
268
+ store.set(key, {
269
+ value,
270
+ expiresAt: Date.now() + options.ttl * 1000
271
+ });
272
+ },
273
+
274
+ async del(key: string): Promise<void> {
275
+ if (!env.IS_CACHE_ENABLED) return;
276
+ store.delete(key);
277
+ },
278
+
279
+ async delPattern(pattern: string): Promise<void> {
280
+ if (!env.IS_CACHE_ENABLED) return;
281
+ const regex = new RegExp("^" + pattern.replace("*", ".*") + "$");
282
+ for (const key of store.keys()) {
283
+ if (regex.test(key)) {
284
+ store.delete(key);
285
+ }
286
+ }
287
+ },
288
+ };
289
+ `,Je=`export const cacheKeys = {
290
+ users: {
291
+ detail: (id: string) => \`users:detail:\${id}\`,
292
+ },
293
+ };
294
+ `;var Ze=`import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
295
+ import { resourceFromAttributes } from "@opentelemetry/resources";
296
+ import {
297
+ LoggerProvider,
298
+ BatchLogRecordProcessor,
299
+ } from "@opentelemetry/sdk-logs";
300
+ import { SeverityNumber, logs } from "@opentelemetry/api-logs";
301
+ import type { AnyValueMap } from "@opentelemetry/api-logs";
302
+ import { env } from "../config/env";
303
+
304
+ const resource = resourceFromAttributes({
305
+ "service.name": env.SERVICE_NAME,
306
+ "service.version": env.SERVICE_VERSION,
307
+ "deployment.environment": env.NODE_ENV,
308
+ });
309
+
310
+ const processors = [
311
+ new BatchLogRecordProcessor(
312
+ new OTLPLogExporter({
313
+ url: \`\${env.POSTHOG_URL}\`,
314
+ headers: {
315
+ Authorization: \`Bearer \${env.POSTHOG_API_KEY}\`,
316
+ },
317
+ }),
318
+ ),
319
+ ];
320
+
321
+ const provider = new LoggerProvider({
322
+ resource,
323
+ processors,
324
+ });
325
+
326
+ logs.setGlobalLoggerProvider(provider);
327
+ const otelLogger = logs.getLogger(env.SERVICE_NAME);
328
+
329
+ function emit(
330
+ severityText: string,
331
+ severityNumber: SeverityNumber,
332
+ body: string,
333
+ attrs?: object,
334
+ ) {
335
+ otelLogger.emit({
336
+ severityText,
337
+ severityNumber,
338
+ body,
339
+ attributes: (attrs ?? {}) as AnyValueMap,
340
+ });
341
+
342
+ if (env.IS_DEV) {
343
+ const meta = attrs ? \` \${JSON.stringify(attrs)}\` : "";
344
+ const msg = \`[\${severityText}] \${body}\${meta}\`;
345
+
346
+ switch (severityNumber) {
347
+ case SeverityNumber.ERROR:
348
+ console.error(msg);
349
+ break;
350
+ case SeverityNumber.WARN:
351
+ console.warn(msg);
352
+ break;
353
+ case SeverityNumber.DEBUG:
354
+ console.debug(msg);
355
+ break;
356
+ default:
357
+ console.log(msg);
358
+ }
359
+ }
360
+ }
361
+
362
+ export const logger = {
363
+ info: (body: string, attrs?: object) =>
364
+ emit("INFO", SeverityNumber.INFO, body, attrs),
365
+ warn: (body: string, attrs?: object) =>
366
+ emit("WARN", SeverityNumber.WARN, body, attrs),
367
+ error: (body: string, attrs?: object) =>
368
+ emit("ERROR", SeverityNumber.ERROR, body, attrs),
369
+ debug: (body: string, attrs?: object) => {
370
+ if (env.IS_DEV) emit("DEBUG", SeverityNumber.DEBUG, body, attrs);
371
+ },
372
+ };
373
+
374
+ export async function gracefulShutdown(signal: string) {
375
+ logger.info("server.shutdown", { reason: signal });
376
+ await provider.forceFlush();
377
+ await provider.shutdown();
378
+ process.exit(0);
379
+ }
380
+
381
+ export { provider as loggerProvider };
382
+ `,Ve=`import { env } from "../config/env";
383
+
384
+ export const logger = {
385
+ info: (body: string, attrs?: object) => console.log(\`[INFO] \${body}\`, attrs ?? ""),
386
+ warn: (body: string, attrs?: object) => console.warn(\`[WARN] \${body}\`, attrs ?? ""),
387
+ error: (body: string, attrs?: object) => console.error(\`[ERROR] \${body}\`, attrs ?? ""),
388
+ debug: (body: string, attrs?: object) => {
389
+ if (env.IS_DEV) console.debug(\`[DEBUG] \${body}\`, attrs ?? "");
390
+ },
391
+ };
392
+
393
+ export async function gracefulShutdown(signal: string) {
394
+ logger.info("server.shutdown", { reason: signal });
395
+ process.exit(0);
396
+ }
397
+
398
+ export const loggerProvider = {
399
+ forceFlush: async () => {},
400
+ shutdown: async () => {},
401
+ };
402
+ `,Ke=`import type { Request, Response, NextFunction } from "express";
403
+ import { randomUUID } from "crypto";
404
+ import { logger } from "../utils/logger";
405
+
406
+ declare global {
407
+ namespace Express {
408
+ interface Request {
409
+ requestId: string;
410
+ _log: Record<string, unknown>;
411
+ _disableLogging?: boolean;
412
+ _errorHandled?: boolean;
413
+ }
414
+ }
415
+ }
416
+
417
+ export function requestLogger(req: Request, res: Response, next: NextFunction) {
418
+ req.requestId = randomUUID();
419
+ res.setHeader("X-Request-Id", req.requestId);
420
+ req._log = { _startMs: Date.now() };
421
+
422
+ const start = Date.now();
423
+
424
+ const originalJson = res.json.bind(res);
425
+ res.json = (body: any) => {
426
+ res.setHeader("X-Response-Time", \`\${Date.now() - start}ms\`);
427
+ return originalJson(body);
428
+ };
429
+
430
+ res.on("finish", () => {
431
+ if (req._disableLogging) return;
432
+
433
+ const { _startMs, ...logFields } = req._log;
434
+ const attrs = {
435
+ requestId: req.requestId,
436
+ method: req.method,
437
+ path: req.path,
438
+ status: res.statusCode,
439
+ duration_ms: Date.now() - start,
440
+ ...logFields,
441
+ };
442
+
443
+ if (res.statusCode < 400) {
444
+ logger.info("request.completed", attrs);
445
+ } else if (!req._errorHandled) {
446
+ logger.warn("request.rejected", attrs);
447
+ }
448
+ });
449
+
450
+ next();
451
+ }
452
+ `;var Ye=`generator client {
453
+ provider = "prisma-client"
454
+ output = "../generated/prisma"
455
+ }
456
+
457
+ datasource db {
458
+ provider = "postgresql"
459
+ }
460
+
461
+ model User {
462
+ id String @id @default(cuid())
463
+ name String
464
+ email String @unique
465
+ createdAt DateTime @default(now())
466
+ }
467
+ `,Xe=`import "dotenv/config";
468
+ import { defineConfig, env } from "prisma/config";
469
+
470
+ export default defineConfig({
471
+ schema: "prisma/schema.prisma",
472
+ migrations: {
473
+ path: "prisma/migrations",
474
+ },
475
+ datasource: {
476
+ url: env("DIRECT_URL"),
477
+ },
478
+ });
479
+ `,Qe=`import { PrismaPg } from "@prisma/adapter-pg";
480
+ import { PrismaClient } from "@prisma/client";
481
+ import { env } from "./env";
482
+
483
+ const connectionString = \`\${env.DATABASE_URL}\`;
484
+
485
+ const adapter = new PrismaPg({ connectionString });
486
+ export const prisma = new PrismaClient({ adapter });
487
+ `;var Fe=`import { defineConfig } from "drizzle-kit";
488
+
489
+ export default defineConfig({
490
+ dialect: "postgresql",
491
+ schema: "./src/db/schema.ts",
492
+ out: "./drizzle",
493
+ dbCredentials: {
494
+ url: process.env.DATABASE_URL!,
495
+ },
496
+ });
497
+ `,De=`import { drizzle } from "drizzle-orm/node-postgres";
498
+ import { Pool } from "pg";
499
+ import { env } from "./env";
500
+ import * as schema from "../db/schema";
501
+
502
+ const pool = new Pool({
503
+ connectionString: env.DATABASE_URL,
504
+ });
505
+
506
+ export const db = drizzle(pool, { schema });
507
+ `,er=`import { pgTable, text, timestamp } from "drizzle-orm/pg-core";
508
+
509
+ export const users = pgTable("users", {
510
+ id: text("id").primaryKey(),
511
+ name: text("name").notNull(),
512
+ email: text("email").notNull().unique(),
513
+ createdAt: timestamp("created_at").defaultNow().notNull(),
514
+ });
515
+ `;var rr=`import mongoose from "mongoose";
516
+ import { env } from "./env";
517
+
518
+ export async function connectDatabase() {
519
+ try {
520
+ await mongoose.connect(env.DATABASE_URL!);
521
+ console.log("Connected to MongoDB via Mongoose");
522
+ } catch (err) {
523
+ if (env.IS_DEV) {
524
+ console.warn("Failed to connect to MongoDB. App will continue without DB features.");
525
+ } else {
526
+ console.error("Failed to connect to MongoDB", err);
527
+ process.exit(1);
528
+ }
529
+ }
530
+ }
531
+ `,tr=`import mongoose from "mongoose";
532
+
533
+ const userSchema = new mongoose.Schema(
534
+ {
535
+ name: { type: String, required: true },
536
+ email: { type: String, required: true, unique: true },
537
+ },
538
+ { timestamps: true }
539
+ );
540
+
541
+ export const User = mongoose.model("User", userSchema);
542
+ `;var or=`import type { Request, Response, NextFunction } from "express";
543
+ import * as jwt from "jsonwebtoken";
544
+ import { env } from "../config/env";
545
+ import { AppError } from "../utils/app-error";
546
+
547
+ export const authMiddleware = (roles?: string[]) => {
548
+ return (req: Request, res: Response, next: NextFunction) => {
549
+ const authHeader = req.headers.authorization;
550
+ if (!authHeader?.startsWith("Bearer ")) {
551
+ return next(new AppError(401, "Unauthorized"));
552
+ }
553
+
554
+ const token = authHeader.split(" ")[1];
555
+ if (!token) {
556
+ return next(new AppError(401, "Unauthorized"));
557
+ }
558
+
559
+ try {
560
+ const decoded = jwt.verify(token, env.JWT_SECRET!) as any as { id: string; roles: string[] };
561
+ (req as any).user = decoded;
562
+
563
+ if (roles && !roles.some(role => decoded.roles.includes(role))) {
564
+ return next(new AppError(403, "Forbidden"));
565
+ }
566
+
567
+ next();
568
+ } catch (err) {
569
+ next(new AppError(401, "Invalid or expired token"));
570
+ }
571
+ };
572
+ };
573
+ `,nr=`import { requireAuth } from '@clerk/express';
574
+ import type { Request, Response, NextFunction } from "express";
575
+
576
+ // Clerk handles auth via clerkMiddleware() globally in app.ts.
577
+ // requireAuth() ensures the route is protected. Roles are not natively
578
+ // supported by Clerk middleware, use Clerk's RBAC or custom logic.
579
+ export const authMiddleware = (_roles?: string[]) => requireAuth();
580
+ `,ir=`import { betterAuth } from "better-auth";
581
+ import { toNodeHandler } from "better-auth/node";
582
+ import type { Request, Response, NextFunction } from "express";
583
+ import { env } from "../config/env";
584
+ import { AppError } from "../utils/app-error";
585
+
586
+ export const auth = betterAuth({
587
+ database: {
588
+ provider: "postgres", // Change according to your ORM/DB
589
+ url: env.DATABASE_URL!
590
+ },
591
+ emailAndPassword: {
592
+ enabled: true
593
+ }
594
+ });
595
+
596
+ export const authHandler = toNodeHandler(auth);
597
+
598
+ export const authMiddleware = (roles?: string[]) => {
599
+ return async (req: Request, res: Response, next: NextFunction) => {
600
+ try {
601
+ const session = await auth.api.getSession({
602
+ headers: req.headers as any
603
+ });
604
+
605
+ if (!session) {
606
+ return next(new AppError(401, "Unauthorized"));
607
+ }
608
+
609
+ (req as any).user = session.user;
610
+
611
+ if (roles && !roles.some(role => (session.user as any).roles?.includes(role))) {
612
+ return next(new AppError(403, "Forbidden"));
613
+ }
614
+
615
+ next();
616
+ } catch (err) {
617
+ next(err);
618
+ }
619
+ };
620
+ };
621
+ `;var sr=`import { Resend } from "resend";
622
+ import { env } from "../config/env";
623
+
624
+ const resend = new Resend(env.RESEND_API_KEY);
625
+
626
+ interface SendEmailParams {
627
+ to: string;
628
+ subject: string;
629
+ html: string;
630
+ from?: string;
631
+ }
632
+
633
+ export async function sendEmail({ to, subject, html, from = "onboarding@resend.dev" }: SendEmailParams) {
634
+ try {
635
+ const { data, error } = await resend.emails.send({
636
+ from,
637
+ to,
638
+ subject,
639
+ html,
640
+ });
641
+
642
+ if (error) {
643
+ console.error("Resend API Error:", error);
644
+ return { success: false, error };
645
+ }
646
+ return { success: true, data };
647
+ } catch (error) {
648
+ console.error("Failed to send email via Resend:", error);
649
+ return { success: false, error };
650
+ }
651
+ }
652
+ `,mr=`import nodemailer from "nodemailer";
653
+ import { env } from "../config/env";
654
+
655
+ const transporter = nodemailer.createTransport({
656
+ host: env.SMTP_HOST,
657
+ port: env.SMTP_PORT,
658
+ secure: env.SMTP_PORT === 465,
659
+ auth: {
660
+ user: env.SMTP_USER,
661
+ pass: env.SMTP_PASS,
662
+ },
663
+ });
664
+
665
+ interface SendEmailParams {
666
+ to: string;
667
+ subject: string;
668
+ html: string;
669
+ from?: string;
670
+ }
671
+
672
+ export async function sendEmail({ to, subject, html, from = '"API" <no-reply@example.com>' }: SendEmailParams) {
673
+ try {
674
+ const info = await transporter.sendMail({
675
+ from,
676
+ to,
677
+ subject,
678
+ html,
679
+ });
680
+ return { success: true, messageId: info.messageId };
681
+ } catch (error) {
682
+ console.error("Failed to send email via Nodemailer:", error);
683
+ return { success: false, error };
684
+ }
685
+ }
686
+ `;var ar=`import { z, type ZodType } from "zod";
687
+
688
+ export const paginationInput = z.object({
689
+ page: z.coerce.number().int().min(1).default(1),
690
+ limit: z.coerce.number().int().min(1).max(100).default(20),
691
+ });
692
+
693
+ export function paginatedOutput<T extends ZodType>(itemSchema: T) {
694
+ return z.object({
695
+ items: z.array(itemSchema),
696
+ total: z.number(),
697
+ page: z.number(),
698
+ limit: z.number(),
699
+ totalPages: z.number(),
700
+ });
701
+ }
702
+
703
+ export function paginate<T>(
704
+ items: T[],
705
+ total: number,
706
+ page: number,
707
+ limit: number,
708
+ ) {
709
+ return {
710
+ items,
711
+ total,
712
+ page,
713
+ limit,
714
+ totalPages: Math.ceil(total / limit),
715
+ };
716
+ }
717
+ `;var cr=`import { Inngest } from "inngest";
718
+
719
+ export const inngest = new Inngest({ id: "my-app" });
720
+ `,pr=`import { inngest } from "../client";
721
+
722
+ export const helloWorld = inngest.createFunction(
723
+ { id: "hello-world", triggers: [{ event: "test/hello.world" }] },
724
+ async ({ event, step }) => {
725
+ await step.sleep("wait-a-moment", "1s");
726
+ return { message: \`Hello \${event.data.email}!\` };
727
+ },
728
+ );
729
+ `,lr=`import { helloWorld } from "./functions/hello-world";
730
+
731
+ export const functions = [helloWorld];
732
+ `,dr=`import { serve } from "inngest/express";
733
+ import { inngest } from "../inngest/client";
734
+ import { functions } from "../inngest";
735
+ import { healthRoute } from "./health-route";
736
+ import { defineRoute } from "../base/define-route";
737
+ import { z } from "zod";
738
+
739
+ export const inngestRoute = defineRoute({
740
+ method: "post",
741
+ path: "/inngest",
742
+ output: z.any(),
743
+ handler: serve({ client: inngest, functions }),
744
+ });
745
+ `;function br(r,t){let o={cors:"^2.8.5",dotenv:"^16.4.5",express:"^5.0.0",helmet:"^7.1.0",zod:"^3.23.8"};if(t.caching==="redis"||t.rateLimit==="redis")o.redis="^4.7.0";if(t.logger==="otel")o["@opentelemetry/api-logs"]="^0.53.0",o["@opentelemetry/exporter-logs-otlp-http"]="^0.53.0",o["@opentelemetry/resources"]="^1.26.0",o["@opentelemetry/sdk-logs"]="^0.53.0";if(t.orm==="prisma")o["@prisma/adapter-pg"]="^7.4.2",o["@prisma/client"]="^7.4.2",o.pg="^8.20.0",o.prisma="^7.4.2";else if(t.orm==="drizzle")o["drizzle-orm"]="^0.33.0",o["drizzle-kit"]="^0.24.0",o.pg="^8.12.0";else if(t.orm==="mongoose")o.mongoose="^8.6.0";if(t.auth==="clerk")o["@clerk/express"]="^1.3.11";else if(t.auth==="betterauth")o["better-auth"]="^1.1.18";else if(t.auth==="custom")o.jsonwebtoken="^9.0.2";if(t.rateLimit!=="none")o["express-rate-limit"]="^7.4.0";if(t.email==="resend")o.resend="^3.5.0";else if(t.email==="nodemailer")o.nodemailer="^6.9.14";if(t.inngest!=="none")o.inngest="latest";let i={"@types/bun":"latest","@types/cors":"^2.8.19","@types/express":"^5.0.6","@types/node":"^22.0.0"};if(t.email==="nodemailer")i["@types/nodemailer"]="^6.4.15";if(t.auth==="custom")i["@types/jsonwebtoken"]="^9.0.7";if(t.orm==="prisma"||t.orm==="drizzle")i["@types/pg"]="^8.11.6";let n={dev:"bun run --watch src/app.ts"};if(t.orm==="prisma")n["db:generate"]="prisma generate";if(t.formatter==="biome")i["@biomejs/biome"]="1.8.3",n.format="biome format --write .",n.lint="biome check .";else if(t.formatter==="prettier")i.prettier="^3.3.3",i.eslint="^9.9.0",i["typescript-eslint"]="^8.0.1",n.format="prettier --write .",n.lint="eslint .";return JSON.stringify({name:r,module:"src/app.ts",type:"module",private:!0,scripts:n,devDependencies:i,peerDependencies:{typescript:"^5"},dependencies:o},null,2)}function xr(r,t){let o=`PORT=8000
746
+ NODE_ENV=development
747
+ IS_DEV=true
748
+ `;if(r.caching==="redis")o+=`CACHE_ENABLED=true
749
+ REDIS_URL=redis://localhost:6379
750
+ `;if(r.logger==="otel")o+=`SERVICE_NAME=${t}
751
+ POSTHOG_URL=https://us.i.posthog.com/i/v1/logs
752
+ POSTHOG_API_KEY=your_key_here
753
+ `;if(r.orm!=="none")if(r.orm==="mongoose")o+=`DATABASE_URL=mongodb://localhost:27017/my_db
754
+ `;else o+=`DATABASE_URL=postgresql://user:pass@localhost:5432/db?schema=public
755
+ DIRECT_URL=postgresql://user:pass@localhost:5432/db
756
+ `;else if(r.auth==="betterauth")o+=`DATABASE_URL=postgresql://user:pass@localhost:5432/db?schema=public
757
+ `;if(r.auth==="betterauth")o+=`BETTER_AUTH_SECRET=super_secret_string
758
+ BETTER_AUTH_URL=http://localhost:8000
759
+ `;else if(r.auth==="custom")o+=`JWT_SECRET=your_super_secret_jwt_key_here
760
+ `;if(r.email==="resend")o+=`RESEND_API_KEY=re_123456789
761
+ `;else if(r.email==="nodemailer")o+=`SMTP_HOST=smtp.mailtrap.io
762
+ SMTP_PORT=2525
763
+ SMTP_USER=user
764
+ SMTP_PASS=pass
765
+ `;if(r.inngest!=="none")o+=`INNGEST_EVENT_KEY=your_event_key_here
766
+ INNGEST_SIGNING_KEY=your_signing_key_here
767
+ `;return o}function Er(r,t){return`export const env = {
768
+ IS_DEV: process.env.NODE_ENV !== "production",
769
+ NODE_ENV: process.env.NODE_ENV ?? "development",
770
+ PORT: Number(process.env.PORT) || 8000,
771
+ SERVICE_NAME: process.env.SERVICE_NAME ?? "${t}",
772
+ SERVICE_VERSION: process.env.npm_package_version ?? "1.0.0",
773
+ ${r.caching==="redis"?` REDIS_URL: process.env.REDIS_URL,
774
+ IS_CACHE_ENABLED: process.env.CACHE_ENABLED === "true",`:""}
775
+ ${r.caching==="memory"?" IS_CACHE_ENABLED: true,":""}
776
+ ${r.logger==="otel"?` POSTHOG_API_KEY: process.env.POSTHOG_API_KEY,
777
+ POSTHOG_URL: process.env.POSTHOG_URL,`:""}
778
+ ${r.orm!=="none"||r.auth==="betterauth"?" DATABASE_URL: process.env.DATABASE_URL,":""}
779
+ ${r.auth==="clerk"?` CLERK_SECRET_KEY: process.env.CLERK_SECRET_KEY,
780
+ CLERK_PUBLISHABLE_KEY: process.env.CLERK_PUBLISHABLE_KEY,`:""}
781
+ ${r.auth==="betterauth"?` BETTER_AUTH_SECRET: process.env.BETTER_AUTH_SECRET,
782
+ BETTER_AUTH_URL: process.env.BETTER_AUTH_URL,`:""}
783
+ ${r.auth==="custom"?" JWT_SECRET: process.env.JWT_SECRET,":""}
784
+ ${r.email==="resend"?" RESEND_API_KEY: process.env.RESEND_API_KEY,":""}
785
+ ${r.email==="nodemailer"?` SMTP_HOST: process.env.SMTP_HOST,
786
+ SMTP_PORT: Number(process.env.SMTP_PORT) || 587,
787
+ SMTP_USER: process.env.SMTP_USER,
788
+ SMTP_PASS: process.env.SMTP_PASS,`:""}
789
+ ${r.inngest!=="none"?` INNGEST_EVENT_KEY: process.env.INNGEST_EVENT_KEY,
790
+ INNGEST_SIGNING_KEY: process.env.INNGEST_SIGNING_KEY,`:""}
791
+ };
792
+ `}function ur(r){let t=['import express from "express";','import helmet from "helmet";','import cors from "cors";',`import { loadRoutes, registerRoute, errorHandler${r.logger!=="none"?", logger, gracefulShutdown":""}${r.auth==="betterauth"?", authHandler":""} } from "./base";`,r.caching==="redis"?'import { connectRedis } from "./config/redis";':null,r.orm==="mongoose"?'import { connectDatabase } from "./config/mongoose";':null,r.auth==="clerk"?'import { clerkMiddleware } from "@clerk/express";':null,r.logger!=="none"?'import { requestLogger } from "./middlewares/request-logger";':null,r.inngest!=="none"?'import { inngestRoute } from "./routes/inngest-route";':null,'import { env } from "./config/env";'].filter(Boolean).join(`
793
+ `),o=[r.orm==="mongoose"?" await connectDatabase();":null,r.caching==="redis"?" await connectRedis();":null,""," const app = express();"," app.use(helmet());"," app.use(cors());"," app.use(express.json());",r.auth==="clerk"?" app.use(clerkMiddleware());":null,r.logger!=="none"?" app.use(requestLogger);":null,r.auth==="betterauth"?' app.all(["/api/auth", "/api/auth/*path"], authHandler);':null,""," const router = express.Router();"," const routes = await loadRoutes();"," routes.forEach((route) => registerRoute(router, route));",r.inngest!=="none"?" registerRoute(router, inngestRoute);":null,r.logger!=="none"?' logger.info("routes.loaded", { count: routes.length });':" console.log(`Loaded ${routes.length} routes`);","",' app.use("/api", router);'," app.use(errorHandler);","",r.logger!=="none"?` process.on("SIGTERM", () => gracefulShutdown("SIGTERM"));
794
+ process.on("SIGINT", () => gracefulShutdown("SIGINT"));`:null,""," app.listen(env.PORT, () => {",r.logger!=="none"?' logger.info("server.started", { port: env.PORT });':" console.log(`Server started on port ${env.PORT}`);"," });"].filter((i)=>i!==null).join(`
795
+ `);return`${t}
796
+
797
+ async function init() {
798
+ ${o}
799
+ }
800
+
801
+ init().catch(async (err) => {
802
+ ${r.logger!=="none"?` logger.error("server.bootstrap_failed", { error: err.message });
803
+ const { loggerProvider } = await import("./utils/logger");
804
+ await loggerProvider.forceFlush();`:' console.error("server.bootstrap_failed", err);'}
805
+ process.exit(1);
806
+ });
807
+ `}function vr(r){return`import { ZodError } from "zod";
808
+ import type { Request, Response, NextFunction } from "express";
809
+ ${r.logger!=="none"?'import { logger } from "./logger";':""}
810
+ import { AppError } from "./app-error";
811
+
812
+ export function errorHandler(
813
+ err: unknown,
814
+ req: Request,
815
+ res: Response,
816
+ next: NextFunction,
817
+ ) {
818
+ ${r.logger!=="none"?` if (req._disableLogging) {
819
+ if (err instanceof ZodError)
820
+ return res.status(400).json({ success: false, error: "Validation Error", issues: err.flatten() });
821
+ if (err instanceof AppError)
822
+ return res.status(err.statusCode).json({ success: false, error: err.message });
823
+ return res.status(500).json({ success: false, error: "Internal Server Error" });
824
+ }
825
+
826
+ const { _startMs, ...logFields } = req._log;
827
+ req._errorHandled = true;
828
+ const ctx = {
829
+ requestId: req.requestId,
830
+ path: req.path,
831
+ method: req.method,
832
+ duration_ms: _startMs ? Date.now() - (_startMs as number) : undefined,
833
+ ...logFields,
834
+ };
835
+ `:" const ctx = { path: req.path, method: req.method };"}
836
+
837
+ if (err instanceof ZodError) {
838
+ ${r.logger!=="none"?' logger.warn("request.validation_failed", { ...ctx, issues: err.flatten().fieldErrors });':' console.warn("request.validation_failed", err.flatten());'}
839
+ return res.status(400).json({
840
+ success: false,
841
+ error: "Validation Error",
842
+ issues: err.flatten(),
843
+ });
844
+ }
845
+
846
+ if (err instanceof AppError) {
847
+ ${r.logger!=="none"?` const event = err.statusCode === 401 ? "request.unauthorized" : err.statusCode === 404 ? "request.not_found" : "request.app_error";
848
+ logger.warn(event, { ...ctx, statusCode: err.statusCode, reason: err.message });`:' console.warn("request.app_error", { ...ctx, statusCode: err.statusCode, reason: err.message });'}
849
+ return res.status(err.statusCode).json({
850
+ success: false,
851
+ error: err.message,
852
+ });
853
+ }
854
+
855
+ ${r.logger!=="none"?` logger.error("request.unhandled_error", {
856
+ ...ctx,
857
+ error: err instanceof Error ? err.message : String(err),
858
+ stack: err instanceof Error ? err.stack : undefined,
859
+ });`:' console.error("request.unhandled_error", err);'}
860
+
861
+ res.status(500).json({ success: false, error: "Internal Server Error" });
862
+ }
863
+ `}function hr(r){return`import { z, type ZodType } from "zod";
864
+
865
+ ${r.auth!=="none"?`export interface AuthUser {
866
+ id: string;
867
+ roles: string[];
868
+ }`:""}
869
+
870
+ export type HttpMethod = "get" | "post" | "put" | "patch" | "delete";
871
+
872
+ export interface RouteConfig<
873
+ TBody extends ZodType = ZodType,
874
+ TQuery extends ZodType = ZodType,
875
+ TParams extends ZodType = ZodType,
876
+ TOutput extends ZodType = ZodType,
877
+ > {
878
+ method: HttpMethod;
879
+ path: string;
880
+ input?: {
881
+ body?: TBody;
882
+ query?: TQuery;
883
+ params?: TParams;
884
+ };
885
+ output: TOutput;
886
+ ${r.rateLimit!=="none"?` rateLimit?: {
887
+ enabled: boolean;
888
+ windowMs?: number;
889
+ max?: number;
890
+ };`:""}
891
+ ${r.auth!=="none"?` auth?: {
892
+ required: boolean;
893
+ roles?: string[];
894
+ };`:""}
895
+ ${r.caching!=="none"?` cache?: {
896
+ enabled: boolean;
897
+ ttl: number;
898
+ key: (ctx: { params: any; query: any${r.auth!=="none"?"; user: any":""} }) => string;
899
+ };`:""}
900
+ ${r.logger!=="none"?` logging?: {
901
+ enabled: boolean;
902
+ fields?: Array<keyof z.infer<TOutput>>;
903
+ redact?: Array<keyof z.infer<TOutput>>;
904
+ };`:""}
905
+
906
+ onRequest?: (ctx: {
907
+ body: TBody extends ZodType ? z.infer<TBody> : never;
908
+ query: TQuery extends ZodType ? z.infer<TQuery> : never;
909
+ params: TParams extends ZodType ? z.infer<TParams> : never;
910
+ ${r.auth!=="none"?" user?: AuthUser;":""}
911
+ ${r.logger!=="none"?" log: (attrs: Record<string, unknown>) => void;":""}
912
+ }) => void | Promise<void>;
913
+
914
+ onResponse?: (ctx: {
915
+ output: z.infer<TOutput>;
916
+ ${r.auth!=="none"?" user?: AuthUser;":""}
917
+ ${r.logger!=="none"?" log: (attrs: Record<string, unknown>) => void;":""}
918
+ }) => void | Promise<void>;
919
+
920
+ ${r.caching!=="none"?` invalidates?: (ctx: {
921
+ output: z.infer<TOutput>;
922
+ params: TParams extends ZodType ? z.infer<TParams> : never;
923
+ ${r.auth!=="none"?"user?: AuthUser;":""}
924
+ }) => string[];`:""}
925
+
926
+ handler: (ctx: {
927
+ body: TBody extends ZodType ? z.infer<TBody> : never;
928
+ query: TQuery extends ZodType ? z.infer<TQuery> : never;
929
+ params: TParams extends ZodType ? z.infer<TParams> : never;
930
+ ${r.auth!=="none"?" user?: AuthUser;":""}
931
+ ${r.logger!=="none"?" log: (attrs: Record<string, unknown>) => void;":""}
932
+ }) => Promise<z.infer<TOutput>>;
933
+ }
934
+
935
+ export function defineRoute<
936
+ TBody extends ZodType,
937
+ TQuery extends ZodType,
938
+ TParams extends ZodType,
939
+ TOutput extends ZodType,
940
+ >(config: RouteConfig<TBody, TQuery, TParams, TOutput>) {
941
+ return config;
942
+ }
943
+ `}function wr(r){return`import {
944
+ type Router,
945
+ type Request,
946
+ type Response,
947
+ type NextFunction,
948
+ } from "express";
949
+ ${r.rateLimit!=="none"?'import rateLimit from "express-rate-limit";':""}
950
+ import type { RouteConfig } from "./define-route";
951
+ ${r.auth!=="none"?'import { authMiddleware } from "../middlewares/auth";':""}
952
+ ${r.caching!=="none"?'import { cache } from "../utils/cache";':""}
953
+
954
+ export function registerRoute(
955
+ router: Router,
956
+ route: RouteConfig<any, any, any, any>,
957
+ ) {
958
+ const middlewares: any[] = [];
959
+
960
+ ${r.rateLimit!=="none"?` if (route.rateLimit?.enabled) {
961
+ middlewares.push(
962
+ rateLimit({
963
+ windowMs: route.rateLimit.windowMs ?? 60_000,
964
+ max: route.rateLimit.max ?? 100,
965
+ standardHeaders: true,
966
+ legacyHeaders: false,
967
+ }),
968
+ );
969
+ }`:""}
970
+
971
+ ${r.auth!=="none"?` if (route.auth?.required) {
972
+ middlewares.push(authMiddleware(route.auth.roles));
973
+ }`:""}
974
+
975
+ const handler = async (req: Request, res: Response, next: NextFunction) => {
976
+ try {
977
+ const body = route.input?.body ? route.input.body.parse(req.body) : undefined;
978
+ const query = route.input?.query ? route.input.query.parse(req.query) : undefined;
979
+ const params = route.input?.params ? route.input.params.parse(req.params) : undefined;
980
+ ${r.auth!=="none"?" const user = (req as any).user;":""}
981
+ ${r.logger!=="none"?` const log = (attrs: Record<string, unknown>) => Object.assign(req._log, attrs);
982
+ req._log.route = route.path;
983
+
984
+ if (route.logging && !route.logging.enabled) {
985
+ (req as any)._disableLogging = true;
986
+ }`:""}
987
+
988
+ if (route.onRequest) {
989
+ await route.onRequest({ body, query, params${r.auth!=="none"?", user":""}${r.logger!=="none"?", log":""} });
990
+ }
991
+
992
+ ${r.caching!=="none"?` if (route.cache?.enabled) {
993
+ const key = route.cache.key({ params, query${r.auth!=="none"?", user":""} });
994
+ const cached = await cache.get(key);
995
+ if (cached) {
996
+ return res.json({ success: true, data: cached, fromCache: true });
997
+ }
998
+ }`:""}
999
+
1000
+ const result = await route.handler({ body, query, params${r.auth!=="none"?", user":""}${r.logger!=="none"?", log":""} });
1001
+ const validatedOutput = route.output.parse(result);
1002
+
1003
+ ${r.caching!=="none"?` if (route.cache?.enabled) {
1004
+ const cacheKey = route.cache.key({ params, query${r.auth!=="none"?", user":""} });
1005
+ const ttl = route.cache.ttl;
1006
+ setImmediate(() => {
1007
+ cache.set(cacheKey, validatedOutput, { ttl }).catch(console.error);
1008
+ });
1009
+ }`:""}
1010
+
1011
+ ${r.logger!=="none"?` if (route.logging?.enabled && route.logging.fields?.length) {
1012
+ const redactSet = new Set((route.logging.redact as string[]) ?? []);
1013
+ for (const field of route.logging.fields) {
1014
+ if (validatedOutput[field] !== undefined) {
1015
+ req._log[field as string] = redactSet.has(field as string) ? "[REDACTED]" : validatedOutput[field];
1016
+ }
1017
+ }
1018
+ }`:""}
1019
+
1020
+ if (route.onResponse) {
1021
+ setImmediate(async () => {
1022
+ try {
1023
+ await route.onResponse!({ output: validatedOutput${r.auth!=="none"?", user":""}${r.logger!=="none"?", log":""} });
1024
+ } catch (err) {
1025
+ console.error(\`[onResponse Error] route \${route.path}:\`, err);
1026
+ }
1027
+ });
1028
+ }
1029
+
1030
+ ${r.caching!=="none"?` if (route.invalidates) {
1031
+ const keys = route.invalidates({ output: validatedOutput, params${r.auth!=="none"?", user":""} });
1032
+ setImmediate(async () => {
1033
+ for (const key of keys) {
1034
+ try {
1035
+ if (key.includes("*")) {
1036
+ await cache.delPattern(key);
1037
+ } else {
1038
+ await cache.del(key);
1039
+ }
1040
+ } catch (err) {
1041
+ console.error(\`[Cache Inval Error]\`, err);
1042
+ }
1043
+ }
1044
+ });
1045
+ }`:""}
1046
+
1047
+ res.json({ success: true, data: validatedOutput });
1048
+ } catch (err) {
1049
+ next(err);
1050
+ }
1051
+ };
1052
+
1053
+ router[route.method](route.path, ...middlewares, handler);
1054
+ }
1055
+ `}function Sr(r){let t=`export { defineRoute } from "./define-route";
1056
+ export { loadRoutes } from "./route-loader";
1057
+ export { registerRoute } from "./route-registry";
1058
+ export { errorHandler } from "../utils/error-handler";
1059
+ export { AppError } from "../utils/app-error";
1060
+ `;if(r.caching!=="none")t+=`export { cache } from "../utils/cache";
1061
+ export { cacheKeys } from "../utils/cache-keys";
1062
+ `;if(r.logger!=="none")t+=`export { logger, gracefulShutdown } from "../utils/logger";
1063
+ `;if(r.orm==="prisma")t+=`export { prisma } from "../config/prisma";
1064
+ `;else if(r.orm==="drizzle")t+=`export { db } from "../config/drizzle";
1065
+ `;else if(r.orm==="mongoose")t+=`export { connectDatabase } from "../config/mongoose";
1066
+ `;if(r.auth!=="none")t+=`export { authMiddleware${r.auth==="betterauth"?", authHandler":""} } from "../middlewares/auth";
1067
+ `;if(r.pagination)t+=`export { paginationInput, paginatedOutput, paginate } from "../utils/pagination";
1068
+ `;if(r.email!=="none")t+=`export { sendEmail } from "../utils/email";
1069
+ `;return t}function yr(r){return`import { z } from "zod";
1070
+ import { defineRoute } from "../base/define-route";
1071
+ ${r.caching==="redis"?'import { redisClient } from "../config/redis";':""}
1072
+ import { env } from "../config/env";
1073
+
1074
+ const startedAt = Date.now();
1075
+
1076
+ export const healthRoute = defineRoute({
1077
+ method: "get",
1078
+ path: "/health",
1079
+ output: z.object({
1080
+ status: z.string(),
1081
+ uptime_s: z.number(),
1082
+ version: z.string(),
1083
+ ${r.caching==="redis"?' redis: z.enum(["connected", "disconnected", "disabled"]),':""}
1084
+ }),
1085
+ handler: async () => {
1086
+ ${r.caching==="redis"?` let redis: "connected" | "disconnected" | "disabled" = "disabled";
1087
+ if (env.IS_CACHE_ENABLED) {
1088
+ try {
1089
+ await redisClient.ping();
1090
+ redis = "connected";
1091
+ } catch {
1092
+ redis = "disconnected";
1093
+ }
1094
+ }
1095
+ `:""}
1096
+ return {
1097
+ status: "ok",
1098
+ uptime_s: Math.floor((Date.now() - startedAt) / 1000),
1099
+ version: env.SERVICE_VERSION || "1.0.0",
1100
+ ${r.caching==="redis"?" redis,":""}
1101
+ };
1102
+ },
1103
+ });
1104
+ `}var So=vt(ut);async function Rr(r,t,o){let i=Le();i.start("Scaffolding your project...");let n=[r,a.join(r,"src"),a.join(r,"src","routes"),a.join(r,"src","base"),a.join(r,"src","config"),a.join(r,"src","middlewares"),a.join(r,"src","utils")];if(o.orm==="prisma")n.push(a.join(r,"prisma"));else if(o.orm==="drizzle")n.push(a.join(r,"src","db"));else if(o.orm==="mongoose")n.push(a.join(r,"src","models"));if(o.inngest!=="none")n.push(a.join(r,"src","inngest")),n.push(a.join(r,"src","inngest","functions"));for(let u of n)await p.mkdir(u,{recursive:!0});if(await p.writeFile(a.join(r,"package.json"),br(t,o)),await p.writeFile(a.join(r,"tsconfig.json"),Ge),await p.writeFile(a.join(r,".gitignore"),ke),await p.writeFile(a.join(r,".env"),xr(o,t)),o.formatter==="biome")await p.writeFile(a.join(r,"biome.json"),ze);else if(o.formatter==="prettier")await p.writeFile(a.join(r,".prettierrc"),qe),await p.writeFile(a.join(r,"eslint.config.js"),Ue);if(o.orm==="prisma")await p.writeFile(a.join(r,"prisma.config.ts"),Xe),await p.writeFile(a.join(r,"prisma","schema.prisma"),Ye);else if(o.orm==="drizzle")await p.writeFile(a.join(r,"drizzle.config.ts"),Fe);await p.writeFile(a.join(r,"src","app.ts"),ur(o)),await p.writeFile(a.join(r,"src","routes","health-route.ts"),yr(o));let s=a.join(r,"src"),e=a.join(s,"base"),c=a.join(s,"config"),d=a.join(s,"middlewares"),l=a.join(s,"utils");if(await p.writeFile(a.join(e,"index.ts"),Sr(o)),await p.writeFile(a.join(e,"define-route.ts"),hr(o)),await p.writeFile(a.join(e,"route-loader.ts"),Be),await p.writeFile(a.join(e,"route-registry.ts"),wr(o)),await p.writeFile(a.join(c,"env.ts"),Er(o,t)),await p.writeFile(a.join(l,"app-error.ts"),fe),await p.writeFile(a.join(l,"error-handler.ts"),vr(o)),o.caching!=="none"){if(o.caching==="redis")await p.writeFile(a.join(c,"redis.ts"),He),await p.writeFile(a.join(l,"cache.ts"),$e);else await p.writeFile(a.join(l,"cache.ts"),We);await p.writeFile(a.join(l,"cache-keys.ts"),Je)}if(o.logger!=="none"){if(o.logger==="otel")await p.writeFile(a.join(l,"logger.ts"),Ze);else await p.writeFile(a.join(l,"logger.ts"),Ve);await p.writeFile(a.join(d,"request-logger.ts"),Ke)}if(o.orm==="prisma")await p.writeFile(a.join(c,"prisma.ts"),Qe);else if(o.orm==="drizzle")await p.writeFile(a.join(c,"drizzle.ts"),De),await p.writeFile(a.join(r,"src","db","schema.ts"),er);else if(o.orm==="mongoose")await p.writeFile(a.join(c,"mongoose.ts"),rr),await p.writeFile(a.join(r,"src","models","user.model.ts"),tr);if(o.auth==="custom")await p.writeFile(a.join(d,"auth.ts"),or);else if(o.auth==="clerk")await p.writeFile(a.join(d,"auth.ts"),nr);else if(o.auth==="betterauth")await p.writeFile(a.join(d,"auth.ts"),ir);if(o.pagination)await p.writeFile(a.join(l,"pagination.ts"),ar);if(o.email==="resend")await p.writeFile(a.join(l,"email.ts"),sr);else if(o.email==="nodemailer")await p.writeFile(a.join(l,"email.ts"),mr);if(o.inngest!=="none"){let u=a.join(r,"src","inngest");await p.writeFile(a.join(u,"client.ts"),cr),await p.writeFile(a.join(u,"index.ts"),lr),await p.writeFile(a.join(u,"functions","hello-world.ts"),pr),await p.writeFile(a.join(r,"src","routes","inngest-route.ts"),dr)}return i.stop("Project generated successfully."),r}import wt from"path";var Ir={name:"@ahmadjavaiddev/aura",version:"1.0.0",type:"module",description:"Interactive CLI scaffolder to generate custom API structures",main:"./dist/index.js",bin:{aura:"dist/index.js"},files:["dist"],publishConfig:{access:"public"},scripts:{start:"bun run src/cli.ts",build:"bun build ./src/cli.ts --outfile ./dist/index.js --target node --bundle --minify",prepublishOnly:"bun run build"},dependencies:{"@clack/prompts":"^0.8.2"},devDependencies:{"@types/bun":"latest","@types/node":"^22.0.0",typescript:"^5.0.0"}};async function St(){let r=process.argv.slice(2);if(r.includes("--version")||r.includes("-v"))console.log(`v${Ir.version}`),process.exit(0);if(r.includes("--help")||r.includes("-h"))console.log(`
1105
+ Usage: aura [project-name]
1106
+
1107
+ Options:
1108
+ -v, --version Show version number
1109
+ -h, --help Show help information
1110
+
1111
+ Examples:
1112
+ npx @ahmadjavaid/aura my-new-app
1113
+ aura .
1114
+ `),process.exit(0);Ce("\uD83D\uDE80 Welcome to Aura!");let t=r[0];if(!t){let n=await Te({message:"What is your project named?",placeholder:"my-api",validate:(s)=>{if(!s)return"Please enter a path.";return}});if(C(n))B("Operation cancelled."),process.exit(0);t=n}let o=await Me(),i=wt.resolve(process.cwd(),t);await Rr(i,t,o),je(`✨ Project scaffolding complete!
1115
+
1116
+ Next steps:
1117
+ cd ${t}
1118
+ bun install${o.orm==="prisma"?`
1119
+ bun run db:generate`:""}
1120
+ ${o.orm!=="none"?`# Note: Make sure your ${o.orm} database is running`:""}
1121
+ bun update
1122
+ bun run dev
1123
+ `)}St().catch(console.error);
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@ahmadjavaiddev/aura",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "Interactive CLI scaffolder to generate custom API structures",
6
+ "main": "./dist/index.js",
7
+ "bin": {
8
+ "aura": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "publishConfig": {
14
+ "access": "public"
15
+ },
16
+ "scripts": {
17
+ "start": "bun run src/cli.ts",
18
+ "build": "bun build ./src/cli.ts --outfile ./dist/index.js --target node --bundle --minify",
19
+ "prepublishOnly": "bun run build"
20
+ },
21
+ "dependencies": {
22
+ "@clack/prompts": "^0.8.2"
23
+ },
24
+ "devDependencies": {
25
+ "@types/bun": "latest",
26
+ "@types/node": "^22.0.0",
27
+ "typescript": "^5.0.0"
28
+ }
29
+ }