UNPKG

create-pol-ui

Version:

Create web application using pol-ui

27 lines (26 loc) 15.4 kB
#!/usr/bin/env node import T from"path";import{execa as Lt}from"execa";import J from"fs-extra";import*as p from"@clack/prompts";import G from"chalk";import{Command as Mt}from"commander";import B from"path";import{fileURLToPath as bt}from"url";var vt=bt(import.meta.url),_t=B.dirname(vt),m=B.join(_t,"../"),z=` ____ ___ _ _ _ ___ | _ \\ / _ \\| | | | | |_ _| | |_) | | | | | _____| | | || | | __/| |_| | |__|_____| |_| || | |_| \\___/|_____| \\___/|___| `,I="pol-ui",N="create-pol-ui";var c=()=>{let t=process.env.npm_config_user_agent;return t?t.startsWith("yarn")?"yarn":t.startsWith("pnpm")?"pnpm":t.startsWith("bun")?"bun":"npm":"npm"};import It from"path";import St from"fs-extra";var y=()=>{let t=It.join(m,"package.json");return St.readJSONSync(t).version??"1.0.0"};var k=class extends Error{constructor(e){super(e)}};import S from"chalk";var s={error(...t){console.log(S.red(...t))},warn(...t){console.log(S.yellow(...t))},info(...t){console.log(S.cyan(...t))},success(...t){console.log(S.green(...t))}};var A=t=>(t.length>1&&t.endsWith("/")&&(t=t.slice(0,-1)),t);var At=/^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/,L=t=>{let e=A(t),n=e.split("/"),i=n.findIndex(o=>o.startsWith("@")),a=n[n.length-1];if(n.findIndex(o=>o.startsWith("@"))!==-1&&(a=n.slice(i).join("/")),!(e==="."||At.test(a??"")))return"App name must consist of only lowercase alphanumeric characters, '-', and '_'"};var Y=t=>{if(t.startsWith(".")||t.startsWith("/"))return"Import alias can't start with '.' or '/'"};var w={appName:I,packages:["tailwind"],flags:{noGit:!1,noInstall:!1,default:!1,CI:!1,importAlias:"~/"}},H=async()=>{let t=w,e=new Mt().name(N).description("A CLI for bootstrapping a new app using pol-ui.").argument("[dir]","The name of the application, as well as the name of the directory to create").option("--noGit","Explicitly tell the CLI to not initialize a new git repo in the project",!1).option("--noInstall","Explicitly tell the CLI to not run the package manager's install command",!1).option("-y, --default","Bypass the CLI and use all default options to bootstrap a new t3-app",!1).option("--CI","Boolean value if we're running in CI",!1).option("--tailwind [boolean]","Experimental: Boolean value if we should install Tailwind CSS. Must be used in conjunction with `--CI`.",i=>!!i&&i!=="false").option("-i, --import-alias","Explicitly tell the CLI to use a custom import alias",w.flags.importAlias).version(y(),"-v, --version","Display the version number").addHelpText("afterAll",` Pol-ui was created by ${G.hex("#E8DCFF").bold("@polgubau")} and has been used to build awesome fullstack applications like ${G.hex("#b49cff").underline("https://cursosAlbert.com")} `).parse(process.argv);process.env.npm_config_user_agent?.startsWith("yarn/3")&&s.warn(` WARNING: It looks like you are using Yarn 3. This is currently not supported, and likely to result in a crash. Please run create-pol-ui with another package manager such as pnpm, npm, or Yarn Classic. See: https://github.com/polgubau/create-pol-ui/issues/57`);let n=e.args[0];if(n&&(t.appName=n),t.flags=e.opts(),t.flags.CI)return t.packages=[],t.packages.push("tailwind"),t;if(t.flags.default)return t;try{if(process.env.TERM_PROGRAM?.toLowerCase().includes("mintty"))throw s.warn(` \u{1F538} WARNING: It looks like you are using MinTTY, which is non-interactive. This is most likely because you are using Git Bash. If that's that case, please use Git Bash from another terminal, such as Windows Terminal. Alternatively, you can provide the arguments from the CLI directly: https://create.t3.gg/en/installation#experimental-usage to skip the prompts.`),new k("Non-interactive environment");let i=c(),a=await p.group({...!n&&{name:()=>p.text({message:"What will your project be called?",defaultValue:n,validate:L,placeholder:n})},language:()=>p.select({message:"Will you be using TypeScript or JavaScript?",options:[{value:"typescript",label:"TypeScript"},{value:"javascript",label:"JavaScript"}],initialValue:"typescript"}),_:({results:r})=>r.language==="javascript"?p.note(G.redBright("Wrong answer, using TypeScript instead")):void 0,...!t.flags.noGit&&{git:()=>p.confirm({message:"Should we initialize a Git repository and stage the changes?",initialValue:!w.flags.noGit})},...!t.flags.noInstall&&{install:()=>p.confirm({message:`Should we run '${i}`+(i==="yarn"?"'?":" install' for you?"),initialValue:!w.flags.noInstall})},importAlias:()=>p.text({message:"What import alias would you like to use?",defaultValue:w.flags.importAlias,placeholder:w.flags.importAlias,validate:Y})},{onCancel(){process.exit(1)}}),o=[];return o.push("tailwind"),{appName:a.name??t.appName,packages:o,flags:{...t.flags,noGit:!a.git||t.flags.noGit,noInstall:!a.install||t.flags.noInstall,importAlias:a.importAlias??t.flags.importAlias}}}catch(i){if(i instanceof k)s.warn(` ${N} needs an interactive terminal to provide options`),await p.confirm({message:"Continue scaffolding a default T3 app?",initialValue:!0})||(s.info("Exiting..."),process.exit(0)),s.info(`Bootstrapping a default T3 app in ./${t.appName}`);else throw i}return t};import Ot from"fs";import D from"path";import K from"chalk";import Ct from"ora";var X=t=>{let{packages:e}=t;s.info("Adding boilerplate...");for(let[n,i]of Object.entries(e))if(i.inUse){let a=Ct(`Boilerplating ${n}...`).start();i.installer(t),a.succeed(K.green(`Successfully setup boilerplate for ${K.green.bold(n)}`))}s.info("")};import $ from"path";import*as M from"@clack/prompts";import h from"chalk";import P from"fs-extra";import jt from"ora";var q=async({projectName:t,projectDir:e,pkgManager:n,noInstall:i})=>{let a=$.join(m,"template/base");i?s.info(""):s.info(` Using: ${h.cyan.bold(n)} `);let o=jt(`Scaffolding in: ${e}... `).start();if(P.existsSync(e))if(P.readdirSync(e).length===0)t!=="."&&o.info(`${h.cyan.bold(t)} exists but is empty, continuing... `);else{o.stopAndPersist();let l=await M.select({message:`${h.redBright.bold("Warning:")} ${h.cyan.bold(t)} already exists and isn't empty. How would you like to proceed?`,options:[{label:"Abort installation (recommended)",value:"abort"},{label:"Clear the directory and continue installation",value:"clear"},{label:"Continue installation and overwrite conflicting files",value:"overwrite"}],initialValue:"abort"});l==="abort"&&(o.fail("Aborting installation..."),process.exit(1)),await M.confirm({message:`Are you sure you want to ${l==="clear"?"clear the directory":"overwrite conflicting files"}?`,initialValue:!1})||(o.fail("Aborting installation..."),process.exit(1)),l==="clear"&&(o.info(`Emptying ${h.cyan.bold(t)} and creating pol-ui... `),P.emptyDirSync(e))}o.start(),P.copySync(a,e),P.renameSync($.join(e,"_gitignore"),$.join(e,".gitignore"));let r=t==="."?"App":h.cyan.bold(t);o.succeed(`${r} ${h.green("Your new Pol-ui app is ready!")} `)};import x from"path";import Q from"fs-extra";var Z=({projectDir:t,packages:e})=>{let n=x.join(m,"template/extras/src/app/layout"),i=e.tailwind.inUse,a=e.trpc.inUse,o="base.tsx";a&&i?o="with-trpc-tw.tsx":a&&!i?o="with-trpc.tsx":!a&&i&&(o="with-tw.tsx");let r=x.join(n,o),l=x.join(t,"src/app/layout.tsx");Q.copySync(r,l)};var tt=({projectDir:t,packages:e})=>{let n=x.join(m,"template/extras/src/app/page"),i=e.trpc.inUse,a=e.tailwind.inUse,o=e.nextAuth.inUse,r="base.tsx";i&&a&&o?r="with-auth-trpc-tw.tsx":i&&!a&&o?r="with-auth-trpc.tsx":i&&a?r="with-trpc-tw.tsx":i&&!a?r="with-trpc.tsx":!i&&a&&(r="with-tw.tsx");let l=x.join(n,r),f=x.join(t,"src/app/page.tsx");Q.copySync(l,f)};var et=async({projectName:t,scopedAppName:e,packages:n,noInstall:i})=>{let a=c(),o=D.resolve(process.cwd(),t);return await q({projectName:t,projectDir:o,pkgManager:a,scopedAppName:e,noInstall:i}),X({projectName:t,scopedAppName:e,projectDir:o,pkgManager:a,packages:n,noInstall:i}),Ot.copyFileSync(D.join(m,"template/extras/config/next-config-appdir.js"),D.join(o,"next.config.js")),Z({projectDir:o,packages:n}),tt({projectDir:o,packages:n}),o};import{execSync as E}from"child_process";import R from"path";import*as U from"@clack/prompts";import b from"chalk";import{execa as v}from"execa";import it from"fs-extra";import Tt from"ora";var Nt=t=>{try{return E("git --version",{cwd:t}),!0}catch{return!1}},F=t=>it.existsSync(R.join(t,".git")),W=async t=>{try{return await v("git",["rev-parse","--is-inside-work-tree"],{cwd:t,stdout:"ignore"}),!0}catch{return!1}},Gt=()=>{let e=E("git --version").toString().trim().split(" ")[2],n=e?.split(".")[0],i=e?.split(".")[1];return{major:Number(n),minor:Number(i)}},$t=()=>E("git config --global init.defaultBranch || echo main").toString().trim(),nt=async t=>{if(s.info("\u{1F955} Initializing Git..."),!Nt(t)){s.warn("Git is not installed. Skipping Git initialization.");return}let e=Tt(`Creating a new git repo... `).start(),n=F(t),i=await W(t),a=R.parse(t).name;if(i&&n){if(e.stop(),!await U.confirm({message:`${b.redBright.bold("Warning:")} Git is already initialized in "${a}". Initializing a new git repository would delete the previous history. Would you like to continue anyways?`,initialValue:!1})){e.info("Skipping Git initialization.");return}it.removeSync(R.join(t,".git"))}else if(i&&!n&&(e.stop(),!await U.confirm({message:`${b.redBright.bold("Warning:")} "${a}" is already in a git worktree. Would you still like to initialize a new git repository in this directory?`,initialValue:!1}))){e.info("Skipping Git initialization.");return}try{let o=$t(),{major:r,minor:l}=Gt();r<2||r==2&&l<28?(await v("git",["init"],{cwd:t}),await v("git",["symbolic-ref","HEAD",`refs/heads/${o}`],{cwd:t})):await v("git",["init",`--initial-branch=${o}`],{cwd:t}),await v("git",["add","."],{cwd:t}),e.succeed(`${b.green("Successfully initialized and staged")} ${b.green.bold("git")} `)}catch{e.fail(`${b.bold.red("Failed:")} could not initialize git. Update git to the latest version! `)}};var ot=async({projectName:t=I,noInstall:e,projectDir:n})=>{let i=c();s.info("Next steps:"),t!=="."&&s.info(` cd ${t}`),e&&(i==="yarn"?s.info(` ${i}`):s.info(` ${i} install`)),["npm","bun"].includes(i)?s.info(` ${i} run dev`):s.info(` ${i} dev`),!await W(n)&&!F(n)&&s.info(" git init"),s.info(' git commit -m "initial commit"'),s.success(` Thank you for using create-pol-ui \u{1F389}. If you have any feedback, please open an issue!`)};import C from"fs";import Rt from"path";function at(t,e,n){C.readdirSync(t).forEach(a=>{let o=Rt.join(t,a);if(C.statSync(o).isDirectory())at(o,e,n);else{let l=C.readFileSync(o,"utf8").replace(new RegExp(e,"g"),n);C.writeFileSync(o,l,"utf8")}})}var st=(t,e)=>{let n=e.replace(/\*/g,"").replace(/[^\/]$/,"$&/");at(t,"~/",n)};import d from"path";import O from"fs-extra";import lt from"path";import pt from"fs-extra";import Ut from"sort-package-json";var rt={tailwindcss:"^3.3.5",autoprefixer:"^10.4.14",postcss:"^8.4.31",prettier:"^3.1.0","prettier-plugin-tailwindcss":"^0.5.7","pol-ui":"2.1.11"};var j=t=>{let{dependencies:e,devMode:n,projectDir:i}=t,a=pt.readJSONSync(lt.join(i,"package.json"));e.forEach(r=>{let l=rt[r];n&&a.devDependencies?a.devDependencies[r]=l:a.dependencies&&(a.dependencies[r]=l)});let o=Ut(a);pt.writeJSONSync(lt.join(i,"package.json"),o,{spaces:2})};var ct=({projectDir:t})=>{j({projectDir:t,dependencies:["tailwindcss","postcss","autoprefixer","prettier","prettier-plugin-tailwindcss"],devMode:!0});let e=d.join(m,"template/extras"),n=d.join(e,"config/tailwind.config.ts"),i=d.join(t,"tailwind.config.ts"),a=d.join(e,"config/postcss.config.cjs"),o=d.join(t,"postcss.config.cjs"),r=d.join(e,"config/_prettier.config.js"),l=d.join(t,"prettier.config.js"),f=d.join(e,"src/styles/globals.css"),u=d.join(t,"src/styles/globals.css");O.copySync(n,i),O.copySync(a,o),O.copySync(f,u),O.copySync(r,l)};var gt=({projectDir:t})=>{j({projectDir:t,dependencies:["pol-ui"],devMode:!0})};var mt=t=>({tailwind:{inUse:t.includes("tailwind"),installer:ct},"pol-ui":{inUse:t.includes("pol-ui"),installer:gt}});import ft from"path";var dt=t=>{let n=A(t).split("/"),i=n[n.length-1];if(i==="."){let r=ft.resolve(process.cwd());i=ft.basename(r)}let a=n.findIndex(r=>r.startsWith("@"));n.findIndex(r=>r.startsWith("@"))!==-1&&(i=n.slice(a).join("/"));let o=n.filter(r=>!r.startsWith("@")).join("/");return[i,o]};import Et from"gradient-string";var Ft=["#add7ff","#89ddff","#C3B6EA","#fae4fc","#d0679d","#A28CE5"],ut=()=>{let t=Et(Ft),e=c();(e==="yarn"||e==="pnpm")&&console.log(""),console.log(t.multiline(z))};import Wt from"chalk";import{execa as ht}from"execa";import yt from"ora";var V=async(t,e,n)=>{let{onDataHandle:i,args:a=["install"],stdout:o="pipe"}=n,r=yt(`Running ${e} install...`).start(),l=ht(e,a,{cwd:t,stdout:o});return await new Promise((f,u)=>{i&&l.stdout?.on("data",i(r)),l.on("error",g=>u(g)),l.on("close",()=>f())}),r},Vt=async(t,e)=>{switch(t){case"npm":return await ht(t,["install"],{cwd:e,stderr:"inherit"}),null;case"pnpm":return V(e,t,{onDataHandle:n=>i=>{let a=i.toString();a.includes("Progress")&&(n.text=a.includes("|")?a.split(" | ")[1]??"":a)}});case"yarn":return V(e,t,{onDataHandle:n=>i=>{n.text=i.toString()}});case"bun":return V(e,t,{stdout:"ignore"})}},wt=async({projectDir:t})=>{s.info("Installing dependencies...");let e=c();(await Vt(e,t)??yt()).succeed(Wt.green(`Successfully installed dependencies! `))};import{execSync as Jt}from"child_process";import Bt from"https";var xt=t=>{let e=y();console.log("\u{1F7E3} Current version:",e),console.log("\u{1F7E3} NPM version:",t),e===t?s.success(" You are using the latest version of create-pol-ui."):e.includes("beta")?(s.warn(" You are using a beta version of pol-ui."),s.warn(" Please report any bugs you encounter.")):e.includes("next")?(s.warn(" You are running create-pol-ui with the @next tag which is no longer maintained."),s.warn(" Please run the CLI with @latest instead.")):e!==t&&(s.warn(" You are using an outdated version of create-pol-ui."),s.warn(" Your version:",e+".","Latest version in the npm registry:",t),s.warn(" Please run the CLI with @latest to get the latest updates.")),console.log("")};function zt(){return new Promise((t,e)=>{Bt.get("https://registry.npmjs.org/-/package/create-pol-ui/dist-tags",n=>{if(n.statusCode===200){let i="";n.on("data",a=>i+=a),n.on("end",()=>{t(JSON.parse(i).latest)})}else e(new Error("Unable to fetch latest version."))}).on("error",()=>{s.error("Unable to check for latest version."),e(new Error("Unable to check for latest version."))})})}var kt=()=>zt().catch(()=>{try{return Jt("npm view create-pol-ui version").toString().trim()}catch{return null}});var Yt=async()=>{let t=await kt(),e=c();ut(),t&&xt(t);let{appName:n,packages:i,flags:{noGit:a,noInstall:o,importAlias:r}}=await H(),l=mt(i),[f,u]=dt(n),g=await et({projectName:u,scopedAppName:f,packages:l,importAlias:r,noInstall:o}),_=J.readJSONSync(T.join(g,"package.json"));if(_.name=f,_.Metadata={initVersion:y()},e!=="bun"){let{stdout:Pt}=await Lt(e,["-v"],{cwd:g});_.packageManager=`${e}@${Pt.trim()}`}J.writeJSONSync(T.join(g,"package.json"),_,{spaces:2}),r!=="~/"&&st(g,r),o||await wt({projectDir:g}),J.renameSync(T.join(g,"_eslintrc.cjs"),T.join(g,".eslintrc.cjs")),a||await nt(g),await ot({projectName:u,noInstall:o,projectDir:g}),process.exit(0)};Yt().catch(t=>{s.error("Aborting installation..."),t instanceof Error?s.error(t):(s.error("An unknown error has occurred. Please open an issue on github with the below:"),console.log(t)),process.exit(1)});