@jongh/cli 1.6.0 → 1.6.1
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/README.md +38 -0
- package/dist/index.js +7 -7
- package/package.json +2 -1
package/README.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
## ⚡ 주요 기능
|
|
2
|
+
|
|
3
|
+
### init
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx @jongh/cli init
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
- primary / secondary / grey color를 입력받아, 컴포넌트 스타일의 기반이 될 preset을 생성합니다
|
|
10
|
+
- 사용자의 경로 설정 파일을 분석하여 이후 코드가 저장될 장소를 components.json이라는 파일에 저장합니다
|
|
11
|
+
|
|
12
|
+
### add
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx @jongh/cli add [component-name]
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
- 원격 Registry에서 컴포넌트 코드를 가져와 components.json에 명시된 경로에 저장합니다
|
|
19
|
+
- ui 코드 뿐 아니라 hook,util 등의 코드도 같이 저장될 수 있습니다
|
|
20
|
+
|
|
21
|
+
### codemod: radix-ui-import
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx @jongh/cli radix-ui-import
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
- 최근 변경된 Radix UI의 설치 방식에 맞게 기존 코드를 자동으로 변환합니다
|
|
28
|
+
- 기존에 사용하던 import statement 방식에 따라 변경사항이 다를 수 있습니다
|
|
29
|
+
|
|
30
|
+
**변환 예시:**
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
// before
|
|
34
|
+
import * as AccordionPrimitive from "@radix-ui/react-accordion"
|
|
35
|
+
|
|
36
|
+
// after
|
|
37
|
+
import { Accordion as AccordionPrimitive } from "radix-ui"
|
|
38
|
+
```
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {Command}from'commander';import {intro,confirm,outro,spinner,select,log}from'@clack/prompts';import
|
|
2
|
+
import {Command}from'commander';import {intro,confirm,outro,spinner,select,log}from'@clack/prompts';import te from'chalk';import A from'fs-extra';import C from'path';import {z as z$1}from'zod';import be from'fast-glob';import {loadConfig,createMatchPath}from'tsconfig-paths';import {Project,SyntaxKind}from'ts-morph';import {detect,resolveCommand}from'package-manager-detector';import {packageDirectory}from'pkg-dir';import Fe from'handlebars';import {McpServer,ResourceTemplate}from'@modelcontextprotocol/sdk/server/mcp.js';import {StdioServerTransport}from'@modelcontextprotocol/sdk/server/stdio.js';var V=o=>{let e={};for(let t of o)e[t]=t;return e},O=V(["config_not_found","resolve_path_fail","failed_to_fetch"]);V(["components.json","tsconfig.json","panda.config.*","package.json"]);var b=class extends Error{issue;constructor(e){super(),this.name="NewError",this.issue=e;}get format(){return this.issue.code+`
|
|
3
3
|
`+this.issue.message?.join(`
|
|
4
|
-
`)}},
|
|
5
|
-
${
|
|
4
|
+
`)}},u=o=>{let e;switch(o.code){case O.config_not_found:e=`error occured while config ${o.configFile}`;break;case O.resolve_path_fail:e=`failed to resolve your path, current ${o.cwd}`;break;case O.failed_to_fetch:e=`failed to fetch ${o.target} [${o.statusCode}]`;break;default:e="error occured";}return new b({...o,message:[...o.message||"",e]})};var w={fileName:"components.json",schema:z$1.object({utils:z$1.string(),components:z$1.string(),hooks:z$1.string(),styledsystem:z$1.string()}).strict()},he=["ui","hooks","utils"],xe=z$1.object({name:z$1.string(),content:z$1.string(),type:z$1.enum(he)}),W=z$1.object({name:z$1.string(),dependencies:z$1.array(z$1.string()).optional(),files:z$1.array(xe).optional()});z$1.object({name:z$1.string(),dependencies:z$1.array(z$1.string()).optional(),file:z$1.string()});function H(o){try{return A.readJsonSync(C.resolve(o,w.fileName))}catch(e){return u({code:"config_not_found",configFile:w.fileName,message:[e instanceof Error?e.message:""]})}}function T(o){let e=loadConfig(o);if(e.resultType==="failed")throw u({code:"config_not_found",configFile:"tsconfig.json",message:["cannot found tsconfig.json"]});return e}async function Y(o){return await A.pathExists(C.join(o,"components.json"))}function Z(o,e){let t=["./","./src/","./app/","./src/app"].map(r=>C.resolve(o,r));for(let[r,s]of Object.entries(e.paths)){let a=C.join(o,e.baseUrl||"",s[0].replace(/\/\*$/,""));if(t.some(l=>l===a||l.includes(a)))return r.replace(/\/\*$/,"")}return null}function Q(o,e,t){let r=C.join(o,e);for(let[s,a]of Object.entries(t.paths)){let l=a[0].replace(/\/\*$/,"");if(r===C.join(o,t.baseUrl||"",l))return s.replace(/\/\*$/,"")}return null}async function I(o){try{let e=await be.glob(["panda.config.*"],{cwd:o,deep:3});if(!e.length)throw u({code:"config_not_found",configFile:"panda.config.*",message:["failed to find panda.config file"]});return e[0]}catch(e){throw u({code:"config_not_found",configFile:"panda.config.*",message:[e instanceof Error?e.message:"unknown error occured finding panda.config"]})}}async function F(o,e){let t=createMatchPath(e.absoluteBaseUrl,e.paths)(o,void 0,()=>true);if(!t)throw u({code:"resolve_path_fail",target:o,cwd:process.cwd(),message:["resolve error"]});return t}async function $(o){let e=o.match(/outdir:\s*["']([^"']+)["']/),t=o.match(/importMap:\s*({[^}]+}|["'][^"']+["'])/),r=e?e[1]:null,s=null;if(t){let a=t[1];if(a.startsWith("{")){let l=a.match(/css:\s*["']([^"']+)["']/);s=l?l[1].replace(/\/css$/,""):null;}else s=a.replace(/["']/g,"");}return {outdir:r,importMap:s}}function q(o,e){let t=o;return [{from:/@utils\//g,to:`${e.utils}/`},{from:/@hooks\//g,to:`${e.hooks}/`},{from:/@styled-system\//g,to:`${e.styledsystem}/`},{from:/@components\//g,to:`${e.components}/`}].forEach(({from:s,to:a})=>{t=t.replace(s,a);}),t}function X(o){let t=new Project().addSourceFileAtPath(o),r=[{namedImports:[{name:"preset"}],moduleSpecifier:"panda-animation"},{namedImports:[{name:"defaultPreset"}],moduleSpecifier:"./preset"}];t.addImportDeclarations(r);let a=t.getFirstDescendantByKind(SyntaxKind.CallExpression)?.getArguments()[0];a?(a.getProperty("presets")||a.addPropertyAssignment({name:"presets",initializer:'[preset(), "@pandacss/preset-panda", defaultPreset]'}),t.saveSync()):console.warn("Could not modify panda.config.ts. add presets : [preset(), @pandacss/preset-panda, defaultPreset] in your panda.config");}async function ee(o,e){let t=await detect({cwd:o}),r=resolveCommand(t?.agent||"npm","add",e);if(r)return r}var Te=z$1.object({components:z$1.array(z$1.string()).optional(),cwd:z$1.string()}),Ie="https://whdgur.shop",v=te.bold.red,z=te.bold.blue,re=new Command().name("add").argument("[components...]").option("-c, --cwd <cwd>","current working directory, default to process.cwd()",process.cwd()).action(async(o,e)=>{try{let t=Te.parse({components:o,...e});intro(z("install components..."));let r=w.schema.parse(H(t.cwd)),s=T(t.cwd),a=await I(t.cwd),l=await A.readFile(C.resolve(t.cwd,a),"utf-8"),{outdir:g}=await $(l),y=w.schema.parse({utils:await F(r.utils,s),components:await F(r.components,s),hooks:await F(r.hooks,s),styledsystem:C.join(t.cwd,g||"styled-system")},{errorMap:()=>({message:"validation failed at components.json"})}),m=t.components?.map(d=>d.toLowerCase());if(!m?.length)return;let h=await Promise.allSettled(m.map(async d=>{let n=await fetch(`${Ie}/${d}.json`);if(!n.ok)throw u({code:"failed_to_fetch",target:d,statusCode:n.status,message:[n.statusText]});return await n.json()}));for(let[d,n]of h.entries()){if(n.status==="rejected"){n.reason instanceof b?console.log(v(n.reason.format)):console.log(v(n.reason));continue}try{let i=W.parse(n.value,{errorMap:()=>({message:`registry for ${m[d]} is invaliad`})}),f=C.join(y.components,m[d]);if(A.pathExistsSync(f)&&!await confirm({message:`Component ${m[d]} already exists. Do you want to overwrite it?`}))return;i.files?.forEach(x=>{let K=q(x.content,r);x.type==="ui"?A.outputFileSync(C.join(f,x.name),K):A.outputFileSync(C.join(y[x.type],x.name),K,"utf-8");});let p=await ee(t.cwd,i.dependencies||[]),P=p?`Run this command in the terminal : ${p.command} ${p.args.join(" ")}`:`Cannot find your package manager, install this dependencies: ${i.dependencies?.join(" ")}`;outro(z(`${m[d]} completed successfully
|
|
5
|
+
${P}`));}catch(i){i instanceof Error&&console.log(v(i.message));}}}catch(t){outro(v(z("error occured"))),t instanceof z$1.ZodError&&console.log(t.message),t instanceof b&&console.log(v(t.format)),t instanceof Error&&console.log(v(t.message)),process.exit(1);}});var se=`
|
|
6
6
|
import { defineSemanticTokens, definePreset } from "@pandacss/dev"
|
|
7
7
|
|
|
8
8
|
const colors = defineSemanticTokens.colors({
|
|
@@ -105,7 +105,7 @@ export const defaultPreset = definePreset({
|
|
|
105
105
|
})
|
|
106
106
|
|
|
107
107
|
|
|
108
|
-
`;var _=["rose","pink","fuchsia","purple","violet","indigo","blue","sky","cyan","teal","emerald","green","lime","yellow","amber","orange","red","neutral","stone","zinc","gray","slate"],
|
|
109
|
-
<your package manager's delete command> ${
|
|
110
|
-
<your package manager's install command> ${
|
|
111
|
-
`).forEach(log.step):outro("no transform occured");});var
|
|
108
|
+
`;var _=["rose","pink","fuchsia","purple","violet","indigo","blue","sky","cyan","teal","emerald","green","lime","yellow","amber","orange","red","neutral","stone","zinc","gray","slate"],R=["neutral","stone","zinc","gray","slate"],ae=z$1.object({primary:z$1.enum(_),secondary:z$1.enum(_),gray:z$1.enum(R)}),ne=o=>Fe.compile(se)(o);var Ne=z$1.object({cwd:z$1.string(),default:z$1.boolean()}),J=te.bold.red,Le=te.bold.blue,ce=new Command().name("init").description("Initialize the project").option("-c, --cwd <cwd>","current working directory, default to process.cwd()",process.cwd()).option("-d, --default","use default color",false).action(async o=>{let e=spinner();e.start("Initializing");try{let t=Ne.parse({cwd:C.resolve(o.cwd),default:o.default});await Oe(t),e.stop("successfully Initialized!");}catch(t){e.stop(J(Le("error occured"))),t instanceof z$1.ZodError&&console.log(t.message),t instanceof b&&console.log(J(t.format)),t instanceof Error&&console.log(J(t.message)),process.exit(1);}});async function Oe(o){let e=o.cwd||await packageDirectory();if(!e)throw u({code:"config_not_found",configFile:"package.json",message:[`cannot find package.json in ${e}`]});let t=T(e);await Y(e)&&(await confirm({message:"you already initialize,are you want to overwrite it?"})||process.exit(0));let s=await I(e),a=await A.readFile(C.join(e,s),"utf-8"),l=Z(e,t);if(l===null)throw u({code:"resolve_path_fail",target:"tsconfig.json",cwd:e,message:[`cannot find paths alias in your ${C.join(e,"tsconfig.json")}`]});let g="styled-system",{outdir:y,importMap:m}=await $(a);m?g=m:g=Q(e,y||"styled-system",t)||".",y&&(g=y);let h=w.schema.parse({utils:`${l}/utils`,components:`${l}/components`,hooks:`${l}/hooks`,styledsystem:g},{errorMap:()=>({message:"components.json is invalid"})});A.writeFile(C.resolve(e,"components.json"),JSON.stringify(h),"utf-8");let d="neutral",n="slate",i="gray";o.default||(d=await select({message:"Pick primary color",initialValue:"neutral",options:_.map(p=>({value:p,label:p}))}),n=await select({message:"Pick secondary color",initialValue:"slate",options:_.map(p=>({value:p,label:p}))}),i=await select({message:"Pick gray color",initialValue:"gray",options:R.map(p=>({value:p,label:p}))}));let f=ne(ae.parse({primary:d,secondary:n,gray:i}));return A.writeFile(C.join(e,"preset.ts"),f),X(C.resolve(e,s)),h}var N=new McpServer({name:"Echo",version:"1.0.0"});N.resource("echo",new ResourceTemplate("echo://{message}",{list:void 0}),async(o,{message:e})=>({contents:[{uri:o.href,text:`Resource echo: ${e}`}]}));N.tool("echo",{message:z$1.string()},async({message:o})=>({content:[{type:"text",text:`Tool echo: ${o}`}]}));N.prompt("echo",{message:z$1.string()},({message:o})=>({messages:[{role:"user",content:{type:"text",text:`Please process this message: ${o}`}}]}));var de=new Command().name("mcp").action(async()=>{try{let o=new StdioServerTransport;await N.connect(o);}catch(o){console.error(o);}});var pe={"@radix-ui/react-accessible-icon":"AccessibleIcon","@radix-ui/react-accordion":"Accordion","@radix-ui/react-alert-dialog":"AlertDialog","@radix-ui/react-aspect-ratio":"AspectRatio","@radix-ui/react-avatar":"Avatar","@radix-ui/react-checkbox":"Checkbox","@radix-ui/react-collapsible":"Collapsible","@radix-ui/react-context-menu":"ContextMenu","@radix-ui/react-dialog":"Dialog","@radix-ui/react-direction":"Direction","@radix-ui/react-dropdown-menu":"DropdownMenu","@radix-ui/react-form":"Form","@radix-ui/react-hover-card":"HoverCard","@radix-ui/react-label":"Label","@radix-ui/react-menubar":"Menubar","@radix-ui/react-navigation-menu":"NavigationMenu","@radix-ui/react-popover":"Popover","@radix-ui/react-portal":"Portal","@radix-ui/react-progress":"Progress","@radix-ui/react-radio-group":"RadioGroup","@radix-ui/react-scroll-area":"ScrollArea","@radix-ui/react-select":"Select","@radix-ui/react-separator":"Separator","@radix-ui/react-slider":"Slider","@radix-ui/react-slot":"Slot","@radix-ui/react-switch":"Switch","@radix-ui/react-tabs":"Tabs","@radix-ui/react-toast":"Toast","@radix-ui/react-toggle":"Toggle","@radix-ui/react-toggle-group":"ToggleGroup","@radix-ui/react-toolbar":"Toolbar","@radix-ui/react-tooltip":"Tooltip","@radix-ui/react-visually-hidden":"VisuallyHidden"};function L(o,e,t){return t?o===t:o===e}function me(o){return `import {${o}} from "radix-ui"`}function fe(o){let e=[];return o.getImportDeclarations().forEach(t=>{let r=t.getModuleSpecifierValue();if(!(r in pe))return;let s=pe[r];e.push(r);let a=t.getNamespaceImport();if(a){let g=a.getText();s!==g&&(s+=` as ${g}`),t.replaceWithText(me(s));return}let l=t.getNamedImports();if(l.length){let g=s;l.forEach(y=>{let m=y.getName(),h=y.getAliasNode()?.getText(),d=`${g}.${m}`;for(let n of [SyntaxKind.JsxOpeningElement,SyntaxKind.JsxClosingElement,SyntaxKind.JsxSelfClosingElement])o.getDescendantsOfKind(n).forEach(i=>{let f=i.getTagNameNode().getText();L(f,m,h)&&i.getTagNameNode().replaceWithText(d);});o.getDescendantsOfKind(SyntaxKind.TypeQuery).forEach(n=>{n.getChildren().forEach(i=>{let f=i.getText();L(f,m,h)&&i.replaceWithText(d);});}),o.getDescendantsOfKind(SyntaxKind.ExpressionStatement).forEach(n=>{n.getChildrenOfKind(SyntaxKind.BinaryExpression).forEach(f=>{f.getRight().getChildren().forEach(P=>{let x=P.getText();L(x,m,h)&&P.replaceWithText(d);});});}),o.getDescendantsOfKind(SyntaxKind.VariableDeclaration).forEach(n=>{let i=n.getInitializer();i&&i.getChildren().forEach(f=>{let p=f.getText();L(p,m,h)&&f.replaceWithText(d);});});}),t.replaceWithText(me(g));}}),{source:o.getFullText(),packages:e}}var ue=new Command().name("radix-ui-import").action(()=>{intro("find .tsx files...");let o=be.sync("**/*.tsx",{ignore:["**/node_modules/**"],dot:false}),e=new Project,t="";o.forEach(r=>{let s=e.addSourceFileAtPathIfExists(C.join(process.cwd(),r));if(s)try{let{packages:a}=fe(s);t+=a.join(" "),s.save();}catch(a){log.error(`failed to transform ${r} ${a}`);}}),t.length?`copy this to delete and install new package
|
|
109
|
+
<your package manager's delete command> ${t}
|
|
110
|
+
<your package manager's install command> ${te.bgGreen("radix-ui")}`.split(`
|
|
111
|
+
`).forEach(log.step):outro("no transform occured");});var ye={version:"1.6.0"};async function qe(){new Command().name("design-system").version(ye.version).addCommand(ce).addCommand(re).addCommand(ue).addCommand(de).parse();}qe();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jongh/cli",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.01",
|
|
4
4
|
"description": "",
|
|
5
5
|
"bin": "./dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"@clack/prompts": "^0.7.0",
|
|
25
25
|
"@effect/platform": "^0.69.13",
|
|
26
26
|
"@effect/schema": "^0.75.5",
|
|
27
|
+
"@modelcontextprotocol/sdk": "^1.11.0",
|
|
27
28
|
"@types/babel__traverse": "^7.20.6",
|
|
28
29
|
"chalk": "^5.4.1",
|
|
29
30
|
"commander": "^13.0.0",
|