untitledui 0.1.44-beta.2 → 0.1.45-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.mjs +1 -1
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import{Command as Q1}from"commander";import Q3 from"async-retry";import y from"chalk";import{Command as _3}from"commander";import{execa as b0}from"execa";import*as F from"fs";import B0 from"ora";import E3 from"os";import*as k from"path";import s from"prompts";import{Project as T3}from"ts-morph";import d0 from"node-fetch";import{Readable as L3,pipeline as b3}from"stream";import{x as M3}from"tar";import{promisify as H3}from"util";var j3=H3(b3);async function f0(z,W){try{let Q=await G3(W);await j3(Q,M3({cwd:z,strip:1}))}catch(Q){throw new Error(`Failed to download or extract repository from API: ${Q instanceof Error?Q.message:Q}`)}}async function G3(z){let W=`https://www.untitledui.com/react/api/download-repo?template=${z.template}`;try{let Q=await d0(W,{method:"GET",headers:{"Content-Type":"application/json",Accept:"application/octet-stream"}});if(Q.status===403||Q.status===404)throw new Error("Repository not found");if(!Q.ok)throw new Error(`Failed to download from API. Status: ${Q.status} ${Q.statusText}`);if(!Q.body)throw new Error("Response body is empty");return L3.from(Q.body)}catch(Q){throw new Error(`Error downloading tarball: ${Q instanceof Error?Q.message:Q}`)}}async function K0(z){let W=`https://www.untitledui.com/react/api/validate-key?key=${z}`;try{return(await d0(W)).status===200}catch{return!1}}import v3 from"node-fetch";var m0={invalid_key:"Invalid key provided",no_components_found:"No components found",no_components_provided:"No components provided"};async function J0(z,W,Q){let $=W.map((Z)=>{if(Z.includes("modals/"))if(Z.includes("-modal"))return Z;else return Z+"-modal";return Z});try{let Z=await v3("https://www.untitledui.com/react/api/components",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({type:z,components:$,key:Q})});if(!Z.ok)console.log(m0?.[Z.statusText]||m0.no_components_found),process.exit(1);return await Z.json()}catch(Z){return null}}import R0 from"node-fetch";var e={invalid_key:"Invalid key provided",no_components_found:"No components found",no_components_provided:"No components provided"};async function l0(z,W=""){let Q=`https://www.untitledui.com/react/api/components/list?key=${W}&type=${z}`;try{let B=await R0(Q),$=await B.json();if(!B.ok)console.log(e?.[B.statusText]||e.no_components_found),process.exit(1);if(!$?.components?.length)return null;return $}catch(B){return console.error(B),null}}async function c0(z,W="",Q){let B=`https://www.untitledui.com/react/api/components/list?key=${W}&type=${z}&subfolders=${Q.join(",")}`;try{let $=await R0(B);if(!$.ok)console.log(e?.[$.statusText]||e.no_components_found),process.exit(1);let Z=await $.json();if(!Z?.components?.length)return null;return Z}catch($){return console.error($),null}}async function a0(z=""){let W=`https://www.untitledui.com/react/api/components/list?key=${z}`;try{let Q=await R0(W);if(!Q.ok)console.log(e?.[Q.statusText]||e.no_components_found),process.exit(1);let B=await Q.json();if(!B?.types?.length)return null;return B}catch(Q){return console.error(Q),null}}import p0 from"fast-glob";import*as V0 from"fs";import*as a from"path";import{Project as A3}from"ts-morph";import{loadConfig as t0}from"tsconfig-paths";import u3 from"prettier";async function s0(z,W="typescript"){try{return await u3.format(z,{parser:W,printWidth:160,tabWidth:4})}catch(Q){return console.error("Error formatting with Prettier:",Q),z}}import m from"fast-glob";import*as d from"fs";import*as c from"path";import{loadConfig as N0}from"tsconfig-paths";import r0 from"fs";import I3 from"path";function i0(z=""){let W=I3.join(z,"package.json");if(!r0.existsSync(W))return null;else return JSON.parse(r0.readFileSync(W,"utf-8"))}var P=["**/node_modules/**",".next","public","dist","build"],n0={"next-app":"Next.js (App)","next-pages":"Next.js (Pages)",vite:"Vite",other:"Other"};async function z0(z){let W=d.existsSync(c.resolve(z,"src")),Q=d.existsSync(c.resolve(z,`${W?"src/":""}app`)),[B,$,Z,v,j]=await Promise.all([m.glob("**/{next,vite,astro}.config.*|gatsby-config.*",{cwd:z,deep:2,ignore:P}),R3(z),N3(z),y3(z),i0(z)]),J=d.existsSync(c.resolve(z,"components.json")),b=null;if(J)b=JSON.parse(d.readFileSync(c.resolve(z,"components.json"),"utf-8"));let L=m.sync(["**/**/theme.css"],{cwd:z,absolute:!0,onlyFiles:!0,ignore:P}),M=L?.[0]&&d.readFileSync(L[0],"utf-8").match(/(--color-brand+-\d{1,3}):\s*(rgb\([^)]+\))/g)?.[1]||void 0,K={tailwind:{config:Z||void 0,brandColor:M?.replace(/--color-([^-]+(?:-[^-]+)?)-\d+:.*/,"$1")||void 0},aliases:b?.aliases||v||{},isTsx:$,isSrcDir:W,isAppDir:Q,framework:"other"};if(B.find((Y)=>Y.startsWith("next.config."))?.length)return K.framework=Q?"next-app":"next-pages",K;else if(B.find((Y)=>Y.startsWith("vite.config."))?.length)return K.framework="vite",K;else if(B?.length||d.existsSync(c.resolve(z,"package.json")))return K.framework="other",K;else if(Object.keys(j?.dependencies||{}).includes("react"))return K.framework="next-pages",K;return null}async function R3(z){return(await m.glob("tsconfig.*",{cwd:z,deep:2,ignore:P})).length>0}async function N3(z){let W=await m.glob("tailwind.config.*",{cwd:z,deep:2,ignore:P});if(!W.length)return null;return W[0]}async function y3(z){let[W,Q]=await Promise.all([m.glob("next.config.*",{cwd:z,deep:1,ignore:P}),m.glob("vite.config.*",{cwd:z,deep:1,ignore:P})]),B=W.length>0,$=Q.length>0,Z;if(B)Z=N0(z);else if($){if(Z=N0(z),Z?.resultType==="failed"||!Object.keys(Z.paths||{}).length){let J=await m.glob(["tsconfig.app.*","*/tsconfig.app.*"],{cwd:z,deep:1,onlyFiles:!0,absolute:!0,ignore:P}),[b]=J;if(b)try{let M=function(q){return q.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\/\/.*$/gm,"").replace(/,(\s*[}\]])/g,"$1")},L=d.readFileSync(b,"utf-8"),K=M(L),Y=JSON.parse(K);if(Y.compilerOptions?.paths)Z={resultType:"success",paths:Y?.compilerOptions?.paths,baseUrl:Y.compilerOptions.baseUrl||".",absoluteBaseUrl:c.resolve(z,Y.compilerOptions.baseUrl||".")}}catch{}}}else Z=N0(z);if(Z?.resultType==="failed"||!Object.keys(Z.paths).length)return null;let v={},j={app:/\/?app\/\*$/,components:/\/?components\/\*$/,utils:/\/?utils\/\*$/,styles:/\/?styles\/\*$/,hooks:/\/?hooks\/\*$/,src:/^(\.\/src\/\*|\.\/\*|\/src\/\*|src\/\*|\/\*|\*)$/};for(let[J,b]of Object.entries(Z.paths)){let L=J.replace(/\/\*$/,"/");for(let[M,K]of Object.entries(j))if(b.some((Y)=>K.test(Y))){v[M]=L;break}}return v||null}function Q0(z){let W=t0(z),Q=p0.sync(["tailwind.config.*","**/globals.css","**/{layout,_app,main}.tsx","package.json"],{cwd:z,deep:4,absolute:!0,onlyFiles:!0,ignore:P}),B={tailwindFile:Q.find(($)=>$.includes("tailwind.config.")),cssFile:Q.find(($)=>$.includes("globals.css")),layoutFile:Q.find(($)=>$.includes("layout")),appFile:Q.find(($)=>$.includes("_app")),mainFile:Q.find(($)=>$.includes("main")),packageJson:Q.find(($)=>$.includes("package.json")),tsConfig:W?.resultType==="success"?W?.configFileAbsolutePath:void 0};if(W.resultType==="failed")throw new Error(`Failed to load tsconfig.json. ${W.message??""}`.trim());return B}function W0(z,W,Q={}){if(z.includes("components")&&Q?.components)return z.replace(/@\/components\//,a.posix.join(Q?.components||"",W?W.replace(/components\/?/,""):"","/"));if(z.includes("app")&&Q?.app)return z.replace(/^@\/app\//,a.posix.join(Q?.app,"/"));if(z.includes("utils")&&Q?.utils)return z.replace(/^@\/utils\//,a.posix.join(Q?.utils,"/"));if(z.includes("hooks")&&Q?.hooks)return z.replace(/^@\/hooks\//,a.posix.join(Q?.hooks,"/"));if(z.includes("styles")&&Q?.styles)return z.replace(/^@\/styles\//,a.posix.join(Q?.styles,"/"));if(Q?.src)return z.replace(/^@\//,a.posix.join(Q?.src,"/"));return z}async function o0(z,W,Q="@/*"){let B=await t0(z);if(B?.resultType==="failed")return null;let $={};if(!Object.keys(B.paths).length){B.paths={[Q]:[`./${W?"src/":""}*`]},$.src=Q.replace(/\/\*$/,"");let Z=await V0.promises.readFile(B.configFileAbsolutePath,"utf-8"),v,j=/(?:\/\/\s*)?"paths":\s*\{(?:[^{}]|\{[^}]*\})*\}/;if(!j.test(Z))v=Z.replace(/"compilerOptions":\s*{/,`"compilerOptions": {
3
- "paths": ${JSON.stringify(B.paths)},`);else v=Z.replace(j,`"paths": ${JSON.stringify(B.paths)}`);let b=new A3,L=await s0(v,"json");return b.createSourceFile(B.configFileAbsolutePath,L,{overwrite:!0}),await b.save(),$}return $||null}function e0(z){let W=p0.sync(["vite.config.*"],{cwd:z,absolute:!0,onlyFiles:!0,ignore:P})?.[0];if(!W)return!1;try{let Q=V0.readFileSync(W,"utf-8");return D3(Q)}catch{return!1}}function D3(z){let W=z.replace(/\/\/.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,"");if(!["tailwindcss","@tailwindcss/vite","tailwind("].some((Z)=>W.includes(Z)))return!1;return["plugins:","postcss:","css:"].some((Z)=>W.includes(Z))}function S(){if("bun/1.2.18 npm/? node/v24.3.0 darwin arm64".startsWith("yarn"))return"yarn";if("bun/1.2.18 npm/? node/v24.3.0 darwin arm64".startsWith("pnpm"))return"pnpm";if("bun/1.2.18 npm/? node/v24.3.0 darwin arm64".startsWith("bun"))return"bun";return"npm"}function Y0(){switch(S()){case"yarn":return"yarn";case"pnpm":return"pnpx";case"bun":return"bunx";default:return"npx"}}function z3(){switch(S()){case"yarn":return"yarn dev";case"pnpm":return"pnpm dev";case"bun":return"bun dev";default:return"npm run dev"}}function L0(z){return z.replace(/^[ \t]*\/\/\s*(TODO:|collapse-(start|end)).*\r?\n?|[ \t]*{\s*\/\*\s*(TODO:|collapse-(start|end)).*?\*\/\s*}\r?\n?/gm,"")}var x3=k.join(E3.homedir(),".untitledui"),r=k.join(x3,"config.json"),X={components:[],path:"",type:void 0,license:""};if(F.existsSync(r)){let z=JSON.parse(F.readFileSync(r,"utf-8"));X.license=z.license}var Z0=(z)=>{if(z.aborted)process.stdout.write("\x1B[?25h"),process.stdout.write(`
3
+ "paths": ${JSON.stringify(B.paths)},`);else v=Z.replace(j,`"paths": ${JSON.stringify(B.paths)}`);let b=new A3,L=await s0(v,"json");return b.createSourceFile(B.configFileAbsolutePath,L,{overwrite:!0}),await b.save(),$}return $||null}function e0(z){let W=p0.sync(["vite.config.*"],{cwd:z,absolute:!0,onlyFiles:!0,ignore:P})?.[0];if(!W)return!1;try{let Q=V0.readFileSync(W,"utf-8");return D3(Q)}catch{return!1}}function D3(z){let W=z.replace(/\/\/.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,"");if(!["tailwindcss","@tailwindcss/vite","tailwind("].some((Z)=>W.includes(Z)))return!1;return["plugins:","postcss:","css:"].some((Z)=>W.includes(Z))}function S(){if("bun/1.2.20 npm/? node/v24.3.0 darwin arm64".startsWith("yarn"))return"yarn";if("bun/1.2.20 npm/? node/v24.3.0 darwin arm64".startsWith("pnpm"))return"pnpm";if("bun/1.2.20 npm/? node/v24.3.0 darwin arm64".startsWith("bun"))return"bun";return"npm"}function Y0(){switch(S()){case"yarn":return"yarn";case"pnpm":return"pnpx";case"bun":return"bunx";default:return"npx"}}function z3(){switch(S()){case"yarn":return"yarn dev";case"pnpm":return"pnpm dev";case"bun":return"bun dev";default:return"npm run dev"}}function L0(z){return z.replace(/^[ \t]*\/\/\s*(TODO:|collapse-(start|end)).*\r?\n?|[ \t]*{\s*\/\*\s*(TODO:|collapse-(start|end)).*?\*\/\s*}\r?\n?/gm,"")}var x3=k.join(E3.homedir(),".untitledui"),r=k.join(x3,"config.json"),X={components:[],path:"",type:void 0,license:""};if(F.existsSync(r)){let z=JSON.parse(F.readFileSync(r,"utf-8"));X.license=z.license}var Z0=(z)=>{if(z.aborted)process.stdout.write("\x1B[?25h"),process.stdout.write(`
4
4
  `),process.exit(1)},W3=new _3().name("add").description("add a component to your project").argument("[components...]","the components to add").option("-a, --all","add all available components",!1).option("-o, --overwrite","overwrite existing files.",!1).option("-p, --path <path>","the path to add the component to.").option("-d, --dir <directory>","the directory where the project is located.").option("-t, --type <base|marketing|shared-assets|application|foundations>","the type of the component to add.").action(async(z,W)=>{if(z)X.components=z;if(W)X.all=W.all,X.dir=W.dir,X.path=W.path,X.overwrite=W.overwrite,X.license=W.license||X.license;try{await y0(X)}catch(Q){console.error(y.red(Q))}});async function y0(z){if(z)X={...X,...z};let W=B0().start(),Q=k.posix.join(process.cwd(),X.dir||"");if(!F.existsSync(k.resolve(Q,"package.json")))W.warn("This command should be run in a project directory."),process.exit(1);let $=await z0(Q);if(X.license){if(!await K0(X.license))W.fail("Invalid license key"),process.exit(1);if(!F.existsSync(r)){let V=k.dirname(r);F.mkdirSync(V,{recursive:!0}),F.writeFileSync(r,JSON.stringify({license:X.license},null,2))}if(JSON.parse(F.readFileSync(r,"utf-8")).license!==X.license)F.writeFileSync(r,JSON.stringify({license:X.license},null,2),"utf-8")}if(W.stop(),!$?.tailwind.brandColor)console.log(y.red("The project does not seem to be configured with Untitled UI Tailwind. Please follow the setup instructions in the documentation: https://www.untitledui.com/react/docs or run init command.")),process.exit(1);let Z=[];if(X.components.length){let Y=await J0(X.type,X.components,X.license);if(Y&&Y.pro&&Y.pro.length>0){if(console.log(),Y.pro.length===1){let q=Y.pro[0]?.split("/")[1]||Y.pro[0];console.log(y.yellow(`\uD83D\uDD12 The ${y.cyan(q)} component requires PRO access.`))}else console.log(y.yellow("\uD83D\uDD12 The following components require PRO access:")),Y.pro.forEach((q)=>{let V=q?.split("/")[1]||q;console.log(` • ${y.cyan(V)}`)});console.log(),console.log("To access PRO components:"),console.log(` ${y.green("→")} If you've already purchased: ${y.cyan(`${Y0()} untitledui@latest login`)}`),console.log(` ${y.green("→")} To purchase PRO components: ${y.cyan("https://www.untitledui.com/buy/react")}`),console.log(),process.exit(1)}if(!Y?.components.length)console.log("No components found"),process.exit(1);Z.push(...Y.components)}if(!X?.type&&!X?.components.length){let Y=await a0(X.license);if(!Y)console.log("No component types found"),process.exit(1);let q=await s({type:"select",name:"type",onState:Z0,message:`What type of ${y.cyan("component")} are you adding?`,choices:Y?.types.map((V)=>({title:V,value:V}))});X.type=q.type}if(!X?.path){let Y=await s({type:"text",name:"path",onState:Z0,message:`Where would you like to add the ${y.cyan("components")}?`,initial:"components"});X.path=Y.path}if($&&!Object.keys($?.aliases).length){let Y=/^[^*"]+\/\*\s*$/,q=await s({type:"text",name:"aliasPrefix",onState:Z0,initial:"@/*",message:`What is the ${y.cyan("import alias")} for your project?`,validate:(V)=>Y.test(V)?!0:"Import alias must follow the pattern <prefix>/*"});$.aliases=await o0(Q,$?.isSrcDir,q?.aliasPrefix)}if(!X?.components.length){let Y=await l0(X?.type,X.license);if(!Y)console.log("No components found"),process.exit(1);let q=await s({type:"multiselect",name:"components",onState:Z0,message:`Which ${y.cyan("components")} would you like to add?`,choices:Y?.components?.map((G)=>({title:G?.name+(G?.count?` (${G?.count} variants)`:"")||"example",value:G||"example",selected:X.components.includes(G.name)})),instructions:!1,hint:"- Space to select. Return to submit"});if(!q.components||!q.components.length)console.log("No option selected. Exiting..."),process.exit(1);let V=q.components.filter((G)=>G?.type==="file").map((G)=>G.name),N=q.components.filter((G)=>G?.type==="dir").map((G)=>G.name),T=[];if(N.length){let G=await c0(X?.type,X.license,N);if(G&&G.components.length)for(let R of G.components){let[D,C]=Object.entries(R)[0]||[],w=await s({type:"select",name:"component",onState:Z0,message:`Which ${y.cyan("variant")} from ${y.cyan(D)} would you like to add?`,choices:C?.map((h)=>({title:h?.name.replace(/-modal/g,"")||"example",value:h?.name||"example",selected:X.components.includes(h.name)})),instructions:!1,hint:"- Space to select. Return to submit"});if(!w.component)console.log("No variant selected for "+y.cyan(D));T.push(D+"/"+w.component)}else console.log("No variants found")}X.components=[...T,...V]}if(!X.components?.length)W.warn("No components selected. Exiting."),process.exit(1);let v=Q0(Q),j=new Set,J=new Set,b=new Set,L=new T3({tsConfigFilePath:v?.tsConfig});if(W.start(),X.type&&X.components.length){let Y=await J0(X.type,X.components,X.license);if(!Y?.components.length)console.log("No components found"),process.exit(1);Z.push(...Y.components)}let M=new Set;if(Z.forEach((Y)=>{Y?.components?.forEach((q)=>{M.add({name:q.name,path:q.path})})}),W.stop(),M.size){let Y=Array.from(M).filter((q)=>!F.existsSync(k.posix.join(Q,`${$?.isSrcDir?"src":""}`,q?.path?.replace(/components\//,X.path+"/"))));if(Y?.length){let q=await s({type:"multiselect",name:"baseComponents",onState:Z0,message:"Select which base components you want to add",choices:Y.map((V)=>({title:V?.name,value:V?.name,selected:!0})),instructions:!1,hint:"- Space to select. Return to submit"});if(X.baseComponents=q.baseComponents,!Y.length&&!q.baseComponents?.length)W.warn("No components selected")}}if(W.start(),X?.baseComponents?.length){let Y=await J0("",X.baseComponents,X.license);if(!Y||!Y?.components.length)console.log("No base components found");else Z.push(...Y.components)}if(W.stop(),Z.forEach((Y)=>{let q=B0(`Adding ${Y.name}...`).start(),V=Y.files;Y?.dependencies?.forEach((N)=>J.add(N)),Y?.devDependencies?.forEach((N)=>b.add(N));try{if(V?.forEach(async({path:N,code:T})=>{let G=k.posix.join(Q,`${$?.isSrcDir?"src":""}`,N.replace(/components\//,X.path+"/")),R=$?.framework==="vite"?T.replace(`"use client";
5
5
 
6
6
  `,""):T,D=L0(R),C=k.dirname(G);if(F.existsSync(G)&&!X.overwrite){if(F.readFileSync(G,"utf-8")!==D)j.add({code:D,path:G})}else{F.mkdirSync(C,{recursive:!0}),F.writeFileSync(G,D);let w=L.addSourceFileAtPath(k.resolve(G));w.getImportDeclarations().forEach((h)=>{let O=h.getModuleSpecifierValue();h.setModuleSpecifier(W0(O,X.path,$?.aliases))}),await w.save()}}),j.size)q.warn(`Some files of ${y.yellow(Y.name)} already exist`);else q.succeed(`${y.green(Y.name)} is added successfully`)}catch(N){q.fail(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "untitledui",
3
- "version": "0.1.44-beta.2",
3
+ "version": "0.1.45-beta.0",
4
4
  "main": "dist/index.mjs",
5
5
  "description": "The Untitled UI CLI tool helps you quickly scaffold projects with Untitled UI React and add components and page examples to your existing projects with an interactive interface in seconds.",
6
6
  "type": "module",