hq-kit
Version:
The command line interface for HQ UI.
9 lines • 14.8 kB
JavaScript
import{program as $}from"commander";var F={name:"hq-kit",type:"module",version:"1.0.12",description:"The command line interface for HQ UI.",repository:{type:"git",url:"git+https://github.com/hq-kit/cli.git"},files:["dist","src"],main:"./dist/index.js",bin:{"hq-kit":"./dist/index.js"},homepage:"https://hq-ui.vercel.app",scripts:{rp:"npm uninstall @tabler/icons-react tailwindcss clsx cmdk embla-carousel-react embla-carousel-autoplay motion recharts input-otp react-aria-components tailwind-variants tailwindcss-animate tailwindcss-react-aria-components lexical @lexical/react",clean:"rimraf hq.json && rimraf src/styles && rimraf src/index.css && rimraf src/app && rimraf app && rimraf styles/app.css && rimraf src/app/globals.css && rimraf app/globals.css && rimraf src/components && rimraf styles && rimraf resources && rimraf src/components && rimraf components && rimraf lib && rimraf src/lib && npm run rp",dev:"tsup --watch",start:"tsc && npm link",format:"biome lint --fix && biome check --write","format:unsafe":"biome check --unsafe --write",build:"tsup && npm run format",preview:"npm run clean && npm run build && npm link",pre:"chmod a+x dist/index.js","start:init":"npm run dist/index.js init","start:add":"npm run dist/index.js add","start:diff":"npm run dist/index.js diff",release:"release-it"},keywords:["cli","hq-kit-ui","hq-kit","cleon","cleon-ui","design-system","react-ui","react-aria-components"],author:"Diqi Al-Haqqi",license:"MIT",devDependencies:{"@biomejs/biome":"1.9.4","@commitlint/cli":"^19.8.1","@commitlint/config-conventional":"^19.8.1","@release-it/conventional-changelog":"^10.0.1","@tailwindcss/vite":"^4.1.11","@types/babel__core":"^7.20.5","@types/diff":"^7.0.2","@types/fs-extra":"^11.0.4","@types/node":"^22.16.5",husky:"^9.1.7","release-it":"^18.1.2",rimraf:"^6.0.1",tsup:"^8.5.0","tw-animate-css":"^1.3.6",typescript:"^5.8.3"},dependencies:{"@antfu/ni":"^24.4.0","@babel/core":"^7.28.0","@babel/parser":"^7.28.0","@babel/plugin-transform-typescript":"^7.28.0","@inquirer/prompts":"^7.7.1",chalk:"^5.4.1",commander:"^13.1.0",diff:"^7.0.0","node-fetch":"^3.3.2",ora:"^8.2.0","react-stately":"^3.40.0",recast:"^0.23.11","ts-morph":"^25.0.1"},"release-it":{git:{commitMessage:"chore: release ${version}",tagName:"v${version}",tag:!0,commit:!0,push:!0},github:{release:!0,tokenRef:"GITHUB_TOKEN"},npm:{publish:!1},publishConfig:{access:"public",registry:"https://npm.pkg.github.com"},plugins:{"@release-it/conventional-changelog":{infile:"CHANGELOG.md",preset:{name:"conventionalcommits",types:[{type:"feat",section:"Features"},{type:"fix",section:"Bug Fixes"},{type:"refactor",section:"Refactors"},{type:"chore",section:"Chores"}]}}}}};import{spawn as Oe}from"child_process";import J from"fs";import Ie from"path";import{checkbox as Re}from"@inquirer/prompts";import _ from"chalk";import oe from"ora";import S from"fs";import a from"path";import{fileURLToPath as Te}from"url";import qe from"chalk";import f from"fs";import{existsSync as ge}from"fs";import T from"path";import D from"chalk";function he(e){let t=T.join(process.cwd(),"hq.json");return f.existsSync(t)?JSON.parse(f.readFileSync(t,"utf8"))[e]:(console.error(`${D.red("hq.json not found")}. ${D.gray(`Please run ${D.blue("npx hq-kit init")} to initialize the project.`)}`),"")}function j(e){let t=T.join(process.cwd(),e);return f.existsSync(t)}function G(){return w()?"resources/css/app.css":u()&&j("src")?"src/app/globals.css":u()&&!j("src")?"app/globals.css":x()?"app/tailwind.css":(q()||b(),"src/index.css")}function N(){return w()?"resources/js/components":u()&&j("src")?"src/components":u()&&!j("src")?"components":x()?"app/components":q()||b()?"src/components":"components"}function z(){return w()?"resources/js/lib":u()&&j("src")?"src/lib":u()&&!j("src")||x()?"lib":q()||b()?"src/lib":"lib"}function u(){return f.existsSync("next.config.ts")||f.existsSync("next.config.js")||f.existsSync("next.config.mjs")}function x(){let e=T.join(process.cwd(),"package.json");if(ge(e)){let t=JSON.parse(f.readFileSync(e,"utf8")),{dependencies:n={},devDependencies:o={}}=t;return"@remix-run/react"in n||"@remix-run/react"in o}return!1}function w(){return f.existsSync(T.resolve(process.cwd(),"artisan"))}function q(){return f.existsSync("vite.config.ts")||f.existsSync("vite.config.js")}function b(){return f.existsSync("astro.config.mjs")||f.existsSync("astro.config.cjs")||f.existsSync("astro.config.ts")||f.existsSync("astro.config.js")}function d(){return f.existsSync(T.resolve(process.cwd(),"tsconfig.json"))}function M(){let e=he("ui");return e||`${N()}/ui`}import{promises as ye}from"fs";import{tmpdir as xe}from"os";import K from"path";import{transformFromAstSync as we}from"@babel/core";import{parse as be}from"@babel/parser";import Se from"@babel/plugin-transform-typescript";import Q from"recast";import{Project as ve,ScriptKind as je}from"ts-morph";var ke={sourceType:"module",allowImportExportEverywhere:!0,allowReturnOutsideFunction:!0,startLine:1,tokens:!0,plugins:["asyncGenerators","bigInt","classPrivateMethods","classPrivateProperties","classProperties","classStaticBlock","decimal","decorators-legacy","doExpressions","dynamicImport","exportDefaultFrom","exportNamespaceFrom","functionBind","functionSent","importAssertions","importMeta","nullishCoalescingOperator","numericSeparator","objectRestSpread","optionalCatchBinding","optionalChaining",["pipelineOperator",{proposal:"minimal"}],["recordAndTuple",{syntaxType:"hash"}],"throwExpressions","topLevelAwait","v8intrinsic","typescript","jsx"]},Ce=async({sourceFile:e})=>{let t=e.getFullText(),n=Q.parse(t,{parser:{parse:c=>be(c,ke)}}),o=we(n,t,{cloneInputAst:!1,code:!1,ast:!0,plugins:[Se],configFile:!1});if(!o||!o.ast)throw new Error("Failed to transform JSX");return Q.print(o.ast).code},Pe=new ve({compilerOptions:{}});async function $e(e){let t=await ye.mkdtemp(K.join(xe(),"hq-"));return K.join(t,e)}async function Fe({content:e,writePath:t}){let n=await $e(t);return Pe.createSourceFile(n,e,{scriptKind:je.TSX})}async function k({content:e,writePath:t}){let n=await Fe({content:e,writePath:t});return await Ce({sourceFile:n})}var Ee=Te(import.meta.url),Je=a.dirname(Ee),g=a.resolve(Je,"../src/resources/stubs");function H(e){let t=M();return a.join(t,`${e}.tsx`)}async function C(e,t){let o=await(await fetch(e)).text();o=d()?o:await k({content:o,writePath:t}),o=u()?o:o.replace(/['"]use client['"]\s*\n?/g,"");let c=d()?t:t.replace(/\.tsx$/,".jsx").replace(/\.ts$/,".js");S.writeFileSync(c,o,{flag:"w"})}async function V(e){let t,n;u()?(t=a.join(g,"next/providers.stub"),n=a.join(g,"next/theme-toggle.stub")):w()?(t=a.join(g,"laravel/providers.stub"),n=a.join(g,"laravel/theme-toggle.stub")):x()?(t=a.join(g,"remix/providers.stub"),n=a.join(g,"remix/theme-toggle.stub")):b()?(t=a.join(g,"astro/providers.stub"),n=a.join(g,"astro/theme-toggle.stub")):(t=a.join(g,"vite/providers.stub"),n=a.join(g,"vite/theme-toggle.stub"));let o=S.readFileSync(t,"utf8"),c=d()?o:await k({content:o,writePath:a.join(e,"providers.jsx")}),s=d()?a.join(e,"providers.tsx"):a.join(e,"providers.jsx");S.writeFileSync(s,c,{flag:"w"});let l=S.readFileSync(n,"utf8"),r=d()?l:await k({content:l,writePath:a.join(e,"theme-toggle.jsx")}),i=d()?a.join(e,"theme-toggle.tsx"):a.join(e,"theme-toggle.jsx");S.writeFileSync(i,r,{flag:"w"})}function X(){let e=M(),t=S.readdirSync(e),n=t.filter(c=>!c.endsWith(".ts")).map(c=>`export * from './${c.replace(".tsx","").replace(".jsx","")}';`).join(`
`),o=d()?a.join(e,"index.ts"):a.join(e,"index.js");S.writeFileSync(o,n),console.log(qe.green(`\u2714 ${t.length-1} components added to index`))}import{detect as Le}from"@antfu/ni";async function R(){let e=await Le({programmatic:!0});return e==="yarn@berry"?"yarn":e==="pnpm@6"?"pnpm":e==="bun"?"bun":e??"npm"}var E="https://raw.githubusercontent.com/hq-kit/ui/main",A=e=>`${E}/components/ui/${e}.tsx`,Y=`${E}/lib/styles/default.css`,Z=`${E}/lib/utils/index.ts`,ee=`${E}/lib/hooks/index.ts`;async function te(){let t=await(await fetch(`${E}/components/docs/generated/components.json`)).text();return JSON.parse(t)}async function B(e){let t=H(e),n=Ie.dirname(t);J.existsSync(n)||J.mkdirSync(n,{recursive:!0});let o=oe(`Creating ${e}...`).start(),c=A(e);try{await C(c,t),o.succeed(`${e} created`)}catch{o.fail(`Error writing component to ${t}`)}}async function ne(e,t,n,o,c,s,l=!1){let r=H(e);if(J.existsSync(r))if(s&&!l)console.log(`${_.yellow("Replacing")} ${e}...`),J.rmSync(r,{recursive:!0,force:!0});else{console.warn(`${_.blue("\u2139")} ${e} already exists. Use the -o flag to override.`);return}o.add(e);let i=c.find(p=>p.name===e);if(J.existsSync(r)||(i?.deps&&await Ae(i?.deps,t,n),await B(e)),i?.children)for(let p of i.children)await ne(p.name,t,n,o,c,!0,!0)}async function re(e){let t=await te(),{component:n}=e,o=n?n.split(" "):[];if(o.length===0){let r=[],i="";for(let p of t.sort((y,v)=>y.section.localeCompare(v.section)))p.section!==i&&(r.push({type:"separator",separator:`== ${p.section.toUpperCase()} ==`}),i=p.section),r.push({name:p.name,value:p.name});o=await Re({required:!0,message:"Choose components to add:",choices:r,pageSize:17,loop:!1})}let c=await R(),s=c==="npm"?"i ":"add ",l=new Set;for(let r of o){if(!t.find(p=>p.name===r)){console.log(_.yellow("No component found"));return}console.log(`Starting to add ${r}...`),await ne(r,c,s,l,t,!0)}X()}async function Ae(e,t,n){let o=oe("Installing dependencies...").start(),c=`${t} ${n} ${e.join(" ")}`,s=Oe(c,{stdio:"ignore",shell:!0});await new Promise(l=>{s.on("close",()=>{o.stop(),l()})}),o.succeed("Dependencies installed")}import O from"fs";import I from"path";import{checkbox as Ue}from"@inquirer/prompts";import L from"chalk";import{diffLines as De}from"diff";import Ne from"node-fetch";var se=(e,t)=>{let n=JSON.parse(O.readFileSync(e,"utf-8"));return d()?I.join(n.ui,`${t}.tsx`):I.join(n.ui,`${t}.jsx`)},ie=async e=>{let t=A(e),n=await Ne(t);if(!n.ok)throw new Error(`Failed to fetch component: ${n.statusText}`);let o=await n.text();return o=d()?o:await k({content:o,writePath:""}),o=u()?o.replace(/['"]use client['"]\s*\n?/g,""):o,o},Me=(e,t)=>De(e,t).filter(o=>o.added||o.removed),ce=async(...e)=>{try{let t=I.resolve(process.cwd(),"hq.json"),o=JSON.parse(O.readFileSync(t,"utf-8")).ui,c=["index"],s=O.readdirSync(o).filter(r=>r.endsWith(".tsx")||r.endsWith(".jsx")).map(r=>r.endsWith(".tsx")?I.basename(r,".tsx"):I.basename(r,".jsx")).filter(r=>!c.includes(r));e.length>0&&(s=s.filter(r=>e.includes(r)));let l=[];for(let r of s){let i=se(t,r),p=O.readFileSync(i,"utf-8");try{let y=await ie(r),v=Me(p,y);if(v.length>0){console.log(`Differences found in ${r}:`);for(let m of v){let me=m.added?"+":"-",fe=m.added?L.green:L.red;process.stdout.write(m.value.split(`
`).map(ue=>fe(`${me} ${ue}`)).join(`
`))}console.log(`
`),l.push(r)}else console.log(`${L.green(`\u2714 ${r}`)} is up to date.`)}catch{}}if(l.length>0){let r=await Ue({message:"Select components to update",choices:[...l.map(i=>({title:i,value:i}))],initial:l});if(r.includes("none")||r.length===0){console.log("No components selected for update.");return}for(let i of r)try{let p=await ie(i),y=se(t,i);O.writeFileSync(y,p),console.log(`${L.green(`\u2714 ${i} is updated.`)}`)}catch(p){console.error(`Error updating ${i}: ${p.message}`)}}else console.log(L.green("\u2714 All components are up to date."))}catch(t){console.error("Error checking differences:",t.message)}};var He=F.version;function ae(e){e.command("help [command]").description("Show help information").action(t=>{if(console.log(`CLI Tool v${He}
`),t){let n=e.commands.find(o=>o.name()===t);n?n.outputHelp():console.log(`Command "${t}" not found.`)}else e.outputHelp()})}import{spawn as _e}from"child_process";import h from"fs";import P from"path";import{input as W}from"@inquirer/prompts";import U from"chalk";import Be from"ora";async function pe(){let e,t,n,o;e=await W({message:"Enter the path to your components folder:",default:N(),validate:m=>m.trim()!==""||"Path cannot be empty. Please enter a valid path."}),t=P.join(e,"ui"),o=await W({message:"Enter the path to your lib folder:",default:z(),validate:m=>m.trim()!==""||"Path cannot be empty. Please enter a valid path."}),n=await W({message:"Where would you like to place the CSS file?",default:G(),validate:m=>m.trim()!==""||"Path cannot be empty. Please enter a valid path."}),h.existsSync(t)||h.mkdirSync(t,{recursive:!0}),h.existsSync(o)||h.mkdirSync(o,{recursive:!0});let c={$schema:"https://hq-ui.vercel.app/schema.json",ui:t,css:n,lib:o},s=Be("Initializing HQ...").start();h.existsSync(P.dirname(n))||(h.mkdirSync(P.dirname(n),{recursive:!0}),s.succeed(`Created directory for CSS at ${U.blue(P.dirname(n))}`));let l=await R(),r="react-aria-components @tabler/icons-react",i="tailwindcss tailwindcss-react-aria-components tailwind-variants clsx tw-animate-css";u()&&(i+=" next-themes @tailwindcss/postcss postcss"),(w()||q()||b())&&(i+=" @tailwindcss/vite @types/node"),x()&&(i+=" remix-themes");let p=l==="npm"?"i":"add",y=`${l} ${p} ${r} && ${l} ${p} -D ${i}`;s.info("Installing dependencies...");let v=_e(y,{stdio:"inherit",shell:!0});await new Promise(m=>{v.on("close",()=>{m()})});try{await C(Y,n),s.succeed(`CSS file copied to ${n}`)}catch{s.fail(`Failed to write CSS file to ${n}`)}try{await C(Z,P.join(o,"utils.ts")),s.succeed(`utils file copied to ${o}`)}catch{s.fail("Error writing utils file")}try{await C(ee,P.join(o,"hooks.ts")),s.succeed(`hooks file copied to ${o}`)}catch{s.fail("Error writing hooks file")}try{await V(e),s.succeed(`Provider files copied to ${e}`)}catch(m){s.fail(`Failed to write Providers file: ${m.message}`)}h.existsSync("hq.json")&&h.unlinkSync("hq.json"),h.writeFileSync("hq.json",JSON.stringify(c,null,2)),s.succeed("Configuration saved to hq.json"),s.succeed("Installation complete."),await B("button"),console.log(U.blueBright("========================")),console.log("|| Happy coding! \u{1F525} ||"),console.log(U.blueBright("========================")),console.info(`
Now try to add some components to your project`),console.info(`by running: ${U.blue("npx hq-kit add <component-name>")}`),s.stop()}var We=F.version,le=process.argv.slice(2);(le.includes("--version")||le.includes("-v"))&&(console.log(F.version),process.exit(0));$.version(We,"-v, --version","Output the version number").description("CLI Tool Description");$.command("init").option("--skip <type>","Skip a specific step").action(pe);$.command("add [components...]").option("--skip <type>","Skip").option("-o, --override","Override existing components").action(async(e,t)=>{await re({component:e.join(" "),...t})});$.command("diff [components...]").description("Show differences between local and remote components").action(async e=>{await ce(...e)});ae($);$.parse(process.argv);
//# sourceMappingURL=index.js.map