@seed-design/cli 1.3.5 → 1.4.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.
- package/bin/index.mjs +20 -20
- package/package.json +1 -1
- package/src/commands/add-all.ts +9 -3
- package/src/commands/add.ts +9 -3
- package/src/commands/compat.ts +15 -7
- package/src/commands/docs.ts +70 -18
- package/src/commands/init.ts +9 -2
- package/src/tests/docs-command.test.ts +150 -0
- package/src/utils/compatibility.ts +35 -11
- package/src/utils/fetch.ts +17 -6
- package/src/utils/get-config.ts +1 -0
- package/src/utils/init-config.ts +29 -1
- package/src/utils/write.ts +3 -0
package/bin/index.mjs
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import*as
|
|
3
|
-
[verbose] stack trace`)),
|
|
4
|
-
`,"utf-8"),{relativePath:
|
|
2
|
+
import*as le from"@clack/prompts";import{cosmiconfig as $t}from"cosmiconfig";import{z as ce}from"zod";import*as Z from"@clack/prompts";import{ZodError as ft}from"zod";import dt from"picocolors";var l=e=>dt.cyan(e);var $=class extends Error{hint;details;constructor({message:t,hint:r,details:n=[],cause:o}){super(t,{cause:o}),this.name="CliError",this.hint=r,this.details=n}},D=class extends Error{constructor(t="\uC791\uC5C5\uC774 \uCDE8\uC18C\uB410\uC5B4\uC694."){super(t),this.name="CliCancelError"}};function G(e){return e instanceof D}function W(e){return!e||typeof e!="object"||!("verbose"in e)?!1:e.verbose===!0}function gt(e,t){if(e instanceof $)return{reason:e.message,hint:e.hint??t,details:e.details,stack:ut(e.cause??e)};if(e instanceof ft){let r=e.issues.map(n=>`${n.path.join(".")||"(root)"}: ${n.message}`);return{reason:"\uC785\uB825\uAC12 \uB610\uB294 \uC124\uC815 \uD30C\uC77C \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC544\uC694.",hint:t,details:r,stack:e.stack}}if(e instanceof Error){let r=e,n=[];return(r.escapedCommand||r.command)&&n.push(`\uC2E4\uD589 \uBA85\uB839\uC5B4: ${r.escapedCommand??r.command}`),typeof r.exitCode=="number"&&n.push(`\uC885\uB8CC \uCF54\uB4DC: ${r.exitCode}`),r.stderr?.trim()?n.push(`stderr: ${r.stderr.trim()}`):r.stdout?.trim()&&n.push(`stdout: ${r.stdout.trim()}`),{reason:r.shortMessage??e.message,hint:t,details:n,stack:e.stack}}return typeof e=="string"?{reason:e,hint:t,details:[]}:{reason:"\uC54C \uC218 \uC5C6\uB294 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC5B4\uC694.",hint:t,details:[]}}function ut(e){if(e instanceof Error)return e.stack}function Y(e,{defaultMessage:t,defaultHint:r,verbose:n=!1}){let o=gt(e,r);Z.log.error(t),Z.log.error(`\uC6D0\uC778: ${o.reason}`);for(let i of o.details)Z.log.info(i);o.hint&&Z.log.info(`\uD574\uACB0 \uD78C\uD2B8: ${o.hint}`),n&&o.stack&&(Z.log.message(l(`
|
|
3
|
+
[verbose] stack trace`)),Z.log.message(o.stack)),Z.outro(l("\uC791\uC5C5\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694."))}import*as Q from"@clack/prompts";import Ct from"fs-extra";import je from"path";import yt from"findup-sync";import ht from"fs-extra";var wt="package.json";function bt(e=process.cwd()){let t=yt(wt,{cwd:e});if(!t)throw new Error("No package.json file found in the project.");return t}function se(e=process.cwd()){let t=bt(e);return ht.readJSONSync(t)}var H={rsc:!1,tsx:!0,framework:"react",path:"./seed-design",telemetry:!0};function Ee(e){try{let t=se(e),r={...t.dependencies,...t.devDependencies,...t.peerDependencies};if("@lynx-js/react"in r||"@seed-design/lynx-react"in r)return"lynx"}catch{}return"react"}async function Ae(e){let t=Ee(e);return await Q.group({tsx:()=>Q.confirm({message:`${l("TypeScript")}\uB97C \uC0AC\uC6A9\uC911\uC774\uC2E0\uAC00\uC694?`,initialValue:H.tsx}),rsc:()=>Q.confirm({message:`${l("React Server Components")}\uB97C \uC0AC\uC6A9\uC911\uC774\uC2E0\uAC00\uC694?`,initialValue:H.rsc}),framework:()=>Q.select({message:`\uC5B4\uB5A4 ${l("\uD504\uB808\uC784\uC6CC\uD06C")}\uB97C \uC0AC\uC6A9\uD558\uC2DC\uB098\uC694?`,initialValue:t,options:[{value:"react",label:"React"},{value:"lynx",label:"Lynx"}]}),path:()=>Q.text({message:`${l("seed-design \uD3F4\uB354")} \uACBD\uB85C\uB97C \uC785\uB825\uD574\uC8FC\uC138\uC694. (\uAE30\uBCF8\uAC12\uC740 \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8\uC5D0 \uC0DD\uC131\uB429\uB2C8\uB2E4.)`,initialValue:H.path,defaultValue:H.path,placeholder:H.path}),telemetry:()=>Q.confirm({message:`\uAC1C\uC120\uC744 \uC704\uD574 ${l("\uC775\uBA85 \uC0AC\uC6A9 \uB370\uC774\uD130")}\uB97C \uC218\uC9D1\uD560\uAE4C\uC694?`,initialValue:H.telemetry})},{onCancel:()=>{throw new D}})}async function Ce({cwd:e,config:t}){let r=je.resolve(e,"seed-design.json");return await Ct.writeFile(r,`${JSON.stringify(t,null,2)}
|
|
4
|
+
`,"utf-8"),{relativePath:je.relative(process.cwd(),r),targetPath:r}}var De="seed-design",xt=$t(De,{searchPlaces:[`${De}.json`]}),Oe=ce.object({$schema:ce.string().optional(),rsc:ce.coerce.boolean().default(!1),tsx:ce.coerce.boolean().default(!0),framework:ce.enum(["react","lynx"]).default("react"),path:ce.string(),telemetry:ce.coerce.boolean().optional().default(!0)}).strict();async function $e(e){let t=await oe(e);if(t)return t;le.log.error("\uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8 \uACBD\uB85C\uC5D0 `seed-design.json` \uD30C\uC77C\uC774 \uC5C6\uC5B4\uC694.");let r=await le.confirm({message:"seed-design.json \uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uC2DC\uACA0\uC5B4\uC694?"});if(le.isCancel(r)||!r)throw new D;try{return await Ce({cwd:e,config:H}),le.log.message("seed-design.json \uD30C\uC77C\uC774 \uC0DD\uC131\uB410\uC5B4\uC694."),Oe.parse(H)}catch(n){throw new $({message:"seed-design.json \uD30C\uC77C \uC0DD\uC131\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694.",hint:"\uB514\uB809\uD1A0\uB9AC \uC4F0\uAE30 \uAD8C\uD55C\uACFC \uACBD\uB85C\uB97C \uD655\uC778\uD55C \uB4A4 \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uBCF4\uC138\uC694.",cause:n})}}async function oe(e){let t=await xt.search(e);if(!t||t.isEmpty)return null;try{return Oe.parse(t.config)}catch(r){throw new $({message:"seed-design.json \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC544\uC694.",hint:"https://seed-design.com/react/getting-started/cli/configuration \uBB38\uC11C\uB97C \uCC38\uACE0\uD574 \uC8FC\uC138\uC694.",cause:r})}}function xe({selectedItemKeys:e,publicRegistries:t}){let r=[],n=new Set;function o(i,s){let a=r.find(c=>c.registryId===i);if(!a?.items.some(c=>c.id===s.id)){if(a?a.items.push(s):r.push({registryId:i,items:[s]}),s.dependencies?.length)for(let c of s.dependencies)n.add(c);if(s.innerDependencies?.length)for(let c of s.innerDependencies)for(let m of c.itemIds){let y=t.find(g=>g.id===c.registryId)?.items.find(g=>g.id===m);if(!y)throw new Error(`Cannot find dependency item: ${c.registryId}:${m}`);o(c.registryId,y)}}}for(let i of e){let[s,...a]=i.split(":"),c=a.join(":");if(!s||!c)throw new Error(`Invalid snippet format: "${i}"`);let m=t.find(y=>y.id===s)?.items.find(y=>y.id===c);if(!m)throw new Error(`Cannot find snippet: "${i}"`);o(s,m)}return{registryItemsToAdd:r,npmDependenciesToAdd:n}}import*as ve from"@clack/prompts";import{z as f}from"zod";var Re=f.object({id:f.string(),description:f.string().optional(),deprecated:f.boolean().optional(),hideFromCLICatalog:f.boolean().optional(),dependencies:f.array(f.string()).optional(),innerDependencies:f.array(f.object({registryId:f.string(),itemIds:f.array(f.string())})).optional(),snippets:f.array(f.object({path:f.string(),dependencies:f.record(f.string(),f.string()).optional(),content:f.string()}))}),Te=f.object({id:f.string(),hideFromCLICatalog:f.boolean().optional(),items:f.array(Re.omit({snippets:!0}).extend({snippets:f.array(f.object({path:f.string(),dependencies:f.record(f.string(),f.string()).optional()}))}))}),Me=f.array(f.object({id:f.string()})),It=f.object({label:f.string(),path:f.string()}),kt=f.object({id:f.string(),title:f.string(),description:f.string().optional(),docUrl:f.string(),deprecated:f.boolean().optional(),snippetKey:f.string().optional(),snippets:f.array(It).optional()}),Pt=f.object({id:f.string(),label:f.string(),items:f.array(kt)}),St=f.object({id:f.string(),label:f.string(),sections:f.array(Pt)}),Le=f.object({categories:f.array(St)});var Et=1e4;async function Fe(e,t=Et){let r=new AbortController,n=setTimeout(()=>r.abort(),t);try{return await fetch(e,{signal:r.signal})}catch(o){throw o instanceof Error&&o.name==="AbortError"?new $({message:`\uC694\uCCAD \uC2DC\uAC04\uC774 \uCD08\uACFC\uB418\uC5C8\uC5B4\uC694 (${t}ms): ${e}`,hint:"\uB124\uD2B8\uC6CC\uD06C \uC0C1\uD0DC\uB97C \uD655\uC778\uD558\uACE0 \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694."}):o}finally{clearTimeout(n)}}async function _e({baseUrl:e}){let t=await fetch(`${e}/__docs__/index.json`);if(!t.ok)throw new $({message:`\uBB38\uC11C \uBAA9\uB85D\uC744 \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694: ${t.status} ${t.statusText}`});let r=await t.json(),{success:n,data:o,error:i}=Le.safeParse(r);if(!n)throw new $({message:`\uBB38\uC11C \uBAA9\uB85D \uD30C\uC2F1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694: ${i?.message}`});return o}async function pe({baseUrl:e,framework:t}){let r=await fetch(`${e}/__registry__/${t}/index.json`);if(!r.ok)throw new Error(`Failed to fetch registries: ${r.status} ${r.statusText}`);let n=await r.json(),{success:o,data:i,error:s}=Me.safeParse(n);if(!o)throw new Error(`Failed to parse registries: ${s?.message}`);return i}async function de({baseUrl:e,framework:t,registryId:r}){let n=await fetch(`${e}/__registry__/${t}/${r}/index.json`);if(!n.ok)throw new Error(`Failed to fetch ${r} registry: ${n.status} ${n.statusText}`);let o=await n.json(),{success:i,data:s,error:a}=Te.safeParse(o);if(!i)throw new Error(`Failed to parse ${r} registry: ${a?.message}`);return s}async function Rt({baseUrl:e,framework:t,registryId:r,registryItemId:n}){let o=await fetch(`${e}/__registry__/${t}/${r}/${n}.json`);if(!o.ok)throw new Error(`Failed to fetch ${n}: ${o.status} ${o.statusText}`);let i=await o.json(),{success:s,data:a,error:c}=Re.safeParse(i);if(!s)throw new Error(`Failed to parse ${n}: ${c?.message}`);return a}async function Ue({url:e}){let t=await Fe(e);if(!t.ok)throw new $({message:`llms.txt\uB97C \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694: ${t.status} ${t.statusText}`,hint:`${e} \uC5D0 \uC811\uADFC\uD560 \uC218 \uC788\uB294\uC9C0 \uD655\uC778\uD574\uC8FC\uC138\uC694.`});return t.text()}async function Ke({baseUrl:e,query:t}){let r=t.startsWith("/")?t.slice(1):t,n=[`${e}/llms/${r}.txt`,`${e}/llms/${r}/llms.txt`],o;for(let i of n){let s;try{s=await Fe(i)}catch(a){o=a;continue}if(s.ok)return s.text();if(s.status===404){o=new $({message:`llms.txt\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694: ${r}`,hint:`\uB2E4\uC74C \uACBD\uB85C\uB97C \uC2DC\uB3C4\uD588\uC5B4\uC694:
|
|
5
5
|
${n.map(a=>` - ${a}`).join(`
|
|
6
|
-
`)}`});continue}throw new
|
|
7
|
-
${n.map(
|
|
8
|
-
`)}`})}async function
|
|
9
|
-
${
|
|
10
|
-
`)}`),
|
|
11
|
-
${
|
|
12
|
-
`),V.log.message(g),V.select({message:"\uD604\uC7AC \uD30C\uC77C\uC5D0 \uC2A4\uD0C0\uC77C \uBCC0\uACBD, \uB85C\uAE45 \uB4F1 \uCEE4\uC2A4\uD130\uB9C8\uC774\uC9D5\uC774 \uC801\uC6A9\uB418\uC5B4 \uC788\uB294 \uACBD\uC6B0 \uC2E0\uADDC \uD30C\uC77C\uC5D0 \uB3D9\uC77C\uD55C \uCEE4\uC2A4\uD130\uB9C8\uC774\uC9D5\uC744 \uC801\uC6A9\uD558\uB294 \uAC83\uC744 \uAC80\uD1A0\uD574\uBCF4\uC138\uC694.",options:[{value:"overwrite",label:`${B} \uB36E\uC5B4\uC4F0\uAE30`},{value:"backup",label:`\uAE30\uC874 \uD30C\uC77C \uB0B4\uC6A9\uC744 ${W}\uC73C\uB85C \uC62E\uAE30\uACE0 ${B} \uBC1B\uAE30`},{value:"skip",label:"\uC0C8 \uD30C\uC77C \uBC1B\uC9C0 \uC54A\uACE0 \uADF8\uB300\uB85C \uB450\uAE30"}]})})();if(V.isCancel(b)||b==="skip"){V.log.info(`${p($)}: \uD30C\uC77C\uC744 \uBC1B\uC9C0 \uC54A\uACE0 \uAC74\uB108\uB6F0\uC5C8\uC5B4\uC694.`);continue}if(b==="backup"){let l=J.dirname(f),g=J.join(l,W);await ae.rename(f,g),V.log.info(`${p($)}: \uAE30\uC874 \uD30C\uC77C\uC744 ${p(J.relative(r,g))}\uB85C \uC62E\uACBC\uC5B4\uC694.`)}}await ae.writeFile(f,u),x.push(h)}if(x.length>0){let h=x.map(({name:f,relativePath:u})=>({name:f,path:u}));i.push(...h),V.log.success(`${p(`${a}:${w}`)} \uAD00\uB828 \uC2A4\uB2C8\uD3AB \uB2E4\uC6B4\uB85C\uB4DC \uC644\uB8CC: ${p(h.map(f=>f.path).join(", "))}`)}}}}import*as T from"@clack/prompts";import sr from"path";import{z as se}from"zod";var F="https://seed-design.io";import*as Ve from"@clack/prompts";import{execa as Ut}from"execa";import{detect as At}from"@antfu/ni";async function ze(e){let t=await At({programmatic:!0,cwd:e});return t==="yarn@berry"?"yarn":t==="pnpm@6"?"pnpm":t==="bun"?"bun":t==="deno"?"deno":t??"npm"}import Ot from"findup-sync";import Mt from"fs-extra";var Lt="package.json";function Ft(e=process.cwd()){let t=Ot(Lt,{cwd:e});if(!t)throw new Error("No package.json file found in the project.");return t}function ce(e=process.cwd()){let t=Ft(e);return Mt.readJSONSync(t)}async function $e({cwd:e,deps:t,dev:r=!1}){let{start:n,stop:o}=Ve.spinner(),s=await ze(e),a={...ce(e).dependencies},c=new Set(t.filter(x=>!a[x])),d=new Set(t.filter(x=>a[x]));if(!c.size)return{installed:new Set,filtered:c};n("\uC758\uC874\uC131 \uC124\uCE58\uC911...");let C=[s==="npm"?"install":"add",r?"-D":null,...c].filter(x=>!!x),E=`${s} ${C.join(" ")}`;try{await Ut(s,C,{cwd:e})}catch(x){throw o("\uC758\uC874\uC131 \uC124\uCE58\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694."),new I({message:"\uC758\uC874\uC131 \uC124\uCE58\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694.",hint:"\uB124\uD2B8\uC6CC\uD06C \uC0C1\uD0DC\uB97C \uD655\uC778\uD558\uACE0, \uC124\uCE58 \uBA85\uB839\uC5B4\uB97C \uC9C1\uC811 \uC2E4\uD589\uD574 \uC0C1\uC138 \uC624\uB958\uB97C \uD655\uC778\uD574\uBCF4\uC138\uC694.",details:[`\uC2E4\uD589 \uBA85\uB839\uC5B4: ${E}`],cause:x})}return o("\uC758\uC874\uC131 \uC124\uCE58\uAC00 \uC644\uB8CC\uB410\uC5B4\uC694."),{installed:c,filtered:d}}import{randomUUID as Kt}from"node:crypto";import*as Be from"@clack/prompts";var Nt="seed_cli";async function zt(e){if(process.env.DISABLE_TELEMETRY==="true"||process.env.SEED_DISABLE_TELEMETRY==="true")return!1;try{if((await de(e))?.telemetry===!1)return!1}catch{}return!0}function Vt(){return Kt()}var qt=Vt(),qe=!1;function He(e){return Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0))}function Bt(e){return e instanceof Error&&e.name?e.name:typeof e=="object"&&e!==null?e.constructor?.name??"Object":typeof e}async function Ge(e,{event:t,properties:r={}}){if(!await zt(e))return;let o=`${Nt}.${t}`;qe||(Be.log.info("\u{1F4CA} \uC0AC\uC6A9 \uB370\uC774\uD130 \uC218\uC9D1 \uC911 (\uBE44\uD65C\uC131\uD654: seed-design.json \uB610\uB294 DISABLE_TELEMETRY \uD658\uACBD \uBCC0\uC218)"),qe=!0);try{let s="https://us.i.posthog.com/capture",i={"Content-Type":"application/json"},a={api_key:"phc_seod8HhifElOP1R92KmvsQybrtUmkOTgZBsq0mfCelR",event:o,distinct_id:qt,properties:{...r,$process_person_profile:!1},timestamp:new Date().toISOString()},c=new AbortController,d=setTimeout(()=>c.abort(),5e3);try{await fetch(s,{method:"POST",headers:i,body:JSON.stringify(a),signal:c.signal})}finally{clearTimeout(d)}}catch{}}async function Je(e,{command:t,status:r,result:n,properties:o={}}){await Ge(e,{event:t,properties:He({status:r,result:n,...o})})}async function Ht(e,{command:t,error:r,result:n,properties:o={}}){await Je(e,{command:t,status:"failed",result:n,properties:He({error_type:Bt(r),...o})})}var R={track:Ge,trackCommandFailure:Ht,trackCommandOutcome:Je};import*as re from"@clack/prompts";import Gt from"fs-extra";import Jt from"path";import{intersects as Wt,satisfies as Yt,valid as Ye,validRange as Xe}from"semver";var fe=["@seed-design/react","@seed-design/css"],We="workspace:",Xt="npm:";function le(e){try{let t=ce(e),r={...t.dependencies,...t.devDependencies,...t.peerDependencies,...t.optionalDependencies},n={};for(let o of fe){let s=r[o];typeof s=="string"&&(n[o]=s)}return n}catch{return{}}}function pe({publicRegistries:e,itemKeys:t,projectPackageVersions:r}){let n=Array.from(new Set(t)),o=new Map(e.flatMap(i=>i.items.map(a=>[`${i.id}:${a.id}`,a]))),s=[];for(let i of n){let a=o.get(i);if(!a)continue;let c=Qt(a);for(let d of fe){let y=Array.from(c[d]??[]);if(!y.length)continue;let w=r[d];if(!w){s.push({itemKey:i,packageName:d,requiredRanges:y,type:"missing-package"});continue}let C=Zt(w);if(!C){s.push({itemKey:i,packageName:d,requiredRanges:y,installedVersionSpec:w,type:"invalid-version-spec"});continue}y.every(x=>er({currentVersionSpec:C,requiredRange:x}))||s.push({itemKey:i,packageName:d,requiredRanges:y,installedVersionSpec:w,type:"incompatible-version"})}}return{checkedItemKeys:n,projectPackageVersions:r,issues:s}}function me({report:e,title:t}){if(!e.issues.length)return;re.log.warn(t),re.log.info(`\uD604\uC7AC \uD504\uB85C\uC81D\uD2B8 \uBC84\uC804: ${fe.map(n=>`${n}@${p(e.projectPackageVersions[n]??"\uBBF8\uC124\uCE58")}`).join(", ")}`);let r=new Map;for(let n of e.issues){let o=r.get(n.itemKey)??[];o.push(n),r.set(n.itemKey,o)}for(let[n,o]of r.entries()){re.log.warn(p(n));for(let s of o){let i=s.requiredRanges.join(" | ");if(s.type==="missing-package"){re.log.info(` - ${s.packageName}: \uD328\uD0A4\uC9C0\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC544\uC694. \uD544\uC694 \uBC94\uC704: ${i}`);continue}if(s.type==="invalid-version-spec"){re.log.info(` - ${s.packageName}: \uD604\uC7AC \uBC84\uC804 \uD615\uC2DD\uC744 \uD574\uC11D\uD558\uC9C0 \uBABB\uD588\uC5B4\uC694 (${s.installedVersionSpec}). \uD544\uC694 \uBC94\uC704: ${i}`);continue}re.log.info(` - ${s.packageName}: \uD604\uC7AC ${s.installedVersionSpec}, \uD544\uC694 \uBC94\uC704 ${i}`)}}}function Qe({publicRegistries:e,rootPath:t}){let r=[];for(let n of e)for(let o of n.items)o.snippets.some(i=>tr(i.path).some(a=>Gt.existsSync(Jt.join(t,n.id,a))))&&r.push(`${n.id}:${o.id}`);return r}function Qt(e){let t=Object.fromEntries(fe.map(r=>[r,new Set]));for(let r of e.snippets)for(let[n,o]of Object.entries(r.dependencies??{}))rr(n)&&t[n].add(o);return t}function Zt(e){let t=e.trim();if(t.startsWith(We)&&(t=t.slice(We.length).trim()),t.startsWith(Xt)){let r=t.split("@").at(-1);if(!r)return null;t=r}return!t||t==="*"?null:Ye(t)||Xe(t)?t:null}function er({currentVersionSpec:e,requiredRange:t}){let r=Xe(t);return r?Ye(e)?Yt(e,r,{includePrerelease:!0}):Wt(e,r,{includePrerelease:!0}):!1}function tr(e){let t=new Set([e]);return e.endsWith(".tsx")&&t.add(`${e.slice(0,-4)}.jsx`),e.endsWith(".ts")&&t.add(`${e.slice(0,-3)}.js`),e.endsWith(".jsx")&&t.add(`${e.slice(0,-4)}.tsx`),e.endsWith(".js")&&t.add(`${e.slice(0,-3)}.ts`),Array.from(t)}function rr(e){return fe.includes(e)}var or=se.object({itemIds:se.array(se.string()).optional(),all:se.boolean(),cwd:se.string(),baseUrl:se.string().default(F),onDiff:se.enum(["overwrite","backup"]).optional()}),Ze=e=>{e.command("add [...item-ids]","add items").option("-a, --all","[Deprecated] Add all items",{default:!1}).option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",{default:process.cwd()}).option("-u, --baseUrl <baseUrl>","the base url of the registry. defaults to the current directory.",{default:F}).option("--on-diff <mode>","Action when file differs: overwrite or backup").example("seed-design add ui:action-button").example("seed-design add ui:alert-dialog").action(async(t,r)=>{let n=Date.now(),o=H(r),s=typeof r?.cwd=="string"?r.cwd:process.cwd();T.intro("seed-design add");try{let i=or.safeParse({itemIds:t,...r});if(!i.success)throw i.error;let{data:{all:a,...c}}=i;if(a)throw new I({message:"`--all` \uC635\uC158\uC740 \uB354 \uC774\uC0C1 \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uC544\uC694. \uB300\uC2E0 `seed-design add-all` \uBA85\uB839\uC5B4\uB97C \uC0AC\uC6A9\uD574\uC8FC\uC138\uC694."});let d=c.cwd,y=c.baseUrl,w=await he(d),C=sr.resolve(d,w.path),{start:E,stop:x}=T.spinner();E("Registry\uB97C \uAC00\uC838\uC624\uACE0 \uC788\uC5B4\uC694...");let h=await(async()=>{try{let l=await Promise.all((await ie({baseUrl:y})).map(async({id:g})=>ne({baseUrl:y,registryId:g})));return x("Registry\uB97C \uAC00\uC838\uC654\uC5B4\uC694."),l}catch(l){throw x("Registry\uB97C \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694."),l}})(),f=await(async()=>{if(c.itemIds?.length)return c.itemIds;let l=await T.multiselect({message:"\uCD94\uAC00\uD560 \uD56D\uBAA9\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694 (\uC2A4\uD398\uC774\uC2A4 \uBC14\uB85C \uC5EC\uB7EC \uAC1C \uC120\uD0DD \uAC00\uB2A5)",options:h.filter(({hideFromCLICatalog:g})=>!g).flatMap(({id:g,items:k})=>k.filter(({hideFromCLICatalog:A})=>!A).sort((A,D)=>A.id.localeCompare(D.id)).map(({id:A,description:D,deprecated:S})=>({label:`${S?"(deprecated) ":""}${p(g)}:${A}`,value:`${g}:${A}`,hint:D,deprecated:S,registryItemCount:k.length}))).sort((g,k)=>g.deprecated!==k.deprecated?g.deprecated?1:-1:k.registryItemCount-g.registryItemCount)});if(T.isCancel(l))throw new _;return l})();if(!f?.length)throw new _("\uCD94\uAC00\uD560 \uD56D\uBAA9\uC774 \uC120\uD0DD\uB418\uC9C0 \uC54A\uC558\uC5B4\uC694.");T.log.message(`\uC120\uD0DD\uB41C \uD56D\uBAA9: ${p(f.join(", "))}`);let u=[];for(let l of f){let[g,...k]=l.split(":"),A=k.join(":");if(!g||!A)throw new I({message:`${p(l)}: \uD56D\uBAA9 \uC774\uB984\uC774 \uC798\uBABB\uB418\uC5C8\uC5B4\uC694.`,hint:`${p("ui:action-button")}\uACFC \uAC19\uC740 \uD615\uC2DD\uC73C\uB85C \uC785\uB825\uD574\uBCF4\uC138\uC694.`});let D=h.find(S=>S.id===g)?.items.find(S=>S.id===A);if(!D)throw new I({message:`${p(l)}: \uD56D\uBAA9\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.`});if(D.deprecated){let S=await T.confirm({message:`${p(D.id)}: deprecated \uB418\uC5C8\uC5B4\uC694. \uCD94\uAC00\uD560\uAE4C\uC694?`,initialValue:!1});if(T.isCancel(S))throw new _;if(S===!1){T.log.info(`${p(D.id)}: \uCD94\uAC00\uD558\uC9C0 \uC54A\uC744\uAC8C\uC694.`);continue}}u.push(l)}let{registryItemsToAdd:$,npmDependenciesToAdd:O}=we({selectedItemKeys:u,publicRegistries:h}),B=pe({publicRegistries:h,itemKeys:$.flatMap(({registryId:l,items:g})=>g.map(k=>`${l}:${k.id}`)),projectPackageVersions:le(c.cwd)});me({report:B,title:"\uD604\uC7AC \uD504\uB85C\uC81D\uD2B8 \uBC84\uC804\uACFC \uD638\uD658\uB418\uC9C0 \uC54A\uC744 \uC218 \uC788\uB294 \uC2A4\uB2C8\uD3AB\uC774 \uC788\uC5B4\uC694."}),T.log.info(`\uCD94\uAC00\uD560 \uD56D\uBAA9: ${p($.map(l=>l.items.map(g=>`${l.registryId}:${g.id}`).join(", ")).join(", ")||"\uC5C6\uC74C")}
|
|
6
|
+
`)}`});continue}throw new $({message:`llms.txt \uC694\uCCAD\uC774 \uC2E4\uD328\uD588\uC5B4\uC694: ${s.status} ${s.statusText}`,hint:`URL: ${i}`})}throw o??new $({message:`llms.txt\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694: ${r}`,hint:`\uB2E4\uC74C \uACBD\uB85C\uB97C \uC2DC\uB3C4\uD588\uC5B4\uC694:
|
|
7
|
+
${n.map(i=>` - ${i}`).join(`
|
|
8
|
+
`)}`})}async function Ne({baseUrl:e,framework:t,registryId:r,registryItemIds:n}){return await Promise.all(n.map(async o=>{try{return await Rt({baseUrl:e,framework:t,registryId:r,registryItemId:o})}catch(i){let s=await fetch(`${e}/__registry__/${t}/${r}/index.json`);if(!s.ok)throw new Error(`${r} \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uB97C \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694: ${s.status} ${s.statusText}`);let a=await s.json(),{success:c,data:m}=Te.safeParse(a);throw c?(ve.log.error(`${o} \uC2A4\uB2C8\uD3AB\uC774 ${r} \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC5D0 \uC5C6\uC5B4\uC694.`),ve.log.info(`${r} \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC5D0 \uC874\uC7AC\uD558\uB294 \uC2A4\uB2C8\uD3AB:
|
|
9
|
+
${m.items.map(y=>y.id).join(`
|
|
10
|
+
`)}`),i):new Error(`Failed to parse registry index for ${r}`)}}))}import{promises as Dt}from"fs";import{tmpdir as Ot}from"os";import Be from"path";import{transformFromAstSync as Tt}from"@babel/core";import vt from"@babel/plugin-transform-typescript";import*as Ie from"recast";import{parse as _t}from"@babel/parser";var jt={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"]},ze=async({sourceFile:e,config:t})=>{let r=e.getFullText();if(t.tsx)return r;let n=Ie.parse(r,{parser:{parse:i=>_t(i,jt)}}),o=Tt(n,r,{cloneInputAst:!1,code:!1,ast:!0,plugins:[vt],configFile:!1});if(!o||!o.ast)throw new Error("Failed to transform JSX");return Ie.print(o.ast).code};import{SyntaxKind as At}from"ts-morph";var Ve=async({sourceFile:e,config:t})=>{if(t.rsc)return e;let r=e.getFirstChildByKind(At.ExpressionStatement);if(!r)return e;let n=r.getExpression();if(!n)return e;let o=n.getText().trim();if(o!=='"use client"'&&o!=="'use client'")return e;let i=r.getText(),s=r.getFullText();if(i.trim()===s.trim())return e;let c=s.replace(i,"").replace(/^\s*\n/,"").replace(/\n\s*$/,"");return r.replaceWithText(c),e};import{Project as Mt,ScriptKind as Lt}from"ts-morph";var Ft=[Ve],Ut=new Mt({compilerOptions:{}});async function Kt(e){let t=await Dt.mkdtemp(Be.join(Ot(),"seed-design-"));return Be.join(t,e)}async function qe(e){let t=await Kt(e.filename),r=Ut.createSourceFile(t,e.raw,{scriptKind:Lt.TSX});for(let n of Ft)n({sourceFile:r,...e});return await ze({sourceFile:r,...e})}import*as J from"@clack/prompts";import fe from"fs-extra";import X from"path";import{createPatch as Nt}from"diff";import zt from"@npmcli/disparity-colors";async function ke({registryItemsToAdd:e,rootPath:t,cwd:r,baseUrl:n,framework:o,config:i,onDiff:s}){let a=[];for(let{registryId:c,items:m}of e){let y=X.join(t,c);fe.ensureDirSync(y);let g=await Ne({baseUrl:n,framework:o,registryId:c,registryItemIds:m.map(u=>u.id)});for(let{id:u,snippets:k}of g){let I=await Promise.all(k.map(async E=>{let C=await qe({filename:E.path,config:i,raw:E.content}),h=X.join(y,E.path);return i.tsx||(h=h.replace(/\.tsx$/,".jsx"),h=h.replace(/\.ts$/,".js")),{filePath:h,content:C,relativePath:X.relative(r,h),name:`${c}:${u}`}})),S=[];for(let E of I){let{filePath:C,content:h,relativePath:w}=E;if(await fe.ensureDir(X.dirname(C)),fe.existsSync(C)){let b=await fe.readFile(C,"utf-8");if(b===h){J.log.info(`${l(w)}: \uC774\uBBF8 \uCD5C\uC2E0 \uC0C1\uD0DC\uC608\uC694.`);continue}let P=X.basename(C),U=X.extname(C),B=X.basename(C,U),R=Date.now(),q=`legacy-${B}-${R}${U}`,x=await(async()=>{if(s)return s;let p=Nt(w,b,h),d=zt(p);return J.log.message(`
|
|
11
|
+
${l(w)}: \uD604\uC7AC \uD30C\uC77C\uACFC \uBC1B\uC73C\uB824\uB294 \uD30C\uC77C\uC758 \uB0B4\uC6A9\uC774 \uB2EC\uB77C\uC694.
|
|
12
|
+
`),J.log.message(d),J.select({message:"\uD604\uC7AC \uD30C\uC77C\uC5D0 \uC2A4\uD0C0\uC77C \uBCC0\uACBD, \uB85C\uAE45 \uB4F1 \uCEE4\uC2A4\uD130\uB9C8\uC774\uC9D5\uC774 \uC801\uC6A9\uB418\uC5B4 \uC788\uB294 \uACBD\uC6B0 \uC2E0\uADDC \uD30C\uC77C\uC5D0 \uB3D9\uC77C\uD55C \uCEE4\uC2A4\uD130\uB9C8\uC774\uC9D5\uC744 \uC801\uC6A9\uD558\uB294 \uAC83\uC744 \uAC80\uD1A0\uD574\uBCF4\uC138\uC694.",options:[{value:"overwrite",label:`${P} \uB36E\uC5B4\uC4F0\uAE30`},{value:"backup",label:`\uAE30\uC874 \uD30C\uC77C \uB0B4\uC6A9\uC744 ${q}\uC73C\uB85C \uC62E\uAE30\uACE0 ${P} \uBC1B\uAE30`},{value:"skip",label:"\uC0C8 \uD30C\uC77C \uBC1B\uC9C0 \uC54A\uACE0 \uADF8\uB300\uB85C \uB450\uAE30"}]})})();if(J.isCancel(x)||x==="skip"){J.log.info(`${l(w)}: \uD30C\uC77C\uC744 \uBC1B\uC9C0 \uC54A\uACE0 \uAC74\uB108\uB6F0\uC5C8\uC5B4\uC694.`);continue}if(x==="backup"){let p=X.dirname(C),d=X.join(p,q);await fe.rename(C,d),J.log.info(`${l(w)}: \uAE30\uC874 \uD30C\uC77C\uC744 ${l(X.relative(r,d))}\uB85C \uC62E\uACBC\uC5B4\uC694.`)}}await fe.writeFile(C,h),S.push(E)}if(S.length>0){let E=S.map(({name:C,relativePath:h})=>({name:C,path:h}));a.push(...E),J.log.success(`${l(`${c}:${u}`)} \uAD00\uB828 \uC2A4\uB2C8\uD3AB \uB2E4\uC6B4\uB85C\uB4DC \uC644\uB8CC: ${l(E.map(C=>C.path).join(", "))}`)}}}}import*as j from"@clack/prompts";import mr from"path";import{z as ne}from"zod";var K="https://seed-design.io";import*as He from"@clack/prompts";import{execa as Bt}from"execa";import{detect as Vt}from"@antfu/ni";async function Ge(e){let t=await Vt({programmatic:!0,cwd:e});return t==="yarn@berry"?"yarn":t==="pnpm@6"?"pnpm":t==="bun"?"bun":t==="deno"?"deno":t??"npm"}async function Pe({cwd:e,deps:t,dev:r=!1}){let{start:n,stop:o}=He.spinner(),i=await Ge(e),a={...se(e).dependencies},c=new Set(t.filter(I=>!a[I])),m=new Set(t.filter(I=>a[I]));if(!c.size)return{installed:new Set,filtered:c};n("\uC758\uC874\uC131 \uC124\uCE58\uC911...");let u=[i==="npm"?"install":"add",r?"-D":null,...c].filter(I=>!!I),k=`${i} ${u.join(" ")}`;try{await Bt(i,u,{cwd:e})}catch(I){throw o("\uC758\uC874\uC131 \uC124\uCE58\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694."),new $({message:"\uC758\uC874\uC131 \uC124\uCE58\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694.",hint:"\uB124\uD2B8\uC6CC\uD06C \uC0C1\uD0DC\uB97C \uD655\uC778\uD558\uACE0, \uC124\uCE58 \uBA85\uB839\uC5B4\uB97C \uC9C1\uC811 \uC2E4\uD589\uD574 \uC0C1\uC138 \uC624\uB958\uB97C \uD655\uC778\uD574\uBCF4\uC138\uC694.",details:[`\uC2E4\uD589 \uBA85\uB839\uC5B4: ${k}`],cause:I})}return o("\uC758\uC874\uC131 \uC124\uCE58\uAC00 \uC644\uB8CC\uB410\uC5B4\uC694."),{installed:c,filtered:m}}import{randomUUID as qt}from"node:crypto";import*as We from"@clack/prompts";var Gt="seed_cli";async function Ht(e){if(process.env.DISABLE_TELEMETRY==="true"||process.env.SEED_DISABLE_TELEMETRY==="true")return!1;try{if((await oe(e))?.telemetry===!1)return!1}catch{}return!0}function Jt(){return qt()}var Wt=Jt(),Je=!1;function Ye(e){return Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0))}function Yt(e){return e instanceof Error&&e.name?e.name:typeof e=="object"&&e!==null?e.constructor?.name??"Object":typeof e}async function Qe(e,{event:t,properties:r={}}){if(!await Ht(e))return;let o=`${Gt}.${t}`;Je||(We.log.info("\u{1F4CA} \uC0AC\uC6A9 \uB370\uC774\uD130 \uC218\uC9D1 \uC911 (\uBE44\uD65C\uC131\uD654: seed-design.json \uB610\uB294 DISABLE_TELEMETRY \uD658\uACBD \uBCC0\uC218)"),Je=!0);try{let i="https://us.i.posthog.com/capture",s={"Content-Type":"application/json"},a={api_key:"phc_seod8HhifElOP1R92KmvsQybrtUmkOTgZBsq0mfCelR",event:o,distinct_id:Wt,properties:{...r,$process_person_profile:!1},timestamp:new Date().toISOString()},c=new AbortController,m=setTimeout(()=>c.abort(),5e3);try{await fetch(i,{method:"POST",headers:s,body:JSON.stringify(a),signal:c.signal})}finally{clearTimeout(m)}}catch{}}async function Xe(e,{command:t,status:r,result:n,properties:o={}}){await Qe(e,{event:t,properties:Ye({status:r,result:n,...o})})}async function Qt(e,{command:t,error:r,result:n,properties:o={}}){await Xe(e,{command:t,status:"failed",result:n,properties:Ye({error_type:Yt(r),...o})})}var _={track:Qe,trackCommandFailure:Qt,trackCommandOutcome:Xe};import*as me from"@clack/prompts";import Xt from"fs-extra";import Zt from"path";import{intersects as er,satisfies as tr,valid as et,validRange as tt}from"semver";var rr=["@seed-design/react","@seed-design/css"],sr=["@seed-design/lynx-react","@seed-design/lynx-css"];function ie(e){return e==="lynx"?sr:rr}var Ze="workspace:",or="npm:";function ge(e,t="react"){try{let r=se(e),n={...r.dependencies,...r.devDependencies,...r.peerDependencies,...r.optionalDependencies},o={},i=ie(t);for(let s of i){let a=n[s];typeof a=="string"&&(o[s]=a)}return o}catch{return{}}}function ue({publicRegistries:e,itemKeys:t,projectPackageVersions:r,framework:n="react"}){let o=Array.from(new Set(t)),i=new Map(e.flatMap(c=>c.items.map(m=>[`${c.id}:${m.id}`,m]))),s=[],a=ie(n);for(let c of o){let m=i.get(c);if(!m)continue;let y=ir(m,n);for(let g of a){let u=Array.from(y[g]??[]);if(!u.length)continue;let k=r[g];if(!k){s.push({itemKey:c,packageName:g,requiredRanges:u,type:"missing-package"});continue}let I=nr(k);if(!I){s.push({itemKey:c,packageName:g,requiredRanges:u,installedVersionSpec:k,type:"invalid-version-spec"});continue}u.every(E=>ar({currentVersionSpec:I,requiredRange:E}))||s.push({itemKey:c,packageName:g,requiredRanges:u,installedVersionSpec:k,type:"incompatible-version"})}}return{checkedItemKeys:o,projectPackageVersions:r,issues:s}}function ye({report:e,title:t,framework:r="react"}){if(!e.issues.length)return;let n=ie(r);me.log.warn(t),me.log.info(`\uD604\uC7AC \uD504\uB85C\uC81D\uD2B8 \uBC84\uC804: ${n.map(i=>`${i}@${l(e.projectPackageVersions[i]??"\uBBF8\uC124\uCE58")}`).join(", ")}`);let o=new Map;for(let i of e.issues){let s=o.get(i.itemKey)??[];s.push(i),o.set(i.itemKey,s)}for(let[i,s]of o.entries()){me.log.warn(l(i));for(let a of s){let c=a.requiredRanges.join(" | ");if(a.type==="missing-package"){me.log.info(` - ${a.packageName}: \uD328\uD0A4\uC9C0\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC544\uC694. \uD544\uC694 \uBC94\uC704: ${c}`);continue}if(a.type==="invalid-version-spec"){me.log.info(` - ${a.packageName}: \uD604\uC7AC \uBC84\uC804 \uD615\uC2DD\uC744 \uD574\uC11D\uD558\uC9C0 \uBABB\uD588\uC5B4\uC694 (${a.installedVersionSpec}). \uD544\uC694 \uBC94\uC704: ${c}`);continue}me.log.info(` - ${a.packageName}: \uD604\uC7AC ${a.installedVersionSpec}, \uD544\uC694 \uBC94\uC704 ${c}`)}}}function rt({publicRegistries:e,rootPath:t}){let r=[];for(let n of e)for(let o of n.items)o.snippets.some(s=>cr(s.path).some(a=>Xt.existsSync(Zt.join(t,n.id,a))))&&r.push(`${n.id}:${o.id}`);return r}function ir(e,t="react"){let r=ie(t),n=Object.fromEntries(r.map(o=>[o,new Set]));for(let o of e.snippets)for(let[i,s]of Object.entries(o.dependencies??{}))lr(i,t)&&n[i].add(s);return n}function nr(e){let t=e.trim();if(t.startsWith(Ze)&&(t=t.slice(Ze.length).trim()),t.startsWith(or)){let r=t.split("@").at(-1);if(!r)return null;t=r}return!t||t==="*"?null:et(t)||tt(t)?t:null}function ar({currentVersionSpec:e,requiredRange:t}){let r=tt(t);return r?et(e)?tr(e,r,{includePrerelease:!0}):er(e,r,{includePrerelease:!0}):!1}function cr(e){let t=new Set([e]);return e.endsWith(".tsx")&&t.add(`${e.slice(0,-4)}.jsx`),e.endsWith(".ts")&&t.add(`${e.slice(0,-3)}.js`),e.endsWith(".jsx")&&t.add(`${e.slice(0,-4)}.tsx`),e.endsWith(".js")&&t.add(`${e.slice(0,-3)}.ts`),Array.from(t)}function lr(e,t="react"){return ie(t).includes(e)}var pr=ne.object({itemIds:ne.array(ne.string()).optional(),all:ne.boolean(),cwd:ne.string(),baseUrl:ne.string().default(K),framework:ne.enum(["react","lynx"]).optional(),onDiff:ne.enum(["overwrite","backup"]).optional()}),st=e=>{e.command("add [...item-ids]","add items").option("-a, --all","[Deprecated] Add all items",{default:!1}).option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",{default:process.cwd()}).option("-u, --baseUrl <baseUrl>","the base url of the registry. defaults to the current directory.",{default:K}).option("-f, --framework <framework>","\uD504\uB808\uC784\uC6CC\uD06C (react \uB610\uB294 lynx)").option("--on-diff <mode>","Action when file differs: overwrite or backup").example("seed-design add ui:action-button").example("seed-design add ui:alert-dialog").action(async(t,r)=>{let n=Date.now(),o=W(r),i=typeof r?.cwd=="string"?r.cwd:process.cwd();j.intro("seed-design add");try{let s=pr.safeParse({itemIds:t,...r});if(!s.success)throw s.error;let{data:{all:a,...c}}=s;if(a)throw new $({message:"`--all` \uC635\uC158\uC740 \uB354 \uC774\uC0C1 \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uC544\uC694. \uB300\uC2E0 `seed-design add-all` \uBA85\uB839\uC5B4\uB97C \uC0AC\uC6A9\uD574\uC8FC\uC138\uC694."});let m=c.cwd,y=c.baseUrl,g=await $e(m),u=c.framework??g.framework,k=mr.resolve(m,g.path),{start:I,stop:S}=j.spinner();I("Registry\uB97C \uAC00\uC838\uC624\uACE0 \uC788\uC5B4\uC694...");let E=await(async()=>{try{let p=await Promise.all((await pe({baseUrl:y,framework:u})).map(async({id:d})=>de({baseUrl:y,framework:u,registryId:d})));return S("Registry\uB97C \uAC00\uC838\uC654\uC5B4\uC694."),p}catch(p){throw S("Registry\uB97C \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694."),p}})(),C=await(async()=>{if(c.itemIds?.length)return c.itemIds;let p=await j.multiselect({message:"\uCD94\uAC00\uD560 \uD56D\uBAA9\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694 (\uC2A4\uD398\uC774\uC2A4 \uBC14\uB85C \uC5EC\uB7EC \uAC1C \uC120\uD0DD \uAC00\uB2A5)",options:E.filter(({hideFromCLICatalog:d})=>!d).flatMap(({id:d,items:T})=>T.filter(({hideFromCLICatalog:M})=>!M).sort((M,v)=>M.id.localeCompare(v.id)).map(({id:M,description:v,deprecated:L})=>({label:`${L?"(deprecated) ":""}${l(d)}:${M}`,value:`${d}:${M}`,hint:v,deprecated:L,registryItemCount:T.length}))).sort((d,T)=>d.deprecated!==T.deprecated?d.deprecated?1:-1:T.registryItemCount-d.registryItemCount)});if(j.isCancel(p))throw new D;return p})();if(!C?.length)throw new D("\uCD94\uAC00\uD560 \uD56D\uBAA9\uC774 \uC120\uD0DD\uB418\uC9C0 \uC54A\uC558\uC5B4\uC694.");j.log.message(`\uC120\uD0DD\uB41C \uD56D\uBAA9: ${l(C.join(", "))}`);let h=[];for(let p of C){let[d,...T]=p.split(":"),M=T.join(":");if(!d||!M)throw new $({message:`${l(p)}: \uD56D\uBAA9 \uC774\uB984\uC774 \uC798\uBABB\uB418\uC5C8\uC5B4\uC694.`,hint:`${l("ui:action-button")}\uACFC \uAC19\uC740 \uD615\uC2DD\uC73C\uB85C \uC785\uB825\uD574\uBCF4\uC138\uC694.`});let v=E.find(L=>L.id===d)?.items.find(L=>L.id===M);if(!v)throw new $({message:`${l(p)}: \uD56D\uBAA9\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.`});if(v.deprecated){let L=await j.confirm({message:`${l(v.id)}: deprecated \uB418\uC5C8\uC5B4\uC694. \uCD94\uAC00\uD560\uAE4C\uC694?`,initialValue:!1});if(j.isCancel(L))throw new D;if(L===!1){j.log.info(`${l(v.id)}: \uCD94\uAC00\uD558\uC9C0 \uC54A\uC744\uAC8C\uC694.`);continue}}h.push(p)}let{registryItemsToAdd:w,npmDependenciesToAdd:b}=xe({selectedItemKeys:h,publicRegistries:E}),P=ue({publicRegistries:E,itemKeys:w.flatMap(({registryId:p,items:d})=>d.map(T=>`${p}:${T.id}`)),projectPackageVersions:ge(c.cwd,u),framework:u});ye({report:P,title:"\uD604\uC7AC \uD504\uB85C\uC81D\uD2B8 \uBC84\uC804\uACFC \uD638\uD658\uB418\uC9C0 \uC54A\uC744 \uC218 \uC788\uB294 \uC2A4\uB2C8\uD3AB\uC774 \uC788\uC5B4\uC694.",framework:u}),j.log.info(`\uCD94\uAC00\uD560 \uD56D\uBAA9: ${l(w.map(p=>p.items.map(d=>`${p.registryId}:${d.id}`).join(", ")).join(", ")||"\uC5C6\uC74C")}
|
|
13
13
|
|
|
14
|
-
\uC124\uCE58\uD560 \uC758\uC874\uC131: ${p(Array.from(O).join(", ")||"\uC5C6\uC74C")}`),await Ce({registryItemsToAdd:$,rootPath:C,cwd:d,baseUrl:y,config:w,onDiff:c.onDiff});let{installed:P,filtered:M}=await $e({cwd:d,deps:Array.from(O)});P.size===0&&T.log.message("\uBAA8\uB4E0 \uC758\uC874\uC131\uC774 \uC774\uBBF8 \uC124\uCE58\uB418\uC5B4 \uC788\uC5B4\uC694."),P.size&&(T.log.message(`\uC758\uC874\uC131 \uC124\uCE58 \uC644\uB8CC: ${p(Array.from(P).join(", "))}`),M.size&&T.log.message(`\uC124\uCE58\uD558\uC9C0 \uC54A\uC740 \uC758\uC874\uC131 (\uC774\uBBF8 \uC124\uCE58\uB428): ${p(Array.from(M).join(", "))}`)),T.outro("\uC644\uB8CC\uD588\uC5B4\uC694.");let L=Date.now()-n,W=new Set($.map(l=>l.registryId)),b=f.some(l=>{let[g,...k]=l.split(":"),A=k.join(":");return h.find(D=>D.id===g)?.items.find(D=>D.id===A)?.deprecated});try{await R.trackCommandOutcome(c.cwd,{command:"add",status:"completed",properties:{items_count:u.length,registries:Array.from(W),has_deprecated:b,dependencies_count:O.size,duration_ms:L}})}catch(l){o&&console.error("[Telemetry] add \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",l)}}catch(i){if(N(i)){try{await R.trackCommandOutcome(s,{command:"add",status:"cancelled",properties:{duration_ms:Date.now()-n}})}catch(a){o&&console.error("[Telemetry] add \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",a)}T.outro(p(i.message)),process.exit(0)}try{await R.trackCommandFailure(s,{command:"add",error:i,properties:{duration_ms:Date.now()-n}})}catch(a){o&&console.error("[Telemetry] add \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",a)}G(i,{defaultMessage:"\uCD94\uAC00\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694.",defaultHint:"`--verbose` \uC635\uC158\uC73C\uB85C \uC0C1\uC138 \uC624\uB958\uB97C \uD655\uC778\uD574\uBCF4\uC138\uC694.",verbose:o}),process.exit(1)}})};import*as j from"@clack/prompts";import ir from"path";import{z as Z}from"zod";var nr=Z.object({registryIds:Z.array(Z.string()).optional(),all:Z.boolean(),includeDeprecated:Z.boolean().optional(),cwd:Z.string(),baseUrl:Z.string().default(F),onDiff:Z.enum(["overwrite","backup"]).optional()}),et=e=>{e.command("add-all [...registry-ids]","add all items from registries").option("-a, --all","Add all items from all registries",{default:!1}).option("--include-deprecated","Include deprecated items when used with `--all`",{default:!1}).option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",{default:process.cwd()}).option("-u, --baseUrl <baseUrl>","the base url of the registry. defaults to the current directory.",{default:F}).option("--on-diff <mode>","Action when file differs: overwrite or backup").example("seed-design add-all ui --include-deprecated").example("seed-design add-all ui lib breeze").action(async(t,r)=>{let n=Date.now(),o=H(r),s=typeof r?.cwd=="string"?r.cwd:process.cwd();j.intro("seed-design add-all");try{let i=nr.safeParse({registryIds:t,...r});if(!i.success)throw i.error;let{data:a}=i,c=a.cwd,d=a.baseUrl,y=await he(c),w=ir.resolve(c,y.path),{start:C,stop:E}=j.spinner();C("Registry\uB97C \uAC00\uC838\uC624\uACE0 \uC788\uC5B4\uC694...");let x=await(async()=>{try{let b=await Promise.all((await ie({baseUrl:d})).map(async({id:l})=>ne({baseUrl:d,registryId:l})));return E("Registry\uB97C \uAC00\uC838\uC654\uC5B4\uC694."),b}catch(b){throw E("Registry\uB97C \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694."),b}})(),h=await(async()=>{if(a.all){let l=x.map(g=>g.id);return j.log.message(`\uBAA8\uB4E0 \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC758 \uBAA8\uB4E0 \uD56D\uBAA9\uC744 \uCD94\uAC00\uD569\uB2C8\uB2E4: ${p(l.join(", "))}`),l}if(a.registryIds?.length){let l=x.map(g=>g.id);for(let g of a.registryIds)if(!l.includes(g))throw new I({message:`\uB808\uC9C0\uC2A4\uD2B8\uB9AC '${g}'\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.`,details:[`\uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uB808\uC9C0\uC2A4\uD2B8\uB9AC: ${l.join(", ")}`]});return j.log.message(`\uC120\uD0DD\uB41C \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC758 \uBAA8\uB4E0 \uD56D\uBAA9\uC744 \uCD94\uAC00\uD569\uB2C8\uB2E4: ${p(a.registryIds.join(", "))}`),a.registryIds}let b=await j.multiselect({message:"\uCD94\uAC00\uD560 \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uB97C \uC120\uD0DD\uD574\uC8FC\uC138\uC694 (\uC2A4\uD398\uC774\uC2A4 \uBC14\uB85C \uC5EC\uB7EC \uAC1C \uC120\uD0DD \uAC00\uB2A5)",options:x.filter(({hideFromCLICatalog:l})=>!l).sort((l,g)=>g.items.length-l.items.length).map(l=>{let g=l.items[0]?.id,k=g?`${l.items.length}\uAC1C \uD56D\uBAA9 (${g} \uB4F1)`:`${l.items.length}\uAC1C \uD56D\uBAA9 (\uD56D\uBAA9 \uC5C6\uC74C)`;return{label:l.id,value:l.id,hint:k}})});if(j.isCancel(b))throw new _;return j.log.message(`\uC120\uD0DD\uB41C \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC758 \uD56D\uBAA9\uC744 \uCD94\uAC00\uD569\uB2C8\uB2E4: ${p(b.join(", "))}`),b})(),f=x.filter(b=>h.includes(b.id)),u=f.flatMap(b=>b.items.filter(l=>l.deprecated?a.includeDeprecated:!0).map(l=>`${b.id}:${l.id}`)),$=f.reduce((b,l)=>b+l.items.filter(g=>g.deprecated).length,0);if(!a.includeDeprecated&&$>0&&j.log.info(`${$}\uAC1C\uC758 deprecated \uD56D\uBAA9\uC740 \uC81C\uC678\uB418\uC5C8\uC5B4\uC694. --include-deprecated \uC635\uC158\uC744 \uC0AC\uC6A9\uD558\uBA74 \uCD94\uAC00\uD560 \uC218 \uC788\uC5B4\uC694.`),!u.length)throw new _("\uCD94\uAC00\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC5B4\uC694.");j.log.message(`\uCD1D ${p(u.length.toString())}\uAC1C\uC758 \uD56D\uBAA9\uC744 \uCD94\uAC00\uD569\uB2C8\uB2E4.`);let{registryItemsToAdd:O,npmDependenciesToAdd:B}=we({selectedItemKeys:u,publicRegistries:x}),P=pe({publicRegistries:x,itemKeys:O.flatMap(({registryId:b,items:l})=>l.map(g=>`${b}:${g.id}`)),projectPackageVersions:le(a.cwd)});me({report:P,title:"\uD604\uC7AC \uD504\uB85C\uC81D\uD2B8 \uBC84\uC804\uACFC \uD638\uD658\uB418\uC9C0 \uC54A\uC744 \uC218 \uC788\uB294 \uC2A4\uB2C8\uD3AB\uC774 \uC788\uC5B4\uC694."}),await Ce({registryItemsToAdd:O,rootPath:w,cwd:c,baseUrl:d,config:y,onDiff:a.onDiff});let{installed:M,filtered:L}=await $e({cwd:c,deps:Array.from(B)});M.size===0&&j.log.message("\uBAA8\uB4E0 \uC758\uC874\uC131\uC774 \uC774\uBBF8 \uC124\uCE58\uB418\uC5B4 \uC788\uC5B4\uC694."),M.size&&(j.log.message(`\uC758\uC874\uC131 \uC124\uCE58 \uC644\uB8CC: ${p(Array.from(M).join(", "))}`),L.size&&j.log.message(`\uC124\uCE58\uD558\uC9C0 \uC54A\uC740 \uC758\uC874\uC131 (\uC774\uBBF8 \uC124\uCE58\uB428): ${p(Array.from(L).join(", "))}`)),j.outro("\uC644\uB8CC\uD588\uC5B4\uC694.");let W=Date.now()-n;try{await R.trackCommandOutcome(a.cwd,{command:"add-all",status:"completed",properties:{registries:h,items_count:u.length,include_deprecated:a.includeDeprecated||!1,dependencies_count:B.size,duration_ms:W}})}catch(b){o&&console.error("[Telemetry] add-all \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",b)}}catch(i){if(N(i)){try{await R.trackCommandOutcome(s,{command:"add-all",status:"cancelled",properties:{duration_ms:Date.now()-n}})}catch(a){o&&console.error("[Telemetry] add-all \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",a)}j.outro(p(i.message)),process.exit(0)}try{await R.trackCommandFailure(s,{command:"add-all",error:i,properties:{duration_ms:Date.now()-n}})}catch(a){o&&console.error("[Telemetry] add-all \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",a)}G(i,{defaultMessage:"\uCD94\uAC00\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694.",defaultHint:"`--verbose` \uC635\uC158\uC73C\uB85C \uC0C1\uC138 \uC624\uB958\uB97C \uD655\uC778\uD574\uBCF4\uC138\uC694.",verbose:o}),process.exit(1)}})};import*as U from"@clack/prompts";import tt from"path";import{z as q}from"zod";var ar=q.object({itemIds:q.array(q.string()).optional(),component:q.union([q.string(),q.array(q.string())]).optional(),all:q.boolean(),registry:q.string().optional(),cwd:q.string(),baseUrl:q.string().default(F)});function cr({itemIds:e,component:t}){let r=s=>s.trim().replace(/\s+/g,"-"),n=(e??[]).map(r).filter(Boolean),o=(Array.isArray(t)?t:[t]).filter(s=>!!s).flatMap(s=>s.split(",")).map(r).filter(Boolean);return Array.from(new Set([...n,...o]))}function lr({publicRegistries:e,targetInputs:t,defaultRegistry:r}){let n=e.filter(s=>typeof s.id=="string"&&Array.isArray(s.items)).flatMap(s=>s.items.filter(i=>typeof i.id=="string").map(i=>`${s.id}:${i.id}`)),o=new Set;for(let s of t){let i=s.includes(":")?s:r?`${r}:${s}`:(()=>{let a=n.filter(c=>c.endsWith(`:${s}`));if(!a.length)throw new I({message:`${p(s)}: \uD56D\uBAA9\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.`,hint:`${p("ui:action-button")}\uCC98\uB7FC registry\uB97C \uD3EC\uD568\uD574\uC11C \uC785\uB825\uD574\uBCF4\uC138\uC694.`});if(a.length>1)throw new I({message:`${p(s)}: \uAC19\uC740 \uC774\uB984\uC758 \uD56D\uBAA9\uC774 \uC5EC\uB7EC \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC5D0 \uC788\uC5B4\uC694.`,details:a.map(c=>`- ${c}`),hint:`${p("ui:action-button")}\uCC98\uB7FC registry\uB97C \uD3EC\uD568\uD574\uC11C \uC785\uB825\uD574\uBCF4\uC138\uC694.`});return a[0]})();if(!n.includes(i))throw new I({message:`${p(i)}: \uD56D\uBAA9\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.`});o.add(i)}return Array.from(o)}var rt=e=>{e.command("compat [...item-ids]","check snippet compatibility").option("-c, --component <component>","\uAC80\uC0AC\uD560 \uCEF4\uD3EC\uB10C\uD2B8. \uC5EC\uB7EC \uBC88 \uB610\uB294 \uC27C\uD45C\uB85C \uC9C0\uC815 \uAC00\uB2A5").option("-a, --all","\uBAA8\uB4E0 registry \uD56D\uBAA9\uC744 \uAC80\uC0AC",{default:!1}).option("-r, --registry <registryId>","\uCEF4\uD3EC\uB10C\uD2B8 shorthand \uC785\uB825 \uC2DC \uAE30\uBCF8 registry").option("--cwd <cwd>","the working directory. defaults to the current directory.",{default:process.cwd()}).option("-u, --baseUrl <baseUrl>","the base url of the registry. defaults to the current directory.",{default:F}).example("seed-design compat").example("seed-design compat -c action-button").example("seed-design compat ui:action-button ui:alert-dialog").example("seed-design compat --all").action(async(t,r)=>{let n=Date.now(),o=H(r),s=typeof r?.cwd=="string"?r.cwd:process.cwd();U.intro("seed-design compat");try{let i=ar.safeParse({itemIds:t,...r});if(!i.success)throw i.error;let{data:a}=i,{start:c,stop:d}=U.spinner();c("Registry\uB97C \uAC00\uC838\uC624\uACE0 \uC788\uC5B4\uC694...");let y=await(async()=>{try{let f=await Promise.all((await ie({baseUrl:a.baseUrl})).map(async({id:u})=>ne({baseUrl:a.baseUrl,registryId:u})));return d("Registry\uB97C \uAC00\uC838\uC654\uC5B4\uC694."),f}catch(f){throw d("Registry\uB97C \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694."),f}})(),w=cr({itemIds:a.itemIds,component:a.component}),C=a.all?y.flatMap(u=>u.items.map($=>`${u.id}:${$.id}`)):w.length>0?lr({publicRegistries:y,targetInputs:w,defaultRegistry:a.registry}):de(a.cwd),E=Array.isArray(C)?C:await(async()=>{let f=await C;if(!f)throw new I({message:"seed-design.json \uD30C\uC77C\uC774 \uC5C6\uC5B4 \uC124\uCE58\uB41C \uC2A4\uB2C8\uD3AB \uACBD\uB85C\uB97C \uC54C \uC218 \uC5C6\uC5B4\uC694.",hint:"`seed-design init`\uC73C\uB85C \uC124\uC815\uC744 \uB9CC\uB4E0 \uB4A4 \uC2E4\uD589\uD558\uAC70\uB098, `--all`/`-c`\uB85C \uAC80\uC0AC \uB300\uC0C1\uC744 \uC9C1\uC811 \uC9C0\uC815\uD574\uC8FC\uC138\uC694."});let u=tt.resolve(a.cwd,f.path),$=Qe({publicRegistries:y,rootPath:u});return $.length?$:(U.log.info(`${p(tt.relative(a.cwd,u)||f.path)}\uC5D0\uC11C \uC124\uCE58\uB41C \uC2A4\uB2C8\uD3AB\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC5B4\uC694.`),[])})();if(!E.length){try{await R.trackCommandOutcome(a.cwd,{command:"compat",status:"completed",result:"empty",properties:{duration_ms:Date.now()-n}})}catch(f){o&&console.error("[Telemetry] compat \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",f)}U.outro("\uAC80\uC0AC\uD560 \uC2A4\uB2C8\uD3AB\uC774 \uC5C6\uC5B4\uC694."),process.exit(0)}let x=le(a.cwd),h=pe({publicRegistries:y,itemKeys:E,projectPackageVersions:x});if(U.log.info(`\uAC80\uC0AC \uB300\uC0C1: ${p(h.checkedItemKeys.join(", "))}`),!h.issues.length){U.outro("\uBAA8\uB4E0 \uC2A4\uB2C8\uD3AB\uC774 \uD604\uC7AC @seed-design/react, @seed-design/css\uC640 \uD638\uD658\uB3FC\uC694.");try{await R.trackCommandOutcome(a.cwd,{command:"compat",status:"completed",result:"compatible",properties:{checked_items_count:h.checkedItemKeys.length,incompatible_items_count:0,duration_ms:Date.now()-n}})}catch(f){o&&console.error("[Telemetry] compat \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",f)}process.exit(0)}me({report:h,title:"\uD604\uC7AC \uD504\uB85C\uC81D\uD2B8 \uBC84\uC804\uACFC \uD638\uD658\uB418\uC9C0 \uC54A\uB294 \uC2A4\uB2C8\uD3AB\uC744 \uCC3E\uC558\uC5B4\uC694."}),U.log.info("\uD544\uC694\uD55C \uBC84\uC804\uC73C\uB85C @seed-design/react \uB610\uB294 @seed-design/css\uB97C \uB9DE\uCD98 \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD574\uBCF4\uC138\uC694."),U.outro("\uD638\uD658\uC131 \uC774\uC288\uAC00 \uC788\uC5B4\uC694.");try{await R.trackCommandOutcome(a.cwd,{command:"compat",status:"completed",result:"incompatible",properties:{checked_items_count:h.checkedItemKeys.length,incompatible_items_count:new Set(h.issues.map(f=>f.itemKey)).size,issue_count:h.issues.length,duration_ms:Date.now()-n}})}catch(f){o&&console.error("[Telemetry] compat \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",f)}process.exit(1)}catch(i){if(N(i)){try{await R.trackCommandOutcome(s,{command:"compat",status:"cancelled",properties:{duration_ms:Date.now()-n}})}catch(a){o&&console.error("[Telemetry] compat \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",a)}U.outro(p(i.message)),process.exit(0)}try{await R.trackCommandFailure(s,{command:"compat",error:i,properties:{duration_ms:Date.now()-n}})}catch(a){o&&console.error("[Telemetry] compat \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",a)}G(i,{defaultMessage:"\uD638\uD658\uC131 \uAC80\uC0AC\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694.",defaultHint:"`--verbose` \uC635\uC158\uC73C\uB85C \uC0C1\uC138 \uC624\uB958\uB97C \uD655\uC778\uD574\uBCF4\uC138\uC694.",verbose:o}),process.exit(1)}})};import*as v from"@clack/prompts";import{z as Ie}from"zod";var pr="https://raw.githubusercontent.com/daangn/seed-design/refs/heads/dev/docs/registry",mr=Ie.object({query:Ie.string().optional(),baseUrl:Ie.string().optional(),raw:Ie.boolean()});function st(e,t){return`${pr}/${e}/${t}`}function dr(e,t){let r=`${t}${e.docUrl}`,n=`${t}/llms${e.docUrl}.txt`,o=[e.id,`- docs: ${r}`,`- llms.txt: ${n}`];if(e.snippetKey&&e.snippets&&e.snippets.length>0){let[s]=e.snippetKey.split(":");if(s==="ui"||s==="breeze")if(e.snippets.length===1)o.push(`- snippet: ${st(s,e.snippets[0].path)}`);else{o.push("- snippet:");for(let i of e.snippets)o.push(` - ${i.label}: ${st(s,i.path)}`)}}v.log.message(o.join(`
|
|
15
|
-
`))}function
|
|
16
|
-
`)}function
|
|
14
|
+
\uC124\uCE58\uD560 \uC758\uC874\uC131: ${l(Array.from(b).join(", ")||"\uC5C6\uC74C")}`),await ke({registryItemsToAdd:w,rootPath:k,cwd:m,baseUrl:y,framework:u,config:g,onDiff:c.onDiff});let{installed:U,filtered:B}=await Pe({cwd:m,deps:Array.from(b)});U.size===0&&j.log.message("\uBAA8\uB4E0 \uC758\uC874\uC131\uC774 \uC774\uBBF8 \uC124\uCE58\uB418\uC5B4 \uC788\uC5B4\uC694."),U.size&&(j.log.message(`\uC758\uC874\uC131 \uC124\uCE58 \uC644\uB8CC: ${l(Array.from(U).join(", "))}`),B.size&&j.log.message(`\uC124\uCE58\uD558\uC9C0 \uC54A\uC740 \uC758\uC874\uC131 (\uC774\uBBF8 \uC124\uCE58\uB428): ${l(Array.from(B).join(", "))}`)),j.outro("\uC644\uB8CC\uD588\uC5B4\uC694.");let R=Date.now()-n,q=new Set(w.map(p=>p.registryId)),x=C.some(p=>{let[d,...T]=p.split(":"),M=T.join(":");return E.find(v=>v.id===d)?.items.find(v=>v.id===M)?.deprecated});try{await _.trackCommandOutcome(c.cwd,{command:"add",status:"completed",properties:{items_count:h.length,registries:Array.from(q),has_deprecated:x,dependencies_count:b.size,duration_ms:R}})}catch(p){o&&console.error("[Telemetry] add \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",p)}}catch(s){if(G(s)){try{await _.trackCommandOutcome(i,{command:"add",status:"cancelled",properties:{duration_ms:Date.now()-n}})}catch(a){o&&console.error("[Telemetry] add \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",a)}j.outro(l(s.message)),process.exit(0)}try{await _.trackCommandFailure(i,{command:"add",error:s,properties:{duration_ms:Date.now()-n}})}catch(a){o&&console.error("[Telemetry] add \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",a)}Y(s,{defaultMessage:"\uCD94\uAC00\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694.",defaultHint:"`--verbose` \uC635\uC158\uC73C\uB85C \uC0C1\uC138 \uC624\uB958\uB97C \uD655\uC778\uD574\uBCF4\uC138\uC694.",verbose:o}),process.exit(1)}})};import*as O from"@clack/prompts";import dr from"path";import{z as ee}from"zod";var fr=ee.object({registryIds:ee.array(ee.string()).optional(),all:ee.boolean(),includeDeprecated:ee.boolean().optional(),cwd:ee.string(),baseUrl:ee.string().default(K),framework:ee.enum(["react","lynx"]).optional(),onDiff:ee.enum(["overwrite","backup"]).optional()}),ot=e=>{e.command("add-all [...registry-ids]","add all items from registries").option("-a, --all","Add all items from all registries",{default:!1}).option("--include-deprecated","Include deprecated items when used with `--all`",{default:!1}).option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",{default:process.cwd()}).option("-u, --baseUrl <baseUrl>","the base url of the registry. defaults to the current directory.",{default:K}).option("-f, --framework <framework>","\uD504\uB808\uC784\uC6CC\uD06C (react \uB610\uB294 lynx)").option("--on-diff <mode>","Action when file differs: overwrite or backup").example("seed-design add-all ui --include-deprecated").example("seed-design add-all ui lib breeze").action(async(t,r)=>{let n=Date.now(),o=W(r),i=typeof r?.cwd=="string"?r.cwd:process.cwd();O.intro("seed-design add-all");try{let s=fr.safeParse({registryIds:t,...r});if(!s.success)throw s.error;let{data:a}=s,c=a.cwd,m=a.baseUrl,y=await $e(c),g=a.framework??y.framework,u=dr.resolve(c,y.path),{start:k,stop:I}=O.spinner();k("Registry\uB97C \uAC00\uC838\uC624\uACE0 \uC788\uC5B4\uC694...");let S=await(async()=>{try{let x=await Promise.all((await pe({baseUrl:m,framework:g})).map(async({id:p})=>de({baseUrl:m,framework:g,registryId:p})));return I("Registry\uB97C \uAC00\uC838\uC654\uC5B4\uC694."),x}catch(x){throw I("Registry\uB97C \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694."),x}})(),E=await(async()=>{if(a.all){let p=S.map(d=>d.id);return O.log.message(`\uBAA8\uB4E0 \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC758 \uBAA8\uB4E0 \uD56D\uBAA9\uC744 \uCD94\uAC00\uD569\uB2C8\uB2E4: ${l(p.join(", "))}`),p}if(a.registryIds?.length){let p=S.map(d=>d.id);for(let d of a.registryIds)if(!p.includes(d))throw new $({message:`\uB808\uC9C0\uC2A4\uD2B8\uB9AC '${d}'\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.`,details:[`\uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uB808\uC9C0\uC2A4\uD2B8\uB9AC: ${p.join(", ")}`]});return O.log.message(`\uC120\uD0DD\uB41C \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC758 \uBAA8\uB4E0 \uD56D\uBAA9\uC744 \uCD94\uAC00\uD569\uB2C8\uB2E4: ${l(a.registryIds.join(", "))}`),a.registryIds}let x=await O.multiselect({message:"\uCD94\uAC00\uD560 \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uB97C \uC120\uD0DD\uD574\uC8FC\uC138\uC694 (\uC2A4\uD398\uC774\uC2A4 \uBC14\uB85C \uC5EC\uB7EC \uAC1C \uC120\uD0DD \uAC00\uB2A5)",options:S.filter(({hideFromCLICatalog:p})=>!p).sort((p,d)=>d.items.length-p.items.length).map(p=>{let d=p.items[0]?.id,T=d?`${p.items.length}\uAC1C \uD56D\uBAA9 (${d} \uB4F1)`:`${p.items.length}\uAC1C \uD56D\uBAA9 (\uD56D\uBAA9 \uC5C6\uC74C)`;return{label:p.id,value:p.id,hint:T}})});if(O.isCancel(x))throw new D;return O.log.message(`\uC120\uD0DD\uB41C \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC758 \uD56D\uBAA9\uC744 \uCD94\uAC00\uD569\uB2C8\uB2E4: ${l(x.join(", "))}`),x})(),C=S.filter(x=>E.includes(x.id)),h=C.flatMap(x=>x.items.filter(p=>p.deprecated?a.includeDeprecated:!0).map(p=>`${x.id}:${p.id}`)),w=C.reduce((x,p)=>x+p.items.filter(d=>d.deprecated).length,0);if(!a.includeDeprecated&&w>0&&O.log.info(`${w}\uAC1C\uC758 deprecated \uD56D\uBAA9\uC740 \uC81C\uC678\uB418\uC5C8\uC5B4\uC694. --include-deprecated \uC635\uC158\uC744 \uC0AC\uC6A9\uD558\uBA74 \uCD94\uAC00\uD560 \uC218 \uC788\uC5B4\uC694.`),!h.length)throw new D("\uCD94\uAC00\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC5B4\uC694.");O.log.message(`\uCD1D ${l(h.length.toString())}\uAC1C\uC758 \uD56D\uBAA9\uC744 \uCD94\uAC00\uD569\uB2C8\uB2E4.`);let{registryItemsToAdd:b,npmDependenciesToAdd:P}=xe({selectedItemKeys:h,publicRegistries:S}),U=ue({publicRegistries:S,itemKeys:b.flatMap(({registryId:x,items:p})=>p.map(d=>`${x}:${d.id}`)),projectPackageVersions:ge(a.cwd,g),framework:g});ye({report:U,title:"\uD604\uC7AC \uD504\uB85C\uC81D\uD2B8 \uBC84\uC804\uACFC \uD638\uD658\uB418\uC9C0 \uC54A\uC744 \uC218 \uC788\uB294 \uC2A4\uB2C8\uD3AB\uC774 \uC788\uC5B4\uC694.",framework:g}),await ke({registryItemsToAdd:b,rootPath:u,cwd:c,baseUrl:m,framework:g,config:y,onDiff:a.onDiff});let{installed:B,filtered:R}=await Pe({cwd:c,deps:Array.from(P)});B.size===0&&O.log.message("\uBAA8\uB4E0 \uC758\uC874\uC131\uC774 \uC774\uBBF8 \uC124\uCE58\uB418\uC5B4 \uC788\uC5B4\uC694."),B.size&&(O.log.message(`\uC758\uC874\uC131 \uC124\uCE58 \uC644\uB8CC: ${l(Array.from(B).join(", "))}`),R.size&&O.log.message(`\uC124\uCE58\uD558\uC9C0 \uC54A\uC740 \uC758\uC874\uC131 (\uC774\uBBF8 \uC124\uCE58\uB428): ${l(Array.from(R).join(", "))}`)),O.outro("\uC644\uB8CC\uD588\uC5B4\uC694.");let q=Date.now()-n;try{await _.trackCommandOutcome(a.cwd,{command:"add-all",status:"completed",properties:{registries:E,items_count:h.length,include_deprecated:a.includeDeprecated||!1,dependencies_count:P.size,duration_ms:q}})}catch(x){o&&console.error("[Telemetry] add-all \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",x)}}catch(s){if(G(s)){try{await _.trackCommandOutcome(i,{command:"add-all",status:"cancelled",properties:{duration_ms:Date.now()-n}})}catch(a){o&&console.error("[Telemetry] add-all \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",a)}O.outro(l(s.message)),process.exit(0)}try{await _.trackCommandFailure(i,{command:"add-all",error:s,properties:{duration_ms:Date.now()-n}})}catch(a){o&&console.error("[Telemetry] add-all \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",a)}Y(s,{defaultMessage:"\uCD94\uAC00\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694.",defaultHint:"`--verbose` \uC635\uC158\uC73C\uB85C \uC0C1\uC138 \uC624\uB958\uB97C \uD655\uC778\uD574\uBCF4\uC138\uC694.",verbose:o}),process.exit(1)}})};import*as N from"@clack/prompts";import it from"path";import{z}from"zod";var gr=z.object({itemIds:z.array(z.string()).optional(),component:z.union([z.string(),z.array(z.string())]).optional(),all:z.boolean(),registry:z.string().optional(),cwd:z.string(),baseUrl:z.string().default(K),framework:z.enum(["react","lynx"]).optional()});function ur({itemIds:e,component:t}){let r=i=>i.trim().replace(/\s+/g,"-"),n=(e??[]).map(r).filter(Boolean),o=(Array.isArray(t)?t:[t]).filter(i=>!!i).flatMap(i=>i.split(",")).map(r).filter(Boolean);return Array.from(new Set([...n,...o]))}function yr({publicRegistries:e,targetInputs:t,defaultRegistry:r}){let n=e.filter(i=>typeof i.id=="string"&&Array.isArray(i.items)).flatMap(i=>i.items.filter(s=>typeof s.id=="string").map(s=>`${i.id}:${s.id}`)),o=new Set;for(let i of t){let s=i.includes(":")?i:r?`${r}:${i}`:(()=>{let a=n.filter(c=>c.endsWith(`:${i}`));if(!a.length)throw new $({message:`${l(i)}: \uD56D\uBAA9\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.`,hint:`${l("ui:action-button")}\uCC98\uB7FC registry\uB97C \uD3EC\uD568\uD574\uC11C \uC785\uB825\uD574\uBCF4\uC138\uC694.`});if(a.length>1)throw new $({message:`${l(i)}: \uAC19\uC740 \uC774\uB984\uC758 \uD56D\uBAA9\uC774 \uC5EC\uB7EC \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC5D0 \uC788\uC5B4\uC694.`,details:a.map(c=>`- ${c}`),hint:`${l("ui:action-button")}\uCC98\uB7FC registry\uB97C \uD3EC\uD568\uD574\uC11C \uC785\uB825\uD574\uBCF4\uC138\uC694.`});return a[0]})();if(!n.includes(s))throw new $({message:`${l(s)}: \uD56D\uBAA9\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.`});o.add(s)}return Array.from(o)}var nt=e=>{e.command("compat [...item-ids]","check snippet compatibility").option("-c, --component <component>","\uAC80\uC0AC\uD560 \uCEF4\uD3EC\uB10C\uD2B8. \uC5EC\uB7EC \uBC88 \uB610\uB294 \uC27C\uD45C\uB85C \uC9C0\uC815 \uAC00\uB2A5").option("-a, --all","\uBAA8\uB4E0 registry \uD56D\uBAA9\uC744 \uAC80\uC0AC",{default:!1}).option("-r, --registry <registryId>","\uCEF4\uD3EC\uB10C\uD2B8 shorthand \uC785\uB825 \uC2DC \uAE30\uBCF8 registry").option("--cwd <cwd>","the working directory. defaults to the current directory.",{default:process.cwd()}).option("-u, --baseUrl <baseUrl>","the base url of the registry. defaults to the current directory.",{default:K}).option("-f, --framework <framework>","\uD504\uB808\uC784\uC6CC\uD06C (react \uB610\uB294 lynx)").example("seed-design compat").example("seed-design compat -c action-button").example("seed-design compat ui:action-button ui:alert-dialog").example("seed-design compat --all").action(async(t,r)=>{let n=Date.now(),o=W(r),i=typeof r?.cwd=="string"?r.cwd:process.cwd();N.intro("seed-design compat");try{let s=gr.safeParse({itemIds:t,...r});if(!s.success)throw s.error;let{data:a}=s,c=await oe(a.cwd),m=a.framework??c?.framework??"react",{start:y,stop:g}=N.spinner();y("Registry\uB97C \uAC00\uC838\uC624\uACE0 \uC788\uC5B4\uC694...");let u=await(async()=>{try{let w=await Promise.all((await pe({baseUrl:a.baseUrl,framework:m})).map(async({id:b})=>de({baseUrl:a.baseUrl,framework:m,registryId:b})));return g("Registry\uB97C \uAC00\uC838\uC654\uC5B4\uC694."),w}catch(w){throw g("Registry\uB97C \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694."),w}})(),k=ur({itemIds:a.itemIds,component:a.component}),I=a.all?u.flatMap(b=>b.items.map(P=>`${b.id}:${P.id}`)):k.length>0?yr({publicRegistries:u,targetInputs:k,defaultRegistry:a.registry}):oe(a.cwd),S=Array.isArray(I)?I:await(async()=>{let w=await I;if(!w)throw new $({message:"seed-design.json \uD30C\uC77C\uC774 \uC5C6\uC5B4 \uC124\uCE58\uB41C \uC2A4\uB2C8\uD3AB \uACBD\uB85C\uB97C \uC54C \uC218 \uC5C6\uC5B4\uC694.",hint:"`seed-design init`\uC73C\uB85C \uC124\uC815\uC744 \uB9CC\uB4E0 \uB4A4 \uC2E4\uD589\uD558\uAC70\uB098, `--all`/`-c`\uB85C \uAC80\uC0AC \uB300\uC0C1\uC744 \uC9C1\uC811 \uC9C0\uC815\uD574\uC8FC\uC138\uC694."});let b=it.resolve(a.cwd,w.path),P=rt({publicRegistries:u,rootPath:b});return P.length?P:(N.log.info(`${l(it.relative(a.cwd,b)||w.path)}\uC5D0\uC11C \uC124\uCE58\uB41C \uC2A4\uB2C8\uD3AB\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC5B4\uC694.`),[])})();if(!S.length){try{await _.trackCommandOutcome(a.cwd,{command:"compat",status:"completed",result:"empty",properties:{duration_ms:Date.now()-n}})}catch(w){o&&console.error("[Telemetry] compat \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",w)}N.outro("\uAC80\uC0AC\uD560 \uC2A4\uB2C8\uD3AB\uC774 \uC5C6\uC5B4\uC694."),process.exit(0)}let E=ge(a.cwd,m),C=ue({publicRegistries:u,itemKeys:S,projectPackageVersions:E,framework:m});if(N.log.info(`\uAC80\uC0AC \uB300\uC0C1: ${l(C.checkedItemKeys.join(", "))}`),!C.issues.length){let w=ie(m);N.outro(`\uBAA8\uB4E0 \uC2A4\uB2C8\uD3AB\uC774 \uD604\uC7AC ${w.join(", ")}\uC640 \uD638\uD658\uB3FC\uC694.`);try{await _.trackCommandOutcome(a.cwd,{command:"compat",status:"completed",result:"compatible",properties:{checked_items_count:C.checkedItemKeys.length,incompatible_items_count:0,duration_ms:Date.now()-n}})}catch(b){o&&console.error("[Telemetry] compat \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",b)}process.exit(0)}ye({report:C,title:"\uD604\uC7AC \uD504\uB85C\uC81D\uD2B8 \uBC84\uC804\uACFC \uD638\uD658\uB418\uC9C0 \uC54A\uB294 \uC2A4\uB2C8\uD3AB\uC744 \uCC3E\uC558\uC5B4\uC694.",framework:m});let h=ie(m);N.log.info(`\uD544\uC694\uD55C \uBC84\uC804\uC73C\uB85C ${h.join(" \uB610\uB294 ")}\uB97C \uB9DE\uCD98 \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD574\uBCF4\uC138\uC694.`),N.outro("\uD638\uD658\uC131 \uC774\uC288\uAC00 \uC788\uC5B4\uC694.");try{await _.trackCommandOutcome(a.cwd,{command:"compat",status:"completed",result:"incompatible",properties:{checked_items_count:C.checkedItemKeys.length,incompatible_items_count:new Set(C.issues.map(w=>w.itemKey)).size,issue_count:C.issues.length,duration_ms:Date.now()-n}})}catch(w){o&&console.error("[Telemetry] compat \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",w)}process.exit(1)}catch(s){if(G(s)){try{await _.trackCommandOutcome(i,{command:"compat",status:"cancelled",properties:{duration_ms:Date.now()-n}})}catch(a){o&&console.error("[Telemetry] compat \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",a)}N.outro(l(s.message)),process.exit(0)}try{await _.trackCommandFailure(i,{command:"compat",error:s,properties:{duration_ms:Date.now()-n}})}catch(a){o&&console.error("[Telemetry] compat \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",a)}Y(s,{defaultMessage:"\uD638\uD658\uC131 \uAC80\uC0AC\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694.",defaultHint:"`--verbose` \uC635\uC158\uC73C\uB85C \uC0C1\uC138 \uC624\uB958\uB97C \uD655\uC778\uD574\uBCF4\uC138\uC694.",verbose:o}),process.exit(1)}})};import*as A from"@clack/prompts";import{z as te}from"zod";var hr="https://raw.githubusercontent.com/daangn/seed-design/refs/heads/dev/docs/registry",wr=te.object({query:te.union([te.string(),te.array(te.string())]).optional().transform(e=>{let r=(Array.isArray(e)?e.join(" "):e)?.trim();return r||void 0}),baseUrl:te.string().optional(),cwd:te.string().default(process.cwd()),framework:te.enum(["react","lynx"]).optional(),raw:te.boolean()});function at(e,t){return`${hr}/${e}/${t}`}function br(e,t){let r=`${t}${e.docUrl}`,n=`${t}/llms${e.docUrl}.txt`,o=[e.id,`- docs: ${r}`,`- llms.txt: ${n}`];if(e.snippetKey&&e.snippets&&e.snippets.length>0){let[i]=e.snippetKey.split(":");if(i)if(e.snippets.length===1)o.push(`- snippet: ${at(i,e.snippets[0].path)}`);else{o.push("- snippet:");for(let s of e.snippets)o.push(` - ${s.label}: ${at(i,s.path)}`)}}A.log.message(o.join(`
|
|
15
|
+
`))}function Cr(e,t){let r=e.length,n=t.length,o=Array.from({length:r+1},(i,s)=>Array.from({length:n+1},(a,c)=>s===0?c:c===0?s:0));for(let i=1;i<=r;i++)for(let s=1;s<=n;s++)o[i][s]=Math.min(o[i-1][s]+1,o[i][s-1]+1,o[i-1][s-1]+(e[i-1]!==t[s-1]?1:0));return o[r][n]}function ae(e,t,r=3){let n=e.toLowerCase();return t.map(o=>({value:o,dist:Cr(n,o.toLowerCase())})).filter(({dist:o})=>o>0&&o<=r).sort((o,i)=>o.dist-i.dist).map(({value:o})=>o)}function $r(e,t){if(e.length===0)return;let r=[],n=t.map(s=>s.id),o=ae(e[0],n);if(o.length===0){let s=t.flatMap(m=>m.sections.flatMap(y=>y.items.map(g=>`${m.id}/${y.id}/${g.id}`))),a=e.join("/"),c=ae(a,s,5);c.length>0&&r.push(...c.slice(0,3))}else{let s=t.find(a=>a.id===o[0]);if(s&&e.length>=2){let a=s.sections.map(m=>m.id),c=ae(e[1],a);if(c.length>0){let m=s.sections.find(y=>y.id===c[0]);if(m&&e.length>=3){let y=m.items.map(u=>u.id),g=ae(e[2],y);for(let u of g.slice(0,3))r.push(`${s.id}/${m.id}/${u}`)}else for(let y of c.slice(0,3))r.push(`${s.id}/${y}`)}else{let m=s.sections.flatMap(g=>g.items.map(u=>({path:`${s.id}/${g.id}/${u.id}`,id:u.id}))),y=ae(e[1],m.map(g=>g.id));for(let g of y.slice(0,3)){let u=m.find(k=>k.id===g);u&&r.push(u.path)}}}else for(let a of o.slice(0,3))r.push(a)}if(r.length===0)return;let i=["","\u{1F4A1} \uC774\uAC83\uC744 \uC758\uBBF8\uD588\uB098\uC694?"];for(let s of r)i.push(` - ${s}`);return i.join(`
|
|
16
|
+
`)}function lt(e){return e.split(/[\/\s]+/).map(t=>t.trim()).filter(Boolean)}function xr(e){let[,t]=e.split(":");return t??e}function Ir({query:e,framework:t,categoryIds:r}){if(!e)return;let n=lt(e).map(xr);if(!n.length)return;let[o]=n;return!r.includes(o)&&t&&r.includes(t)?[t,...n].join("/"):n.join("/")}function kr(e,t){let r=t.toLowerCase();return e.flatMap(n=>n.sections.flatMap(o=>o.items.filter(i=>i.id.toLowerCase().includes(r)||i.title.toLowerCase().includes(r)).map(i=>({item:i,categoryLabel:n.label,sectionLabel:o.label}))))}async function we(e){let t=await A.select({message:"\uD56D\uBAA9\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694",options:e.map(r=>({label:`${r.deprecated?"(deprecated) ":""}${r.title}`,value:r,hint:r.description}))});if(A.isCancel(t))throw new D;return t}async function ct(e){let t=await A.select({message:"\uC139\uC158\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694",options:e.map(r=>({label:r.label,value:r,hint:`${r.items.length}\uAC1C \uD56D\uBAA9`}))});if(A.isCancel(t))throw new D;return t}async function Pr(e){let t=await A.select({message:"\uCE74\uD14C\uACE0\uB9AC\uB97C \uC120\uD0DD\uD574\uC8FC\uC138\uC694",options:e.map(r=>({label:r.label,value:r,hint:`${r.sections.reduce((n,o)=>n+o.items.length,0)}\uAC1C \uD56D\uBAA9`}))});if(A.isCancel(t))throw new D;return t}var mt=e=>{e.command("docs [...query]","\uBB38\uC11C \uB9C1\uD06C, llms.txt \uB9C1\uD06C, \uC2A4\uB2C8\uD3AB \uB9C1\uD06C\uB97C \uC870\uD68C\uD569\uB2C8\uB2E4").option("-u, --baseUrl <baseUrl>",`\uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC758 \uAE30\uBCF8 URL (\uAE30\uBCF8\uAC12: ${K})`,{default:K}).option("--cwd <cwd>","the working directory. defaults to the current directory.",{default:process.cwd()}).option("-f, --framework <framework>","\uD504\uB808\uC784\uC6CC\uD06C (react \uB610\uB294 lynx)").option("--raw","llms.txt \uB0B4\uC6A9\uC744 \uC9C1\uC811 \uAC00\uC838\uC640 \uCD9C\uB825\uD569\uB2C8\uB2E4. LLM \uD30C\uC774\uD504\uC5D0 \uC720\uC6A9\uD569\uB2C8\uB2E4.",{default:!1}).example("seed-design docs").example("seed-design docs action-button").example("seed-design docs react").example("seed-design docs lynx action-button").example("seed-design docs react/components").example("seed-design docs react/components/action-button").example("seed-design docs react/updates/changelog --raw").action(async(t,r)=>{let n=Date.now(),o=W(r),i=r.raw??!1,s=process.cwd();i||A.intro("seed-design docs");try{let a=wr.safeParse({query:t,...r});if(!a.success)throw a.error;let{data:c}=a;s=c.cwd;let m=c.baseUrl??K,y=await oe(c.cwd).catch(()=>null),g=c.framework??y?.framework;if(c.raw&&!c.query)throw new $({message:"--raw \uBAA8\uB4DC\uC5D0\uC11C\uB294 \uCFFC\uB9AC\uAC00 \uD544\uC694\uD574\uC694.",hint:"\uC608: `seed-design docs react/updates/changelog --raw`"});let u=await(async()=>{if(i)return await _e({baseUrl:m});let{start:h,stop:w}=A.spinner();h("\uBB38\uC11C \uBAA9\uB85D\uC744 \uAC00\uC838\uC624\uACE0 \uC788\uC5B4\uC694...");try{let b=await _e({baseUrl:m});return w("\uBB38\uC11C \uBAA9\uB85D\uC744 \uAC00\uC838\uC654\uC5B4\uC694."),b}catch(b){throw w("\uBB38\uC11C \uBAA9\uB85D\uC744 \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694."),b}})(),{categories:k}=u,I=Ir({query:c.query,framework:g,categoryIds:k.map(h=>h.id)}),S,E=async()=>{if(I){let b=lt(I);if(i&&b.length>3)return;let P=k.find(R=>R.id===b[0]);if(P&&b.length>=2){let R=P.sections.find(d=>d.id===b[1]);if(R&&b.length>=3){let d=R.items.find(v=>v.id===b[2]);if(d)return d;let T=b[2].toLowerCase(),M=R.items.filter(v=>v.id.toLowerCase().includes(T)||v.title.toLowerCase().includes(T));if(M.length===0){let v=ae(b[2],R.items.map(he=>he.id)),L=v.length>0?`
|
|
17
17
|
|
|
18
18
|
\u{1F4A1} \uC774\uAC83\uC744 \uC758\uBBF8\uD588\uB098\uC694?
|
|
19
|
-
${
|
|
20
|
-
`)}`:"";throw new
|
|
19
|
+
${v.slice(0,3).map(he=>` - ${P.id}/${R.id}/${he}`).join(`
|
|
20
|
+
`)}`:"";throw new $({message:`${l(I)}: \uBB38\uC11C\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.${L}`,hint:`\`seed-design docs ${P.id}/${R.id}\`\uB85C \uBAA9\uB85D\uC744 \uD655\uC778\uD574\uBCF4\uC138\uC694.`})}return M.length===1?M[0]:await we(M)}if(R)return await we(R.items);let q=b[1].toLowerCase(),x=P.sections.flatMap(d=>d.items.filter(T=>T.id.toLowerCase().includes(q)||T.title.toLowerCase().includes(q)).map(T=>({item:T,sectionLabel:d.label})));if(x.length===0){let d=P.sections.map(F=>F.id),T=ae(b[1],d),M=P.sections.flatMap(F=>F.items.map(be=>({path:`${P.id}/${F.id}/${be.id}`,id:be.id}))),v=ae(b[1],M.map(F=>F.id)),L=[...T.slice(0,2).map(F=>`${P.id}/${F}`),...v.slice(0,2).map(F=>M.find(be=>be.id===F)?.path).filter(F=>F!=null)],he=L.length>0?`
|
|
21
21
|
|
|
22
22
|
\u{1F4A1} \uC774\uAC83\uC744 \uC758\uBBF8\uD588\uB098\uC694?
|
|
23
|
-
${
|
|
24
|
-
`)}`:"";throw new
|
|
23
|
+
${L.map(F=>` - ${F}`).join(`
|
|
24
|
+
`)}`:"";throw new $({message:`${l(I)}: \uBB38\uC11C\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.${he}`,hint:`\`seed-design docs ${P.id}\`\uB85C \uBAA9\uB85D\uC744 \uD655\uC778\uD574\uBCF4\uC138\uC694.`})}if(x.length===1)return x[0].item;let p=await A.select({message:`${l(b[1])}\uC5D0 \uD574\uB2F9\uD558\uB294 \uD56D\uBAA9\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694`,options:x.map(({item:d,sectionLabel:T})=>({label:`[${T}] ${d.title}`,value:d,hint:d.description}))});if(A.isCancel(p))throw new D;return p}if(P){if(P.sections.length===1)return await we(P.sections[0].items);let R=await ct(P.sections);return await we(R.items)}let U=kr(k,I);if(U.length===0){let R=$r(b,k);throw new $({message:`${l(I)}: \uBB38\uC11C\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.${R??""}`,hint:"`seed-design docs`\uB85C \uC804\uCCB4 \uBAA9\uB85D\uC744 \uD655\uC778\uD574\uBCF4\uC138\uC694."})}if(U.length===1)return U[0].item;let B=await A.select({message:`${l(I)}\uC5D0 \uD574\uB2F9\uD558\uB294 \uD56D\uBAA9\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694`,options:U.map(({item:R,categoryLabel:q,sectionLabel:x})=>({label:`[${q} > ${x}] ${R.title}`,value:R,hint:R.description}))});if(A.isCancel(B))throw new D;return B}let h=await Pr(k),w;return h.sections.length===1?w=h.sections[0]:w=await ct(h.sections),await we(w.items)};if(i)try{S=await E()}catch(h){if(G(h))throw h}else S=await E();if(i){let h;if(S){let w=`${m}/llms${S.docUrl}.txt`;h=await Ue({url:w})}else h=await Ke({baseUrl:m,query:I});console.log(h)}else br(S,m),A.outro("\uC644\uB8CC\uD588\uC5B4\uC694.");let C=Date.now()-n;try{await _.trackCommandOutcome(s,{command:"docs",status:"completed",properties:{query:c.query??null,item_id:S?.id??c.query??null,has_snippet:!!(S?.snippets&&S.snippets.length>0),raw_mode:i,duration_ms:C}})}catch(h){o&&console.error("[Telemetry] docs \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",h)}}catch(a){if(G(a)){try{await _.trackCommandOutcome(s,{command:"docs",status:"cancelled",properties:{raw_mode:i,duration_ms:Date.now()-n}})}catch(c){o&&console.error("[Telemetry] docs \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",c)}i||A.outro(l(a.message)),process.exit(0)}try{await _.trackCommandFailure(s,{command:"docs",error:a,properties:{raw_mode:i,duration_ms:Date.now()-n}})}catch(c){o&&console.error("[Telemetry] docs \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",c)}if(i){let c=a instanceof Error?a.message:String(a);console.error(c),process.exit(1)}Y(a,{defaultMessage:"\uBB38\uC11C \uC870\uD68C\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694.",defaultHint:"`--verbose` \uC635\uC158\uC73C\uB85C \uC0C1\uC138 \uC624\uB958\uB97C \uD655\uC778\uD574\uBCF4\uC138\uC694.",verbose:o}),process.exit(1)}})};import*as V from"@clack/prompts";import{z as Se}from"zod";import Sr from"dedent";var Er=Se.object({cwd:Se.string(),yes:Se.boolean().optional(),default:Se.boolean().optional()}),pt=e=>{e.command("init","seed-design.json \uD30C\uC77C \uC0DD\uC131").option("-c, --cwd <cwd>","\uC791\uC5C5 \uB514\uB809\uD1A0\uB9AC. \uAE30\uBCF8\uAC12\uC740 \uD604\uC7AC \uB514\uB809\uD1A0\uB9AC.",{default:process.cwd()}).option("-y, --yes","\uBAA8\uB4E0 \uC9C8\uBB38\uC5D0 \uB300\uD574 \uAE30\uBCF8\uAC12\uC73C\uB85C \uB2F5\uBCC0\uD569\uB2C8\uB2E4.").option("--default","Deprecated. --yes\uC640 \uB3D9\uC77C\uD558\uAC8C \uAE30\uBCF8\uAC12\uC73C\uB85C \uC0DD\uC131\uD569\uB2C8\uB2E4.").action(async t=>{let r=Date.now(),n=W(t),o=typeof t?.cwd=="string"?t.cwd:process.cwd();V.intro("seed-design.json \uD30C\uC77C \uC0DD\uC131");try{let i=Er.safeParse(t);if(!i.success)throw i.error;let s=i.data,a=s.yes||s.default,c=a?{...H,framework:Ee(s.cwd)}:await Ae(s.cwd),{start:m,stop:y}=V.spinner();m("seed-design.json \uD30C\uC77C \uC0DD\uC131\uC911...");let g=await(async()=>{try{return(await Ce({cwd:s.cwd,config:c})).relativePath}catch(k){throw y("seed-design.json \uD30C\uC77C \uC0DD\uC131\uC774 \uC911\uB2E8\uB410\uC5B4\uC694."),k}})();y(`seed-design.json \uD30C\uC77C\uC774 ${l(g)}\uC5D0 \uC0DD\uC131\uB410\uC5B4\uC694.`),V.log.info(l("seed-design add {component} \uBA85\uB839\uC5B4\uB85C \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uCD94\uAC00\uD574\uBCF4\uC138\uC694!")),V.log.info(l("seed-design add \uBA85\uB839\uC5B4\uB85C \uCD94\uAC00\uD560 \uC218 \uC788\uB294 \uBAA8\uB4E0 \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uD655\uC778\uD574\uBCF4\uC138\uC694.")),V.note(Sr(`SEED Design CLI\uB294 \uAC1C\uC120\uC744 \uC704\uD574 \uC775\uBA85 \uC0AC\uC6A9 \uB370\uC774\uD130\uB97C \uC218\uC9D1\uD574\uC694.
|
|
25
25
|
|
|
26
26
|
\uBE44\uD65C\uC131\uD654\uD558\uB824\uBA74:
|
|
27
|
-
\u2022 seed-design.json\uC5D0\uC11C ${
|
|
28
|
-
\u2022 ${
|
|
27
|
+
\u2022 seed-design.json\uC5D0\uC11C ${l('"telemetry": false')}\uB85C \uC124\uC815
|
|
28
|
+
\u2022 ${l("DISABLE_TELEMETRY=true")} \uD658\uACBD \uBCC0\uC218 \uC124\uC815
|
|
29
29
|
|
|
30
|
-
\uC790\uC138\uD55C \uB0B4\uC6A9: https://seed-design.com/react/getting-started/cli/configuration#telemetry`),"Telemetry \uC548\uB0B4"),
|
|
30
|
+
\uC790\uC138\uD55C \uB0B4\uC6A9: https://seed-design.com/react/getting-started/cli/configuration#telemetry`),"Telemetry \uC548\uB0B4"),V.outro("\uC791\uC5C5\uC774 \uC644\uB8CC\uB410\uC5B4\uC694.");let u=Date.now()-r;try{await _.trackCommandOutcome(s.cwd,{command:"init",status:"completed",properties:{tsx:c.tsx,rsc:c.rsc,telemetry:c.telemetry,yes_option:a,duration_ms:u}})}catch(k){n&&console.error("[Telemetry] init \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",k)}}catch(i){if(G(i)){try{await _.trackCommandOutcome(o,{command:"init",status:"cancelled",properties:{duration_ms:Date.now()-r}})}catch(s){n&&console.error("[Telemetry] init \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",s)}V.outro(l(i.message)),process.exit(0)}try{await _.trackCommandFailure(o,{command:"init",error:i,properties:{duration_ms:Date.now()-r}})}catch(s){n&&console.error("[Telemetry] init \uC774\uBCA4\uD2B8 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694:",s)}Y(i,{defaultMessage:"seed-design.json \uD30C\uC77C \uC0DD\uC131\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694.",defaultHint:"`--verbose` \uC635\uC158\uC73C\uB85C \uC0C1\uC138 \uC624\uB958\uB97C \uD655\uC778\uD574\uBCF4\uC138\uC694.",verbose:n}),process.exit(1)}})};import{cac as Rr}from"cac";var Tr="seed-design",re=Rr(Tr);async function vr(){let e=se();re.option("--verbose","\uC624\uB958 \uC0C1\uC138 \uC815\uBCF4\uB97C \uCD9C\uB825\uD569\uB2C8\uB2E4."),st(re),ot(re),nt(re),mt(re),pt(re),re.version(e.version||"1.0.0","-v, --version"),re.help(),re.parse()}vr();
|
package/package.json
CHANGED
package/src/commands/add-all.ts
CHANGED
|
@@ -30,6 +30,7 @@ const addAllOptionsSchema = z.object({
|
|
|
30
30
|
includeDeprecated: z.boolean().optional(),
|
|
31
31
|
cwd: z.string(),
|
|
32
32
|
baseUrl: z.string().default(BASE_URL),
|
|
33
|
+
framework: z.enum(["react", "lynx"]).optional(),
|
|
33
34
|
onDiff: z.enum(["overwrite", "backup"]).optional(),
|
|
34
35
|
});
|
|
35
36
|
|
|
@@ -50,6 +51,7 @@ export const addAllCommand = (cli: CAC) => {
|
|
|
50
51
|
"the base url of the registry. defaults to the current directory.",
|
|
51
52
|
{ default: BASE_URL },
|
|
52
53
|
)
|
|
54
|
+
.option("-f, --framework <framework>", "프레임워크 (react 또는 lynx)")
|
|
53
55
|
.option("--on-diff <mode>", "Action when file differs: overwrite or backup")
|
|
54
56
|
.example("seed-design add-all ui --include-deprecated")
|
|
55
57
|
.example("seed-design add-all ui lib breeze")
|
|
@@ -70,6 +72,7 @@ export const addAllCommand = (cli: CAC) => {
|
|
|
70
72
|
const cwd = options.cwd;
|
|
71
73
|
const baseUrl = options.baseUrl;
|
|
72
74
|
const config = await getConfig(cwd);
|
|
75
|
+
const framework = options.framework ?? config.framework;
|
|
73
76
|
const rootPath = path.resolve(cwd, config.path);
|
|
74
77
|
|
|
75
78
|
const { start, stop } = p.spinner();
|
|
@@ -78,8 +81,8 @@ export const addAllCommand = (cli: CAC) => {
|
|
|
78
81
|
const publicRegistries = await (async () => {
|
|
79
82
|
try {
|
|
80
83
|
const registries = await Promise.all(
|
|
81
|
-
(await fetchAvailableRegistries({ baseUrl })).map(async ({ id }) =>
|
|
82
|
-
fetchRegistry({ baseUrl, registryId: id }),
|
|
84
|
+
(await fetchAvailableRegistries({ baseUrl, framework })).map(async ({ id }) =>
|
|
85
|
+
fetchRegistry({ baseUrl, framework, registryId: id }),
|
|
83
86
|
),
|
|
84
87
|
);
|
|
85
88
|
stop("Registry를 가져왔어요.");
|
|
@@ -187,12 +190,14 @@ export const addAllCommand = (cli: CAC) => {
|
|
|
187
190
|
itemKeys: registryItemsToAdd.flatMap(({ registryId, items }) =>
|
|
188
191
|
items.map((item) => `${registryId}:${item.id}`),
|
|
189
192
|
),
|
|
190
|
-
projectPackageVersions: getProjectSeedPackageVersionSpecs(options.cwd),
|
|
193
|
+
projectPackageVersions: getProjectSeedPackageVersionSpecs(options.cwd, framework),
|
|
194
|
+
framework,
|
|
191
195
|
});
|
|
192
196
|
|
|
193
197
|
logCompatibilityReport({
|
|
194
198
|
report: compatibilityReport,
|
|
195
199
|
title: "현재 프로젝트 버전과 호환되지 않을 수 있는 스니펫이 있어요.",
|
|
200
|
+
framework,
|
|
196
201
|
});
|
|
197
202
|
|
|
198
203
|
await writeRegistryItemSnippets({
|
|
@@ -200,6 +205,7 @@ export const addAllCommand = (cli: CAC) => {
|
|
|
200
205
|
rootPath,
|
|
201
206
|
cwd,
|
|
202
207
|
baseUrl,
|
|
208
|
+
framework,
|
|
203
209
|
config,
|
|
204
210
|
onDiff: options.onDiff,
|
|
205
211
|
});
|
package/src/commands/add.ts
CHANGED
|
@@ -32,6 +32,7 @@ const addOptionsSchema = z.object({
|
|
|
32
32
|
all: z.boolean(),
|
|
33
33
|
cwd: z.string(),
|
|
34
34
|
baseUrl: z.string().default(BASE_URL),
|
|
35
|
+
framework: z.enum(["react", "lynx"]).optional(),
|
|
35
36
|
onDiff: z.enum(["overwrite", "backup"]).optional(),
|
|
36
37
|
});
|
|
37
38
|
|
|
@@ -49,6 +50,7 @@ export const addCommand = (cli: CAC) => {
|
|
|
49
50
|
"the base url of the registry. defaults to the current directory.",
|
|
50
51
|
{ default: BASE_URL },
|
|
51
52
|
)
|
|
53
|
+
.option("-f, --framework <framework>", "프레임워크 (react 또는 lynx)")
|
|
52
54
|
.option("--on-diff <mode>", "Action when file differs: overwrite or backup")
|
|
53
55
|
.example("seed-design add ui:action-button")
|
|
54
56
|
.example("seed-design add ui:alert-dialog")
|
|
@@ -78,6 +80,7 @@ export const addCommand = (cli: CAC) => {
|
|
|
78
80
|
const cwd = options.cwd;
|
|
79
81
|
const baseUrl = options.baseUrl;
|
|
80
82
|
const config = await getConfig(cwd);
|
|
83
|
+
const framework = options.framework ?? config.framework;
|
|
81
84
|
const rootPath = path.resolve(cwd, config.path);
|
|
82
85
|
|
|
83
86
|
const { start, stop } = p.spinner();
|
|
@@ -86,8 +89,8 @@ export const addCommand = (cli: CAC) => {
|
|
|
86
89
|
const publicRegistries = await (async () => {
|
|
87
90
|
try {
|
|
88
91
|
const registries = await Promise.all(
|
|
89
|
-
(await fetchAvailableRegistries({ baseUrl })).map(async ({ id }) =>
|
|
90
|
-
fetchRegistry({ baseUrl, registryId: id }),
|
|
92
|
+
(await fetchAvailableRegistries({ baseUrl, framework })).map(async ({ id }) =>
|
|
93
|
+
fetchRegistry({ baseUrl, framework, registryId: id }),
|
|
91
94
|
),
|
|
92
95
|
);
|
|
93
96
|
stop("Registry를 가져왔어요.");
|
|
@@ -194,12 +197,14 @@ export const addCommand = (cli: CAC) => {
|
|
|
194
197
|
itemKeys: registryItemsToAdd.flatMap(({ registryId, items }) =>
|
|
195
198
|
items.map((item) => `${registryId}:${item.id}`),
|
|
196
199
|
),
|
|
197
|
-
projectPackageVersions: getProjectSeedPackageVersionSpecs(options.cwd),
|
|
200
|
+
projectPackageVersions: getProjectSeedPackageVersionSpecs(options.cwd, framework),
|
|
201
|
+
framework,
|
|
198
202
|
});
|
|
199
203
|
|
|
200
204
|
logCompatibilityReport({
|
|
201
205
|
report: compatibilityReport,
|
|
202
206
|
title: "현재 프로젝트 버전과 호환되지 않을 수 있는 스니펫이 있어요.",
|
|
207
|
+
framework,
|
|
203
208
|
});
|
|
204
209
|
|
|
205
210
|
p.log.info(
|
|
@@ -213,6 +218,7 @@ export const addCommand = (cli: CAC) => {
|
|
|
213
218
|
rootPath,
|
|
214
219
|
cwd,
|
|
215
220
|
baseUrl,
|
|
221
|
+
framework,
|
|
216
222
|
config,
|
|
217
223
|
onDiff: options.onDiff,
|
|
218
224
|
});
|
package/src/commands/compat.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { highlight } from "../utils/color";
|
|
|
11
11
|
import {
|
|
12
12
|
analyzeRegistryItemCompatibility,
|
|
13
13
|
findInstalledSnippetItemKeys,
|
|
14
|
+
getCompatPackageNames,
|
|
14
15
|
getProjectSeedPackageVersionSpecs,
|
|
15
16
|
logCompatibilityReport,
|
|
16
17
|
} from "../utils/compatibility";
|
|
@@ -23,6 +24,7 @@ const compatOptionsSchema = z.object({
|
|
|
23
24
|
registry: z.string().optional(),
|
|
24
25
|
cwd: z.string(),
|
|
25
26
|
baseUrl: z.string().default(BASE_URL),
|
|
27
|
+
framework: z.enum(["react", "lynx"]).optional(),
|
|
26
28
|
});
|
|
27
29
|
|
|
28
30
|
function parseTargetInputs({
|
|
@@ -116,6 +118,7 @@ export const compatCommand = (cli: CAC) => {
|
|
|
116
118
|
"the base url of the registry. defaults to the current directory.",
|
|
117
119
|
{ default: BASE_URL },
|
|
118
120
|
)
|
|
121
|
+
.option("-f, --framework <framework>", "프레임워크 (react 또는 lynx)")
|
|
119
122
|
.example("seed-design compat")
|
|
120
123
|
.example("seed-design compat -c action-button")
|
|
121
124
|
.example("seed-design compat ui:action-button ui:alert-dialog")
|
|
@@ -133,14 +136,17 @@ export const compatCommand = (cli: CAC) => {
|
|
|
133
136
|
}
|
|
134
137
|
|
|
135
138
|
const { data: options } = parsed;
|
|
139
|
+
const rawConfig = await getRawConfig(options.cwd);
|
|
140
|
+
const framework = options.framework ?? rawConfig?.framework ?? "react";
|
|
136
141
|
const { start, stop } = p.spinner();
|
|
137
142
|
|
|
138
143
|
start("Registry를 가져오고 있어요...");
|
|
139
144
|
const publicRegistries = await (async () => {
|
|
140
145
|
try {
|
|
141
146
|
const registries = await Promise.all(
|
|
142
|
-
(await fetchAvailableRegistries({ baseUrl: options.baseUrl })).map(
|
|
143
|
-
|
|
147
|
+
(await fetchAvailableRegistries({ baseUrl: options.baseUrl, framework })).map(
|
|
148
|
+
async ({ id }) =>
|
|
149
|
+
fetchRegistry({ baseUrl: options.baseUrl, framework, registryId: id }),
|
|
144
150
|
),
|
|
145
151
|
);
|
|
146
152
|
stop("Registry를 가져왔어요.");
|
|
@@ -221,17 +227,19 @@ export const compatCommand = (cli: CAC) => {
|
|
|
221
227
|
process.exit(0);
|
|
222
228
|
}
|
|
223
229
|
|
|
224
|
-
const projectPackageVersions = getProjectSeedPackageVersionSpecs(options.cwd);
|
|
230
|
+
const projectPackageVersions = getProjectSeedPackageVersionSpecs(options.cwd, framework);
|
|
225
231
|
const compatibilityReport = analyzeRegistryItemCompatibility({
|
|
226
232
|
publicRegistries,
|
|
227
233
|
itemKeys: resolvedTargetItemKeys,
|
|
228
234
|
projectPackageVersions,
|
|
235
|
+
framework,
|
|
229
236
|
});
|
|
230
237
|
|
|
231
238
|
p.log.info(`검사 대상: ${highlight(compatibilityReport.checkedItemKeys.join(", "))}`);
|
|
232
239
|
|
|
233
240
|
if (!compatibilityReport.issues.length) {
|
|
234
|
-
|
|
241
|
+
const compatPkgNames = getCompatPackageNames(framework);
|
|
242
|
+
p.outro(`모든 스니펫이 현재 ${compatPkgNames.join(", ")}와 호환돼요.`);
|
|
235
243
|
|
|
236
244
|
try {
|
|
237
245
|
await analytics.trackCommandOutcome(options.cwd, {
|
|
@@ -256,10 +264,10 @@ export const compatCommand = (cli: CAC) => {
|
|
|
256
264
|
logCompatibilityReport({
|
|
257
265
|
report: compatibilityReport,
|
|
258
266
|
title: "현재 프로젝트 버전과 호환되지 않는 스니펫을 찾았어요.",
|
|
267
|
+
framework,
|
|
259
268
|
});
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
);
|
|
269
|
+
const compatPkgList = getCompatPackageNames(framework);
|
|
270
|
+
p.log.info(`필요한 버전으로 ${compatPkgList.join(" 또는 ")}를 맞춘 뒤 다시 실행해보세요.`);
|
|
263
271
|
p.outro("호환성 이슈가 있어요.");
|
|
264
272
|
|
|
265
273
|
try {
|
package/src/commands/docs.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { z } from "zod";
|
|
|
5
5
|
import { BASE_URL } from "../constants";
|
|
6
6
|
import { analytics } from "../utils/analytics";
|
|
7
7
|
import { highlight } from "../utils/color";
|
|
8
|
+
import { getRawConfig } from "../utils/get-config";
|
|
8
9
|
import {
|
|
9
10
|
CliCancelError,
|
|
10
11
|
CliError,
|
|
@@ -18,13 +19,22 @@ const GITHUB_SNIPPET_BASE =
|
|
|
18
19
|
"https://raw.githubusercontent.com/daangn/seed-design/refs/heads/dev/docs/registry";
|
|
19
20
|
|
|
20
21
|
const docsOptionsSchema = z.object({
|
|
21
|
-
query: z
|
|
22
|
+
query: z
|
|
23
|
+
.union([z.string(), z.array(z.string())])
|
|
24
|
+
.optional()
|
|
25
|
+
.transform((query) => {
|
|
26
|
+
const normalized = Array.isArray(query) ? query.join(" ") : query;
|
|
27
|
+
const trimmed = normalized?.trim();
|
|
28
|
+
return trimmed ? trimmed : undefined;
|
|
29
|
+
}),
|
|
22
30
|
baseUrl: z.string().optional(),
|
|
31
|
+
cwd: z.string().default(process.cwd()),
|
|
32
|
+
framework: z.enum(["react", "lynx"]).optional(),
|
|
23
33
|
raw: z.boolean(),
|
|
24
34
|
});
|
|
25
35
|
|
|
26
|
-
function buildSnippetUrl(
|
|
27
|
-
return `${GITHUB_SNIPPET_BASE}/${
|
|
36
|
+
function buildSnippetUrl(registryPath: string, snippetPath: string): string {
|
|
37
|
+
return `${GITHUB_SNIPPET_BASE}/${registryPath}/${snippetPath}`;
|
|
28
38
|
}
|
|
29
39
|
|
|
30
40
|
function printDocsResult(item: DocsItem, baseUrl: string) {
|
|
@@ -34,14 +44,14 @@ function printDocsResult(item: DocsItem, baseUrl: string) {
|
|
|
34
44
|
const lines = [item.id, `- docs: ${docLink}`, `- llms.txt: ${llmsLink}`];
|
|
35
45
|
|
|
36
46
|
if (item.snippetKey && item.snippets && item.snippets.length > 0) {
|
|
37
|
-
const [
|
|
38
|
-
if (
|
|
47
|
+
const [registryPath] = item.snippetKey.split(":");
|
|
48
|
+
if (registryPath) {
|
|
39
49
|
if (item.snippets.length === 1) {
|
|
40
|
-
lines.push(`- snippet: ${buildSnippetUrl(
|
|
50
|
+
lines.push(`- snippet: ${buildSnippetUrl(registryPath, item.snippets[0].path)}`);
|
|
41
51
|
} else {
|
|
42
52
|
lines.push("- snippet:");
|
|
43
53
|
for (const snippet of item.snippets) {
|
|
44
|
-
lines.push(` - ${snippet.label}: ${buildSnippetUrl(
|
|
54
|
+
lines.push(` - ${snippet.label}: ${buildSnippetUrl(registryPath, snippet.path)}`);
|
|
45
55
|
}
|
|
46
56
|
}
|
|
47
57
|
}
|
|
@@ -162,11 +172,40 @@ function buildSuggestionHint(segments: string[], categories: DocsCategory[]): st
|
|
|
162
172
|
*/
|
|
163
173
|
function parseQueryPath(query: string): string[] {
|
|
164
174
|
return query
|
|
165
|
-
.split(
|
|
175
|
+
.split(/[\/\s]+/)
|
|
166
176
|
.map((s) => s.trim())
|
|
167
177
|
.filter(Boolean);
|
|
168
178
|
}
|
|
169
179
|
|
|
180
|
+
function normalizeRegistryKeySegment(segment: string): string {
|
|
181
|
+
const [, itemId] = segment.split(":");
|
|
182
|
+
return itemId ?? segment;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function normalizeDocsQuery({
|
|
186
|
+
query,
|
|
187
|
+
framework,
|
|
188
|
+
categoryIds,
|
|
189
|
+
}: {
|
|
190
|
+
query?: string;
|
|
191
|
+
framework?: string;
|
|
192
|
+
categoryIds: string[];
|
|
193
|
+
}): string | undefined {
|
|
194
|
+
if (!query) return undefined;
|
|
195
|
+
|
|
196
|
+
const segments = parseQueryPath(query).map(normalizeRegistryKeySegment);
|
|
197
|
+
if (!segments.length) return undefined;
|
|
198
|
+
|
|
199
|
+
const [firstSegment] = segments;
|
|
200
|
+
const isCategoryQuery = categoryIds.includes(firstSegment);
|
|
201
|
+
|
|
202
|
+
if (!isCategoryQuery && framework && categoryIds.includes(framework)) {
|
|
203
|
+
return [framework, ...segments].join("/");
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return segments.join("/");
|
|
207
|
+
}
|
|
208
|
+
|
|
170
209
|
/**
|
|
171
210
|
* Search all items across all categories/sections.
|
|
172
211
|
*/
|
|
@@ -229,16 +268,21 @@ async function selectCategory(categories: DocsCategory[]): Promise<DocsCategory>
|
|
|
229
268
|
|
|
230
269
|
export const docsCommand = (cli: CAC) => {
|
|
231
270
|
cli
|
|
232
|
-
.command("docs [query]", "문서 링크, llms.txt 링크, 스니펫 링크를 조회합니다")
|
|
271
|
+
.command("docs [...query]", "문서 링크, llms.txt 링크, 스니펫 링크를 조회합니다")
|
|
233
272
|
.option("-u, --baseUrl <baseUrl>", `레지스트리의 기본 URL (기본값: ${BASE_URL})`, {
|
|
234
273
|
default: BASE_URL,
|
|
235
274
|
})
|
|
275
|
+
.option("--cwd <cwd>", "the working directory. defaults to the current directory.", {
|
|
276
|
+
default: process.cwd(),
|
|
277
|
+
})
|
|
278
|
+
.option("-f, --framework <framework>", "프레임워크 (react 또는 lynx)")
|
|
236
279
|
.option("--raw", "llms.txt 내용을 직접 가져와 출력합니다. LLM 파이프에 유용합니다.", {
|
|
237
280
|
default: false,
|
|
238
281
|
})
|
|
239
282
|
.example("seed-design docs")
|
|
240
283
|
.example("seed-design docs action-button")
|
|
241
284
|
.example("seed-design docs react")
|
|
285
|
+
.example("seed-design docs lynx action-button")
|
|
242
286
|
.example("seed-design docs react/components")
|
|
243
287
|
.example("seed-design docs react/components/action-button")
|
|
244
288
|
.example("seed-design docs react/updates/changelog --raw")
|
|
@@ -246,7 +290,7 @@ export const docsCommand = (cli: CAC) => {
|
|
|
246
290
|
const startTime = Date.now();
|
|
247
291
|
const verbose = isVerboseMode(opts);
|
|
248
292
|
const raw = opts.raw ?? false;
|
|
249
|
-
|
|
293
|
+
let trackCwd = process.cwd();
|
|
250
294
|
|
|
251
295
|
if (!raw) p.intro("seed-design docs");
|
|
252
296
|
|
|
@@ -257,7 +301,10 @@ export const docsCommand = (cli: CAC) => {
|
|
|
257
301
|
}
|
|
258
302
|
|
|
259
303
|
const { data: options } = parsed;
|
|
304
|
+
trackCwd = options.cwd;
|
|
260
305
|
const baseUrl = options.baseUrl ?? BASE_URL;
|
|
306
|
+
const rawConfig = await getRawConfig(options.cwd).catch(() => null);
|
|
307
|
+
const framework = options.framework ?? rawConfig?.framework;
|
|
261
308
|
|
|
262
309
|
if (options.raw && !options.query) {
|
|
263
310
|
throw new CliError({
|
|
@@ -283,12 +330,17 @@ export const docsCommand = (cli: CAC) => {
|
|
|
283
330
|
})();
|
|
284
331
|
|
|
285
332
|
const { categories } = docsIndex;
|
|
333
|
+
const docsQuery = normalizeDocsQuery({
|
|
334
|
+
query: options.query,
|
|
335
|
+
framework,
|
|
336
|
+
categoryIds: categories.map((category) => category.id),
|
|
337
|
+
});
|
|
286
338
|
let selectedItem: DocsItem | undefined;
|
|
287
339
|
|
|
288
340
|
// In --raw mode, wrap index resolution in try-catch to allow fallback to direct URL
|
|
289
341
|
const resolveFromIndex = async (): Promise<DocsItem | undefined> => {
|
|
290
|
-
if (
|
|
291
|
-
const segments = parseQueryPath(
|
|
342
|
+
if (docsQuery) {
|
|
343
|
+
const segments = parseQueryPath(docsQuery);
|
|
292
344
|
|
|
293
345
|
// Deep paths (more than category/section/item) can't be resolved from index
|
|
294
346
|
// e.g., react/updates/changelog/react/1.2.9 — skip to fallback in --raw mode
|
|
@@ -326,7 +378,7 @@ export const docsCommand = (cli: CAC) => {
|
|
|
326
378
|
.join("\n")}`
|
|
327
379
|
: "";
|
|
328
380
|
throw new CliError({
|
|
329
|
-
message: `${highlight(
|
|
381
|
+
message: `${highlight(docsQuery)}: 문서를 찾을 수 없어요.${suggestion}`,
|
|
330
382
|
hint: `\`seed-design docs ${matchedCategory.id}/${matchedSection.id}\`로 목록을 확인해보세요.`,
|
|
331
383
|
});
|
|
332
384
|
}
|
|
@@ -374,7 +426,7 @@ export const docsCommand = (cli: CAC) => {
|
|
|
374
426
|
? `\n\n💡 이것을 의미했나요?\n${suggestions.map((s) => ` - ${s}`).join("\n")}`
|
|
375
427
|
: "";
|
|
376
428
|
throw new CliError({
|
|
377
|
-
message: `${highlight(
|
|
429
|
+
message: `${highlight(docsQuery)}: 문서를 찾을 수 없어요.${suggestion}`,
|
|
378
430
|
hint: `\`seed-design docs ${matchedCategory.id}\`로 목록을 확인해보세요.`,
|
|
379
431
|
});
|
|
380
432
|
}
|
|
@@ -401,12 +453,12 @@ export const docsCommand = (cli: CAC) => {
|
|
|
401
453
|
return await selectItem(section.items);
|
|
402
454
|
}
|
|
403
455
|
// No category match — global search
|
|
404
|
-
const matched = searchAllItems(categories,
|
|
456
|
+
const matched = searchAllItems(categories, docsQuery);
|
|
405
457
|
|
|
406
458
|
if (matched.length === 0) {
|
|
407
459
|
const suggestion = buildSuggestionHint(segments, categories);
|
|
408
460
|
throw new CliError({
|
|
409
|
-
message: `${highlight(
|
|
461
|
+
message: `${highlight(docsQuery)}: 문서를 찾을 수 없어요.${suggestion ?? ""}`,
|
|
410
462
|
hint: "`seed-design docs`로 전체 목록을 확인해보세요.",
|
|
411
463
|
});
|
|
412
464
|
}
|
|
@@ -414,7 +466,7 @@ export const docsCommand = (cli: CAC) => {
|
|
|
414
466
|
return matched[0].item;
|
|
415
467
|
}
|
|
416
468
|
const selected = await p.select({
|
|
417
|
-
message: `${highlight(
|
|
469
|
+
message: `${highlight(docsQuery)}에 해당하는 항목을 선택해주세요`,
|
|
418
470
|
options: matched.map(({ item, categoryLabel, sectionLabel }) => ({
|
|
419
471
|
label: `[${categoryLabel} > ${sectionLabel}] ${item.title}`,
|
|
420
472
|
value: item,
|
|
@@ -456,7 +508,7 @@ export const docsCommand = (cli: CAC) => {
|
|
|
456
508
|
const llmsUrl = `${baseUrl}/llms${selectedItem.docUrl}.txt`;
|
|
457
509
|
content = await fetchLlmsTxt({ url: llmsUrl });
|
|
458
510
|
} else {
|
|
459
|
-
content = await tryFetchLlmsTxt({ baseUrl, query:
|
|
511
|
+
content = await tryFetchLlmsTxt({ baseUrl, query: docsQuery! });
|
|
460
512
|
}
|
|
461
513
|
console.log(content);
|
|
462
514
|
} else {
|
package/src/commands/init.ts
CHANGED
|
@@ -3,7 +3,12 @@ import { z } from "zod";
|
|
|
3
3
|
import { analytics } from "../utils/analytics";
|
|
4
4
|
import { highlight } from "../utils/color";
|
|
5
5
|
import { handleCliError, isCliCancelError, isVerboseMode } from "../utils/error";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
DEFAULT_INIT_CONFIG,
|
|
8
|
+
detectFramework,
|
|
9
|
+
promptInitConfig,
|
|
10
|
+
writeInitConfigFile,
|
|
11
|
+
} from "../utils/init-config";
|
|
7
12
|
|
|
8
13
|
import type { Config } from "@/src/utils/get-config";
|
|
9
14
|
|
|
@@ -38,7 +43,9 @@ export const initCommand = (cli: CAC) => {
|
|
|
38
43
|
|
|
39
44
|
const options = parsed.data;
|
|
40
45
|
const isDefaultMode = options.yes || options.default;
|
|
41
|
-
const config: Config = isDefaultMode
|
|
46
|
+
const config: Config = isDefaultMode
|
|
47
|
+
? { ...DEFAULT_INIT_CONFIG, framework: detectFramework(options.cwd) }
|
|
48
|
+
: await promptInitConfig(options.cwd);
|
|
42
49
|
|
|
43
50
|
const { start, stop } = p.spinner();
|
|
44
51
|
start("seed-design.json 파일 생성중...");
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { afterAll, beforeAll, describe, expect, it } from "bun:test";
|
|
2
|
+
import { createServer, type Server } from "node:http";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
const repoRoot = path.resolve(import.meta.dir, "../../../..");
|
|
6
|
+
|
|
7
|
+
const docsIndex = {
|
|
8
|
+
categories: [
|
|
9
|
+
{
|
|
10
|
+
id: "lynx",
|
|
11
|
+
label: "Lynx",
|
|
12
|
+
sections: [
|
|
13
|
+
{
|
|
14
|
+
id: "components",
|
|
15
|
+
label: "Components",
|
|
16
|
+
items: [
|
|
17
|
+
{
|
|
18
|
+
id: "action-button",
|
|
19
|
+
title: "Action Button",
|
|
20
|
+
docUrl: "/lynx/components/action-button",
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: "checkbox",
|
|
24
|
+
title: "Checkbox",
|
|
25
|
+
docUrl: "/lynx/components/checkbox",
|
|
26
|
+
snippetKey: "lynx/ui:checkbox",
|
|
27
|
+
snippets: [{ label: "checkbox", path: "checkbox.tsx" }],
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
describe("docs command", () => {
|
|
37
|
+
let server: Server;
|
|
38
|
+
let baseUrl: string;
|
|
39
|
+
const requests: string[] = [];
|
|
40
|
+
|
|
41
|
+
beforeAll(async () => {
|
|
42
|
+
server = createServer((request, response) => {
|
|
43
|
+
const url = request.url ? new URL(request.url, "http://127.0.0.1") : undefined;
|
|
44
|
+
const pathname = url?.pathname ?? "/";
|
|
45
|
+
requests.push(pathname);
|
|
46
|
+
|
|
47
|
+
if (pathname === "/__docs__/index.json") {
|
|
48
|
+
response.writeHead(200, { "Content-Type": "application/json" });
|
|
49
|
+
response.end(JSON.stringify(docsIndex));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
response.writeHead(404, { "Content-Type": "text/plain" });
|
|
54
|
+
response.end("Not found");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
await new Promise<void>((resolve) => {
|
|
58
|
+
server.listen(0, "127.0.0.1", resolve);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const address = server.address();
|
|
62
|
+
if (!address || typeof address === "string") {
|
|
63
|
+
throw new Error("Failed to start test docs server");
|
|
64
|
+
}
|
|
65
|
+
baseUrl = `http://127.0.0.1:${address.port}`;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
afterAll(async () => {
|
|
69
|
+
await new Promise<void>((resolve, reject) => {
|
|
70
|
+
server.close((error) => {
|
|
71
|
+
if (error) {
|
|
72
|
+
reject(error);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
resolve();
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
async function runDocsCommand(args: string[]) {
|
|
81
|
+
const proc = Bun.spawn({
|
|
82
|
+
cmd: [process.execPath, "packages/cli/src/index.ts", "docs", ...args, "-u", baseUrl],
|
|
83
|
+
cwd: repoRoot,
|
|
84
|
+
env: {
|
|
85
|
+
...process.env,
|
|
86
|
+
DISABLE_TELEMETRY: "true",
|
|
87
|
+
FORCE_COLOR: "0",
|
|
88
|
+
},
|
|
89
|
+
stderr: "pipe",
|
|
90
|
+
stdout: "pipe",
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const [exitCode, stdout, stderr] = await Promise.all([
|
|
94
|
+
proc.exited,
|
|
95
|
+
new Response(proc.stdout).text(),
|
|
96
|
+
new Response(proc.stderr).text(),
|
|
97
|
+
]);
|
|
98
|
+
return { exitCode, stderr, stdout };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
it("resolves unquoted Lynx component queries to docs and llms links", async () => {
|
|
102
|
+
requests.length = 0;
|
|
103
|
+
const result = await runDocsCommand(["lynx", "action-button"]);
|
|
104
|
+
|
|
105
|
+
if (result.exitCode !== 0) {
|
|
106
|
+
throw new Error(
|
|
107
|
+
`docs command failed\nbaseUrl:${baseUrl}\nrequests:${requests.join(",")}\nstdout:\n${result.stdout}\nstderr:\n${result.stderr}`,
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
expect(result.stdout).toContain("- docs: http://");
|
|
111
|
+
expect(result.stdout).toContain("/lynx/components/action-button");
|
|
112
|
+
expect(result.stdout).toContain("- llms.txt: http://");
|
|
113
|
+
expect(result.stdout).toContain("/llms/lynx/components/action-button.txt");
|
|
114
|
+
expect(result.stdout).not.toContain("- snippet:");
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("prints Lynx snippet URLs for quoted Lynx component queries", async () => {
|
|
118
|
+
requests.length = 0;
|
|
119
|
+
const result = await runDocsCommand(["lynx checkbox"]);
|
|
120
|
+
|
|
121
|
+
if (result.exitCode !== 0) {
|
|
122
|
+
throw new Error(
|
|
123
|
+
`docs command failed\nbaseUrl:${baseUrl}\nrequests:${requests.join(",")}\nstdout:\n${result.stdout}\nstderr:\n${result.stderr}`,
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
expect(result.stdout).toContain("- docs: http://");
|
|
127
|
+
expect(result.stdout).toContain("/lynx/components/checkbox");
|
|
128
|
+
expect(result.stdout).toContain("- llms.txt: http://");
|
|
129
|
+
expect(result.stdout).toContain("/llms/lynx/components/checkbox.txt");
|
|
130
|
+
expect(result.stdout).toContain(
|
|
131
|
+
"- snippet: https://raw.githubusercontent.com/daangn/seed-design/refs/heads/dev/docs/registry/lynx/ui/checkbox.tsx",
|
|
132
|
+
);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("resolves registry-key queries with an explicit framework", async () => {
|
|
136
|
+
requests.length = 0;
|
|
137
|
+
const result = await runDocsCommand(["ui:checkbox", "--framework", "lynx"]);
|
|
138
|
+
|
|
139
|
+
if (result.exitCode !== 0) {
|
|
140
|
+
throw new Error(
|
|
141
|
+
`docs command failed\nbaseUrl:${baseUrl}\nrequests:${requests.join(",")}\nstdout:\n${result.stdout}\nstderr:\n${result.stderr}`,
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
expect(result.stdout).toContain("- docs: http://");
|
|
145
|
+
expect(result.stdout).toContain("/lynx/components/checkbox");
|
|
146
|
+
expect(result.stdout).toContain(
|
|
147
|
+
"- snippet: https://raw.githubusercontent.com/daangn/seed-design/refs/heads/dev/docs/registry/lynx/ui/checkbox.tsx",
|
|
148
|
+
);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
@@ -6,8 +6,16 @@ import path from "path";
|
|
|
6
6
|
import { intersects, satisfies, valid, validRange } from "semver";
|
|
7
7
|
import { highlight } from "./color";
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
const REACT_COMPAT_PACKAGES = ["@seed-design/react", "@seed-design/css"] as const;
|
|
10
|
+
const LYNX_COMPAT_PACKAGES = ["@seed-design/lynx-react", "@seed-design/lynx-css"] as const;
|
|
11
|
+
|
|
12
|
+
export type CompatPackageName =
|
|
13
|
+
| (typeof REACT_COMPAT_PACKAGES)[number]
|
|
14
|
+
| (typeof LYNX_COMPAT_PACKAGES)[number];
|
|
15
|
+
|
|
16
|
+
export function getCompatPackageNames(framework: string): readonly CompatPackageName[] {
|
|
17
|
+
return framework === "lynx" ? LYNX_COMPAT_PACKAGES : REACT_COMPAT_PACKAGES;
|
|
18
|
+
}
|
|
11
19
|
|
|
12
20
|
const WORKSPACE_VERSION_PREFIX = "workspace:";
|
|
13
21
|
const NPM_ALIAS_PREFIX = "npm:";
|
|
@@ -28,6 +36,7 @@ export interface CompatibilityReport {
|
|
|
28
36
|
|
|
29
37
|
export function getProjectSeedPackageVersionSpecs(
|
|
30
38
|
cwd: string,
|
|
39
|
+
framework = "react",
|
|
31
40
|
): Partial<Record<CompatPackageName, string>> {
|
|
32
41
|
try {
|
|
33
42
|
const packageInfo = getPackageInfo(cwd);
|
|
@@ -38,8 +47,9 @@ export function getProjectSeedPackageVersionSpecs(
|
|
|
38
47
|
...packageInfo.optionalDependencies,
|
|
39
48
|
};
|
|
40
49
|
const result: Partial<Record<CompatPackageName, string>> = {};
|
|
50
|
+
const compatPackages = getCompatPackageNames(framework);
|
|
41
51
|
|
|
42
|
-
for (const packageName of
|
|
52
|
+
for (const packageName of compatPackages) {
|
|
43
53
|
const value = packageDeps[packageName];
|
|
44
54
|
if (typeof value === "string") {
|
|
45
55
|
result[packageName] = value;
|
|
@@ -56,10 +66,12 @@ export function analyzeRegistryItemCompatibility({
|
|
|
56
66
|
publicRegistries,
|
|
57
67
|
itemKeys,
|
|
58
68
|
projectPackageVersions,
|
|
69
|
+
framework = "react",
|
|
59
70
|
}: {
|
|
60
71
|
publicRegistries: PublicRegistry[];
|
|
61
72
|
itemKeys: string[];
|
|
62
73
|
projectPackageVersions: Partial<Record<CompatPackageName, string>>;
|
|
74
|
+
framework?: string;
|
|
63
75
|
}): CompatibilityReport {
|
|
64
76
|
const checkedItemKeys = Array.from(new Set(itemKeys));
|
|
65
77
|
const itemMap = new Map<string, PublicRegistry["items"][number]>(
|
|
@@ -69,14 +81,15 @@ export function analyzeRegistryItemCompatibility({
|
|
|
69
81
|
);
|
|
70
82
|
|
|
71
83
|
const issues: CompatibilityIssue[] = [];
|
|
84
|
+
const compatPackages = getCompatPackageNames(framework);
|
|
72
85
|
|
|
73
86
|
for (const itemKey of checkedItemKeys) {
|
|
74
87
|
const item = itemMap.get(itemKey);
|
|
75
88
|
if (!item) continue;
|
|
76
89
|
|
|
77
|
-
const requiredRangesByPackage = collectRequiredRangesByPackage(item);
|
|
90
|
+
const requiredRangesByPackage = collectRequiredRangesByPackage(item, framework);
|
|
78
91
|
|
|
79
|
-
for (const packageName of
|
|
92
|
+
for (const packageName of compatPackages) {
|
|
80
93
|
const requiredRanges = Array.from(requiredRangesByPackage[packageName] ?? []);
|
|
81
94
|
|
|
82
95
|
if (!requiredRanges.length) continue;
|
|
@@ -135,15 +148,19 @@ export function analyzeRegistryItemCompatibility({
|
|
|
135
148
|
export function logCompatibilityReport({
|
|
136
149
|
report,
|
|
137
150
|
title,
|
|
151
|
+
framework = "react",
|
|
138
152
|
}: {
|
|
139
153
|
report: CompatibilityReport;
|
|
140
154
|
title: string;
|
|
155
|
+
framework?: string;
|
|
141
156
|
}) {
|
|
142
157
|
if (!report.issues.length) return;
|
|
143
158
|
|
|
159
|
+
const compatPackages = getCompatPackageNames(framework);
|
|
160
|
+
|
|
144
161
|
p.log.warn(title);
|
|
145
162
|
p.log.info(
|
|
146
|
-
`현재 프로젝트 버전: ${
|
|
163
|
+
`현재 프로젝트 버전: ${compatPackages.map((packageName) => `${packageName}@${highlight(report.projectPackageVersions[packageName] ?? "미설치")}`).join(", ")}`,
|
|
147
164
|
);
|
|
148
165
|
|
|
149
166
|
const issuesByItem = new Map<string, CompatibilityIssue[]>();
|
|
@@ -207,14 +224,18 @@ export function findInstalledSnippetItemKeys({
|
|
|
207
224
|
return installedItemKeys;
|
|
208
225
|
}
|
|
209
226
|
|
|
210
|
-
function collectRequiredRangesByPackage(
|
|
227
|
+
function collectRequiredRangesByPackage(
|
|
228
|
+
item: PublicRegistry["items"][number],
|
|
229
|
+
framework = "react",
|
|
230
|
+
) {
|
|
231
|
+
const compatPackages = getCompatPackageNames(framework);
|
|
211
232
|
const requiredRangesByPackage = Object.fromEntries(
|
|
212
|
-
|
|
233
|
+
compatPackages.map((packageName) => [packageName, new Set<string>()]),
|
|
213
234
|
) as Record<CompatPackageName, Set<string>>;
|
|
214
235
|
|
|
215
236
|
for (const snippet of item.snippets) {
|
|
216
237
|
for (const [packageName, requiredRange] of Object.entries(snippet.dependencies ?? {})) {
|
|
217
|
-
if (!isCompatPackageName(packageName)) continue;
|
|
238
|
+
if (!isCompatPackageName(packageName, framework)) continue;
|
|
218
239
|
requiredRangesByPackage[packageName].add(requiredRange);
|
|
219
240
|
}
|
|
220
241
|
}
|
|
@@ -286,6 +307,9 @@ function getSnippetPathCandidates(originalPath: string): string[] {
|
|
|
286
307
|
return Array.from(candidates);
|
|
287
308
|
}
|
|
288
309
|
|
|
289
|
-
function isCompatPackageName(
|
|
290
|
-
|
|
310
|
+
function isCompatPackageName(
|
|
311
|
+
packageName: string,
|
|
312
|
+
framework = "react",
|
|
313
|
+
): packageName is CompatPackageName {
|
|
314
|
+
return (getCompatPackageNames(framework) as readonly string[]).includes(packageName);
|
|
291
315
|
}
|
package/src/utils/fetch.ts
CHANGED
|
@@ -53,11 +53,12 @@ export async function fetchDocsIndex({ baseUrl }: { baseUrl: string }): Promise<
|
|
|
53
53
|
|
|
54
54
|
export async function fetchAvailableRegistries({
|
|
55
55
|
baseUrl,
|
|
56
|
+
framework,
|
|
56
57
|
}: {
|
|
57
58
|
baseUrl: string;
|
|
59
|
+
framework: string;
|
|
58
60
|
}): Promise<PublicAvailableRegistries> {
|
|
59
|
-
|
|
60
|
-
const response = await fetch(`${baseUrl}/__registry__/index.json`);
|
|
61
|
+
const response = await fetch(`${baseUrl}/__registry__/${framework}/index.json`);
|
|
61
62
|
|
|
62
63
|
if (!response.ok)
|
|
63
64
|
throw new Error(`Failed to fetch registries: ${response.status} ${response.statusText}`);
|
|
@@ -76,12 +77,14 @@ export async function fetchAvailableRegistries({
|
|
|
76
77
|
|
|
77
78
|
export async function fetchRegistry({
|
|
78
79
|
baseUrl,
|
|
80
|
+
framework,
|
|
79
81
|
registryId,
|
|
80
82
|
}: {
|
|
81
83
|
baseUrl: string;
|
|
84
|
+
framework: string;
|
|
82
85
|
registryId: PublicRegistry["id"];
|
|
83
86
|
}): Promise<PublicRegistry> {
|
|
84
|
-
const response = await fetch(`${baseUrl}/__registry__/${registryId}/index.json`);
|
|
87
|
+
const response = await fetch(`${baseUrl}/__registry__/${framework}/${registryId}/index.json`);
|
|
85
88
|
|
|
86
89
|
if (!response.ok)
|
|
87
90
|
throw new Error(
|
|
@@ -98,14 +101,18 @@ export async function fetchRegistry({
|
|
|
98
101
|
|
|
99
102
|
async function fetchRegistryItem({
|
|
100
103
|
baseUrl,
|
|
104
|
+
framework,
|
|
101
105
|
registryId,
|
|
102
106
|
registryItemId,
|
|
103
107
|
}: {
|
|
104
108
|
baseUrl: string;
|
|
109
|
+
framework: string;
|
|
105
110
|
registryId: PublicRegistry["id"];
|
|
106
111
|
registryItemId: PublicRegistryItem["id"];
|
|
107
112
|
}): Promise<PublicRegistryItem> {
|
|
108
|
-
const response = await fetch(
|
|
113
|
+
const response = await fetch(
|
|
114
|
+
`${baseUrl}/__registry__/${framework}/${registryId}/${registryItemId}.json`,
|
|
115
|
+
);
|
|
109
116
|
|
|
110
117
|
if (!response.ok) {
|
|
111
118
|
throw new Error(`Failed to fetch ${registryItemId}: ${response.status} ${response.statusText}`);
|
|
@@ -195,20 +202,24 @@ export async function tryFetchLlmsTxt({
|
|
|
195
202
|
|
|
196
203
|
export async function fetchRegistryItems({
|
|
197
204
|
baseUrl,
|
|
205
|
+
framework,
|
|
198
206
|
registryId,
|
|
199
207
|
registryItemIds,
|
|
200
208
|
}: {
|
|
201
209
|
baseUrl: string;
|
|
210
|
+
framework: string;
|
|
202
211
|
registryId: PublicRegistry["id"];
|
|
203
212
|
registryItemIds: PublicRegistryItem["id"][];
|
|
204
213
|
}): Promise<PublicRegistryItem[]> {
|
|
205
214
|
return await Promise.all(
|
|
206
215
|
registryItemIds.map(async (itemId) => {
|
|
207
216
|
try {
|
|
208
|
-
return await fetchRegistryItem({ baseUrl, registryId, registryItemId: itemId });
|
|
217
|
+
return await fetchRegistryItem({ baseUrl, framework, registryId, registryItemId: itemId });
|
|
209
218
|
} catch (error) {
|
|
210
219
|
// show available registry items in the registry
|
|
211
|
-
const response = await fetch(
|
|
220
|
+
const response = await fetch(
|
|
221
|
+
`${baseUrl}/__registry__/${framework}/${registryId}/index.json`,
|
|
222
|
+
);
|
|
212
223
|
|
|
213
224
|
if (!response.ok)
|
|
214
225
|
throw new Error(
|
package/src/utils/get-config.ts
CHANGED
|
@@ -15,6 +15,7 @@ export const configSchema = z
|
|
|
15
15
|
$schema: z.string().optional(),
|
|
16
16
|
rsc: z.coerce.boolean().default(false),
|
|
17
17
|
tsx: z.coerce.boolean().default(true),
|
|
18
|
+
framework: z.enum(["react", "lynx"]).default("react"),
|
|
18
19
|
path: z.string(),
|
|
19
20
|
telemetry: z.coerce.boolean().optional().default(true),
|
|
20
21
|
})
|
package/src/utils/init-config.ts
CHANGED
|
@@ -3,17 +3,36 @@ import fs from "fs-extra";
|
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { highlight } from "./color";
|
|
5
5
|
import { CliCancelError } from "./error";
|
|
6
|
+
import { getPackageInfo } from "./get-package-info";
|
|
6
7
|
|
|
7
8
|
import type { Config } from "./get-config";
|
|
8
9
|
|
|
9
10
|
export const DEFAULT_INIT_CONFIG: Config = {
|
|
10
11
|
rsc: false,
|
|
11
12
|
tsx: true,
|
|
13
|
+
framework: "react",
|
|
12
14
|
path: "./seed-design",
|
|
13
15
|
telemetry: true,
|
|
14
16
|
};
|
|
15
17
|
|
|
16
|
-
export
|
|
18
|
+
export function detectFramework(cwd: string): "react" | "lynx" {
|
|
19
|
+
try {
|
|
20
|
+
const pkg = getPackageInfo(cwd);
|
|
21
|
+
const allDeps = {
|
|
22
|
+
...pkg.dependencies,
|
|
23
|
+
...pkg.devDependencies,
|
|
24
|
+
...pkg.peerDependencies,
|
|
25
|
+
};
|
|
26
|
+
if ("@lynx-js/react" in allDeps || "@seed-design/lynx-react" in allDeps) {
|
|
27
|
+
return "lynx";
|
|
28
|
+
}
|
|
29
|
+
} catch {}
|
|
30
|
+
return "react";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function promptInitConfig(cwd: string): Promise<Config> {
|
|
34
|
+
const detectedFramework = detectFramework(cwd);
|
|
35
|
+
|
|
17
36
|
const group = await p.group(
|
|
18
37
|
{
|
|
19
38
|
tsx: () =>
|
|
@@ -26,6 +45,15 @@ export async function promptInitConfig(): Promise<Config> {
|
|
|
26
45
|
message: `${highlight("React Server Components")}를 사용중이신가요?`,
|
|
27
46
|
initialValue: DEFAULT_INIT_CONFIG.rsc,
|
|
28
47
|
}),
|
|
48
|
+
framework: () =>
|
|
49
|
+
p.select({
|
|
50
|
+
message: `어떤 ${highlight("프레임워크")}를 사용하시나요?`,
|
|
51
|
+
initialValue: detectedFramework,
|
|
52
|
+
options: [
|
|
53
|
+
{ value: "react" as const, label: "React" },
|
|
54
|
+
{ value: "lynx" as const, label: "Lynx" },
|
|
55
|
+
],
|
|
56
|
+
}),
|
|
29
57
|
path: () =>
|
|
30
58
|
p.text({
|
|
31
59
|
message: `${highlight("seed-design 폴더")} 경로를 입력해주세요. (기본값은 프로젝트 루트에 생성됩니다.)`,
|
package/src/utils/write.ts
CHANGED
|
@@ -14,6 +14,7 @@ export async function writeRegistryItemSnippets({
|
|
|
14
14
|
rootPath,
|
|
15
15
|
cwd,
|
|
16
16
|
baseUrl,
|
|
17
|
+
framework,
|
|
17
18
|
config,
|
|
18
19
|
onDiff,
|
|
19
20
|
}: {
|
|
@@ -21,6 +22,7 @@ export async function writeRegistryItemSnippets({
|
|
|
21
22
|
rootPath: string;
|
|
22
23
|
cwd: string;
|
|
23
24
|
baseUrl: string;
|
|
25
|
+
framework: string;
|
|
24
26
|
config: Config;
|
|
25
27
|
onDiff?: "overwrite" | "backup";
|
|
26
28
|
}) {
|
|
@@ -33,6 +35,7 @@ export async function writeRegistryItemSnippets({
|
|
|
33
35
|
|
|
34
36
|
const registryItems = await fetchRegistryItems({
|
|
35
37
|
baseUrl,
|
|
38
|
+
framework,
|
|
36
39
|
registryId,
|
|
37
40
|
registryItemIds: items.map((i) => i.id),
|
|
38
41
|
});
|