UNPKG

create-abi

Version:

Interactive CLI for create Abi.js projects.

8 lines (7 loc) 19.5 kB
#!/usr/bin/env node "use strict";var Pe=Object.create;var N=Object.defineProperty;var Ee=Object.getOwnPropertyDescriptor;var $e=Object.getOwnPropertyNames;var Ne=Object.getPrototypeOf,Be=Object.prototype.hasOwnProperty;var v=(n,e)=>()=>(n&&(e=n(n=0)),e);var Me=(n,e)=>{for(var t in e)N(n,t,{get:e[t],enumerable:!0})},We=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of $e(e))!Be.call(n,i)&&i!==t&&N(n,i,{get:()=>e[i],enumerable:!(r=Ee(e,i))||r.enumerable});return n};var m=(n,e,t)=>(t=n!=null?Pe(Ne(n)):{},We(e||!n||!n.__esModule?N(t,"default",{value:n,enumerable:!0}):t,n));var B,te=v(()=>{B={name:"create-abi",type:"module",license:"MIT",version:"0.0.0",description:"Interactive CLI for create Abi.js projects.",scripts:{check:"tsc --noEmit",build:"tsup-node --env.NODE_ENV production",prod:"pnpm check && pnpm build",start:"tsup-node --env.NODE_ENV development --watch",test:"pnm tsx bin/test.ts",tsx:"tsx"},contributors:[{name:"Sigui Kess\xE9 Emmanuel",email:"contact@sigui.ci",url:"https://twitter.com/siguici"}],repository:{type:"git",url:"https://github.com/abi-js/abi",directory:"packages/create-abi"},types:"./dist/index.d.ts",main:"./dist/index.js",module:"./dist/index.js",exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js",require:"./dist/index.cjs",default:"./dist/index.js"},"./app":{types:"./dist/app.d.ts",import:"./dist/app.js",require:"./dist/app.cjs",default:"./dist/app.js"},"./cli":{types:"./dist/cli.d.ts",import:"./dist/cli.js",require:"./dist/cli.cjs",default:"./dist/cli.js"},"./console":{types:"./dist/console.d.ts",import:"./dist/console.js",require:"./dist/console.cjs",default:"./dist/console.js"},"./core":{types:"./dist/core.d.ts",import:"./dist/core.js",require:"./dist/core.cjs",default:"./dist/core.js"},"./tester":{types:"./dist/tester.d.ts",import:"./dist/tester.js",require:"./dist/tester.cjs",default:"./dist/tester.js"},"./utils":{types:"./dist/utils.d.ts",import:"./dist/utils.js",require:"./dist/utils.cjs",default:"./dist/utils.js"},"./package.json":"./package.json"},files:["dist","starters"],bin:"./dist/cli.js",keywords:["abi","abi-js","abi.js","cli","console","create-abi","generator","skeleton","starter-kit","template"],publishConfig:{access:"public"},bugs:"https://github.com/@abi-js/abi/issues",dependencies:{"@clack/prompts":"^0.11.0","cross-spawn":"^7.0.6","fs-extra":"^11.3.0",kleur:"^4.1.5",panam:"^0.3.0",tsx:"^4.20.3",which:"^5.0.0","which-pm-runs":"^1.1.0",yargs:"^18.0.0"},devDependencies:{"@japa/assert":"^4.0.1","@japa/runner":"^4.2.0","@types/cross-spawn":"^6.0.6","@types/fs-extra":"^11.0.4","@types/node":"^24.0.10","@types/which":"^3.0.4","@types/which-pm-runs":"^1.0.2","@types/yargs":"^17.0.33",rimraf:"^6.0.1",tsup:"^8.5.0",typescript:"^5.8.3"}}});function Je(){return process.platform!=="win32"?process.env.TERM!=="linux":!!process.env.CI||!!process.env.WT_SESSION||!!process.env.TERMINUS_SUBLIME||process.env.ConEmuTask==="{cmd::Cmder}"||process.env.TERM_PROGRAM==="Terminus-Sublime"||process.env.TERM_PROGRAM==="vscode"||process.env.TERM==="xterm-256color"||process.env.TERM==="alacritty"||process.env.TERMINAL_EMULATOR==="JetBrains-JediTerm"}function Ve(n){return(0,s.green)(`${R.success} ${n}`)}function ie(n){return(0,s.red)(`${R.error} ${n}`)}function Ge(n){return(0,s.blue)(`${R.info} ${n}`)}function ze(n){return(0,s.yellow)(`${R.warning} ${n}`)}function se(n){g.log.info(Ge(n))}function oe(n){g.log.success(Ve(n))}function ae(n){g.log.step(n)}function ue(n){g.log.warn(ze(n))}function ce(n){g.log.error(ie(n))}function D(n){console.error(`${ne()}${ie(n)}${ne()}`),process.exit(1)}function ne(n=1){return` `.repeat(n)}async function M(n,e,t){let r=t&&await(0,g.text)({message:n,placeholder:e,defaultValue:e})||e;return r!==e&&b(r),r}async function W(n,e,t,r){let i=r&&await(0,g.select)({message:n,options:e,initialValue:t})||t;return i!==t&&b(i),i}async function U(n,e,t,r,i){let o=i===!0&&!e?!1:r===!0&&e===void 0?!0:t?await(0,g.confirm)({message:n,initialValue:e}):e;return o!==e&&J(o),o}function b(n,e){ge(n,e?t=>re(t)&&e(t):re,"string")}function J(n){ge(n,qe,"boolean")}function ge(n,e,t){_e(n,e,t,typeof n)}function _e(n,e,t,r){Le(n)&&D("Operation canceled."),e(n)||D(`Invalid input${t?`: ${t} expected`:""}${r?`, ${r} provided`:""}.`)}function re(n){return typeof n=="string"||n instanceof String}function qe(n){return typeof n=="boolean"}function Le(n){return(0,g.isCancel)(n)||typeof n=="symbol"}var g,s,u,h,R,p,d,f,V=v(()=>{"use strict";g=require("@clack/prompts"),s=require("kleur/colors"),u=require("@clack/prompts");h=Je(),R={success:h?"\u2705":"[OK]",error:h?"\u274C":"[ERROR]",info:h?"\u2139\uFE0F":"[INFO]",warning:h?"\u26A0\uFE0F":"[WARN]",debug:h?"\u{1F41E}":"[DEBUG]",verbose:h?"\u{1F50D}":"[DETAILS]",line:h?"\u2500\u2500":"----"},p={red:s.red,green:s.green,blue:s.blue,yellow:s.yellow,magenta:s.magenta,cyan:s.cyan,gray:s.gray,grey:s.grey,white:s.white,black:s.black},d={red:s.bgRed,green:s.bgGreen,blue:s.bgBlue,yellow:s.bgYellow,magenta:s.bgMagenta,cyan:s.bgCyan,white:s.bgWhite,black:s.bgBlack},f={reset:s.reset,bold:s.bold,dim:s.dim,italic:s.italic,underline:s.underline,inverse:s.inverse,hidden:s.hidden,strikethrough:s.strikethrough}});function _(n,e){(0,l.statSync)(n).isDirectory()?Fe(n,e):Ke(n,e)}function Fe(n,e){let t=(0,l.readdirSync)(n);(0,C.ensureDirSync)(e);for(let r of t)_((0,c.join)(n,r),(0,c.join)(e,r))}function Ke(n,e){let t=(0,c.basename)(n);(0,C.pathExistsSync)(e)?t.endsWith(".json")?He(e,n,!0):t.startsWith(".")&&t.endsWith("ignore")&&Qe(e,n,!0):(0,C.copySync)(n,e)}function He(n,e,t=!1){let r=Ze(w(n),w(e));return t&&xe(n,r),r}function Ze(n,e){return de(JSON.parse(n),JSON.parse(e))}function de(n,e){for(let t of Object.keys(e)){let r=n[t],i=e[t];le(r)&&le(i)?n[t]=de(r,i):Array.isArray(r)&&Array.isArray(i)?n[t]=Array.from(new Set([...r,...i])):n[t]=i}return n}function le(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function Qe(n,e,t=!1){let r=Xe(w(n),w(e));return t&&F(n,r),r}function Xe(n,e){return et(n.split(` `),e.split(` `)).join(` `)}function et(n,e){let t=Array.from(new Set([...n.map(r=>r.trim()),...e.map(r=>r.trim())])).filter(r=>r!=="");return tt(t)}function tt(n){let e=[],t=!1;return n.forEach((r,i)=>{let o=r.startsWith("#");o&&!t&&i!==0&&e.push(""),e.push(r),t=o}),e}function nt(){let t=new Error().stack?.match(/^Error\s+at[^\r\n]+\s+at *(?:[^\r\n(]+\((.+?)(?::\d+:\d+)?\)|(.+?)(?::\d+:\d+)?) *([\r\n]|$)/),r=t?.[1]||t?.[2];return r?.startsWith("file://")?(0,G.fileURLToPath)(r):r||(0,G.fileURLToPath)(ct.url)}function fe(){return!!(process.env.CI||process.env.GITHUB_ACTIONS)}function me(){return!1}function ye(n){return n.startsWith(process.env.HOME??"~/")}function q(n){return ye(n)?(0,c.resolve)(z.default.homedir(),n):(0,c.resolve)(process.cwd(),n)}function L(n){return ye(n)?(0,c.relative)(z.default.homedir(),n):(0,c.relative)(process.cwd(),n)}function Y(n){return l.default.existsSync(n)&&l.default.readdirSync(n).length>0}function w(n){if(!l.default.existsSync(n))throw new Error(`File ${n} not found`);return l.default.readFileSync(n,{encoding:"utf8"}).toString()}function F(n,e){return l.default.writeFileSync(n,e,{encoding:"utf8"})}function rt(n,e,t){let r=w(n);r=r.replace(e,t),F(n,r)}function k(n,e=T){return(0,c.join)(e,`${n}.json`)}function it(n,e,t,r){rt(k(n,e),t,r)}function be(n,e){it(n,e,/npm run/g,pe.default.runCommand())}function O(n){return n=n.trim().replace(/\\/g,"/").split("/").filter(Boolean).map(e=>e.toLowerCase().replace(/[^a-z0-9-_]/g,"-").replace(/^-+|-+$/g,"")).join("-"),n=n.normalize("NFD").replace(/[\u0300-\u036f]/g,""),n=n.replace(/[^a-zA-Z0-9\-._~/@]/g,"-"),n=n.replace(/^[-.]+|[-.]+$/g,""),n=n.replace(/[-.]{2,}/g,"-"),n=n.toLowerCase(),n}function ot(n){return st.test(n)}function at(n){if(n=O(n),!ot(n))throw new Error(`Invalid package name: ${n}`);return n}function K(n,e){let t=k(n,e);return JSON.parse(w(t))}function ut(n,e,t){xe(k(n,e),t)}function xe(n,e){F(n,JSON.stringify(e,null,2))}function ve(n,e="package",t=T){let r=at(n),i=K(e,t);i.name=r,ut(e,t,i)}var l,z,c,G,C,pe,ct,Ye,T,he,st,H=v(()=>{"use strict";l=m(require("fs"),1),z=m(require("os"),1),c=m(require("path"),1),G=require("url"),C=require("fs-extra/esm"),pe=m(require("panam/pm"),1),ct={},Ye=nt(),T=c.default.dirname(Ye);he=async n=>{let e=await l.default.promises.readdir(n);return await Promise.all(e.map(t=>l.default.promises.rm((0,c.join)(n,t),{recursive:!0})))};st=/^(?:(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*)$/});var we,Ce,Z,P,ke=v(()=>{"use strict";we=m(require("yargs"),1),Ce=require("yargs/helpers");V();H();Z=class{constructor(e,t){this.signature=e;this.description=t}arguments=new Map;options=new Map;examples=new Set;#e="";setArgument(e,t){return this.arguments.set(e,t),this}getArgument(e){return this.arguments.get(e)}hasArgument(e){return this.arguments.has(e)}argument(e,t){return t?this.setArgument(e,t):this.getArgument(e)}setOption(e,t){return this.options.set(e,t),this}getOption(e){return this.options.get(e)}hasOption(e){return this.options.has(e)}option(e,t){return t?this.setOption(e,t):this.getOption(e)}addExample(e,t){return this.examples.add({command:e,description:t}),this}getExample(e){return this.examples.values().find(t=>t.command===e||t.description===e)}example(e,t){return t?this.addExample(e,t):this.getExample(e)}getExamples(){return this.examples.values().toArray()}setUsage(e){return this.#e=e,this}getUsage(){return this.#e}usage(e){return e?this.setUsage(e):this.getUsage()}},P=class{constructor(e,t){this.name=e;this.version=t;this.configure()}#e=!1;#r=!1;#t=!1;#n=!1;#i={};commands=new Set;aliases=new Set;interactions=new Map;configure(){}addCommand(e,t){let r=new Z(e,t);return this.#t&&r.option("yes",{alias:"y",type:"boolean",desc:"Skip all prompts by accepting defaults"}),this.#n&&r.option("no",{alias:"n",type:"boolean",desc:"Skip all prompts by declining defaults"}),this.commands.add(r),r}getCommand(e){return this.commands.values().find(t=>t.signature===e||t.description===e)}command(e,t){return t?this.addCommand(e,t):this.getCommand(e)}getCommands(){return this.commands.values().toArray()}strict(e=!0){return this.#e=e,this}conflict(e,t){return this.#i[e]=t,this}interactive(e=!0){return this.#r=e,this}useYes(e=!0){return this.#t=e,this}useNo(e=!0){return this.#n=e,this}addAlias(e,t){return this.aliases.add({shortName:e,longName:t}),this}getAlias(e){return this.aliases.values().find(t=>t.shortName===e||t.longName===e)}alias(e,t){return t?this.addAlias(e,t):this.getAlias(e)}getAliases(){return this.aliases.values().toArray()}async run(e=process.argv){let t=(0,Ce.hideBin)(e),r=this.parse(t),i;return this.isIt()?i=await this.interact(r):i=this.validate(r),await this.execute(i)}isIt(){return this.#r&&!(me()||fe())}intercept(e,t){return this.setInteraction(e,t)}async interact(e){return this.validate(e)}parse(e){let t=(0,we.default)(e);t.scriptName(this.name),this.#e&&t.strict(),this.#t&&this.#n&&t.conflicts("yes","no"),this.#s(t),t.version(this.version);for(let[i,o]of Object.entries(this.#i))t.conflicts(i,o);for(let{shortName:i,longName:o}of this.aliases)t.alias(i,o);return t.argv}#s(e){for(let t of this.commands)this.#o(e,t)}#o(e,t){e.command(t.signature,t.description,r=>{this.#a(e,t.arguments),this.#c(e,t.options),this.#l(e,t.examples),r.usage(t.usage())})}#a(e,t){for(let[r,i]of t)this.#u(e,r,i)}#u(e,t,r){e.positional(t,r)}#c(e,t){for(let[r,i]of t)this.#g(e,r,i)}#g(e,t,r){e.option(t,r)}#l(e,t){for(let r of t)this.#p(e,r.command,r.description)}#p(e,t,r){e.example(t,r)}getInteraction(e){for(let t of this.interactions.keys())if(e.includes(t)||RegExp(t).test(e))return this.interactions.get(t)}setInteraction(e,t){return this.interactions.set(e,t),this}async scanBoolean(e,t,r){let i=this.getInteraction(t);return i!==void 0?(J(i),i):r!==void 0?U(t,r,this.isIt(),this.#t&&e.yes,this.#n&&e.no):U(t,void 0,this.isIt(),this.#t&&e.yes,this.#n&&e.no)}async scanString(e,t){let r=this.getInteraction(e);return r!==void 0?(b(r),r):t?M(e,t,this.isIt()):M(e,void 0,this.isIt())}async scanChoice(e,t,r){let i=this.getInteraction(e);return i!==void 0?(b(i,o=>t.find(a=>a.value===o)!==void 0),i):r?W(e,t,r,this.isIt()):W(e,t,void 0,this.isIt())}panic(e){D(e)}cancel(e){(0,u.cancel)(e)}intro(e){(0,u.intro)(e)}outro(e){(0,u.outro)(e)}note(e,t){(0,u.note)(e,t)}spinner(){return(0,u.spinner)()}info(e){se(e)}warn(e){ue(e)}error(e){ce(e)}step(e){ae(e)}success(e){oe(e)}red(e){return p.red(e)}green(e){return p.green(e)}blue(e){return p.blue(e)}yellow(e){return p.yellow(e)}magenta(e){return p.magenta(e)}cyan(e){return p.cyan(e)}gray(e){return p.gray(e)}grey(e){return p.grey(e)}white(e){return p.white(e)}black(e){return p.black(e)}bgRed(e){return d.red(e)}bgGreen(e){return d.green(e)}bgBlue(e){return d.blue(e)}bgYellow(e){return d.yellow(e)}bgMagenta(e){return d.magenta(e)}bgCyan(e){return d.cyan(e)}bgWhite(e){return d.white(e)}bgBlack(e){return d.black(e)}reset(e){return f.reset(e)}dim(e){return f.dim(e)}bold(e){return f.bold(e)}italic(e){return f.italic(e)}underline(e){return f.underline(e)}inverse(e){return f.inverse(e)}hidden(e){return f.hidden(e)}strikethrough(e){return f.strikethrough(e)}}});function gt(n){return{...y,...n}}function lt(n=B.name,e=B.version){return new Q(n,e)}var E,A,S,$,x,y,Q,X,Se=v(()=>{"use strict";E=m(require("fs"),1),A=m(require("path"),1),S=require("fs-extra/esm"),$=require("panam/executor"),x=m(require("panam/pm"),1);te();V();ke();H();y={destination:"./abi-app",runtime:"node",force:void 0,install:void 0,git:void 0,yes:void 0,no:void 0,dryRun:void 0};Q=class extends P{configure(){this.strict().interactive().alias("h","help").useYes().useNo().command("* [destination] [runtime]","Create a new project powered by Abi.js").argument("destination",{type:"string",default:y.destination,desc:"Directory of the project"}).argument("runtime",{type:"string",default:y.runtime,desc:"JavaScript/TypeScript runtime to use",choices:["node","deno","bun"]}).option("force",{alias:"f",type:"boolean",default:y.force,desc:"Overwrite target directory if it exists"}).option("install",{alias:"i",type:"boolean",default:y.install,desc:"Install dependencies"}).option("git",{type:"boolean",default:y.git,desc:"Use Git to save changes"}).option("dryRun",{type:"boolean",desc:"Walk through steps without executing"}).example("npm create abi@latest","Create a project with default options").example("npm create abi@latest ./abi-app","Create a project in a specific directory").example("npm create abi@latest ./abi-app node","Create a project using a server runtime").example("npm create abi@latest ./abi-app node --it","Create a project in interactive command mode").usage("npm create abi [destination] [runtime] [...options]")}parse(e){return gt(super.parse(e))}validate(e){return{destination:e.destination,runtime:e.runtime,force:e.force??(!!e.yes&&!e.no),install:e.install??(!!e.yes&&!e.no),git:e.git??(!!e.yes&&!e.no),dryRun:!!e.dryRun,outDir:q(e.destination),packageName:O(e.destination)}}async interact(e){let t=e.destination===y.destination?await this.scanString(`Where would you like to create your new project? ${this.gray("(Use './' for current directory)")}`,e.destination):e.destination,r=q(t.trim()),i=Y(r),o=e.force===void 0?i&&!!await this.scanBoolean(e,`Directory "./${L(r)}" already exists and is not empty. Would you like to force the copy?`,!1):e.force,a;if(e.runtime===y.runtime){let ee=await this.scanBoolean(e,"Would you like to use another runtime instead of Node.js?",!1)&&await this.scanChoice("Which runtime do you prefer?",[{value:"node",label:"Node"},{value:"deno",label:"Deno"},{value:"bun",label:"Bun"}],e.runtime)||"node";b(ee,Oe=>["node","deno","bun"].includes(Oe)),a=ee}else a=e.runtime;let Ie=!!(e.install===void 0?await this.scanBoolean(e,`Would you like to install ${x.default.name} dependencies?`):e.install),De=!!(e.git===void 0?await this.scanBoolean(e,!i||o?"Would you like to initialize Git?":"Would you like to save the changes with Git?"):e.git),Re=!!e.dryRun,j="";i&&o&&(E.default.existsSync(k("deno",r))?j="deno":E.default.existsSync(k("package",r))&&(j="package"));let I=j!==""?K(j,r).name:O(t);return I=e.yes?I:await this.scanString("What should be the name of this package?",I),{destination:t,runtime:a,install:Ie,git:De,force:o,outDir:r,packageName:I,dryRun:Re}}async execute(e){try{let t=await this.start(e);return this.updatePackageJson(e),await this.runGit(e),this.end(e,t),0}catch(t){return console.error("An error occurred during Abi.js project creation:",t),1}}async prepareDir(e){let t=e.outDir;Y(t)&&(e.force?(e.dryRun||await he(t),this.info(`Directory "${t}" successfully emptied \u{1F525}`)):(this.error(`Directory "${t}" already exists.`),this.info("Please either remove this directory, choose another location or run the command again with '--force | -f' flag."),this.cancel(),process.exit(1)))}async runCreate(e){await this.prepareDir(e),this.copyStarter(e)}async start(e){return this.intro(`Let's create a ${this.bgYellow(" Abi.js")} App \u2728`),await this.runCreate(e),this.runInstall(e)}end(e,t){let r=e.outDir,i=process.cwd()===r,o=L(r),a=[];i?a.push(`\u{1F984} ${this.bgMagenta(" Success! ")}`):a.push(`\u{1F984} ${this.bgMagenta(" Success! ")} ${this.cyan("Project created in")} ${this.bold(this.magenta(o))} ${this.cyan("directory")}`),a.push(""),a.push(`\u{1F430} ${this.cyan("Next steps:")}`),i||a.push(` cd ${o}`),t||a.push(` ${x.default.name} install`),a.push(` ${x.default.name} start`),this.note(a.join(` `),"Ready to start \u{1F680}"),this.outro("Happy coding! \u{1F4BB}\u{1F389}")}updatePackageJson(e){let{outDir:t,packageName:r}=e,i=e.runtime==="deno"?"deno":"package";ve(r,i,t),this.info(`Updated package name to "${r}" \u{1F4E6}\uFE0F`),x.default.isNpm()||(this.info(`Replacing 'npm run' by '${x.default.runCommand()}' in package.json...`),be(i,t))}async runInstall(e){let t=!1;return e.install&&(this.step("Installing dependencies..."),e.dryRun||await x.default.install({cwd:e.outDir}),t=!0),t}async runGit(e){if(e.git){let t=this.spinner(),r=e.outDir,i=E.default.existsSync(A.default.join(r,".git"));if(i&&this.info("Git has already been initialized before."),t.start("Initializing Git..."),!e.dryRun){let o=[];try{if(i||o.push(await(0,$.$)("git",["init"],{cwd:r}).result),o.push(await(0,$.$)("git",["add","-A"],{cwd:r}).result),o.push(await(0,$.$)("git",["commit","-m","Initial commit \u{1F389}"],{cwd:r}).result),o.some(a=>a.status===!1))throw"";t.stop("Git initialized \u{1F3B2}")}catch{t.stop("Git failed to initialize"),i?this.error("Git failed to add new changes. You can do this manually by running: git add -A && git commit"):this.error("Git failed to initialize. You can do this manually by running: git init")}}}}copyShared(e){for(let t of["gitignore"]){let r=t;t==="gitignore"&&(r=".gitignore");let i=A.default.join(e.outDir,r),o=(0,S.pathExistsSync)(i);if(t.startsWith(".")&&t.endsWith("ignore")&&this.step(`${o?"Merging":"Copying"} \`${r}\` file... \u{1F648}`),!e.dryRun){let a=A.default.join(T,"..","starters",t);_(a,i)}}}copyStarter(e,t){if(this.step(`Creating new project in ${this.bgBlue(` ${e.outDir} `)} ... \u{1F407}`),!e.dryRun){let r=e.outDir;try{(0,S.ensureDirSync)(r),t||(t=A.default.join(T,"..","starters",e.runtime)),(0,S.copySync)(t,r),this.copyShared(e)}catch(i){this.error(this.red(`Template copy failed: ${i}`))}}}};X=lt()});var Ae={};Me(Ae,{app:()=>X,default:()=>pt,run:()=>Te});async function Te(n){return X.run(n)}async function pt(){return Te(process.argv)}var je=v(()=>{"use strict";Se()});Promise.resolve().then(()=>(je(),Ae)).then(n=>n.default());