love-ui 1.2.13 → 1.2.14
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.
- package/dist/index.js +8 -7
- package/dist/mcp-server.js +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{spawnSync as
|
|
2
|
+
import{spawnSync as tt}from"child_process";import{existsSync as g}from"fs";import{cp as et,mkdir as O,readdir as nt,readFile as P,writeFile as I}from"fs/promises";import st from"os";import o from"path";import{pathToFileURL as it,fileURLToPath as rt}from"url";var ot=o.dirname(rt(import.meta.url)),at=o.resolve(ot,".."),F=o.join(at,"packages"),lt=new Set([".ts",".tsx",".cts",".mts",".js",".jsx",".css",".scss",".sass",".mdx",".md"]),G=new Set(["node_modules","dist",".turbo",".next","build",".cache"]),K=new Set(["accordion","alert","alert-dialog","autocomplete","avatar","badge","breadcrumb","button","card","checkbox","checkbox-group","collapsible","combobox","command","dialog","empty","field","fieldset","form","frame","group","input","label","menu","meter","number-field","pagination","popover","preview-card","progress","radio-group","scroll-area","select","separator","sheet","skeleton","slider","switch","table","tabs","textarea","toast","toggle","toggle-group","toolbar","tooltip"]),ct=[".ts",".tsx",".js",".jsx"],Y=/(^|\/)lib\/utils(?:\.[a-z]+)?$/i,ut=/@loveui\/ui\/lib\/utils|@loveui\/shadcn-ui\/lib\/utils|@love-ui\/shadcn-ui\/lib\/utils|@\/lib\/utils|~\/lib\/utils|(?:\.\.\/)+ui\/src\/lib\/utils/,gt=`import { clsx, type ClassValue } from "clsx"
|
|
3
3
|
import { twMerge } from "tailwind-merge"
|
|
4
4
|
|
|
5
5
|
export function cn(...inputs: ClassValue[]) {
|
|
6
6
|
return twMerge(clsx(inputs))
|
|
7
7
|
}
|
|
8
|
-
`;function
|
|
9
|
-
Installing dependencies...`);let r=t.map(([
|
|
8
|
+
`;function A(e){if(!e)return e;let n=e.split("/");return n[n.length-1]||e}function q(e){let n=e.trim();return n&&((n.startsWith("@/")||n.startsWith("~/"))&&(n=`src/${n.slice(2)}`),n.startsWith("/")&&(n=n.slice(1)),n=n.replace(/^\.\//,""),n=n.replace(/\/+$/,""),n)}function pt(e){return e.trim().replace(/\/+$/,"")}function v(e){return e.replace(/\.(?:ts|tsx|js|jsx)$/i,"")}function X(e){let n=v(e);return ct.map(s=>`${n}${s}`)}function ft(e){let n=e.replace(/\/+$/,"");return n==="src"||n.startsWith("src/")?"src":n==="app"||n.startsWith("app/")?"app":null}function B(e){let n=A(e);return n==="ui"?"love-ui":n}function dt(e){let n=e.loveui??{},s=typeof n.target=="string"?n.target.trim():"",t=n.category;if(s){let r=typeof n.includePackageName=="boolean"?n.includePackageName:!1;return{base:s.replace(/\/+$/,""),includePackageName:r}}return t==="feature"?{base:"components",includePackageName:!0}:t==="block"?{base:"components/blocks",includePackageName:!0}:{base:"components/ui",includePackageName:!0}}function mt(e,n,s){let t=e.startsWith("src/")?e.slice(4):e;if(!n.includePackageName){let p=n.base.split("/").filter(Boolean),u=p[p.length-1];u&&t.startsWith(`${u}/`)&&(t=t.slice(u.length+1))}let a=`${(n.includePackageName?`${n.base}/${s}`:n.base).replace(/\/+/g,"/")}/${t}`.replace(/\/+/g,"/");return{cleanedPath:t,target:a}}async function ht(e){let n=o.join(e,"components.json");try{let s=await P(n,"utf8");return JSON.parse(s).aliases??null}catch{return null}}async function yt(e){let n=["tsconfig.json","jsconfig.json"].map(s=>o.join(e,s)).find(s=>g(s));if(!n)return null;try{let s=await P(n,"utf8"),r=JSON.parse(s).compilerOptions?.paths;return!r||typeof r!="object"?null:r}catch{return null}}function bt(e,n){if(typeof e=="string"){if(e.trim().startsWith("~/"))return"~/";if(e.trim().startsWith("@/"))return"@/"}if(n){if(Object.prototype.hasOwnProperty.call(n,"~/*"))return"~/";if(Object.prototype.hasOwnProperty.call(n,"@/*"))return"@/"}return"@/"}async function $t(e,n,s){if(n&&n.length>0)return n;let t=["src/components/ui","app/components/ui","components/ui"];for(let i of t)if(g(o.join(e,i)))return i.replace(/\/ui$/,"");let r=["src/components","app/components","components"];for(let i of r)if(g(o.join(e,i)))return i;if(s){let i=s["@/*"]??s["~/*"]??[];if(Array.isArray(i)&&i.some(a=>/^\.?\/?src\//.test(a)))return"src/components";if(Array.isArray(i)&&i.some(a=>/^\.?\/?app\//.test(a)))return"app/components"}return g(o.join(e,"src"))?"src/components":g(o.join(e,"app"))?"app/components":"components"}async function wt(e,n,s,t){let r=t?.utils??(t?.lib?`${t.lib.replace(/\/+$/,"")}/utils`:void 0);if(r&&r.trim().length>0){let u=v(pt(r)),f=v(q(r));for(let w of X(f))if(g(o.join(e,w)))return{utilsImportPath:u,utilsFilePath:w};return{utilsImportPath:u,utilsFilePath:`${f}.ts`}}let i=ft(n),a=i?`${i}/lib/utils`:"lib/utils",p=Array.from(new Set([a,"src/lib/utils","app/lib/utils","lib/utils"]));for(let u of p)for(let f of X(u))if(g(o.join(e,f)))return{utilsImportPath:`${s}lib/utils`,utilsFilePath:f};return{utilsImportPath:`${s}lib/utils`,utilsFilePath:`${a}.ts`}}function V(e,n,s){let t=a=>{let p=a.startsWith("/"),u=a.endsWith("/"),f=a.split("/").filter(Boolean),w=[];for(let x of f)w[w.length-1]!==x&&w.push(x);let j=w.join("/");return`${p?"/":""}${j}${u?"/":""}`},r=n.replace(/\/+$/,""),i=e.replace(/^\.?\//,"");if(Y.test(i))return t(s);if(i.startsWith("components/")){let a=i.slice(10);return t(`${r}${a}`.replace(/^\//,""))}if(i.startsWith("lib/")){if(r.startsWith("src/"))return t(`src/${i}`);if(r.startsWith("app/"))return t(`app/${i}`)}if(i.startsWith("hooks/")){if(r.startsWith("src/"))return t(`src/${i}`);if(r.startsWith("app/"))return t(`app/${i}`)}return i.startsWith("ui/")?t(`${r}/${i}`):t(i)}function N(e,n){let s=n.startsWith("~/")?"~/":"@/",t=e;return t=t.replace(/@\/registry\/default\/components\//g,`${s}components/`),t=t.replace(/@\/registry\/default\/ui\//g,`${s}components/ui/`),t=t.replace(/@\/registry\/default\/hooks\//g,`${s}hooks/`),t=t.replace(/@\/registry\/default\/lib\//g,`${s}lib/`),t=t.replace(/@loveui\/ui\/ui\//g,`${s}components/ui/`),t=t.replace(/@loveui\/ui\/lib\//g,`${s}lib/`),t=t.replace(/@\/ui\//g,`${s}components/ui/`),t=t.replace(/@\/registry\/building-blocks\/default\/components\//g,`${s}components/`),t=t.replace(/@\/registry\/building-blocks\/default\/ui\//g,`${s}components/ui/`),t=t.replace(/@\/registry\/building-blocks\/default\/lib\//g,`${s}lib/`),t=t.replace(/@\/registry\/building-blocks\/default\/hooks\//g,`${s}hooks/`),t=t.replace(/@\/registry\/default\/components\//g,`${s}components/`),t=t.replace(/@\/registry\/default\/ui\//g,`${s}components/ui/`),t=t.replace(/@\/registry\/default\/lib\//g,`${s}lib/`),t=t.replace(/@\/registry\/default\/hooks\//g,`${s}hooks/`),t=t.replace(/from\s+["']@loveui\/ui\/lib\/utils["']/g,`from "${n}"`),t=t.replace(/from\s+["']@loveui\/shadcn-ui\/lib\/utils["']/g,`from "${n}"`),t=t.replace(/from\s+["']@love-ui\/shadcn-ui\/lib\/utils["']/g,`from "${n}"`),t=t.replace(/from\s+["']@\/lib\/utils["']/g,`from "${n}"`),t=t.replace(/from\s+["']~\/lib\/utils["']/g,`from "${n}"`),t=t.replace(/from\s+["'](?:\.\.\/)+ui\/src\/lib\/utils["']/g,`from "${n}"`),t}async function Pt(e,n){if(g(o.join(e,n)))return!1;let s=gt,t=o.join(F,"love-ui","src","lib","utils.ts");if(g(t))try{s=await P(t,"utf8")}catch{}return await z(n,e),await I(o.join(e,n),s,"utf8"),!0}async function z(e,n){let s=o.dirname(o.join(n,e));await O(s,{recursive:!0})}async function jt(e,n){let s=o.join(e,"package.json"),t={};try{let u=await P(s,"utf8");t=JSON.parse(u)}catch{}let r=dt(t),i=A(n),a=[];async function p(u,f){let w=await nt(u,{withFileTypes:!0});for(let j of w){if(G.has(j.name))continue;let x=o.join(u,j.name);if(j.isDirectory()){await p(x,f);continue}let C=o.extname(j.name);if(!lt.has(C)||j.name==="package.json")continue;let k=o.relative(f,x).split(o.sep).join("/"),{target:m}=mt(k,r,i),D=await P(x,"utf8");a.push({path:k,target:m,content:D})}}return await p(e,e),a}async function xt(e,n){let s=o.join(F,"love-ui"),t=o.join(s,"src","ui",`${e}.tsx`);if(!g(t))return null;try{let r=[],i=await P(t,"utf8");i=N(i,n),r.push({path:`src/ui/${e}.tsx`,target:`components/ui/${e}.tsx`,content:i});let a=o.join(s,"src","lib","utils.ts");if(g(a)){let p=await P(a,"utf8");r.push({path:"src/lib/utils.ts",target:"lib/utils.ts",content:p})}return r}catch(r){return console.warn(`Warning: unable to read ${e} component`,r),null}}async function kt(e,n){if(K.has(e))return await xt(e,n);let s=B(e),t=o.join(F,s);if(!g(t))return null;try{return await jt(t,e)}catch(r){return console.warn(`Warning: unable to read bundled sources for ${e}`,r),null}}async function Rt(e){let n=B(e),s=o.join(F,n);return!g(s)||!g(o.join(s,"SKILL.md"))?null:s}function Q(){let e=process.env.CODEX_HOME?.trim();return e||o.join(st.homedir(),".codex")}async function vt(e){let n=await Rt(e);if(!n)return"missing";let s=Q(),t=o.join(s,"skills"),r=A(e),i=o.join(t,r);return await O(t,{recursive:!0}),g(i)?"exists":(await et(n,i,{recursive:!0,force:!1,filter:a=>{let p=o.basename(a);return!G.has(p)}}),"installed")}var Ft={"@base-ui-components/react":"1.0.0-beta.4","class-variance-authority":"^0.7.1",clsx:"^2.1.1","tailwind-merge":"^3.3.1"};async function Ct(e){if(K.has(e))return{...Ft};let n=B(e),s=o.join(F,n,"package.json");try{let t=await P(s,"utf8");return JSON.parse(t).dependencies??{}}catch{return{}}}async function Dt(e){return g(o.join(e,"bun.lockb"))?"bun":g(o.join(e,"pnpm-lock.yaml"))?"pnpm":g(o.join(e,"yarn.lock"))?"yarn":"npm"}async function Tt(e,n,s){let t=Object.entries(e);if(t.length===0)return!0;console.log(`
|
|
9
|
+
Installing dependencies...`);let r=t.map(([p,u])=>`${p}@${u}`),i;switch(n){case"bun":i=`bun add ${r.join(" ")}`;break;case"pnpm":i=`pnpm add ${r.join(" ")}`;break;case"yarn":i=`yarn add ${r.join(" ")}`;break;default:i=`npm install ${r.join(" ")}`}let a=tt(i,{stdio:"inherit",shell:!0,cwd:s});return a.error||a.status!==0?(console.warn(`
|
|
10
10
|
Failed to install dependencies. You may need to install them manually:`),console.warn(` ${r.join(`
|
|
11
11
|
`)}`),!1):(console.log(`Dependencies installed successfully!
|
|
12
|
-
`),!0)}async function
|
|
13
|
-
Adding ${
|
|
14
|
-
Installing ${
|
|
15
|
-
\u2713 Done! You can now import and use the components in your app
|
|
12
|
+
`),!0)}async function St(e=process.argv.slice(2)){(e.length===0||e.length===1&&(e[0]==="--version"||e[0]==="-v"))&&(console.log("love-ui version 1.1.9"),process.exit(0)),(e.length<2||e[0]!=="add")&&(console.log("Usage: npx love-ui add [...packages]"),console.log(" npx love-ui --version"),process.exit(1));let n=e.slice(1),s=process.cwd(),t=await ht(s),r=await yt(s),i=t?.components?q(t.components):null,a=await $t(s,i,r),p=bt(t?.components,r),{utilsImportPath:u,utilsFilePath:f}=await wt(s,a,p,t),w=await Dt(s),j=a.endsWith("/ui")?a:`${a}/ui`,x=!1,C=!1,k={};for(let m of n){if(!m.trim())continue;console.log(`
|
|
13
|
+
Adding ${m}...`);let D=await vt(m);if(D==="installed"){console.log(`\u2713 Installed skill "${m}" to ${o.join(Q(),"skills",A(m))}`),console.log("Restart Codex to pick up new skills.");continue}if(D==="exists"){console.log(`\u2713 Skill "${m}" is already installed.`),console.log("Restart Codex if you do not see it yet.");continue}x||(await O(o.join(s,a),{recursive:!0}),await O(o.join(s,j),{recursive:!0}),x=!0),C=!0;let d=null,M=null;if(m.startsWith("http://")||m.startsWith("https://")){let l=m;l.includes("/building-blocks/r/")&&(l=l.replace("/building-blocks/r/","/building-blocks/"),console.log(`Auto-corrected URL to: ${l}`));try{let c=await fetch(l);c.ok?d=await c.json():console.warn(`Failed to fetch ${l}: HTTP ${c.status}`)}catch(c){console.warn(`Failed to fetch from ${l}:`,c)}}else{let l=new URL(`r/${m}.json`,"https://www.loveui.dev/");try{let c=await fetch(l);c.ok&&(d=await c.json())}catch{}M=await kt(m,u)}let R=M??d?.files??[];R=R.map(l=>{let c=l.target||l.path;return c.startsWith("registry/default/")&&(c=c.replace("registry/default/","")),{...l,target:c}});let T=R.find(l=>l.target.match(/^components\/comp-\d+\.tsx$/));if(T){let l=R.filter(c=>c.target.match(/^components\/[^/]+\//)&&c.target!==T.target);if(l.length>0&&l[0]){let c=l[0].target.match(/^components\/([^/]+)\//);if(c&&c[1]){let h=c[1];T.target=`components/${h}-demo.tsx`}}else if(d?.meta?.tags&&Array.isArray(d.meta.tags)&&d.meta.tags.length>0){let h=d.meta.tags.slice(0,2).filter(b=>b.length>0);if(h.length>0){let b=h.join("-").toLowerCase().replace(/\s+/g,"-");T.target=`components/${b}.tsx`}}}if(!R.length){console.warn(`Component "${m}" not found. Available components can be found at https://loveui.dev`);continue}R.some(l=>Y.test(l.target)||typeof l.content=="string"&&ut.test(l.content))&&await Pt(s,f);let S=0,U=0;for(let l of R){if(!l.content)continue;let c=V(l.target,a,f),h=o.join(s,c),b=g(h);if(v(c)===v(f)&&b)continue;let W=N(l.content,u);if(b)try{if(await P(h,"utf8")===W)continue}catch{}await z(c,s),await I(h,W,"utf8"),b?U++:S++}if(S>0&&console.log(`\u2713 Created ${S} file${S>1?"s":""}`),U>0&&console.log(`\u2713 Updated ${U} file${U>1?"s":""}`),d?.registryDependencies&&d.registryDependencies.length>0){console.log(`
|
|
14
|
+
Installing ${d.registryDependencies.length} required component${d.registryDependencies.length>1?"s":""}...`);for(let l of d.registryDependencies){let c=l;l.startsWith("https://loveui.dev/building-blocks/r/")&&(c=`https://ui.loveui.dev/ui/r/${l.split("/").pop()}`);try{let h=await fetch(c);if(h.ok){let b=await h.json(),W=(b?.files??[]).map(y=>{let $=y.target||y.path;return $.startsWith("registry/default/")&&($=$.replace("registry/default/","")),{...y,target:$}});for(let y of W){if(!y.content)continue;let $=V(y.target,a,f),L=o.join(s,$),J=g(L);if(v($)===v(f)&&J)continue;let H=N(y.content,u);if(J)try{if(await P(L,"utf8")===H)continue}catch{}await z($,s),await I(L,H,"utf8")}let _=["@loveui/shadcn-ui","jotai","lucide-react","react","react-dom"];if(b?.dependencies)if(Array.isArray(b.dependencies))b.dependencies.forEach(y=>{_.includes(y)||(k[y]="latest")});else{let y=b.dependencies;Object.keys(y).forEach($=>{!_.includes($)&&y[$]&&(k[$]=y[$])})}}else console.warn(` \u2717 Failed to fetch ${c}: HTTP ${h.status}`)}catch(h){console.warn(` \u2717 Failed to install ${c}:`,h.message)}}console.log("\u2713 Installed registry dependencies")}let E={};d?.dependencies?Array.isArray(d.dependencies)?d.dependencies.forEach(l=>{E[l]="latest"}):E=d.dependencies:E=await Ct(m),Object.assign(k,E)}Object.keys(k).length>0&&await Tt(k,w,s),console.log(C?`
|
|
15
|
+
\u2713 Done! You can now import and use the components in your app.`:`
|
|
16
|
+
\u2713 Done! Skill installation complete.`)}var Ut=process.argv[1]&&(import.meta.url===it(process.argv[1]).href||process.argv[1].includes("love-ui")||process.argv[1].includes("loveui"));Ut&&St().catch(e=>{console.error(e),process.exit(1)});export{St as run};
|
package/dist/mcp-server.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{constants as xe}from"fs";import{access as Te,readFile as Q}from"fs/promises";import p from"path";import{fileURLToPath as _e}from"url";import{Server as Ne}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as Oe}from"@modelcontextprotocol/sdk/server/stdio.js";import{CallToolRequestSchema as Ae,ErrorCode as d,ListResourceTemplatesRequestSchema as Ce,ListResourcesRequestSchema as Le,ListToolsRequestSchema as $e,McpError as l,ReadResourceRequestSchema as Fe}from"@modelcontextprotocol/sdk/types.js";var F={name:"love-ui",version:"1.2.12",private:!1,license:"AGPL-3.0-or-later",type:"module",bin:{loveui:"dist/index.js","love-ui":"dist/index.js","loveui-mcp":"dist/mcp-server.js"},files:["dist","packages","public","*.ts","*.tsx","*.css","*.mdx"],main:"packages/love-ui/index.ts",types:"packages/love-ui/index.ts",exports:{".":{import:"./packages/love-ui/index.ts",require:"./packages/love-ui/index.ts"},"./lib/*":"./packages/love-ui/*","./components/*":"./packages/love-ui/components/*","./shadcn-ui/*":"./packages/shadcn-ui/*","./package.json":"./package.json"},dependencies:{"@modelcontextprotocol/sdk":"^1.18.1",postcss:"^8.5.6","postcss-nested":"^7.0.2"},scripts:{build:"tsup",postbuild:"node ./scripts/copy-packages.mjs && node ./scripts/verify-registry.mjs","verify:registry":"node ./scripts/verify-registry.mjs",clean:"rimraf dist packages"},devDependencies:{"@types/node":"^20.14.10",rimraf:"^6.0.1",tsup:"^8.5.0"}};import{constants as me}from"fs";import{access as ue,readFile as U,readdir as W}from"fs/promises";import x,{extname as q,join as j,relative as ge}from"path";import{fileURLToPath as ye}from"url";import z from"postcss";import fe from"postcss-nested";var he=x.dirname(ye(import.meta.url)),ve=x.resolve(he,".."),G=x.join(ve,"packages"),we=new Set([".turbo",".next",".git","dist","build","storybook-static","node_modules","__tests__","__mocks__","coverage"]),Re=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".json",".css",".scss",".sass",".mdx"]),ke=new Set(["package.json","tsconfig.json","tsconfig.build.json","tsconfig.test.json","README.md",".DS_Store"]),Se=new Set(["shadcn-ui","typescript-config","patterns","loveui","love-ui"]),Ee=e=>e.replace(/\\/g,"/"),H=async(e,n,t)=>{let s=await W(e,{withFileTypes:!0});for(let r of s){let o=j(e,r.name);if(r.isDirectory()){if(we.has(r.name))continue;await H(o,n,t);continue}let a=q(r.name);!Re.has(a)||ke.has(r.name)||r.name.endsWith(".d.ts")||r.name.endsWith(".test.ts")||r.name.endsWith(".test.tsx")||r.name.endsWith(".stories.tsx")||t.push({absolute:o,relative:Ee(ge(n,o))})}},Ie=(e,n)=>{let t=e.loveui??{},s=typeof t.target=="string"?t.target.trim():"",r=t.category;if(s.length>0){let o=typeof t.includePackageName=="boolean"?t.includePackageName:!1;return{base:s.replace(/\/+$/,""),includePackageName:o}}return r==="feature"?{base:"components",includePackageName:!0}:r==="block"?{base:"components/blocks",includePackageName:!0}:{base:"components/ui",includePackageName:!0}},De=e=>{let t=(e.loveui??{}).type;return typeof t=="string"&&t.trim().length>0?t:"registry:ui"},Pe=async e=>{try{return await ue(e,me.F_OK),!0}catch{return!1}},b=e=>e.startsWith("@loveui/")||e.startsWith("@love-ui/")||e.startsWith("@repo/"),be=e=>e.replace(/^@repo\//,"").replace(/^@loveui\//,"").replace(/^@love-ui\//,""),je=new Set(["@loveui/shadcn-ui","@love-ui/shadcn-ui"]),M=async()=>(await W(G,{withFileTypes:!0})).filter(n=>n.isDirectory()).map(n=>n.name).filter(n=>!Se.has(n)).sort((n,t)=>n.localeCompare(t)),J=async e=>{let n=j(G,e),t=j(n,"package.json");if(!await Pe(t))throw new Error(`Missing package.json for ${e}`);let s=JSON.parse(await U(t,"utf8")),r=De(s),o=Object.keys(s.dependencies??{}),a=Object.keys(s.peerDependencies??{}),N=Object.keys(s.devDependencies??{}),oe=new Set([...o,...a,...N].filter(b).filter(i=>!je.has(i))),O=[...new Set([...o,...a].filter(i=>!b(i)))],A=[...new Set(N.filter(i=>!b(i)&&!["@loveui/typescript-config","@types/react","@types/react-dom","typescript"].includes(i)))],S=[];for(let i of oe){let h=be(i);S.push(`https://www.loveui.dev/r/${h}.json`)}let C=[];await H(n,n,C);let f=[],m={},g=Ie(s,e);for(let i of C){let h=await U(i.absolute,"utf8"),E=q(i.absolute);if(E===".css"||E===".scss"||E===".sass"){let v=await z([fe]).process(h,{from:void 0});z.parse(v.css).walkAtRules("layer",I=>{let D=`@layer ${I.params}`;m[D]??={},I.walkRules(c=>{if(c.parent&&c.parent.type==="atrule"&&c.parent.name==="media")return;let R=c.selector,u={};c.walkDecls(k=>{u[k.prop]=k.value}),Object.keys(u).length>0&&(m[D][R]=u)}),I.walkAtRules("media",c=>{let R=`@media ${c.params}`,u=m[D];u[R]??={};let k=u[R];c.walkRules(L=>{let pe=L.selector,P={};L.walkDecls($=>{P[$.prop]=$.value}),Object.keys(P).length>0&&(k[pe]=P)})})});continue}let y=i.relative.startsWith("src/")?i.relative.slice(4):i.relative;if(!g.includePackageName){let v=g.base.split("/").filter(Boolean),w=v[v.length-1];w&&y.startsWith(`${w}/`)&&(y=y.slice(w.length+1))}let ce=e.includes("/")?e.split("/").pop()??e:e,le=(g.includePackageName?`${g.base}/${ce}`:g.base).replace(/\/+$/,"");f.push({type:r,path:y,target:`${le}/${y}`.replace(/\/+/g,"/"),content:h})}let ae=!f.length&&Object.keys(m).length>0?"registry:style":r;return{$schema:"https://ui.shadcn.com/schema/registry-item.json",name:e,type:ae,title:s.title??e,description:s.description,author:s.author??"Connor Love <hello@loveconnor.com>",dependencies:O.length?O:void 0,devDependencies:A.length?A:void 0,registryDependencies:S.length?Array.from(new Set(S)):void 0,files:f.length?f:void 0,css:Object.keys(m).length?m:void 0}};var _="loveui://registry/",Ue="loveui://registry/{package}",K="get-loveui-package",Z=new Set(["shadcn-ui","typescript-config","eslint-config","patterns","loveui","love-ui"]),ze=["@loveui/","@love-ui/","@repo/"],ee=new Set(["@loveui/shadcn-ui","@love-ui/shadcn-ui"]),We=e=>`${_}${e}`,qe=p.dirname(_e(import.meta.url)),X=p.resolve(qe,".."),Ge=[p.join(X,"public","r"),p.resolve(X,"..","..","apps","ui","public","r"),p.resolve(process.cwd(),"apps","ui","public","r")],te=async e=>{try{return await Te(e,xe.R_OK),!0}catch{return!1}},ne=e=>ze.some(n=>e.startsWith(n)),He=e=>e.replace(/^@repo\//,"").replace(/^@loveui\//,"").replace(/^@love-ui\//,""),se=e=>Array.isArray(e)?e.filter(n=>typeof n=="string"):e&&typeof e=="object"?Object.keys(e):[],B=e=>{let n=Array.from(new Set(se(e).filter(t=>!ne(t)&&!ee.has(t))));return n.length>0?n:void 0},Me=e=>{let n=Array.from(new Set(se(e).map(t=>t.trim()).filter(Boolean).filter(t=>!ee.has(t)).map(t=>ne(t)?`https://www.loveui.dev/r/${He(t)}.json`:t)));return n.length>0?n:void 0},re=e=>e.trim().replace(/^@repo\//,"").replace(/^@loveui\//,"").replace(/^@love-ui\//,""),Je=e=>{let n=re(e);if(Z.has(n))throw new l(d.InvalidParams,`${n} is an internal package and should not be used directly. Use \`npx love-ui add <component>\` with a public component name.`);return n},Y=e=>{if(!e||typeof e!="object")return{mcpHints:{installPattern:"npx love-ui add <component>",neverInstall:["@loveui/*","@love-ui/*","@repo/*"]}};let n={...e},t=B(n.dependencies),s=B(n.devDependencies),r=Me(n.registryDependencies),o=typeof n.name=="string"&&n.name.trim().length>0?n.name.trim():"<component>",a={...n,mcpHints:{installPattern:"npx love-ui add <component>",installCommand:`npx love-ui add ${o}`,neverInstall:["@loveui/*","@love-ui/*","@repo/*","@loveui/shadcn-ui"]}};return t?a.dependencies=t:delete a.dependencies,s?a.devDependencies=s:delete a.devDependencies,r?a.registryDependencies=r:delete a.registryDependencies,a},T=null,ie=async()=>(T||(T=(async()=>{for(let e of Ge){let n=p.join(e,"registry.json");if(await te(n))try{let t=JSON.parse(await Q(n,"utf8")),s=Array.from(new Set((t.items??[]).map(r=>r.name?.trim()).filter(r=>!!r))).sort((r,o)=>r.localeCompare(o));if(s.length===0)continue;return{dir:e,names:s,nameSet:new Set(s)}}catch{continue}}return null})()),T),Ke=async()=>{let[e,n]=await Promise.all([ie(),M()]),t=new Set(n);for(let s of e?.names??[])t.add(s);return Array.from(t).map(s=>re(s)).filter(s=>!Z.has(s)).sort((s,r)=>s.localeCompare(r))},Xe=async e=>{let n=await ie();if(!n||!n.nameSet.has(e))return null;let t=p.join(n.dir,`${e}.json`);return await te(t)?JSON.parse(await Q(t,"utf8")):null},Be=e=>{if(!e.startsWith(_))throw new l(d.InvalidParams,`Unsupported resource URI: ${e}`);let n=decodeURIComponent(e.slice(_.length)).trim();if(!n)throw new l(d.InvalidParams,"Package name is required.");return n},V=async e=>{let n=Je(e);try{let t=await Xe(n);return Y(t||await J(n))}catch(t){throw t instanceof l?t:t instanceof Error&&t.message.startsWith(`Missing package.json for ${n}`)?new l(d.InvalidParams,`Registry item "${n}" was not found. Call resources/list and use an exact item name from the registry.`):new l(d.InvalidParams,t instanceof Error?t.message:String(t))}};async function Ye(){let e=new Ne({name:"loveui-mcp",version:F.version??"0.0.0"},{capabilities:{resources:{listChanged:!0},tools:{listChanged:!0}}});e.setRequestHandler(Le,async()=>({resources:(await Ke()).map(s=>({uri:We(s),name:s,description:`loveui registry definition for ${s}`,mimeType:"application/json"}))})),e.setRequestHandler(Ce,async()=>({resourceTemplates:[{name:"loveui-registry",uriTemplate:Ue,description:"loveui registry definitions by package name",mimeType:"application/json"}]})),e.setRequestHandler(Fe,async t=>{let s=Be(t.params.uri),r=await V(s);return{contents:[{uri:t.params.uri,mimeType:"application/json",text:JSON.stringify(r,null,2)}]}}),e.setRequestHandler($e,async()=>({tools:[{name:K,description:"Fetch a loveui registry definition by package name. Always install with `npx love-ui add <component>` and never install @loveui/* packages directly.",inputSchema:{type:"object",additionalProperties:!1,properties:{name:{type:"string",description:"Package name, e.g. badge"}},required:["name"]}}]})),e.setRequestHandler(Ae,async t=>{if(t.params.name!==K)throw new l(d.InvalidParams,`Tool ${t.params.name} not found`);let s=t.params.arguments?.name;if(typeof s!="string"||s.trim()==="")throw new l(d.InvalidParams,"Package name is required.");let r=await V(s.trim());return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}});let n=new Oe;await e.connect(n)}Ye().catch(e=>{console.error(e),process.exit(1)});
|
|
2
|
+
import{constants as xe}from"fs";import{access as Te,readFile as Q}from"fs/promises";import p from"path";import{fileURLToPath as _e}from"url";import{Server as Ne}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as Oe}from"@modelcontextprotocol/sdk/server/stdio.js";import{CallToolRequestSchema as Ae,ErrorCode as d,ListResourceTemplatesRequestSchema as Ce,ListResourcesRequestSchema as Le,ListToolsRequestSchema as $e,McpError as l,ReadResourceRequestSchema as Fe}from"@modelcontextprotocol/sdk/types.js";var F={name:"love-ui",version:"1.2.14",private:!1,license:"AGPL-3.0-or-later",type:"module",bin:{loveui:"dist/index.js","love-ui":"dist/index.js","loveui-mcp":"dist/mcp-server.js"},files:["dist","packages","public","*.ts","*.tsx","*.css","*.mdx"],main:"packages/love-ui/index.ts",types:"packages/love-ui/index.ts",exports:{".":{import:"./packages/love-ui/index.ts",require:"./packages/love-ui/index.ts"},"./lib/*":"./packages/love-ui/*","./components/*":"./packages/love-ui/components/*","./shadcn-ui/*":"./packages/shadcn-ui/*","./package.json":"./package.json"},dependencies:{"@modelcontextprotocol/sdk":"^1.18.1",postcss:"^8.5.6","postcss-nested":"^7.0.2"},scripts:{build:"tsup",postbuild:"node ./scripts/copy-packages.mjs && node ./scripts/verify-registry.mjs","verify:registry":"node ./scripts/verify-registry.mjs",clean:"rimraf dist packages"},devDependencies:{"@types/node":"^20.14.10",rimraf:"^6.0.1",tsup:"^8.5.0"}};import{constants as me}from"fs";import{access as ue,readFile as U,readdir as W}from"fs/promises";import x,{extname as q,join as j,relative as ge}from"path";import{fileURLToPath as ye}from"url";import z from"postcss";import fe from"postcss-nested";var he=x.dirname(ye(import.meta.url)),ve=x.resolve(he,".."),G=x.join(ve,"packages"),we=new Set([".turbo",".next",".git","dist","build","storybook-static","node_modules","__tests__","__mocks__","coverage"]),Re=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".json",".css",".scss",".sass",".mdx"]),ke=new Set(["package.json","tsconfig.json","tsconfig.build.json","tsconfig.test.json","README.md",".DS_Store"]),Se=new Set(["shadcn-ui","typescript-config","patterns","loveui","love-ui"]),Ee=e=>e.replace(/\\/g,"/"),H=async(e,n,t)=>{let s=await W(e,{withFileTypes:!0});for(let r of s){let o=j(e,r.name);if(r.isDirectory()){if(we.has(r.name))continue;await H(o,n,t);continue}let a=q(r.name);!Re.has(a)||ke.has(r.name)||r.name.endsWith(".d.ts")||r.name.endsWith(".test.ts")||r.name.endsWith(".test.tsx")||r.name.endsWith(".stories.tsx")||t.push({absolute:o,relative:Ee(ge(n,o))})}},Ie=(e,n)=>{let t=e.loveui??{},s=typeof t.target=="string"?t.target.trim():"",r=t.category;if(s.length>0){let o=typeof t.includePackageName=="boolean"?t.includePackageName:!1;return{base:s.replace(/\/+$/,""),includePackageName:o}}return r==="feature"?{base:"components",includePackageName:!0}:r==="block"?{base:"components/blocks",includePackageName:!0}:{base:"components/ui",includePackageName:!0}},De=e=>{let t=(e.loveui??{}).type;return typeof t=="string"&&t.trim().length>0?t:"registry:ui"},Pe=async e=>{try{return await ue(e,me.F_OK),!0}catch{return!1}},b=e=>e.startsWith("@loveui/")||e.startsWith("@love-ui/")||e.startsWith("@repo/"),be=e=>e.replace(/^@repo\//,"").replace(/^@loveui\//,"").replace(/^@love-ui\//,""),je=new Set(["@loveui/shadcn-ui","@love-ui/shadcn-ui"]),M=async()=>(await W(G,{withFileTypes:!0})).filter(n=>n.isDirectory()).map(n=>n.name).filter(n=>!Se.has(n)).sort((n,t)=>n.localeCompare(t)),J=async e=>{let n=j(G,e),t=j(n,"package.json");if(!await Pe(t))throw new Error(`Missing package.json for ${e}`);let s=JSON.parse(await U(t,"utf8")),r=De(s),o=Object.keys(s.dependencies??{}),a=Object.keys(s.peerDependencies??{}),N=Object.keys(s.devDependencies??{}),oe=new Set([...o,...a,...N].filter(b).filter(i=>!je.has(i))),O=[...new Set([...o,...a].filter(i=>!b(i)))],A=[...new Set(N.filter(i=>!b(i)&&!["@loveui/typescript-config","@types/react","@types/react-dom","typescript"].includes(i)))],S=[];for(let i of oe){let h=be(i);S.push(`https://www.loveui.dev/r/${h}.json`)}let C=[];await H(n,n,C);let f=[],m={},g=Ie(s,e);for(let i of C){let h=await U(i.absolute,"utf8"),E=q(i.absolute);if(E===".css"||E===".scss"||E===".sass"){let v=await z([fe]).process(h,{from:void 0});z.parse(v.css).walkAtRules("layer",I=>{let D=`@layer ${I.params}`;m[D]??={},I.walkRules(c=>{if(c.parent&&c.parent.type==="atrule"&&c.parent.name==="media")return;let R=c.selector,u={};c.walkDecls(k=>{u[k.prop]=k.value}),Object.keys(u).length>0&&(m[D][R]=u)}),I.walkAtRules("media",c=>{let R=`@media ${c.params}`,u=m[D];u[R]??={};let k=u[R];c.walkRules(L=>{let pe=L.selector,P={};L.walkDecls($=>{P[$.prop]=$.value}),Object.keys(P).length>0&&(k[pe]=P)})})});continue}let y=i.relative.startsWith("src/")?i.relative.slice(4):i.relative;if(!g.includePackageName){let v=g.base.split("/").filter(Boolean),w=v[v.length-1];w&&y.startsWith(`${w}/`)&&(y=y.slice(w.length+1))}let ce=e.includes("/")?e.split("/").pop()??e:e,le=(g.includePackageName?`${g.base}/${ce}`:g.base).replace(/\/+$/,"");f.push({type:r,path:y,target:`${le}/${y}`.replace(/\/+/g,"/"),content:h})}let ae=!f.length&&Object.keys(m).length>0?"registry:style":r;return{$schema:"https://ui.shadcn.com/schema/registry-item.json",name:e,type:ae,title:s.title??e,description:s.description,author:s.author??"Connor Love <hello@loveconnor.com>",dependencies:O.length?O:void 0,devDependencies:A.length?A:void 0,registryDependencies:S.length?Array.from(new Set(S)):void 0,files:f.length?f:void 0,css:Object.keys(m).length?m:void 0}};var _="loveui://registry/",Ue="loveui://registry/{package}",K="get-loveui-package",Z=new Set(["shadcn-ui","typescript-config","eslint-config","patterns","loveui","love-ui"]),ze=["@loveui/","@love-ui/","@repo/"],ee=new Set(["@loveui/shadcn-ui","@love-ui/shadcn-ui"]),We=e=>`${_}${e}`,qe=p.dirname(_e(import.meta.url)),X=p.resolve(qe,".."),Ge=[p.join(X,"public","r"),p.resolve(X,"..","..","apps","ui","public","r"),p.resolve(process.cwd(),"apps","ui","public","r")],te=async e=>{try{return await Te(e,xe.R_OK),!0}catch{return!1}},ne=e=>ze.some(n=>e.startsWith(n)),He=e=>e.replace(/^@repo\//,"").replace(/^@loveui\//,"").replace(/^@love-ui\//,""),se=e=>Array.isArray(e)?e.filter(n=>typeof n=="string"):e&&typeof e=="object"?Object.keys(e):[],B=e=>{let n=Array.from(new Set(se(e).filter(t=>!ne(t)&&!ee.has(t))));return n.length>0?n:void 0},Me=e=>{let n=Array.from(new Set(se(e).map(t=>t.trim()).filter(Boolean).filter(t=>!ee.has(t)).map(t=>ne(t)?`https://www.loveui.dev/r/${He(t)}.json`:t)));return n.length>0?n:void 0},re=e=>e.trim().replace(/^@repo\//,"").replace(/^@loveui\//,"").replace(/^@love-ui\//,""),Je=e=>{let n=re(e);if(Z.has(n))throw new l(d.InvalidParams,`${n} is an internal package and should not be used directly. Use \`npx love-ui add <component>\` with a public component name.`);return n},Y=e=>{if(!e||typeof e!="object")return{mcpHints:{installPattern:"npx love-ui add <component>",neverInstall:["@loveui/*","@love-ui/*","@repo/*"]}};let n={...e},t=B(n.dependencies),s=B(n.devDependencies),r=Me(n.registryDependencies),o=typeof n.name=="string"&&n.name.trim().length>0?n.name.trim():"<component>",a={...n,mcpHints:{installPattern:"npx love-ui add <component>",installCommand:`npx love-ui add ${o}`,neverInstall:["@loveui/*","@love-ui/*","@repo/*","@loveui/shadcn-ui"]}};return t?a.dependencies=t:delete a.dependencies,s?a.devDependencies=s:delete a.devDependencies,r?a.registryDependencies=r:delete a.registryDependencies,a},T=null,ie=async()=>(T||(T=(async()=>{for(let e of Ge){let n=p.join(e,"registry.json");if(await te(n))try{let t=JSON.parse(await Q(n,"utf8")),s=Array.from(new Set((t.items??[]).map(r=>r.name?.trim()).filter(r=>!!r))).sort((r,o)=>r.localeCompare(o));if(s.length===0)continue;return{dir:e,names:s,nameSet:new Set(s)}}catch{continue}}return null})()),T),Ke=async()=>{let[e,n]=await Promise.all([ie(),M()]),t=new Set(n);for(let s of e?.names??[])t.add(s);return Array.from(t).map(s=>re(s)).filter(s=>!Z.has(s)).sort((s,r)=>s.localeCompare(r))},Xe=async e=>{let n=await ie();if(!n||!n.nameSet.has(e))return null;let t=p.join(n.dir,`${e}.json`);return await te(t)?JSON.parse(await Q(t,"utf8")):null},Be=e=>{if(!e.startsWith(_))throw new l(d.InvalidParams,`Unsupported resource URI: ${e}`);let n=decodeURIComponent(e.slice(_.length)).trim();if(!n)throw new l(d.InvalidParams,"Package name is required.");return n},V=async e=>{let n=Je(e);try{let t=await Xe(n);return Y(t||await J(n))}catch(t){throw t instanceof l?t:t instanceof Error&&t.message.startsWith(`Missing package.json for ${n}`)?new l(d.InvalidParams,`Registry item "${n}" was not found. Call resources/list and use an exact item name from the registry.`):new l(d.InvalidParams,t instanceof Error?t.message:String(t))}};async function Ye(){let e=new Ne({name:"loveui-mcp",version:F.version??"0.0.0"},{capabilities:{resources:{listChanged:!0},tools:{listChanged:!0}}});e.setRequestHandler(Le,async()=>({resources:(await Ke()).map(s=>({uri:We(s),name:s,description:`loveui registry definition for ${s}`,mimeType:"application/json"}))})),e.setRequestHandler(Ce,async()=>({resourceTemplates:[{name:"loveui-registry",uriTemplate:Ue,description:"loveui registry definitions by package name",mimeType:"application/json"}]})),e.setRequestHandler(Fe,async t=>{let s=Be(t.params.uri),r=await V(s);return{contents:[{uri:t.params.uri,mimeType:"application/json",text:JSON.stringify(r,null,2)}]}}),e.setRequestHandler($e,async()=>({tools:[{name:K,description:"Fetch a loveui registry definition by package name. Always install with `npx love-ui add <component>` and never install @loveui/* packages directly.",inputSchema:{type:"object",additionalProperties:!1,properties:{name:{type:"string",description:"Package name, e.g. badge"}},required:["name"]}}]})),e.setRequestHandler(Ae,async t=>{if(t.params.name!==K)throw new l(d.InvalidParams,`Tool ${t.params.name} not found`);let s=t.params.arguments?.name;if(typeof s!="string"||s.trim()==="")throw new l(d.InvalidParams,"Package name is required.");let r=await V(s.trim());return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}});let n=new Oe;await e.connect(n)}Ye().catch(e=>{console.error(e),process.exit(1)});
|