@decaf-ts/utils
Version:
module management utils for decaf-ts
1 lines • 110 kB
JavaScript
import e from"prompts";import{parseArgs as t}from"util";import{Logging as o,escapeRegExp as r,LoggedClass as s,LoggedEnvironment as n,StopWatch as i,LogLevel as a}from"@decaf-ts/logging";import c from"fs";import l from"path";import{createRequire as d,builtinModules as g}from"module";import{spawn as u,execSync as h}from"child_process";import{style as f}from"styled-string-builder";import{parse as p}from"shell-quote";import m from"zlib";import y from"https";import{writeFile as S,mkdir as v}from"fs/promises";import w from"@rollup/plugin-typescript";import b from"@rollup/plugin-commonjs";import{nodeResolve as T}from"@rollup/plugin-node-resolve";import k from"@rollup/plugin-json";import*as C from"typescript";import{ModuleKind as E,ModuleResolutionKind as $}from"typescript";import{execSync as D,spawnSync as x}from"node:child_process";import N,{existsSync as R,unlinkSync as A,readFileSync as F,mkdtempSync as O,rmSync as _,mkdirSync as I}from"node:fs";import j,{tmpdir as M}from"node:os";import P,{join as U}from"node:path";class L{static{this.logger=o.for(L)}constructor(e){this.type="text",this.name=e}setType(e){return L.logger.verbose("Setting type to: "+e),this.type=e,this}setMessage(e){return L.logger.verbose("Setting message to: "+e),this.message=e,this}setInitial(e){return L.logger.verbose("Setting initial value to: "+e),this.initial=e,this}setStyle(e){return L.logger.verbose("Setting style to: "+e),this.style=e,this}setFormat(e){return L.logger.verbose("Setting format function"),this.format=e,this}setValidate(e){return L.logger.verbose("Setting validate function"),this.validate=e,this}setOnState(e){return L.logger.verbose("Setting onState callback"),this.onState=e,this}setMin(e){return L.logger.verbose("Setting min value to: "+e),this.min=e,this}setMax(e){return L.logger.verbose("Setting max value to: "+e),this.max=e,this}setFloat(e){return L.logger.verbose("Setting float to: "+e),this.float=e,this}setRound(e){return L.logger.verbose("Setting round to: "+e),this.round=e,this}setInstructions(e){return L.logger.verbose("Setting instructions to: "+e),this.instructions=e,this}setIncrement(e){return L.logger.verbose("Setting increment to: "+e),this.increment=e,this}setSeparator(e){return L.logger.verbose("Setting separator to: "+e),this.separator=e,this}setActive(e){return L.logger.verbose("Setting active style to: "+e),this.active=e,this}setInactive(e){return L.logger.verbose("Setting inactive style to: "+e),this.inactive=e,this}setChoices(e){return L.logger.verbose("Setting choices: "+JSON.stringify(e)),this.choices=e,this}setHint(e){return L.logger.verbose("Setting hint to: "+e),this.hint=e,this}setWarn(e){return L.logger.verbose("Setting warn to: "+e),this.warn=e,this}setSuggest(e){return L.logger.verbose("Setting suggest function"),this.suggest=e,this}setLimit(e){return L.logger.verbose("Setting limit to: "+e),this.limit=e,this}setMask(e){return L.logger.verbose("Setting mask to: "+e),this.mask=e,this}setStdout(e){return L.logger.verbose("Setting stdout stream"),this.stdout=e,this}setStdin(e){return this.stdin=e,this}async ask(){return(await L.ask(this))[this.name]}static async ask(t){const o=L.logger.for(this.ask);let r;Array.isArray(t)||(t=[t]);try{o.verbose("Asking questions: "+t.map(e=>e.name).join(", ")),r=await e(t),o.verbose("Received answers: "+JSON.stringify(r,null,2))}catch(e){throw Error("Error while getting input: "+e)}return r}static async askNumber(e,t,o,r,s){L.logger.for(this.askNumber).verbose(`Asking number input: undefined, question: ${t}, min: ${o}, max: ${r}, initial: ${s}`);const n=new L(e).setMessage(t).setType("number");return"number"==typeof o&&n.setMin(o),"number"==typeof r&&n.setMax(r),"number"==typeof s&&n.setInitial(s),(await this.ask(n))[e]}static async askText(e,t,o=void 0,r){L.logger.for(this.askText).verbose(`Asking text input: undefined, question: ${t}, mask: ${o}, initial: ${r}`);const s=new L(e).setMessage(t);return o&&s.setMask(o),"string"==typeof r&&s.setInitial(r),(await this.ask(s))[e]}static async askConfirmation(e,t,o){L.logger.for(this.askConfirmation).verbose(`Asking confirmation input: undefined, question: ${t}, initial: ${o}`);const r=new L(e).setMessage(t).setType("confirm");return void 0!==o&&r.setInitial(o),(await this.ask(r))[e]}static async insist(e,t,o,r=1){const s=L.logger.for(this.insist);let n;s.verbose(`Insisting on input: ${e.name}, test: ${t.toString()}, defaultConfirmation: ${o}, limit: ${r}`);let i,a=0;try{do{n=(await L.ask(e))[e.name],t(n)?(i=await L.askConfirmation(e.name+"-confirm",`Is the ${e.type} correct?`,o),i||(n=void 0)):n=void 0}while(void 0===n&&r>1&&a++<r)}catch(e){throw s.error("Error while insisting: "+e),e}return void 0===n&&s.info("no selection..."),n}static async insistForText(e,t,o,r=void 0,s,n=!1,i=-1){L.logger.for(this.insistForText).verbose(`Insisting for text input: undefined, question: ${t}, test: ${o.toString()}, mask: ${r}, initial: ${s}, defaultConfirmation: ${n}, limit: ${i}`);const a=new L(e).setMessage(t);return r&&a.setMask(r),"string"==typeof s&&a.setInitial(s),await this.insist(a,o,n,i)}static async insistForNumber(e,t,o,r,s,n,i=!1,a=-1){L.logger.for(this.insistForNumber).verbose(`Insisting for number input: undefined, question: ${t}, test: ${o.toString()}, min: ${r}, max: ${s}, initial: ${n}, defaultConfirmation: ${i}, limit: ${a}`);const c=new L(e).setMessage(t).setType("number");return"number"==typeof r&&c.setMin(r),"number"==typeof s&&c.setMax(s),"number"==typeof n&&c.setInitial(n),await this.insist(c,o,i,a)}static parseArgs(e){const o=L.logger.for(this.parseArgs),r={args:process.argv.slice(2),options:e};o.debug("Parsing arguments: "+JSON.stringify(r,null,2));try{return t(r)}catch(t){throw o.debug(`Error while parsing arguments:\n${JSON.stringify(r,null,2)}\n | options\n${JSON.stringify(e,null,2)}\n | ${t}`),Error("Error while parsing arguments: "+t)}}}const B={verbose:{type:"boolean",short:"V",default:void 0},version:{type:"boolean",short:"v",default:void 0},help:{type:"boolean",short:"h",default:!1},logLevel:{type:"string",default:"info"},logStyle:{type:"boolean",default:!0},timestamp:{type:"boolean",default:!0},banner:{type:"boolean",default:!0}},H=Object.keys(B).reduce((e,t)=>(e[t]=B[t].default,e),{}),G="utf-8",V=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z])))/g;var W;(e=>{e.PATCH="patch",e.MINOR="minor",e.MAJOR="major"})(W||(W={}));const K="-no-ci",J="postinstall";var q;(e=>{e.GIT=".token",e.NPM=".npmtoken",e.DOCKER=".dockertoken",e.CONFLUENCE=".confluence-token"})(q||(q={}));const z="Aborted";class X{constructor(e,t,...r){this.cmd=e,this.lock=t,this.logger=o.for(this.cmd)}log(e,t){t=Buffer.isBuffer(t)?t.toString(G):t;const o="stderr"===e?f(t).red.text:t;this.logger.info(o)}data(e){this.log("stdout",e+"")}error(e){this.log("stderr",e+"")}errors(e){this.log("stderr","Error executing command exited : "+e)}exit(e,t){this.log("stdout","command exited code : "+(0===e?f(e.toString()).green.text:f(null===e?"null":e.toString()).red.text)),0===e?this.resolve(t.map(e=>e.trim()).join("\n")):this.reject(Error(t.length?t.join("\n"):e.toString()))}parseCommand(e){if(Array.isArray(e))return this.cmd=e.join(" "),[e[0],e.slice(1)];const t=p(e).filter(e=>"string"==typeof e).map(String);return this.cmd=t.join(" "),[t[0],t.slice(1)]}resolve(e){this.log("stdout",`${this.cmd} executed successfully: ${f(e?"ran to completion":e).green}`),this.lock.resolve(e)}reject(e){e instanceof Error||(e=Error("number"==typeof e?"Exit code "+e:e)),this.log("stderr",`${this.cmd} failed to execute: ${f(e.message).red}`),this.lock.reject(e)}}function Y(e){let t=Promise.resolve();return(...o)=>{const r=t.then(()=>e(...o));return t=r.catch(()=>{}),r}}function Z(e,...t){let o,r;if(e instanceof AbortSignal?(r=new AbortController,o=[e,...t]):(r=e,o=t),r.signal.aborted)return r;const s=()=>r.abort();for(const e of o){if(e.aborted){r.abort();break}e.addEventListener("abort",s,{once:!0,signal:r.signal})}return r}function Q(e,t,o,r,s){function n(t,r){const[n,i]=e.parseCommand(t);s.info("Running command: "+n),s.debug("with args: "+i.join(" "));const a=u(n,i,{...o,cwd:o.cwd||process.cwd(),env:Object.assign({},process.env,o.env,{PATH:process.env.PATH}),shell:o.shell||!1,signal:r.signal});return s.verbose("pid : "+a.pid),a}const i=t.match(/[<>$#]/g);if(i)throw Error(`Invalid command: ${t}. contains invalid characters: ${i}`);if(t.includes(" | ")){const e=t.split(" | "),o=[],s=Array(e.length);s[0]=r;for(let t=0;t<e.length;t++)0!==t&&(s[t]=Z(s[t-1].signal)),o.push(n(e[t],s[t])),0!==t&&o[t-1].stdout.pipe(o[t].stdin);return o[e.length-1]}return n(t,r)}function ee(e,t={},r=X,...s){const n=o.for(ee),i=new AbortController,a={abort:i,command:e,logs:[],errs:[]},c=new Promise((o,c)=>{let l;try{l=new r(e,{resolve:o,reject:c},...s),a.cmd=Q(l,e,t,i,n)}catch(t){return c(Error(`Error running command ${e}: ${t}`))}a.cmd.stdout.setEncoding("utf8"),a.cmd.stdout.on("data",e=>{e=e.toString(),a.logs.push(e),l.data(e)}),a.cmd.stderr.on("data",e=>{e=e.toString(),a.errs.push(e),l.error(e)}),a.cmd.once("error",e=>{l.exit(e.message,a.errs)}),a.cmd.once("exit",(e=0)=>{i.signal.aborted&&null===e&&(e=z),l.exit(e,0===e?a.logs:a.errs)})});return Object.assign(a,{promise:c,pipe:async t=>{const o=n.for("pipe");try{o.verbose(`Executing pipe function ${e}...`);const r=await c;return o.verbose(`Piping output to ${t.name}: ${r}`),t(r)}catch(e){throw o.error("Error piping command output: "+e),e}}}),a}const te=o.for("fs"),oe=d(process.cwd()+"/package.json");function re(e,t,o){const s=te.for(re);if(!c.existsSync(e))throw Error(`File not found at path "${e}".`);let n=se(e);s.verbose(`Patching file "${e}"...`),s.debug("with value: "+JSON.stringify(t));try{n=((e,t,o="g",s)=>(Object.entries(t).forEach(([t,n])=>{const i=RegExp(r(t),o);e=e.replace(i,e=>(!s||s(e),n))}),e))(n,t,"g",o)}catch(e){throw Error("Error patching file: "+e)}ne(e,n)}function se(e){const t=te.for(se);try{return t.verbose(`Reading file "${e}"...`),c.readFileSync(e,"utf8")}catch(o){throw t.verbose(`Error reading file "${e}": ${o}`),Error(`Error reading file "${e}": ${o}`)}}function ne(e,t){const o=te.for(ne);try{o.verbose(`Writing file "${e} with ${t.length} bytes...`),c.writeFileSync(e,t,"utf8")}catch(t){throw o.verbose(`Error writing file "${e}": ${t}`),Error(`Error writing file "${e}": ${t}`)}}function ie(e,t){const o=te.for(ie),r=[];try{return o.verbose(`Retrieving all files from "${e}"...`),c.readdirSync(e).forEach(t=>{const o=l.join(e,t),s=c.statSync(o);s.isFile()?r.push(o):s.isDirectory()&&r.push(...ie(o))}),t?r.filter(t):r}catch(t){throw o.verbose(`Error retrieving files from "${e}": ${t}`),Error(`Error retrieving files from "${e}": ${t}`)}}async function ae(e,t){const o=te.for(ae);let r,s;try{r=c.statSync(e)}catch(t){throw o.verbose(`Source path "${e}" does not exist: ${t}`),Error(`Source path "${e}" does not exist: ${t}`)}try{s=c.statSync(t)}catch(e){}if(s)throw o.verbose(`Destination path "${t}" already exists`),Error(`Destination path "${t}" already exists`);try{o.verbose(`Renaming ${r.isFile()?"file":"directory"} "${e}" to "${t}...`),c.renameSync(e,t),o.verbose(`Successfully renamed to "${t}"`)}catch(s){throw o.verbose(`Error renaming ${r.isFile()?"file":"directory"} "${e}" to "${t}": ${s}`),Error(`Error renaming ${r.isFile()?"file":"directory"} "${e}" to "${t}": ${s}`)}}function ce(e,t){const o=te.for(ce);let r,s;try{r=c.statSync(e)}catch(t){throw o.verbose(`Source path "${e}" does not exist: ${t}`),Error(`Source path "${e}" does not exist: ${t}`)}try{s=c.statSync(t)}catch(e){r.isDirectory()&&(o.verbose(`Dest path "${t}" does not exist. creating`),c.mkdirSync(t,{recursive:!0}))}try{o.verbose(`Copying ${r.isFile()?"file":"directory"} "${e}" to "${t}...`),c.cpSync(e,t,{recursive:!0})}catch(s){throw o.verbose(`Error copying ${r.isFile()?"file":"directory"} "${e}" to "${t}: ${s}`),Error(`Error copying ${r.isFile()?"file":"directory"} "${e}" to "${t}: ${s}`)}}function le(e){const t=te.for(le);try{const o=c.statSync(e);o.isFile()?(t.verbose(`Deleting file "${e}...`),c.rmSync(e,{recursive:!0,force:!0})):o.isDirectory()&&c.rmSync(e,{recursive:!0,force:!0})}catch(o){throw t.verbose(`Error Deleting "${e}": ${o}`),Error(`Error Deleting "${e}": ${o}`)}}function de(e=process.cwd(),t){let o;try{o=JSON.parse(se(l.join(e,"package.json")))}catch(e){throw Error('Failed to retrieve package information" '+e)}if(t){if(!(t in o))throw Error(`Property "${t}" not found in package.json`);return o[t]}return o}function ge(e,t,o=process.cwd()){const r=de(o);r[e]=t,ne(l.join(o,"package.json"),JSON.stringify(r,null,2))}function ue(e=process.cwd()){return de(e,"version")}async function he(e=process.cwd()){const t=l.join(e,"package.json"),o=l.join(e,"package-lock.json");let r,s;try{r=JSON.parse(se(t))}catch(e){throw Error(`Could not read package.json at ${t}: ${e}`)}if(c.existsSync(o))try{s=JSON.parse(se(o))}catch(e){te.warn(`Unable to parse package-lock.json at ${o}: ${e}`)}const n=(e={})=>Object.entries(e).map(([e,t])=>({name:e,version:fe(s,e,t)}));return{prod:n(r.dependencies),dev:n(r.devDependencies),peer:n(r.peerDependencies)}}function fe(e,t,o){if(e){const r=e.packages||{},s="node_modules/"+t;if(r[s]&&r[s].version)return r[s].version;if(e.dependencies&&e.dependencies[t])return e.dependencies[t].version||o}return o}async function pe(){const e=te.for(pe);e.info("checking for updates..."),await ee("npx npm-check-updates -u").promise,e.info("updating..."),await ee("npx npm run do-install").promise}async function me(e,t){e="string"==typeof e?[e]:e;const o={prod:t?.prod?[...t.prod]:[],dev:t?.dev?[...t.dev]:[],peer:t?.peer?[...t.peer]:[]},r=new Set([...o.prod??[],...o.dev??[],...o.peer??[]]),s=[];for(const t of e)if(!r.has(t))try{oe.resolve(t),r.add(t)}catch{s.push(t)}if(s.length){"test"===process.env.NODE_ENV||void 0!==process.env.JEST_WORKER_ID?te.verbose("Skipping dependency install in test environment for: "+s.join(", ")):await Se({dev:s});const e=new Set(o.dev??[]);s.forEach(t=>e.add(t)),o.dev=Array.from(e)}return o}async function ye(){const e=te.for(ye),t=await ee("git config user.name").promise,o=await ee("git config user.email").promise;e.verbose(`cached git id: ${t}/${o}. changing to automation`),await ee('git config user.email "automation@decaf.ts"').promise,await ee('git config user.name "decaf"').promise,e.info("Pushing changes to git..."),await ee("git add .").promise,await ee('git commit -m "refs #1 - after repo setup"').promise,await ee("git push").promise,await ee(`git config user.email "${o}"`).promise,await ee(`git config user.name "${t}"`).promise,e.verbose(`reverted to git id: ${t}/${o}`)}async function Se(e){const t=te.for(Se),o=e.prod||[],r=e.dev||[],s=e.peer||[];o.length&&(t.info(`Installing dependencies ${o.join(", ")}...`),await ee("npm install "+o.join(" "),{cwd:process.cwd()}).promise),r.length&&(t.info(`Installing devDependencies ${r.join(", ")}...`),await ee("npm install --save-dev "+r.join(" "),{cwd:process.cwd()}).promise),s.length&&(t.info(`Installing peerDependencies ${s.join(", ")}...`),await ee("npm install --save-peer "+s.join(" "),{cwd:process.cwd()}).promise)}async function ve(e){return e.then(e=>e.default||e)}async function we(e){const t=te.for(we);try{const o=c.readdirSync(e).map(t=>l.join(e,t)).filter(e=>{try{return c.statSync(e).isFile()&&(e.endsWith(".js")||e.endsWith(".cjs")||e.endsWith(".mjs"))}catch{return!1}});if(0===o.length)throw Error("No JS files found in directory "+e);let r=o[0],s=c.statSync(r).size;for(const e of o.slice(1)){const t=c.statSync(e).size;s>t&&(r=e,s=t)}t.verbose(`Selected smallest bundle: ${r} (${s} bytes)`);const n=c.readFileSync(r),i=m.gzipSync(n),a=Number((i.length/1024).toFixed(1));return t.verbose(`Gzipped size: ${i.length} bytes (${a} KB)`),a}catch(o){throw t.verbose(`Failed to compute gzipped size for ${e}: ${o}`),o}}function be(e=process.cwd(),t){const o=te.for(be);try{return c.existsSync(e)?c.readdirSync(e,{withFileTypes:!0}).filter(e=>!t||t(e.name,e)).map(e=>e.name):[]}catch(t){return o.verbose(`Failed to list folder ${e}: ${t}`),[]}}function Te(e=l.join(process.cwd(),"node_modules")){const t=te.for(Te);try{if(!c.existsSync(e))return[];const o=c.readdirSync(e,{withFileTypes:!0}),r=[];for(const s of o)try{if(!s.isDirectory())continue;if(s.name.startsWith("."))continue;if(s.name.startsWith("@")){const o=l.join(e,s.name);try{const e=c.readdirSync(o,{withFileTypes:!0});for(const t of e)t.isDirectory()&&!t.name.startsWith(".")&&r.push(`${s.name}/${t.name}`)}catch(e){t.verbose(`Failed to read scope ${o}: ${e}`)}}else r.push(s.name)}catch(e){t.verbose(`Skipping entry ${s.name} due to error: ${e}`)}return r}catch(o){return t.verbose(`Failed to list node_modules packages at ${e}: ${o}`),[]}}const ke=[{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That's Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"Decaf-TS: Where smart contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No CRUD, no problem \u2014 Decaf your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS: Your frontend already understands your smart contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye CRUD, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data \u2014 because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From smart contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No CRUD. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently \u2014 and delightfully.",Tags:"DID, Self-Sovereign, Playful"},{Slogan:"Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No boilerplate, no problem \u2014 Decaf-TS your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS-TS: Your frontend already understands your blockchain contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye boilerplate, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data \u2014 because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From blockchain contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No boilerplate. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf-TS.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently \u2014 and delightfully.",Tags:"DID, Self-Sovereign, Playful"},{Slogan:"Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No boilerplate, no problem \u2014 Decaf-TS your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS-TS: Your frontend already understands your blockchain contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye boilerplate, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data \u2014 because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From blockchain contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No boilerplate. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf-TS.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently \u2014 and delightfully.",Tags:"DID, Self-Sovereign, Playful"},{Slogan:"Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No boilerplate, no problem \u2014 Decaf-TS your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS-TS: Your frontend already understands your blockchain contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye boilerplate, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data \u2014 because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From blockchain contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No boilerplate. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf-TS.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently \u2014 and delightfully.",Tags:"DID, Self-Sovereign, Playful"},{Slogan:"Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No boilerplate, no problem \u2014 Decaf-TS your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS-TS: Your frontend already understands your blockchain contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye boilerplate, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data \u2014 because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From blockchain contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No boilerplate. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf-TS.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently \u2014 and delightfully.",Tags:"DID, Self-Sovereign, Playful"}],Ce=["\x1b[38;5;215m","\x1b[38;5;209m","\x1b[38;5;205m","\x1b[38;5;210m","\x1b[38;5;217m","\x1b[38;5;216m","\x1b[38;5;224m","\x1b[38;5;230m","\x1b[38;5;230m"];function Ee(e){const t=$e(),o="# \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \n# ( ( \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \n# ) ) \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \n# [=======] \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \n# `-----\xb4 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \n# \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \n# \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \n#".split("\n"),r=o.reduce((e,t)=>Math.max(e,t.length),0);o.push("# "+t.padStart(r-3)),o.forEach((t,o)=>{(e?e.info.bind(e):(()=>{}).bind())(f(t||"").raw(Ce[o]).text)})}function $e(e){try{return e=void 0===e?Math.floor(Math.random()*ke.length):e,ke[e].Slogan}catch(e){throw Error("Failed to retrieve slogans: "+e)}}class De extends s{constructor(e,t={},r=[]){super(),this.name=e,this.inputs=t,this.requirements=r,De.log||Object.defineProperty(De,"log",{writable:!1,value:o.for(De.name)}),this.inputs=Object.assign({},B,t)}async checkRequirements(){const{prod:e,dev:t,peer:o}=await he(),r=[],s=Array.from(new Set([...e,...t,...o]).values()).map(e=>e.name);for(const e of this.requirements)s.includes(e)||r.push(e);r.length}help(e){return this.log.info("This is help. I'm no use because I should have been overridden.")}async execute(){const e=L.parseArgs(this.inputs),t=n.accumulate(H).accumulate(e.values),{version:o,help:r,banner:s}=t;if(o)return ue();if(r)return this.help(e);let i;s&&Ee(this.log.for(Ee,{timestamp:!1,style:!1,context:!1,logLevel:!1}));try{i=await this.run(t)}catch(e){throw e}return i}}class xe{static{this.log=o.for(xe)}static async downloadFile(e){return new Promise((t,o)=>{!function e(r){r=encodeURI(r),y.get(r,s=>{if(301===s.statusCode||307===s.statusCode)return e(s.headers.location);if(200!==s.statusCode)return xe.log.error(`Failed to fetch ${r} (status: ${s.statusCode})`),o(Error("Failed to fetch "+r));let n="";s.on("data",e=>{n+=e}),s.on("error",e=>{o(e)}),s.on("end",()=>{t(n)})})}(e)})}}const Ne={width:1200,height:260,padding:32,backgroundColor:"#0f172a",headerFont:"bold 18px 'Segoe UI', sans-serif",rowFont:"14px 'Segoe UI', sans-serif",headerColor:"#f8fafc",rowColor:"#cbd5f5"},Re=e=>new Promise(t=>setTimeout(t,e)),Ae=(process.env.PERF_VERBOSE,(...e)=>{});class Fe{constructor(e){this.scenario=e}async run(){this.scenario.initialize&&await this.scenario.initialize();let e=0;const t=this.scenario.phases.map(t=>({phase:t,phaseNumber:++e})),o=[];for(;t.length;){const r=t.shift(),s=r.phase,n=this.mergeContext(s),i=await this.runPhase(s,n);if(o.push(i),s.generator){const n=[...o],a={phaseNumber:r.phaseNumber,phaseName:s.name,iterationCount:s.config.iterations,burstSegments:i.segmentCount,segmentCount:i.segmentCount,mode:s.config.mode,history:n},c=await s.generator({result:i,history:n,metadata:a});if(c){const o="config"in c?{name:c.name??s.name+" \u2192 gen",config:c.config,generator:s.generator}:{name:s.name+" \u2192 gen",config:c,generator:s.generator};t.push({phase:o,phaseNumber:++e})}}}if(await this.logSummary(o),!1!==this.scenario.failOnError){const e=o.reduce((e,t)=>e+t.aggregated.failureCount,0);if(e>0)throw Error(`Scenario "${this.scenario.name}" recorded ${e} failures across ${o.length} phases`)}return o}async runPhase(e,t){await this.runWarmup(e,t);const o=this.buildSegmentIndices(e.config.iterations,e.config.burst),r=[],s=Date.now();for(let s=0;s<o.length;s+=1){const n=o[s];if(!n.length)continue;Ae((e.name,o.length,n[0],n[n.length-1]));const i=await this.executeSegment(this.scenario.handler,e.config,t,n);r.push(...i);const a=e.config.burst?.intervalMs;a&&s<o.length-1&&await Re(a)}const n=Date.now()-s,i=[...r].sort((e,t)=>e.iteration-t.iteration),a=this.aggregateMetrics(i);return e.config.pauseAfterMs&&await Re(e.config.pauseAfterMs),{phase:e,config:e.config,iterationMetrics:i,aggregated:a,context:t,segmentCount:o.length,wallClockMs:n}}async runWarmup(e,t){const o=e.config.warmup;if(!o?.iterations)return;const r=o.handler??this.scenario.handler;for(let s=0;s<o.iterations;s+=1)await r({iteration:s,config:e.config,loadFactor:this.computeLoadFactor(e.config,s),context:t}),o.delayBetweenIterationsMs&&s<o.iterations-1&&await Re(o.delayBetweenIterationsMs)}computeLoadFactor(e,t){return((e.loadStart??1)+(e.loadStep??0)*t)*(e.loadMultiplier??1)}buildSegmentIndices(e,t){const o=Math.max(0,e);if(0===o)return[];const r=t?.size&&t.size>0?Math.min(t.size,o):o,s=[];for(let e=0;o>e;e+=r){const t=Math.min(o,e+r);s.push(Array.from({length:t-e},(t,o)=>e+o))}return s}mergeContext(e){const t=this.scenario.baseContext??{},o=e.config.context??{};return this.mergeContexts(t,o)}mergeContexts(e,t){return Object.assign({},e,t)}async executeSegment(e,t,o,r){return r.length?"concurrent"===t.mode?this.collectConcurrent(e,t,o,r):this.collectSequential(e,t,o,r):[]}async collectSequential(e,t,o,r){const s=[],n=t.delayBetweenIterationsMs;for(let i=0;i<r.length;i+=1)s.push(await this.runIteration(e,t,o,r[i])),n&&i<r.length-1&&await Re(n);return s}async collectConcurrent(e,t,o,r){const s=Math.max(1,Math.min(t.concurrency??r.length,r.length)),n=[];let i=0;const a=async()=>{for(;i<r.length;){const s=r[i];i+=1,n.push(await this.runIteration(e,t,o,s))}};return await Promise.all(Array.from({length:s},()=>a())),n}async runIteration(e,t,o,r){const s=this.computeLoadFactor(t,r),n=new i(!0);let a,c=!0;t.metadata,s.toFixed(2);try{const n=await e({iteration:r,config:t,loadFactor:s,context:o});"boolean"==typeof n?.success&&(c=n.success),a=n?.meta}catch(e){c=!1,a={error:e instanceof Error?e.message:e+""}}const l=n.stop();return l.toFixed(2),{iteration:r,durationMs:l,success:c,meta:a,loadFactor:s}}aggregateMetrics(e){if(0===e.length)return{totalDurationMs:0,minMs:0,maxMs:0,averageMs:0,successCount:0,failureCount:0,loadStart:0,loadEnd:0};const t=e.reduce((e,t)=>e+t.durationMs,0),o=Math.min(...e.map(e=>e.durationMs)),r=Math.max(...e.map(e=>e.durationMs)),s=t/e.length,n=e.filter(e=>e.success).length,i=e.length-n,a=e[0]?.loadFactor??0;return{totalDurationMs:t,minMs:o,maxMs:r,averageMs:s,successCount:n,failureCount:i,loadStart:a,loadEnd:e[e.length-1]?.loadFactor??a}}logPhaseTable(e){e.config.iterations,e.wallClockMs,e.phase.name,e.config.mode,e.config.iterations.toString(),e.wallClockMs.toFixed(0),e.aggregated.averageMs.toFixed(2),e.aggregated.minMs.toFixed(2),e.aggregated.maxMs.toFixed(2),e.aggregated.successCount.toString(),e.aggregated.failureCount.toString(),e.aggregated.loadStart.toFixed(2),e.aggregated.loadEnd.toFixed(2)}async logSummary(e){if(!e.length)return;const t=["Phase","Mode","Iterations","Wall ms","RPS","Avg ms","Min ms","Max ms","Success","Failures","Load range"],o=e.map(e=>{const t=(e.config.iterations/(e.wallClockMs/1e3)).toFixed(1);return[e.phase.name,e.config.mode,e.config.iterations.toString(),e.wallClockMs.toFixed(0),t,e.aggregated.averageMs.toFixed(2),e.aggregated.minMs.toFixed(2),e.aggregated.maxMs.toFixed(2),e.aggregated.successCount.toString(),e.aggregated.failureCount.toString(),`${e.aggregated.loadStart.toFixed(2)} \u2192 ${e.aggregated.loadEnd.toFixed(2)}`]});if(this.shouldRenderCanvas()){const e=this.scenario.canvasOutputPath??l.join(process.cwd(),"workdocs","reports","performance-runner.png");await(async(e,t,o,r)=>{const s={...Ne,...o};let n;try{n=(await import("canvas")).createCanvas}catch(e){return}const i=n(s.width,s.height),a=i.getContext("2d");a.fillStyle=s.backgroundColor,a.fillRect(0,0,s.width,s.height),a.font=s.headerFont,a.fillStyle=s.headerColor;const c=(s.width-2*s.padding)/e.length,d=s.padding+24;e.forEach((e,t)=>{a.fillText(e,s.padding+c*t,d)}),a.font=s.rowFont,a.fillStyle=s.rowColor,t.forEach((e,t)=>{const o=d+12+24*(t+1);e.forEach((e,t)=>{a.fillText(e,s.padding+c*t,o)})}),await(async e=>{await v(l.dirname(e),{recursive:!0})})(r),await S(r,i.toBuffer("image/png"))})(t,o,this.scenario.canvasOptions??Ne,e)}}shouldRenderCanvas(){return this.scenario.enableCanvas??!!this.scenario.canvasOptions}}function Oe(e){return e?Array.isArray(e)?e.map(e=>(""+e).trim()).filter(Boolean):(""+e).split(",").map(e=>e.trim()).filter(Boolean):[]}function _e(e){return e.replace(/^@/,"").split(/[/\-_.]+/).filter(Boolean).map((e,t)=>0===t?e.replace(/[^a-zA-Z0-9]/g,""):`${e.charAt(0).toUpperCase()}${e.slice(1)}`).join("")}function Ie(){let e;try{e=de(process.cwd())}catch{e=void 0}try{if(!e||!(Object.keys(e.dependencies||{}).length>0||Object.keys(e.devDependencies||{}).length>0||Object.keys(e.peerDependencies||{}).length>0)){const t=l.resolve(__dirname,"../../..");try{e=de(t)}catch{}}}catch{}const t=Object.keys(e&&e.dependencies||{}),o=Object.keys(e&&e.peerDependencies||{}),r=Object.keys(e&&e.devDependencies||{});return Array.from(new Set([...t,...o,...r]))}const je="##VERSION##",Me="##COMMIT##",Pe="##FULL_VERSION##",Ue="##PACKAGE##",Le="##PACKAGE_SIZE##";var Be,He,Ge;(e=>{e.CJS="commonjs",e.ESM="es2022"})(Be||(Be={})),(e=>{e.BUILD="build",e.BUNDLE="bundle",e.ALL="all"})(He||(He={})),(e=>{e.ESM="esm",e.CJS_CHECK="cjs-check",e.TYPES="types",e.NODE_NEXT_VALIDATE="nodenext-validate",e.BUNDLE="bundle"})(Ge||(Ge={}));const Ve={prod:{type:"boolean",default:!1},dev:{type:"boolean",default:!1},buildMode:{type:"string",default:He.ALL},includes:{type:"string",default:""},externals:{type:"string",default:""},docs:{type:"boolean",default:!1},commands:{type:"boolean",default:!1},entry:{type:"string",default:"./src/index.ts"},banner:{type:"boolean",default:!1},validateNodeNext:{type:"boolean",default:!1}},We=(e=".cjs")=>{const t=ze.log.for(We),o=new Map;return r=>s=>{const n=l.dirname(s.fileName);function i(r){const s=JSON.stringify([n,r]),i=o.get(s);if(null!=i)return i;let a,d=r;try{d=l.resolve(n,d+".ts")}catch(e){throw Error(`Failed to resolve path ${r}: ${e}`)}try{a=c.statSync(d)}catch(e){try{t.verbose(`Testing existence of path ${d} as a folder defaulting to index file`),a=c.statSync(d.replace(/\.ts$/gm,""))}catch(t){throw Error(`Failed to resolve path ${r}: ${e}, ${t}`)}}if(a.isDirectory()&&(d=d.replace(/\.ts$/gm,"/index.ts")),l.isAbsolute(d)){const t=(/\.tsx?$/.exec(l.basename(d))||[])[0]||void 0;d="./"+l.relative(n,l.resolve(l.dirname(d),l.basename(d,t)+e))}return o.set(s,d),d}function a(e){return!(!e.startsWith("./")&&!e.startsWith("../")||qe(e))}return C.visitNode(s,function e(t){if((e=>!(!C.isImportDeclaration(e)&&!C.isExportDeclaration(e))&&void 0!==e.moduleSpecifier&&!!C.isStringLiteral(e.moduleSpecifier)&&a(e.moduleSpecifier.text))(t)){if(C.isImportDeclaration(t)){const e=i(t.moduleSpecifier.text),o=r.factory.createStringLiteral(e);return r.factory.updateImportDeclaration(t,t.modifiers,t.importClause,o,void 0)}if(C.isExportDeclaration(t)){const e=i(t.moduleSpecifier.text),o=r.factory.createStringLiteral(e);return r.factory.updateExportDeclaration(t,t.modifiers,t.isTypeOnly,t.exportClause,o,void 0)}}else if(C.isCallExpression(t)){const e=(e=>(e=>e.expression.kind===C.SyntaxKind.ImportKeyword)(e)&&e.arguments.length>0&&C.isStringLiteral(e.arguments[0])||C.isIdentifier(e.expression)&&"require"===e.expression.text&&e.arguments.length>0&&C.isStringLiteral(e.arguments[0])?e.arguments[0]:void 0)(t);if(e&&a(e.text)){const o=i(e.text),s=r.factory.createStringLiteral(o),n=t.arguments.map((e,t)=>0===t?s:e);return r.factory.updateCallExpression(t,t.expression,t.typeArguments,r.factory.createNodeArray(n))}}return C.visitEachChild(t,e,r)})}};function Ke(e,t){const o=l.parse(e);return l.join(o.dir,`${o.name}${t}`)}const Je=/\.(?:d\.(?:mts|cts|ts)|mts|cts|tsx|ts|mjs|cjs|jsx|js|json)$/i;function qe(e){return Je.test(l.basename(e))}class ze extends De{constructor(){super("BuildScripts",Object.assign({},B,Ve)),this.replacements={};const e=de(),{name:t,version:o}=e;this.pkgName=t.includes("@")?t.split("/")[1]:t,this.pkgVersion=o;try{this.commitHash=h("git rev-parse --short HEAD",{encoding:"utf8"}).trim()}catch{this.commitHash="unknown"}this.fullVersion=`${this.pkgVersion}-${this.commitHash}`,this.replacements[je]=this.pkgVersion,this.replacements[Me]=this.commitHash,this.replacements[Pe]=this.fullVersion,this.replacements[Ue]=t}patchFiles(e){const t=this.log.for(this.patchFiles),{name:o,version:r}=de();t.info(`Patching ${o} ${r} module in ${e}...`);const s=c.statSync(e),n=e=>{let t=e;return t=t.replace(/((?:^|[\s;,(])(?:const|let|var)\s+VERSION\s*=\s*["'])##VERSION##(["'])/gm,`$1${r}$2`),t=t.replace(/((?:^|[\s;,(])(?:const|let|var)\s+COMMIT\s*=\s*["'])##COMMIT##(["'])/gm,`$1${this.commitHash}$2`),t=t.replace(/((?:^|[\s;,(])(?:const|let|var)\s+FULL_VERSION\s*=\s*["'])##FULL_VERSION##(["'])/gm,`$1${this.fullVersion}$2`),t=t.replace(/((?:^|[\s;,(])(?:exports|module\.exports)\.VERSION\s*=\s*["'])##VERSION##(["'])/gm,`$1${r}$2`),t=t.replace(/((?:^|[\s;,(])(?:exports|module\.exports)\.COMMIT\s*=\s*["'])##COMMIT##(["'])/gm,`$1${this.commitHash}$2`),t=t.replace(/((?:^|[\s;,(])(?:exports|module\.exports)\.FULL_VERSION\s*=\s*["'])##FULL_VERSION##(["'])/gm,`$1${this.fullVersion}$2`),t=t.replace(/((?:^|[\s;,(])\w+\.VERSION\s*=\s*["'])##VERSION##(["'])/gm,`$1${r}$2`),t=t.replace(/((?:^|[\s;,(])\w+\.COMMIT\s*=\s*["'])##COMMIT##(["'])/gm,`$1${this.commitHash}$2`),t=t.replace(/((?:^|[\s;,(])\w+\.FULL_VERSION\s*=\s*["'])##FULL_VERSION##(["'])/gm,`$1${this.fullVersion}$2`),t=t.replace(/((?:^|[\s;,(])(?:const|let|var)\s+PACKAGE_NAME\s*=\s*["'])##PACKAGE##(["'])/gm,`$1${o}$2`),t=t.replace(/((?:^|[\s;,(])(?:exports|module\.exports)\.PACKAGE_NAME\s*=\s*["'])##PACKAGE##(["'])/gm,`$1${o}$2`),t=t.replace(/((?:^|[\s;,(])