@seed-design/cli 1.3.0 → 1.3.2
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 +25 -12
- package/package.json +1 -1
- package/src/commands/docs.ts +256 -66
- package/src/index.ts +1 -0
- package/src/utils/fetch.ts +92 -0
package/bin/index.mjs
CHANGED
|
@@ -1,17 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import*as
|
|
3
|
-
[verbose] stack trace`)),
|
|
4
|
-
`,"utf-8"),{relativePath:
|
|
5
|
-
${
|
|
6
|
-
`)}`
|
|
7
|
-
${
|
|
8
|
-
`),L.log.message(A),L.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 ${x}\uC73C\uB85C \uC62E\uAE30\uACE0 ${P} \uBC1B\uAE30`},{value:"skip",label:"\uC0C8 \uD30C\uC77C \uBC1B\uC9C0 \uC54A\uACE0 \uADF8\uB300\uB85C \uB450\uAE30"}]})})();if(L.isCancel(l)||l==="skip"){L.log.info(`${a(I)}: \uD30C\uC77C\uC744 \uBC1B\uC9C0 \uC54A\uACE0 \uAC74\uB108\uB6F0\uC5C8\uC5B4\uC694.`);continue}if(l==="backup"){let u=q.dirname(d),A=q.join(u,x);await ie.rename(d,A),L.log.info(`${a(I)}: \uAE30\uC874 \uD30C\uC77C\uC744 ${a(q.relative(s,A))}\uB85C \uC62E\uACBC\uC5B4\uC694.`)}}await ie.writeFile(d,w),f.push(g)}if(f.length>0){let g=f.map(({name:d,relativePath:w})=>({name:d,path:w}));i.push(...g),L.log.success(`${a(`${c}:${b}`)} \uAD00\uB828 \uC2A4\uB2C8\uD3AB \uB2E4\uC6B4\uB85C\uB4DC \uC644\uB8CC: ${a(g.map(d=>d.path).join(", "))}`)}}}}import*as S from"@clack/prompts";import Gt from"path";import{z as Z}from"zod";var B="https://seed-design.io";import*as Ke from"@clack/prompts";import{execa as vt}from"execa";import{detect as Pt}from"@antfu/ni";async function Me(e){let t=await Pt({programmatic:!0,cwd:e});return t==="yarn@berry"?"yarn":t==="pnpm@6"?"pnpm":t==="bun"?"bun":t==="deno"?"deno":t??"npm"}import St from"findup-sync";import Rt from"fs-extra";var Et="package.json";function kt(e=process.cwd()){let t=St(Et,{cwd:e});if(!t)throw new Error("No package.json file found in the project.");return t}function oe(e=process.cwd()){let t=kt(e);return Rt.readJSONSync(t)}async function we({cwd:e,deps:t,dev:s=!1}){let{start:o,stop:n}=Ke.spinner(),r=await Me(e),c={...oe(e).dependencies},m=new Set(t.filter(f=>!c[f])),y=new Set(t.filter(f=>c[f]));if(!m.size)return{installed:new Set,filtered:m};o("\uC758\uC874\uC131 \uC124\uCE58\uC911...");let h=[r==="npm"?"install":"add",s?"-D":null,...m].filter(Boolean),j=`${r} ${h.join(" ")}`;try{await vt(r,h,{cwd:e})}catch(f){throw n("\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: ${j}`],cause:f})}return n("\uC758\uC874\uC131 \uC124\uCE58\uAC00 \uC644\uB8CC\uB410\uC5B4\uC694."),{installed:m,filtered:y}}import{randomUUID as jt}from"node:crypto";import*as Ue from"@clack/prompts";var At="seed_cli";async function Dt(e){if(process.env.DISABLE_TELEMETRY==="true"||process.env.SEED_DISABLE_TELEMETRY==="true")return!1;try{if((await le(e))?.telemetry===!1)return!1}catch{}return!0}function Tt(){return jt()}var _t=Tt(),Le=!1;async function Ot(e,{event:t,properties:s={}}){if(!await Dt(e))return;let n=`${At}.${t}`;Le||(Ue.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)"),Le=!0);try{let r="https://us.i.posthog.com/capture",i={"Content-Type":"application/json"},c={api_key:"phc_seod8HhifElOP1R92KmvsQybrtUmkOTgZBsq0mfCelR",event:n,distinct_id:_t,properties:{...s,$process_person_profile:!1},timestamp:new Date().toISOString()},m=new AbortController,y=setTimeout(()=>m.abort(),5e3);try{await fetch(r,{method:"POST",headers:i,body:JSON.stringify(c),signal:m.signal})}finally{clearTimeout(y)}}catch{}}var U={track:Ot};import*as Q from"@clack/prompts";import Mt from"fs-extra";import Kt from"path";import{intersects as Lt,satisfies as Ut,valid as ze,validRange as Fe}from"semver";var me=["@seed-design/react","@seed-design/css"],Ne="workspace:",Nt="npm:";function ne(e){try{let t=oe(e),s={...t.dependencies,...t.devDependencies,...t.peerDependencies,...t.optionalDependencies},o={};for(let n of me){let r=s[n];typeof r=="string"&&(o[n]=r)}return o}catch{return{}}}function ae({publicRegistries:e,itemKeys:t,projectPackageVersions:s}){let o=Array.from(new Set(t)),n=new Map(e.flatMap(i=>i.items.map(c=>[`${i.id}:${c.id}`,c]))),r=[];for(let i of o){let c=n.get(i);if(!c)continue;let m=zt(c);for(let y of me){let C=Array.from(m[y]??[]);if(!C.length)continue;let b=s[y];if(!b){r.push({itemKey:i,packageName:y,requiredRanges:C,type:"missing-package"});continue}let h=Ft(b);if(!h){r.push({itemKey:i,packageName:y,requiredRanges:C,installedVersionSpec:b,type:"invalid-version-spec"});continue}C.every(f=>Vt({currentVersionSpec:h,requiredRange:f}))||r.push({itemKey:i,packageName:y,requiredRanges:C,installedVersionSpec:b,type:"incompatible-version"})}}return{checkedItemKeys:o,projectPackageVersions:s,issues:r}}function ce({report:e,title:t}){if(!e.issues.length)return;Q.log.warn(t),Q.log.info(`\uD604\uC7AC \uD504\uB85C\uC81D\uD2B8 \uBC84\uC804: ${me.map(o=>`${o}@${a(e.projectPackageVersions[o]??"\uBBF8\uC124\uCE58")}`).join(", ")}`);let s=new Map;for(let o of e.issues){let n=s.get(o.itemKey)??[];n.push(o),s.set(o.itemKey,n)}for(let[o,n]of s.entries()){Q.log.warn(a(o));for(let r of n){let i=r.requiredRanges.join(" | ");if(r.type==="missing-package"){Q.log.info(` - ${r.packageName}: \uD328\uD0A4\uC9C0\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC544\uC694. \uD544\uC694 \uBC94\uC704: ${i}`);continue}if(r.type==="invalid-version-spec"){Q.log.info(` - ${r.packageName}: \uD604\uC7AC \uBC84\uC804 \uD615\uC2DD\uC744 \uD574\uC11D\uD558\uC9C0 \uBABB\uD588\uC5B4\uC694 (${r.installedVersionSpec}). \uD544\uC694 \uBC94\uC704: ${i}`);continue}Q.log.info(` - ${r.packageName}: \uD604\uC7AC ${r.installedVersionSpec}, \uD544\uC694 \uBC94\uC704 ${i}`)}}}function Ve({publicRegistries:e,rootPath:t}){let s=[];for(let o of e)for(let n of o.items)n.snippets.some(i=>qt(i.path).some(c=>Mt.existsSync(Kt.join(t,o.id,c))))&&s.push(`${o.id}:${n.id}`);return s}function zt(e){let t=Object.fromEntries(me.map(s=>[s,new Set]));for(let s of e.snippets)for(let[o,n]of Object.entries(s.dependencies??{}))Bt(o)&&t[o].add(n);return t}function Ft(e){let t=e.trim();if(t.startsWith(Ne)&&(t=t.slice(Ne.length).trim()),t.startsWith(Nt)){let s=t.split("@").at(-1);if(!s)return null;t=s}return!t||t==="*"?null:ze(t)||Fe(t)?t:null}function Vt({currentVersionSpec:e,requiredRange:t}){let s=Fe(t);return s?ze(e)?Ut(e,s,{includePrerelease:!0}):Lt(e,s,{includePrerelease:!0}):!1}function qt(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 Bt(e){return me.includes(e)}var Ht=Z.object({itemIds:Z.array(Z.string()).optional(),all:Z.boolean(),cwd:Z.string(),baseUrl:Z.string().optional(),onDiff:Z.enum(["overwrite","backup"]).optional()}),qe=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:B}).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,s)=>{let o=Date.now(),n=F(s);S.intro("seed-design add");try{let r=Ht.safeParse({itemIds:t,...s});if(!r.success)throw r.error;let{data:{all:i,...c}}=r;if(i)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,C=await ge(m),b=Gt.resolve(m,C.path),{start:h,stop:j}=S.spinner();h("Registry\uB97C \uAC00\uC838\uC624\uACE0 \uC788\uC5B4\uC694...");let f=await(async()=>{try{let l=await Promise.all((await se({baseUrl:y})).map(async({id:u})=>re({baseUrl:y,registryId:u})));return j("Registry\uB97C \uAC00\uC838\uC654\uC5B4\uC694."),l}catch(l){throw j("Registry\uB97C \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694."),l}})(),g=await(async()=>{if(c.itemIds?.length)return c.itemIds;let l=await S.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:f.filter(({hideFromCLICatalog:u})=>!u).flatMap(({id:u,items:A})=>A.filter(({hideFromCLICatalog:M})=>!M).sort((M,T)=>M.id.localeCompare(T.id)).map(({id:M,description:T,deprecated:G})=>({label:`${G?"(deprecated) ":""}${a(u)}:${M}`,value:`${u}:${M}`,hint:T,deprecated:G,registryItemCount:A.length}))).sort((u,A)=>u.deprecated!==A.deprecated?u.deprecated?1:-1:A.registryItemCount-u.registryItemCount)});if(S.isCancel(l))throw new k;return l})();if(!g?.length)throw new k("\uCD94\uAC00\uD560 \uD56D\uBAA9\uC774 \uC120\uD0DD\uB418\uC9C0 \uC54A\uC558\uC5B4\uC694.");S.log.message(`\uC120\uD0DD\uB41C \uD56D\uBAA9: ${a(g.join(", "))}`);let d=[];for(let l of g){let[u,...A]=l.split(":"),M=A.join(":");if(!u||!M)throw new $({message:`${a(l)}: \uD56D\uBAA9 \uC774\uB984\uC774 \uC798\uBABB\uB418\uC5C8\uC5B4\uC694.`,hint:`${a("ui:action-button")}\uACFC \uAC19\uC740 \uD615\uC2DD\uC73C\uB85C \uC785\uB825\uD574\uBCF4\uC138\uC694.`});let T=f.find(G=>G.id===u)?.items.find(G=>G.id===M);if(!T)throw new $({message:`${a(l)}: \uD56D\uBAA9\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.`});if(T.deprecated){let G=await S.confirm({message:`${a(T.id)}: deprecated \uB418\uC5C8\uC5B4\uC694. \uCD94\uAC00\uD560\uAE4C\uC694?`,initialValue:!1});if(S.isCancel(G))throw new k;if(G===!1){S.log.info(`${a(T.id)}: \uCD94\uAC00\uD558\uC9C0 \uC54A\uC744\uAC8C\uC694.`);continue}}d.push(l)}let{registryItemsToAdd:w,npmDependenciesToAdd:I}=ue({selectedItemKeys:d,publicRegistries:f}),E=ae({publicRegistries:f,itemKeys:w.flatMap(({registryId:l,items:u})=>u.map(A=>`${l}:${A.id}`)),projectPackageVersions:ne(c.cwd)});ce({report:E,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."}),S.log.info(`\uCD94\uAC00\uD560 \uD56D\uBAA9: ${a(w.map(l=>l.items.map(u=>`${l.registryId}:${u.id}`).join(", ")).join(", ")||"\uC5C6\uC74C")}
|
|
2
|
+
import*as ee from"@clack/prompts";import{cosmiconfig as ct}from"cosmiconfig";import{z as re}from"zod";import*as J from"@clack/prompts";import{ZodError as it}from"zod";import rt from"picocolors";var p=e=>rt.cyan(e);var I=class extends Error{hint;details;constructor({message:t,hint:s,details:n=[],cause:o}){super(t,{cause:o}),this.name="CliError",this.hint=s,this.details=n}},v=class extends Error{constructor(t="\uC791\uC5C5\uC774 \uCDE8\uC18C\uB410\uC5B4\uC694."){super(t),this.name="CliCancelError"}};function U(e){return e instanceof v}function q(e){return!e||typeof e!="object"||!("verbose"in e)?!1:e.verbose===!0}function ot(e,t){if(e instanceof I)return{reason:e.message,hint:e.hint??t,details:e.details,stack:nt(e.cause??e)};if(e instanceof it){let s=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:s,stack:e.stack}}if(e instanceof Error){let s=e,n=[];return(s.escapedCommand||s.command)&&n.push(`\uC2E4\uD589 \uBA85\uB839\uC5B4: ${s.escapedCommand??s.command}`),typeof s.exitCode=="number"&&n.push(`\uC885\uB8CC \uCF54\uB4DC: ${s.exitCode}`),s.stderr?.trim()?n.push(`stderr: ${s.stderr.trim()}`):s.stdout?.trim()&&n.push(`stdout: ${s.stdout.trim()}`),{reason:s.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 nt(e){if(e instanceof Error)return e.stack}function B(e,{defaultMessage:t,defaultHint:s,verbose:n=!1}){let o=ot(e,s);J.log.error(t),J.log.error(`\uC6D0\uC778: ${o.reason}`);for(let r of o.details)J.log.info(r);o.hint&&J.log.info(`\uD574\uACB0 \uD78C\uD2B8: ${o.hint}`),n&&o.stack&&(J.log.message(p(`
|
|
3
|
+
[verbose] stack trace`)),J.log.message(o.stack)),J.outro(p("\uC791\uC5C5\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694."))}import*as X from"@clack/prompts";import at from"fs-extra";import Ee from"path";var K={rsc:!1,tsx:!0,path:"./seed-design",telemetry:!0};async function ke(){return await X.group({tsx:()=>X.confirm({message:`${p("TypeScript")}\uB97C \uC0AC\uC6A9\uC911\uC774\uC2E0\uAC00\uC694?`,initialValue:K.tsx}),rsc:()=>X.confirm({message:`${p("React Server Components")}\uB97C \uC0AC\uC6A9\uC911\uC774\uC2E0\uAC00\uC694?`,initialValue:K.rsc}),path:()=>X.text({message:`${p("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:K.path,defaultValue:K.path,placeholder:K.path}),telemetry:()=>X.confirm({message:`\uAC1C\uC120\uC744 \uC704\uD574 ${p("\uC775\uBA85 \uC0AC\uC6A9 \uB370\uC774\uD130")}\uB97C \uC218\uC9D1\uD560\uAE4C\uC694?`,initialValue:K.telemetry})},{onCancel:()=>{throw new v}})}async function ue({cwd:e,config:t}){let s=Ee.resolve(e,"seed-design.json");return await at.writeFile(s,`${JSON.stringify(t,null,2)}
|
|
4
|
+
`,"utf-8"),{relativePath:Ee.relative(process.cwd(),s),targetPath:s}}var ve="seed-design",lt=ct(ve,{searchPlaces:[`${ve}.json`]}),je=re.object({$schema:re.string().optional(),rsc:re.coerce.boolean().default(!1),tsx:re.coerce.boolean().default(!0),path:re.string(),telemetry:re.coerce.boolean().optional().default(!0)}).strict();async function ye(e){let t=await me(e);if(t)return t;ee.log.error("\uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8 \uACBD\uB85C\uC5D0 `seed-design.json` \uD30C\uC77C\uC774 \uC5C6\uC5B4\uC694.");let s=await ee.confirm({message:"seed-design.json \uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uC2DC\uACA0\uC5B4\uC694?"});if(ee.isCancel(s)||!s)throw new v;try{return await ue({cwd:e,config:K}),ee.log.message("seed-design.json \uD30C\uC77C\uC774 \uC0DD\uC131\uB410\uC5B4\uC694."),je.parse(K)}catch(n){throw new I({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 me(e){let t=await lt.search(e);if(!t||t.isEmpty)return null;try{return je.parse(t.config)}catch(s){throw new I({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:s})}}function he({selectedItemKeys:e,publicRegistries:t}){let s=[],n=new Set;function o(r,i){let a=s.find(l=>l.registryId===r);if(!a?.items.some(l=>l.id===i.id)){if(a?a.items.push(i):s.push({registryId:r,items:[i]}),i.dependencies?.length)for(let l of i.dependencies)n.add(l);if(i.innerDependencies?.length)for(let l of i.innerDependencies)for(let f of l.itemIds){let h=t.find(u=>u.id===l.registryId)?.items.find(u=>u.id===f);if(!h)throw new Error(`Cannot find dependency item: ${l.registryId}:${f}`);o(l.registryId,h)}}}for(let r of e){let[i,...a]=r.split(":"),l=a.join(":");if(!i||!l)throw new Error(`Invalid snippet format: "${r}"`);let f=t.find(h=>h.id===i)?.items.find(h=>h.id===l);if(!f)throw new Error(`Cannot find snippet: "${r}"`);o(i,f)}return{registryItemsToAdd:s,npmDependenciesToAdd:n}}import*as Se from"@clack/prompts";import{z as m}from"zod";var xe=m.object({id:m.string(),description:m.string().optional(),deprecated:m.boolean().optional(),hideFromCLICatalog:m.boolean().optional(),dependencies:m.array(m.string()).optional(),innerDependencies:m.array(m.object({registryId:m.string(),itemIds:m.array(m.string())})).optional(),snippets:m.array(m.object({path:m.string(),dependencies:m.record(m.string(),m.string()).optional(),content:m.string()}))}),Pe=m.object({id:m.string(),hideFromCLICatalog:m.boolean().optional(),items:m.array(xe.omit({snippets:!0}).extend({snippets:m.array(m.object({path:m.string(),dependencies:m.record(m.string(),m.string()).optional()}))}))}),Te=m.array(m.object({id:m.string()})),pt=m.object({label:m.string(),path:m.string()}),mt=m.object({id:m.string(),title:m.string(),description:m.string().optional(),docUrl:m.string(),deprecated:m.boolean().optional(),snippetKey:m.string().optional(),snippets:m.array(pt).optional()}),dt=m.object({id:m.string(),label:m.string(),items:m.array(mt)}),ft=m.object({id:m.string(),label:m.string(),sections:m.array(dt)}),Ae=m.object({categories:m.array(ft)});var gt=1e4;async function _e(e,t=gt){let s=new AbortController,n=setTimeout(()=>s.abort(),t);try{return await fetch(e,{signal:s.signal})}catch(o){throw o instanceof Error&&o.name==="AbortError"?new I({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 Re({baseUrl:e}){let t=await fetch(`${e}/__docs__/index.json`);if(!t.ok)throw new I({message:`\uBB38\uC11C \uBAA9\uB85D\uC744 \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694: ${t.status} ${t.statusText}`});let s=await t.json(),{success:n,data:o,error:r}=Ae.safeParse(s);if(!n)throw new I({message:`\uBB38\uC11C \uBAA9\uB85D \uD30C\uC2F1\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694: ${r?.message}`});return o}async function ie({baseUrl:e}){let t=await fetch(`${e}/__registry__/index.json`);if(!t.ok)throw new Error(`Failed to fetch registries: ${t.status} ${t.statusText}`);let s=await t.json(),{success:n,data:o,error:r}=Te.safeParse(s);if(!n)throw new Error(`Failed to parse registries: ${r?.message}`);return o}async function oe({baseUrl:e,registryId:t}){let s=await fetch(`${e}/__registry__/${t}/index.json`);if(!s.ok)throw new Error(`Failed to fetch ${t} registry: ${s.status} ${s.statusText}`);let n=await s.json(),{success:o,data:r,error:i}=Pe.safeParse(n);if(!o)throw new Error(`Failed to parse ${t} registry: ${i?.message}`);return r}async function ut({baseUrl:e,registryId:t,registryItemId:s}){let n=await fetch(`${e}/__registry__/${t}/${s}.json`);if(!n.ok)throw new Error(`Failed to fetch ${s}: ${n.status} ${n.statusText}`);let o=await n.json(),{success:r,data:i,error:a}=xe.safeParse(o);if(!r)throw new Error(`Failed to parse ${s}: ${a?.message}`);return i}async function De({url:e}){let t=await _e(e);if(!t.ok)throw new I({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 Oe({baseUrl:e,query:t}){let s=t.startsWith("/")?t.slice(1):t,n=[`${e}/llms/${s}.txt`,`${e}/llms/${s}/llms.txt`],o;for(let r of n){let i;try{i=await _e(r)}catch(a){o=a;continue}if(i.ok)return i.text();if(i.status===404){o=new I({message:`llms.txt\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694: ${s}`,hint:`\uB2E4\uC74C \uACBD\uB85C\uB97C \uC2DC\uB3C4\uD588\uC5B4\uC694:
|
|
5
|
+
${n.map(a=>` - ${a}`).join(`
|
|
6
|
+
`)}`});continue}throw new I({message:`llms.txt \uC694\uCCAD\uC774 \uC2E4\uD328\uD588\uC5B4\uC694: ${i.status} ${i.statusText}`,hint:`URL: ${r}`})}throw o??new I({message:`llms.txt\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694: ${s}`,hint:`\uB2E4\uC74C \uACBD\uB85C\uB97C \uC2DC\uB3C4\uD588\uC5B4\uC694:
|
|
7
|
+
${n.map(r=>` - ${r}`).join(`
|
|
8
|
+
`)}`})}async function Me({baseUrl:e,registryId:t,registryItemIds:s}){return await Promise.all(s.map(async n=>{try{return await ut({baseUrl:e,registryId:t,registryItemId:n})}catch(o){let r=await fetch(`${e}/__registry__/${t}/index.json`);if(!r.ok)throw new Error(`${t} \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uB97C \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694: ${r.status} ${r.statusText}`);let i=await r.json(),{success:a,data:l}=Pe.safeParse(i);throw a?(Se.log.error(`${n} \uC2A4\uB2C8\uD3AB\uC774 ${t} \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC5D0 \uC5C6\uC5B4\uC694.`),Se.log.info(`${t} \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC5D0 \uC874\uC7AC\uD558\uB294 \uC2A4\uB2C8\uD3AB:
|
|
9
|
+
${l.items.map(f=>f.id).join(`
|
|
10
|
+
`)}`),o):new Error(`Failed to parse registry index for ${t}`)}}))}import{promises as Ct}from"fs";import{tmpdir as It}from"os";import Ke from"path";import{transformFromAstSync as yt}from"@babel/core";import ht from"@babel/plugin-transform-typescript";import*as we from"recast";import{parse as wt}from"@babel/parser";var bt={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"]},Le=async({sourceFile:e,config:t})=>{let s=e.getFullText();if(t.tsx)return s;let n=we.parse(s,{parser:{parse:r=>wt(r,bt)}}),o=yt(n,s,{cloneInputAst:!1,code:!1,ast:!0,plugins:[ht],configFile:!1});if(!o||!o.ast)throw new Error("Failed to transform JSX");return we.print(o.ast).code};import{SyntaxKind as $t}from"ts-morph";var Ue=async({sourceFile:e,config:t})=>{if(t.rsc)return e;let s=e.getFirstChildByKind($t.ExpressionStatement);if(!s)return e;let n=s.getExpression();if(!n)return e;let o=n.getText().trim();if(o!=='"use client"'&&o!=="'use client'")return e;let r=s.getText(),i=s.getFullText();if(r.trim()===i.trim())return e;let l=i.replace(r,"").replace(/^\s*\n/,"").replace(/\n\s*$/,"");return s.replaceWithText(l),e};import{Project as xt,ScriptKind as Pt}from"ts-morph";var St=[Ue],Rt=new xt({compilerOptions:{}});async function Et(e){let t=await Ct.mkdtemp(Ke.join(It(),"seed-design-"));return Ke.join(t,e)}async function Fe(e){let t=await Et(e.filename),s=Rt.createSourceFile(t,e.raw,{scriptKind:Pt.TSX});for(let n of St)n({sourceFile:s,...e});return await Le({sourceFile:s,...e})}import*as F from"@clack/prompts";import ne from"fs-extra";import H from"path";import{createPatch as kt}from"diff";import vt from"@npmcli/disparity-colors";async function be({registryItemsToAdd:e,rootPath:t,cwd:s,baseUrl:n,config:o,onDiff:r}){let i=[];for(let{registryId:a,items:l}of e){let f=H.join(t,a);ne.ensureDirSync(f);let h=await Me({baseUrl:n,registryId:a,registryItemIds:l.map(u=>u.id)});for(let{id:u,snippets:C}of h){let k=await Promise.all(C.map(async w=>{let d=await Fe({filename:w.path,config:o,raw:w.content}),b=H.join(f,w.path);return o.tsx||(b=b.replace(/\.tsx$/,".jsx"),b=b.replace(/\.ts$/,".js")),{filePath:b,content:d,relativePath:H.relative(s,b),name:`${a}:${u}`}})),y=[];for(let w of k){let{filePath:d,content:b,relativePath:A}=w;if(await ne.ensureDir(H.dirname(d)),ne.existsSync(d)){let V=await ne.readFile(d,"utf-8");if(V===b){F.log.info(`${p(A)}: \uC774\uBBF8 \uCD5C\uC2E0 \uC0C1\uD0DC\uC608\uC694.`);continue}let P=H.basename(d),D=H.extname(d),O=H.basename(d,D),Y=Date.now(),$=`legacy-${O}-${Y}${D}`,c=await(async()=>{if(r)return r;let g=kt(A,V,b),x=vt(g);return F.log.message(`
|
|
11
|
+
${p(A)}: \uD604\uC7AC \uD30C\uC77C\uACFC \uBC1B\uC73C\uB824\uB294 \uD30C\uC77C\uC758 \uB0B4\uC6A9\uC774 \uB2EC\uB77C\uC694.
|
|
12
|
+
`),F.log.message(x),F.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 ${$}\uC73C\uB85C \uC62E\uAE30\uACE0 ${P} \uBC1B\uAE30`},{value:"skip",label:"\uC0C8 \uD30C\uC77C \uBC1B\uC9C0 \uC54A\uACE0 \uADF8\uB300\uB85C \uB450\uAE30"}]})})();if(F.isCancel(c)||c==="skip"){F.log.info(`${p(A)}: \uD30C\uC77C\uC744 \uBC1B\uC9C0 \uC54A\uACE0 \uAC74\uB108\uB6F0\uC5C8\uC5B4\uC694.`);continue}if(c==="backup"){let g=H.dirname(d),x=H.join(g,$);await ne.rename(d,x),F.log.info(`${p(A)}: \uAE30\uC874 \uD30C\uC77C\uC744 ${p(H.relative(s,x))}\uB85C \uC62E\uACBC\uC5B4\uC694.`)}}await ne.writeFile(d,b),y.push(w)}if(y.length>0){let w=y.map(({name:d,relativePath:b})=>({name:d,path:b}));i.push(...w),F.log.success(`${p(`${a}:${u}`)} \uAD00\uB828 \uC2A4\uB2C8\uD3AB \uB2E4\uC6B4\uB85C\uB4DC \uC644\uB8CC: ${p(w.map(d=>d.path).join(", "))}`)}}}}import*as R from"@clack/prompts";import Qt from"path";import{z as se}from"zod";var G="https://seed-design.io";import*as ze from"@clack/prompts";import{execa as Ot}from"execa";import{detect as jt}from"@antfu/ni";async function Ne(e){let t=await jt({programmatic:!0,cwd:e});return t==="yarn@berry"?"yarn":t==="pnpm@6"?"pnpm":t==="bun"?"bun":t==="deno"?"deno":t??"npm"}import Tt from"findup-sync";import At from"fs-extra";var _t="package.json";function Dt(e=process.cwd()){let t=Tt(_t,{cwd:e});if(!t)throw new Error("No package.json file found in the project.");return t}function ae(e=process.cwd()){let t=Dt(e);return At.readJSONSync(t)}async function $e({cwd:e,deps:t,dev:s=!1}){let{start:n,stop:o}=ze.spinner(),r=await Ne(e),a={...ae(e).dependencies},l=new Set(t.filter(y=>!a[y])),f=new Set(t.filter(y=>a[y]));if(!l.size)return{installed:new Set,filtered:l};n("\uC758\uC874\uC131 \uC124\uCE58\uC911...");let C=[r==="npm"?"install":"add",s?"-D":null,...l].filter(Boolean),k=`${r} ${C.join(" ")}`;try{await Ot(r,C,{cwd:e})}catch(y){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: ${k}`],cause:y})}return o("\uC758\uC874\uC131 \uC124\uCE58\uAC00 \uC644\uB8CC\uB410\uC5B4\uC694."),{installed:l,filtered:f}}import{randomUUID as Mt}from"node:crypto";import*as qe from"@clack/prompts";var Lt="seed_cli";async function Ut(e){if(process.env.DISABLE_TELEMETRY==="true"||process.env.SEED_DISABLE_TELEMETRY==="true")return!1;try{if((await me(e))?.telemetry===!1)return!1}catch{}return!0}function Kt(){return Mt()}var Ft=Kt(),Ve=!1;async function Nt(e,{event:t,properties:s={}}){if(!await Ut(e))return;let o=`${Lt}.${t}`;Ve||(qe.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)"),Ve=!0);try{let r="https://us.i.posthog.com/capture",i={"Content-Type":"application/json"},a={api_key:"phc_seod8HhifElOP1R92KmvsQybrtUmkOTgZBsq0mfCelR",event:o,distinct_id:Ft,properties:{...s,$process_person_profile:!1},timestamp:new Date().toISOString()},l=new AbortController,f=setTimeout(()=>l.abort(),5e3);try{await fetch(r,{method:"POST",headers:i,body:JSON.stringify(a),signal:l.signal})}finally{clearTimeout(f)}}catch{}}var N={track:Nt};import*as te from"@clack/prompts";import zt from"fs-extra";import Vt from"path";import{intersects as qt,satisfies as Bt,valid as He,validRange as Ge}from"semver";var de=["@seed-design/react","@seed-design/css"],Be="workspace:",Ht="npm:";function ce(e){try{let t=ae(e),s={...t.dependencies,...t.devDependencies,...t.peerDependencies,...t.optionalDependencies},n={};for(let o of de){let r=s[o];typeof r=="string"&&(n[o]=r)}return n}catch{return{}}}function le({publicRegistries:e,itemKeys:t,projectPackageVersions:s}){let n=Array.from(new Set(t)),o=new Map(e.flatMap(i=>i.items.map(a=>[`${i.id}:${a.id}`,a]))),r=[];for(let i of n){let a=o.get(i);if(!a)continue;let l=Gt(a);for(let f of de){let h=Array.from(l[f]??[]);if(!h.length)continue;let u=s[f];if(!u){r.push({itemKey:i,packageName:f,requiredRanges:h,type:"missing-package"});continue}let C=Jt(u);if(!C){r.push({itemKey:i,packageName:f,requiredRanges:h,installedVersionSpec:u,type:"invalid-version-spec"});continue}h.every(y=>Wt({currentVersionSpec:C,requiredRange:y}))||r.push({itemKey:i,packageName:f,requiredRanges:h,installedVersionSpec:u,type:"incompatible-version"})}}return{checkedItemKeys:n,projectPackageVersions:s,issues:r}}function pe({report:e,title:t}){if(!e.issues.length)return;te.log.warn(t),te.log.info(`\uD604\uC7AC \uD504\uB85C\uC81D\uD2B8 \uBC84\uC804: ${de.map(n=>`${n}@${p(e.projectPackageVersions[n]??"\uBBF8\uC124\uCE58")}`).join(", ")}`);let s=new Map;for(let n of e.issues){let o=s.get(n.itemKey)??[];o.push(n),s.set(n.itemKey,o)}for(let[n,o]of s.entries()){te.log.warn(p(n));for(let r of o){let i=r.requiredRanges.join(" | ");if(r.type==="missing-package"){te.log.info(` - ${r.packageName}: \uD328\uD0A4\uC9C0\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC544\uC694. \uD544\uC694 \uBC94\uC704: ${i}`);continue}if(r.type==="invalid-version-spec"){te.log.info(` - ${r.packageName}: \uD604\uC7AC \uBC84\uC804 \uD615\uC2DD\uC744 \uD574\uC11D\uD558\uC9C0 \uBABB\uD588\uC5B4\uC694 (${r.installedVersionSpec}). \uD544\uC694 \uBC94\uC704: ${i}`);continue}te.log.info(` - ${r.packageName}: \uD604\uC7AC ${r.installedVersionSpec}, \uD544\uC694 \uBC94\uC704 ${i}`)}}}function Je({publicRegistries:e,rootPath:t}){let s=[];for(let n of e)for(let o of n.items)o.snippets.some(i=>Yt(i.path).some(a=>zt.existsSync(Vt.join(t,n.id,a))))&&s.push(`${n.id}:${o.id}`);return s}function Gt(e){let t=Object.fromEntries(de.map(s=>[s,new Set]));for(let s of e.snippets)for(let[n,o]of Object.entries(s.dependencies??{}))Xt(n)&&t[n].add(o);return t}function Jt(e){let t=e.trim();if(t.startsWith(Be)&&(t=t.slice(Be.length).trim()),t.startsWith(Ht)){let s=t.split("@").at(-1);if(!s)return null;t=s}return!t||t==="*"?null:He(t)||Ge(t)?t:null}function Wt({currentVersionSpec:e,requiredRange:t}){let s=Ge(t);return s?He(e)?Bt(e,s,{includePrerelease:!0}):qt(e,s,{includePrerelease:!0}):!1}function Yt(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 Xt(e){return de.includes(e)}var Zt=se.object({itemIds:se.array(se.string()).optional(),all:se.boolean(),cwd:se.string(),baseUrl:se.string().optional(),onDiff:se.enum(["overwrite","backup"]).optional()}),We=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:G}).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,s)=>{let n=Date.now(),o=q(s);R.intro("seed-design add");try{let r=Zt.safeParse({itemIds:t,...s});if(!r.success)throw r.error;let{data:{all:i,...a}}=r;if(i)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 l=a.cwd,f=a.baseUrl,h=await ye(l),u=Qt.resolve(l,h.path),{start:C,stop:k}=R.spinner();C("Registry\uB97C \uAC00\uC838\uC624\uACE0 \uC788\uC5B4\uC694...");let y=await(async()=>{try{let c=await Promise.all((await ie({baseUrl:f})).map(async({id:g})=>oe({baseUrl:f,registryId:g})));return k("Registry\uB97C \uAC00\uC838\uC654\uC5B4\uC694."),c}catch(c){throw k("Registry\uB97C \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694."),c}})(),w=await(async()=>{if(a.itemIds?.length)return a.itemIds;let c=await R.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:y.filter(({hideFromCLICatalog:g})=>!g).flatMap(({id:g,items:x})=>x.filter(({hideFromCLICatalog:_})=>!_).sort((_,T)=>_.id.localeCompare(T.id)).map(({id:_,description:T,deprecated:S})=>({label:`${S?"(deprecated) ":""}${p(g)}:${_}`,value:`${g}:${_}`,hint:T,deprecated:S,registryItemCount:x.length}))).sort((g,x)=>g.deprecated!==x.deprecated?g.deprecated?1:-1:x.registryItemCount-g.registryItemCount)});if(R.isCancel(c))throw new v;return c})();if(!w?.length)throw new v("\uCD94\uAC00\uD560 \uD56D\uBAA9\uC774 \uC120\uD0DD\uB418\uC9C0 \uC54A\uC558\uC5B4\uC694.");R.log.message(`\uC120\uD0DD\uB41C \uD56D\uBAA9: ${p(w.join(", "))}`);let d=[];for(let c of w){let[g,...x]=c.split(":"),_=x.join(":");if(!g||!_)throw new I({message:`${p(c)}: \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 T=y.find(S=>S.id===g)?.items.find(S=>S.id===_);if(!T)throw new I({message:`${p(c)}: \uD56D\uBAA9\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.`});if(T.deprecated){let S=await R.confirm({message:`${p(T.id)}: deprecated \uB418\uC5C8\uC5B4\uC694. \uCD94\uAC00\uD560\uAE4C\uC694?`,initialValue:!1});if(R.isCancel(S))throw new v;if(S===!1){R.log.info(`${p(T.id)}: \uCD94\uAC00\uD558\uC9C0 \uC54A\uC744\uAC8C\uC694.`);continue}}d.push(c)}let{registryItemsToAdd:b,npmDependenciesToAdd:A}=he({selectedItemKeys:d,publicRegistries:y}),V=le({publicRegistries:y,itemKeys:b.flatMap(({registryId:c,items:g})=>g.map(x=>`${c}:${x.id}`)),projectPackageVersions:ce(a.cwd)});pe({report:V,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."}),R.log.info(`\uCD94\uAC00\uD560 \uD56D\uBAA9: ${p(b.map(c=>c.items.map(g=>`${c.registryId}:${g.id}`).join(", ")).join(", ")||"\uC5C6\uC74C")}
|
|
9
13
|
|
|
10
|
-
\uC124\uCE58\uD560 \uC758\uC874\uC131: ${a(Array.from(I).join(", ")||"\uC5C6\uC74C")}`),await he({registryItemsToAdd:w,rootPath:b,cwd:m,baseUrl:y,config:C,onDiff:c.onDiff});let{installed:P,filtered:O}=await we({cwd:m,deps:Array.from(I)});P.size===0&&S.log.message("\uBAA8\uB4E0 \uC758\uC874\uC131\uC774 \uC774\uBBF8 \uC124\uCE58\uB418\uC5B4 \uC788\uC5B4\uC694."),P.size&&(S.log.message(`\uC758\uC874\uC131 \uC124\uCE58 \uC644\uB8CC: ${a(Array.from(P).join(", "))}`),O.size&&S.log.message(`\uC124\uCE58\uD558\uC9C0 \uC54A\uC740 \uC758\uC874\uC131 (\uC774\uBBF8 \uC124\uCE58\uB428): ${a(Array.from(O).join(", "))}`)),S.outro("\uC644\uB8CC\uD588\uC5B4\uC694.");let ee=Date.now()-o,pe=new Set(w.map(l=>l.registryId)),x=g.some(l=>{let[u,...A]=l.split(":"),M=A.join(":");return f.find(T=>T.id===u)?.items.find(T=>T.id===M)?.deprecated});try{await U.track(c.cwd,{event:"add",properties:{items_count:d.length,registries:Array.from(pe),has_deprecated:x,dependencies_count:I.size,duration_ms:ee}})}catch(l){n&&console.error("[Telemetry] add tracking failed:",l)}}catch(r){z(r)&&(S.outro(a(r.message)),process.exit(0)),V(r,{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:n}),process.exit(1)}})};import*as v from"@clack/prompts";import Jt from"path";import{z as Y}from"zod";var Wt=Y.object({registryIds:Y.array(Y.string()).optional(),all:Y.boolean(),includeDeprecated:Y.boolean().optional(),cwd:Y.string(),baseUrl:Y.string().optional(),onDiff:Y.enum(["overwrite","backup"]).optional()}),Be=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:B}).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,s)=>{let o=Date.now(),n=F(s);v.intro("seed-design add-all");try{let r=Wt.safeParse({registryIds:t,...s});if(!r.success)throw r.error;let{data:i}=r,c=i.cwd,m=i.baseUrl,y=await ge(c),C=Jt.resolve(c,y.path),{start:b,stop:h}=v.spinner();b("Registry\uB97C \uAC00\uC838\uC624\uACE0 \uC788\uC5B4\uC694...");let j=await(async()=>{try{let x=await Promise.all((await se({baseUrl:m})).map(async({id:l})=>re({baseUrl:m,registryId:l})));return h("Registry\uB97C \uAC00\uC838\uC654\uC5B4\uC694."),x}catch(x){throw h("Registry\uB97C \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694."),x}})(),f=await(async()=>{if(i.all){let l=j.map(u=>u.id);return v.log.message(`\uBAA8\uB4E0 \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC758 \uBAA8\uB4E0 \uD56D\uBAA9\uC744 \uCD94\uAC00\uD569\uB2C8\uB2E4: ${a(l.join(", "))}`),l}if(i.registryIds?.length){let l=j.map(u=>u.id);for(let u of i.registryIds)if(!l.includes(u))throw new $({message:`\uB808\uC9C0\uC2A4\uD2B8\uB9AC '${u}'\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.`,details:[`\uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uB808\uC9C0\uC2A4\uD2B8\uB9AC: ${l.join(", ")}`]});return v.log.message(`\uC120\uD0DD\uB41C \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC758 \uBAA8\uB4E0 \uD56D\uBAA9\uC744 \uCD94\uAC00\uD569\uB2C8\uB2E4: ${a(i.registryIds.join(", "))}`),i.registryIds}let x=await v.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:j.filter(({hideFromCLICatalog:l})=>!l).sort((l,u)=>u.items.length-l.items.length).map(l=>{let u=l.items[0]?.id,A=u?`${l.items.length}\uAC1C \uD56D\uBAA9 (${u} \uB4F1)`:`${l.items.length}\uAC1C \uD56D\uBAA9 (\uD56D\uBAA9 \uC5C6\uC74C)`;return{label:l.id,value:l.id,hint:A}})});if(v.isCancel(x))throw new k;return v.log.message(`\uC120\uD0DD\uB41C \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC758 \uD56D\uBAA9\uC744 \uCD94\uAC00\uD569\uB2C8\uB2E4: ${a(x.join(", "))}`),x})(),g=j.filter(x=>f.includes(x.id)),d=g.flatMap(x=>x.items.filter(l=>l.deprecated?i.includeDeprecated:!0).map(l=>`${x.id}:${l.id}`)),w=g.reduce((x,l)=>x+l.items.filter(u=>u.deprecated).length,0);if(!i.includeDeprecated&&w>0&&v.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.`),!d.length)throw new k("\uCD94\uAC00\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC5B4\uC694.");v.log.message(`\uCD1D ${a(d.length.toString())}\uAC1C\uC758 \uD56D\uBAA9\uC744 \uCD94\uAC00\uD569\uB2C8\uB2E4.`);let{registryItemsToAdd:I,npmDependenciesToAdd:E}=ue({selectedItemKeys:d,publicRegistries:j}),P=ae({publicRegistries:j,itemKeys:I.flatMap(({registryId:x,items:l})=>l.map(u=>`${x}:${u.id}`)),projectPackageVersions:ne(i.cwd)});ce({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 he({registryItemsToAdd:I,rootPath:C,cwd:c,baseUrl:m,config:y,onDiff:i.onDiff});let{installed:O,filtered:ee}=await we({cwd:c,deps:Array.from(E)});O.size===0&&v.log.message("\uBAA8\uB4E0 \uC758\uC874\uC131\uC774 \uC774\uBBF8 \uC124\uCE58\uB418\uC5B4 \uC788\uC5B4\uC694."),O.size&&(v.log.message(`\uC758\uC874\uC131 \uC124\uCE58 \uC644\uB8CC: ${a(Array.from(O).join(", "))}`),ee.size&&v.log.message(`\uC124\uCE58\uD558\uC9C0 \uC54A\uC740 \uC758\uC874\uC131 (\uC774\uBBF8 \uC124\uCE58\uB428): ${a(Array.from(ee).join(", "))}`)),v.outro("\uC644\uB8CC\uD588\uC5B4\uC694.");let pe=Date.now()-o;try{await U.track(i.cwd,{event:"add-all",properties:{registries:f,items_count:d.length,include_deprecated:i.includeDeprecated||!1,dependencies_count:E.size,duration_ms:pe}})}catch(x){n&&console.error("[Telemetry] add-all tracking failed:",x)}}catch(r){z(r)&&(v.outro(a(r.message)),process.exit(0)),V(r,{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:n}),process.exit(1)}})};import*as D from"@clack/prompts";import Ge from"path";import{z as N}from"zod";var Yt=N.object({itemIds:N.array(N.string()).optional(),component:N.union([N.string(),N.array(N.string())]).optional(),all:N.boolean(),registry:N.string().optional(),cwd:N.string(),baseUrl:N.string().optional()});function Xt({itemIds:e,component:t}){let s=r=>r.trim().replace(/\s+/g,"-"),o=(e??[]).map(s).filter(Boolean),n=(Array.isArray(t)?t:[t]).filter(r=>!!r).flatMap(r=>r.split(",")).map(s).filter(Boolean);return Array.from(new Set([...o,...n]))}function Qt({publicRegistries:e,targetInputs:t,defaultRegistry:s}){let o=e.filter(r=>typeof r.id=="string"&&Array.isArray(r.items)).flatMap(r=>r.items.filter(i=>typeof i.id=="string").map(i=>`${r.id}:${i.id}`)),n=new Set;for(let r of t){let i=r.includes(":")?r:s?`${s}:${r}`:(()=>{let c=o.filter(m=>m.endsWith(`:${r}`));if(!c.length)throw new $({message:`${a(r)}: \uD56D\uBAA9\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.`,hint:`${a("ui:action-button")}\uCC98\uB7FC registry\uB97C \uD3EC\uD568\uD574\uC11C \uC785\uB825\uD574\uBCF4\uC138\uC694.`});if(c.length>1)throw new $({message:`${a(r)}: \uAC19\uC740 \uC774\uB984\uC758 \uD56D\uBAA9\uC774 \uC5EC\uB7EC \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC5D0 \uC788\uC5B4\uC694.`,details:c.map(m=>`- ${m}`),hint:`${a("ui:action-button")}\uCC98\uB7FC registry\uB97C \uD3EC\uD568\uD574\uC11C \uC785\uB825\uD574\uBCF4\uC138\uC694.`});return c[0]})();if(!o.includes(i))throw new $({message:`${a(i)}: \uD56D\uBAA9\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.`});n.add(i)}return Array.from(n)}var He=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:B}).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,s)=>{let o=Date.now(),n=F(s);D.intro("seed-design compat");try{let r=Yt.safeParse({itemIds:t,...s});if(!r.success)throw r.error;let{data:i}=r,{start:c,stop:m}=D.spinner();c("Registry\uB97C \uAC00\uC838\uC624\uACE0 \uC788\uC5B4\uC694...");let y=await(async()=>{try{let g=await Promise.all((await se({baseUrl:i.baseUrl})).map(async({id:d})=>re({baseUrl:i.baseUrl,registryId:d})));return m("Registry\uB97C \uAC00\uC838\uC654\uC5B4\uC694."),g}catch(g){throw m("Registry\uB97C \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694."),g}})(),C=Xt({itemIds:i.itemIds,component:i.component}),b=i.all?y.flatMap(d=>d.items.map(w=>`${d.id}:${w.id}`)):C.length>0?Qt({publicRegistries:y,targetInputs:C,defaultRegistry:i.registry}):le(i.cwd),h=Array.isArray(b)?b:await(async()=>{let g=await b;if(!g)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 d=Ge.resolve(i.cwd,g.path),w=Ve({publicRegistries:y,rootPath:d});return w.length?w:(D.log.info(`${a(Ge.relative(i.cwd,d)||g.path)}\uC5D0\uC11C \uC124\uCE58\uB41C \uC2A4\uB2C8\uD3AB\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC5B4\uC694.`),[])})();h.length||(D.outro("\uAC80\uC0AC\uD560 \uC2A4\uB2C8\uD3AB\uC774 \uC5C6\uC5B4\uC694."),process.exit(0));let j=ne(i.cwd),f=ae({publicRegistries:y,itemKeys:h,projectPackageVersions:j});if(D.log.info(`\uAC80\uC0AC \uB300\uC0C1: ${a(f.checkedItemKeys.join(", "))}`),!f.issues.length){D.outro("\uBAA8\uB4E0 \uC2A4\uB2C8\uD3AB\uC774 \uD604\uC7AC @seed-design/react, @seed-design/css\uC640 \uD638\uD658\uB3FC\uC694.");try{await U.track(i.cwd,{event:"compat",properties:{checked_items_count:f.checkedItemKeys.length,incompatible_items_count:0,duration_ms:Date.now()-o}})}catch(g){n&&console.error("[Telemetry] compat tracking failed:",g)}process.exit(0)}ce({report:f,title:"\uD604\uC7AC \uD504\uB85C\uC81D\uD2B8 \uBC84\uC804\uACFC \uD638\uD658\uB418\uC9C0 \uC54A\uB294 \uC2A4\uB2C8\uD3AB\uC744 \uCC3E\uC558\uC5B4\uC694."}),D.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."),D.outro("\uD638\uD658\uC131 \uC774\uC288\uAC00 \uC788\uC5B4\uC694.");try{await U.track(i.cwd,{event:"compat",properties:{checked_items_count:f.checkedItemKeys.length,incompatible_items_count:new Set(f.issues.map(g=>g.itemKey)).size,issue_count:f.issues.length,duration_ms:Date.now()-o}})}catch(g){n&&console.error("[Telemetry] compat tracking failed:",g)}process.exit(1)}catch(r){z(r)&&(D.outro(a(r.message)),process.exit(0)),V(r,{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:n}),process.exit(1)}})};import*as R from"@clack/prompts";import{z as xe}from"zod";var Zt="https://raw.githubusercontent.com/daangn/seed-design/refs/heads/dev/docs/registry",es=xe.object({query:xe.string().optional(),baseUrl:xe.string().optional()});function Je(e,t){return`${Zt}/${e}/${t}`}function ts(e,t){let s=`${t}${e.docUrl}`,o=`${t}/llms${e.docUrl}.txt`,n=[e.id,`- docs: ${s}`,`- llms.txt: ${o}`];if(e.snippetKey&&e.snippets&&e.snippets.length>0){let[r]=e.snippetKey.split(":");if(r==="ui"||r==="breeze")if(e.snippets.length===1)n.push(`- snippet: ${Je(r,e.snippets[0].path)}`);else{n.push("- snippet:");for(let i of e.snippets)n.push(` - ${i.label}: ${Je(r,i.path)}`)}}R.log.message(n.join(`
|
|
11
|
-
`))}function
|
|
14
|
+
\uC124\uCE58\uD560 \uC758\uC874\uC131: ${p(Array.from(A).join(", ")||"\uC5C6\uC74C")}`),await be({registryItemsToAdd:b,rootPath:u,cwd:l,baseUrl:f,config:h,onDiff:a.onDiff});let{installed:P,filtered:D}=await $e({cwd:l,deps:Array.from(A)});P.size===0&&R.log.message("\uBAA8\uB4E0 \uC758\uC874\uC131\uC774 \uC774\uBBF8 \uC124\uCE58\uB418\uC5B4 \uC788\uC5B4\uC694."),P.size&&(R.log.message(`\uC758\uC874\uC131 \uC124\uCE58 \uC644\uB8CC: ${p(Array.from(P).join(", "))}`),D.size&&R.log.message(`\uC124\uCE58\uD558\uC9C0 \uC54A\uC740 \uC758\uC874\uC131 (\uC774\uBBF8 \uC124\uCE58\uB428): ${p(Array.from(D).join(", "))}`)),R.outro("\uC644\uB8CC\uD588\uC5B4\uC694.");let O=Date.now()-n,Y=new Set(b.map(c=>c.registryId)),$=w.some(c=>{let[g,...x]=c.split(":"),_=x.join(":");return y.find(T=>T.id===g)?.items.find(T=>T.id===_)?.deprecated});try{await N.track(a.cwd,{event:"add",properties:{items_count:d.length,registries:Array.from(Y),has_deprecated:$,dependencies_count:A.size,duration_ms:O}})}catch(c){o&&console.error("[Telemetry] add tracking failed:",c)}}catch(r){U(r)&&(R.outro(p(r.message)),process.exit(0)),B(r,{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 es from"path";import{z as Q}from"zod";var ts=Q.object({registryIds:Q.array(Q.string()).optional(),all:Q.boolean(),includeDeprecated:Q.boolean().optional(),cwd:Q.string(),baseUrl:Q.string().optional(),onDiff:Q.enum(["overwrite","backup"]).optional()}),Ye=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:G}).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,s)=>{let n=Date.now(),o=q(s);j.intro("seed-design add-all");try{let r=ts.safeParse({registryIds:t,...s});if(!r.success)throw r.error;let{data:i}=r,a=i.cwd,l=i.baseUrl,f=await ye(a),h=es.resolve(a,f.path),{start:u,stop:C}=j.spinner();u("Registry\uB97C \uAC00\uC838\uC624\uACE0 \uC788\uC5B4\uC694...");let k=await(async()=>{try{let $=await Promise.all((await ie({baseUrl:l})).map(async({id:c})=>oe({baseUrl:l,registryId:c})));return C("Registry\uB97C \uAC00\uC838\uC654\uC5B4\uC694."),$}catch($){throw C("Registry\uB97C \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694."),$}})(),y=await(async()=>{if(i.all){let c=k.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(c.join(", "))}`),c}if(i.registryIds?.length){let c=k.map(g=>g.id);for(let g of i.registryIds)if(!c.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: ${c.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(i.registryIds.join(", "))}`),i.registryIds}let $=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:k.filter(({hideFromCLICatalog:c})=>!c).sort((c,g)=>g.items.length-c.items.length).map(c=>{let g=c.items[0]?.id,x=g?`${c.items.length}\uAC1C \uD56D\uBAA9 (${g} \uB4F1)`:`${c.items.length}\uAC1C \uD56D\uBAA9 (\uD56D\uBAA9 \uC5C6\uC74C)`;return{label:c.id,value:c.id,hint:x}})});if(j.isCancel($))throw new v;return j.log.message(`\uC120\uD0DD\uB41C \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC758 \uD56D\uBAA9\uC744 \uCD94\uAC00\uD569\uB2C8\uB2E4: ${p($.join(", "))}`),$})(),w=k.filter($=>y.includes($.id)),d=w.flatMap($=>$.items.filter(c=>c.deprecated?i.includeDeprecated:!0).map(c=>`${$.id}:${c.id}`)),b=w.reduce(($,c)=>$+c.items.filter(g=>g.deprecated).length,0);if(!i.includeDeprecated&&b>0&&j.log.info(`${b}\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.`),!d.length)throw new v("\uCD94\uAC00\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC5B4\uC694.");j.log.message(`\uCD1D ${p(d.length.toString())}\uAC1C\uC758 \uD56D\uBAA9\uC744 \uCD94\uAC00\uD569\uB2C8\uB2E4.`);let{registryItemsToAdd:A,npmDependenciesToAdd:V}=he({selectedItemKeys:d,publicRegistries:k}),P=le({publicRegistries:k,itemKeys:A.flatMap(({registryId:$,items:c})=>c.map(g=>`${$}:${g.id}`)),projectPackageVersions:ce(i.cwd)});pe({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 be({registryItemsToAdd:A,rootPath:h,cwd:a,baseUrl:l,config:f,onDiff:i.onDiff});let{installed:D,filtered:O}=await $e({cwd:a,deps:Array.from(V)});D.size===0&&j.log.message("\uBAA8\uB4E0 \uC758\uC874\uC131\uC774 \uC774\uBBF8 \uC124\uCE58\uB418\uC5B4 \uC788\uC5B4\uC694."),D.size&&(j.log.message(`\uC758\uC874\uC131 \uC124\uCE58 \uC644\uB8CC: ${p(Array.from(D).join(", "))}`),O.size&&j.log.message(`\uC124\uCE58\uD558\uC9C0 \uC54A\uC740 \uC758\uC874\uC131 (\uC774\uBBF8 \uC124\uCE58\uB428): ${p(Array.from(O).join(", "))}`)),j.outro("\uC644\uB8CC\uD588\uC5B4\uC694.");let Y=Date.now()-n;try{await N.track(i.cwd,{event:"add-all",properties:{registries:y,items_count:d.length,include_deprecated:i.includeDeprecated||!1,dependencies_count:V.size,duration_ms:Y}})}catch($){o&&console.error("[Telemetry] add-all tracking failed:",$)}}catch(r){U(r)&&(j.outro(p(r.message)),process.exit(0)),B(r,{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 M from"@clack/prompts";import Xe from"path";import{z}from"zod";var ss=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().optional()});function rs({itemIds:e,component:t}){let s=r=>r.trim().replace(/\s+/g,"-"),n=(e??[]).map(s).filter(Boolean),o=(Array.isArray(t)?t:[t]).filter(r=>!!r).flatMap(r=>r.split(",")).map(s).filter(Boolean);return Array.from(new Set([...n,...o]))}function is({publicRegistries:e,targetInputs:t,defaultRegistry:s}){let n=e.filter(r=>typeof r.id=="string"&&Array.isArray(r.items)).flatMap(r=>r.items.filter(i=>typeof i.id=="string").map(i=>`${r.id}:${i.id}`)),o=new Set;for(let r of t){let i=r.includes(":")?r:s?`${s}:${r}`:(()=>{let a=n.filter(l=>l.endsWith(`:${r}`));if(!a.length)throw new I({message:`${p(r)}: \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(r)}: \uAC19\uC740 \uC774\uB984\uC758 \uD56D\uBAA9\uC774 \uC5EC\uB7EC \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC5D0 \uC788\uC5B4\uC694.`,details:a.map(l=>`- ${l}`),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 Qe=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:G}).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,s)=>{let n=Date.now(),o=q(s);M.intro("seed-design compat");try{let r=ss.safeParse({itemIds:t,...s});if(!r.success)throw r.error;let{data:i}=r,{start:a,stop:l}=M.spinner();a("Registry\uB97C \uAC00\uC838\uC624\uACE0 \uC788\uC5B4\uC694...");let f=await(async()=>{try{let w=await Promise.all((await ie({baseUrl:i.baseUrl})).map(async({id:d})=>oe({baseUrl:i.baseUrl,registryId:d})));return l("Registry\uB97C \uAC00\uC838\uC654\uC5B4\uC694."),w}catch(w){throw l("Registry\uB97C \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694."),w}})(),h=rs({itemIds:i.itemIds,component:i.component}),u=i.all?f.flatMap(d=>d.items.map(b=>`${d.id}:${b.id}`)):h.length>0?is({publicRegistries:f,targetInputs:h,defaultRegistry:i.registry}):me(i.cwd),C=Array.isArray(u)?u:await(async()=>{let w=await u;if(!w)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 d=Xe.resolve(i.cwd,w.path),b=Je({publicRegistries:f,rootPath:d});return b.length?b:(M.log.info(`${p(Xe.relative(i.cwd,d)||w.path)}\uC5D0\uC11C \uC124\uCE58\uB41C \uC2A4\uB2C8\uD3AB\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC5B4\uC694.`),[])})();C.length||(M.outro("\uAC80\uC0AC\uD560 \uC2A4\uB2C8\uD3AB\uC774 \uC5C6\uC5B4\uC694."),process.exit(0));let k=ce(i.cwd),y=le({publicRegistries:f,itemKeys:C,projectPackageVersions:k});if(M.log.info(`\uAC80\uC0AC \uB300\uC0C1: ${p(y.checkedItemKeys.join(", "))}`),!y.issues.length){M.outro("\uBAA8\uB4E0 \uC2A4\uB2C8\uD3AB\uC774 \uD604\uC7AC @seed-design/react, @seed-design/css\uC640 \uD638\uD658\uB3FC\uC694.");try{await N.track(i.cwd,{event:"compat",properties:{checked_items_count:y.checkedItemKeys.length,incompatible_items_count:0,duration_ms:Date.now()-n}})}catch(w){o&&console.error("[Telemetry] compat tracking failed:",w)}process.exit(0)}pe({report:y,title:"\uD604\uC7AC \uD504\uB85C\uC81D\uD2B8 \uBC84\uC804\uACFC \uD638\uD658\uB418\uC9C0 \uC54A\uB294 \uC2A4\uB2C8\uD3AB\uC744 \uCC3E\uC558\uC5B4\uC694."}),M.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."),M.outro("\uD638\uD658\uC131 \uC774\uC288\uAC00 \uC788\uC5B4\uC694.");try{await N.track(i.cwd,{event:"compat",properties:{checked_items_count:y.checkedItemKeys.length,incompatible_items_count:new Set(y.issues.map(w=>w.itemKey)).size,issue_count:y.issues.length,duration_ms:Date.now()-n}})}catch(w){o&&console.error("[Telemetry] compat tracking failed:",w)}process.exit(1)}catch(r){U(r)&&(M.outro(p(r.message)),process.exit(0)),B(r,{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 E from"@clack/prompts";import{z as Ce}from"zod";var os="https://raw.githubusercontent.com/daangn/seed-design/refs/heads/dev/docs/registry",ns=Ce.object({query:Ce.string().optional(),baseUrl:Ce.string().optional(),raw:Ce.boolean()});function Ze(e,t){return`${os}/${e}/${t}`}function as(e,t){let s=`${t}${e.docUrl}`,n=`${t}/llms${e.docUrl}.txt`,o=[e.id,`- docs: ${s}`,`- llms.txt: ${n}`];if(e.snippetKey&&e.snippets&&e.snippets.length>0){let[r]=e.snippetKey.split(":");if(r==="ui"||r==="breeze")if(e.snippets.length===1)o.push(`- snippet: ${Ze(r,e.snippets[0].path)}`);else{o.push("- snippet:");for(let i of e.snippets)o.push(` - ${i.label}: ${Ze(r,i.path)}`)}}E.log.message(o.join(`
|
|
15
|
+
`))}function cs(e,t){let s=e.length,n=t.length,o=Array.from({length:s+1},(r,i)=>Array.from({length:n+1},(a,l)=>i===0?l:l===0?i:0));for(let r=1;r<=s;r++)for(let i=1;i<=n;i++)o[r][i]=Math.min(o[r-1][i]+1,o[r][i-1]+1,o[r-1][i-1]+(e[r-1]!==t[i-1]?1:0));return o[s][n]}function Z(e,t,s=3){let n=e.toLowerCase();return t.map(o=>({value:o,dist:cs(n,o.toLowerCase())})).filter(({dist:o})=>o>0&&o<=s).sort((o,r)=>o.dist-r.dist).map(({value:o})=>o)}function ls(e,t){if(e.length===0)return;let s=[],n=t.map(i=>i.id),o=Z(e[0],n);if(o.length===0){let i=t.flatMap(f=>f.sections.flatMap(h=>h.items.map(u=>`${f.id}/${h.id}/${u.id}`))),a=e.join("/"),l=Z(a,i,5);l.length>0&&s.push(...l.slice(0,3))}else{let i=t.find(a=>a.id===o[0]);if(i&&e.length>=2){let a=i.sections.map(f=>f.id),l=Z(e[1],a);if(l.length>0){let f=i.sections.find(h=>h.id===l[0]);if(f&&e.length>=3){let h=f.items.map(C=>C.id),u=Z(e[2],h);for(let C of u.slice(0,3))s.push(`${i.id}/${f.id}/${C}`)}else for(let h of l.slice(0,3))s.push(`${i.id}/${h}`)}else{let f=i.sections.flatMap(u=>u.items.map(C=>({path:`${i.id}/${u.id}/${C.id}`,id:C.id}))),h=Z(e[1],f.map(u=>u.id));for(let u of h.slice(0,3)){let C=f.find(k=>k.id===u);C&&s.push(C.path)}}}else for(let a of o.slice(0,3))s.push(a)}if(s.length===0)return;let r=["","\u{1F4A1} \uC774\uAC83\uC744 \uC758\uBBF8\uD588\uB098\uC694?"];for(let i of s)r.push(` - ${i}`);return r.join(`
|
|
16
|
+
`)}function ps(e){return e.split("/").map(t=>t.trim()).filter(Boolean)}function ms(e,t){let s=t.toLowerCase();return e.flatMap(n=>n.sections.flatMap(o=>o.items.filter(r=>r.id.toLowerCase().includes(s)||r.title.toLowerCase().includes(s)).map(r=>({item:r,categoryLabel:n.label,sectionLabel:o.label}))))}async function fe(e){let t=await E.select({message:"\uD56D\uBAA9\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694",options:e.map(s=>({label:`${s.deprecated?"(deprecated) ":""}${s.title}`,value:s,hint:s.description}))});if(E.isCancel(t))throw new v;return t}async function et(e){let t=await E.select({message:"\uC139\uC158\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694",options:e.map(s=>({label:s.label,value:s,hint:`${s.items.length}\uAC1C \uD56D\uBAA9`}))});if(E.isCancel(t))throw new v;return t}async function ds(e){let t=await E.select({message:"\uCE74\uD14C\uACE0\uB9AC\uB97C \uC120\uD0DD\uD574\uC8FC\uC138\uC694",options:e.map(s=>({label:s.label,value:s,hint:`${s.sections.reduce((n,o)=>n+o.items.length,0)}\uAC1C \uD56D\uBAA9`}))});if(E.isCancel(t))throw new v;return t}var tt=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: ${G})`,{default:G}).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 react/components").example("seed-design docs react/components/action-button").example("seed-design docs react/updates/changelog --raw").action(async(t,s)=>{let n=Date.now(),o=q(s),r=s.raw??!1;r||E.intro("seed-design docs");try{let i=ns.safeParse({query:t,...s});if(!i.success)throw i.error;let{data:a}=i,l=a.baseUrl??G;if(a.raw&&!a.query)throw new I({message:"--raw \uBAA8\uB4DC\uC5D0\uC11C\uB294 \uCFFC\uB9AC\uAC00 \uD544\uC694\uD574\uC694.",hint:"\uC608: `seed-design docs react/updates/changelog --raw`"});let f=await(async()=>{if(r)return await Re({baseUrl:l});let{start:y,stop:w}=E.spinner();y("\uBB38\uC11C \uBAA9\uB85D\uC744 \uAC00\uC838\uC624\uACE0 \uC788\uC5B4\uC694...");try{let d=await Re({baseUrl:l});return w("\uBB38\uC11C \uBAA9\uB85D\uC744 \uAC00\uC838\uC654\uC5B4\uC694."),d}catch(d){throw w("\uBB38\uC11C \uBAA9\uB85D\uC744 \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694."),d}})(),{categories:h}=f,u,C=async()=>{if(a.query){let d=ps(a.query);if(r&&d.length>3)return;let b=h.find(P=>P.id===d[0]);if(b&&d.length>=2){let P=b.sections.find($=>$.id===d[1]);if(P&&d.length>=3){let $=P.items.find(x=>x.id===d[2]);if($)return $;let c=d[2].toLowerCase(),g=P.items.filter(x=>x.id.toLowerCase().includes(c)||x.title.toLowerCase().includes(c));if(g.length===0){let x=Z(d[2],P.items.map(T=>T.id)),_=x.length>0?`
|
|
17
|
+
|
|
18
|
+
\u{1F4A1} \uC774\uAC83\uC744 \uC758\uBBF8\uD588\uB098\uC694?
|
|
19
|
+
${x.slice(0,3).map(T=>` - ${b.id}/${P.id}/${T}`).join(`
|
|
20
|
+
`)}`:"";throw new I({message:`${p(a.query)}: \uBB38\uC11C\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.${_}`,hint:`\`seed-design docs ${b.id}/${P.id}\`\uB85C \uBAA9\uB85D\uC744 \uD655\uC778\uD574\uBCF4\uC138\uC694.`})}return g.length===1?g[0]:await fe(g)}if(P)return await fe(P.items);let D=d[1].toLowerCase(),O=b.sections.flatMap($=>$.items.filter(c=>c.id.toLowerCase().includes(D)||c.title.toLowerCase().includes(D)).map(c=>({item:c,sectionLabel:$.label})));if(O.length===0){let $=b.sections.map(S=>S.id),c=Z(d[1],$),g=b.sections.flatMap(S=>S.items.map(ge=>({path:`${b.id}/${S.id}/${ge.id}`,id:ge.id}))),x=Z(d[1],g.map(S=>S.id)),_=[...c.slice(0,2).map(S=>`${b.id}/${S}`),...x.slice(0,2).map(S=>g.find(ge=>ge.id===S)?.path).filter(S=>S!=null)],T=_.length>0?`
|
|
21
|
+
|
|
22
|
+
\u{1F4A1} \uC774\uAC83\uC744 \uC758\uBBF8\uD588\uB098\uC694?
|
|
23
|
+
${_.map(S=>` - ${S}`).join(`
|
|
24
|
+
`)}`:"";throw new I({message:`${p(a.query)}: \uBB38\uC11C\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.${T}`,hint:`\`seed-design docs ${b.id}\`\uB85C \uBAA9\uB85D\uC744 \uD655\uC778\uD574\uBCF4\uC138\uC694.`})}if(O.length===1)return O[0].item;let Y=await E.select({message:`${p(d[1])}\uC5D0 \uD574\uB2F9\uD558\uB294 \uD56D\uBAA9\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694`,options:O.map(({item:$,sectionLabel:c})=>({label:`[${c}] ${$.title}`,value:$,hint:$.description}))});if(E.isCancel(Y))throw new v;return Y}if(b){if(b.sections.length===1)return await fe(b.sections[0].items);let P=await et(b.sections);return await fe(P.items)}let A=ms(h,a.query);if(A.length===0){let P=ls(d,h);throw new I({message:`${p(a.query)}: \uBB38\uC11C\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC5B4\uC694.${P??""}`,hint:"`seed-design docs`\uB85C \uC804\uCCB4 \uBAA9\uB85D\uC744 \uD655\uC778\uD574\uBCF4\uC138\uC694."})}if(A.length===1)return A[0].item;let V=await E.select({message:`${p(a.query)}\uC5D0 \uD574\uB2F9\uD558\uB294 \uD56D\uBAA9\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694`,options:A.map(({item:P,categoryLabel:D,sectionLabel:O})=>({label:`[${D} > ${O}] ${P.title}`,value:P,hint:P.description}))});if(E.isCancel(V))throw new v;return V}let y=await ds(h),w;return y.sections.length===1?w=y.sections[0]:w=await et(y.sections),await fe(w.items)};if(r)try{u=await C()}catch(y){if(U(y))throw y}else u=await C();if(r){let y;if(u){let w=`${l}/llms${u.docUrl}.txt`;y=await De({url:w})}else y=await Oe({baseUrl:l,query:a.query});console.log(y)}else as(u,l),E.outro("\uC644\uB8CC\uD588\uC5B4\uC694.");let k=Date.now()-n;try{await N.track(process.cwd(),{event:"docs",properties:{query:a.query??null,item_id:u?.id??a.query??null,has_snippet:!!(u?.snippets&&u.snippets.length>0),duration_ms:k}})}catch(y){o&&console.error("[Telemetry] docs tracking failed:",y)}}catch(i){if(U(i)&&(r||E.outro(p(i.message)),process.exit(0)),r){let a=i instanceof Error?i.message:String(i);console.error(a),process.exit(1)}B(i,{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 L from"@clack/prompts";import{z as Ie}from"zod";import fs from"dedent";var gs=Ie.object({cwd:Ie.string(),yes:Ie.boolean().optional(),default:Ie.boolean().optional()}),st=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 s=Date.now(),n=q(t);L.intro("seed-design.json \uD30C\uC77C \uC0DD\uC131");try{let o=gs.safeParse(t);if(!o.success)throw o.error;let r=o.data,i=r.yes||r.default,a=i?K:await ke(),{start:l,stop:f}=L.spinner();l("seed-design.json \uD30C\uC77C \uC0DD\uC131\uC911...");let h=await(async()=>{try{return(await ue({cwd:r.cwd,config:a})).relativePath}catch(C){throw f("seed-design.json \uD30C\uC77C \uC0DD\uC131\uC774 \uC911\uB2E8\uB410\uC5B4\uC694."),C}})();f(`seed-design.json \uD30C\uC77C\uC774 ${p(h)}\uC5D0 \uC0DD\uC131\uB410\uC5B4\uC694.`),L.log.info(p("seed-design add {component} \uBA85\uB839\uC5B4\uB85C \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uCD94\uAC00\uD574\uBCF4\uC138\uC694!")),L.log.info(p("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.")),L.note(fs(`SEED Design CLI\uB294 \uAC1C\uC120\uC744 \uC704\uD574 \uC775\uBA85 \uC0AC\uC6A9 \uB370\uC774\uD130\uB97C \uC218\uC9D1\uD574\uC694.
|
|
12
25
|
|
|
13
26
|
\uBE44\uD65C\uC131\uD654\uD558\uB824\uBA74:
|
|
14
|
-
\u2022 seed-design.json\uC5D0\uC11C ${
|
|
15
|
-
\u2022 ${
|
|
27
|
+
\u2022 seed-design.json\uC5D0\uC11C ${p('"telemetry": false')}\uB85C \uC124\uC815
|
|
28
|
+
\u2022 ${p("DISABLE_TELEMETRY=true")} \uD658\uACBD \uBCC0\uC218 \uC124\uC815
|
|
16
29
|
|
|
17
|
-
\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"),L.outro("\uC791\uC5C5\uC774 \uC644\uB8CC\uB410\uC5B4\uC694.");let u=Date.now()-s;try{await N.track(r.cwd,{event:"init",properties:{tsx:a.tsx,rsc:a.rsc,telemetry:a.telemetry,yes_option:i,duration_ms:u}})}catch(C){n&&console.error("[Telemetry] init tracking failed:",C)}}catch(o){U(o)&&(L.outro(p(o.message)),process.exit(0)),B(o,{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 us}from"cac";var ys="seed-design",W=us(ys);async function hs(){let e=ae();W.option("--verbose","\uC624\uB958 \uC0C1\uC138 \uC815\uBCF4\uB97C \uCD9C\uB825\uD569\uB2C8\uB2E4."),We(W),Ye(W),Qe(W),tt(W),st(W),W.version(e.version||"1.0.0","-v, --version"),W.help(),W.parse()}hs();
|
package/package.json
CHANGED
package/src/commands/docs.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fetchDocsIndex } from "@/src/utils/fetch";
|
|
1
|
+
import { fetchDocsIndex, fetchLlmsTxt, tryFetchLlmsTxt } from "@/src/utils/fetch";
|
|
2
2
|
import * as p from "@clack/prompts";
|
|
3
3
|
import type { CAC } from "cac";
|
|
4
4
|
import { z } from "zod";
|
|
@@ -20,6 +20,7 @@ const GITHUB_SNIPPET_BASE =
|
|
|
20
20
|
const docsOptionsSchema = z.object({
|
|
21
21
|
query: z.string().optional(),
|
|
22
22
|
baseUrl: z.string().optional(),
|
|
23
|
+
raw: z.boolean(),
|
|
23
24
|
});
|
|
24
25
|
|
|
25
26
|
function buildSnippetUrl(registryId: string, snippetPath: string): string {
|
|
@@ -49,6 +50,112 @@ function printDocsResult(item: DocsItem, baseUrl: string) {
|
|
|
49
50
|
p.log.message(lines.join("\n"));
|
|
50
51
|
}
|
|
51
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Compute the Levenshtein (edit) distance between two strings.
|
|
55
|
+
* Used to suggest similar valid paths when users make typos.
|
|
56
|
+
*/
|
|
57
|
+
function levenshtein(a: string, b: string): number {
|
|
58
|
+
const m = a.length;
|
|
59
|
+
const n = b.length;
|
|
60
|
+
const dp: number[][] = Array.from({ length: m + 1 }, (_, i) =>
|
|
61
|
+
Array.from({ length: n + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0)),
|
|
62
|
+
);
|
|
63
|
+
for (let i = 1; i <= m; i++) {
|
|
64
|
+
for (let j = 1; j <= n; j++) {
|
|
65
|
+
dp[i][j] = Math.min(
|
|
66
|
+
dp[i - 1][j] + 1,
|
|
67
|
+
dp[i][j - 1] + 1,
|
|
68
|
+
dp[i - 1][j - 1] + (a[i - 1] !== b[j - 1] ? 1 : 0),
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return dp[m][n];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Find candidates similar to `input` within `maxDistance` edits, sorted by distance.
|
|
77
|
+
*/
|
|
78
|
+
function findSimilar(input: string, candidates: string[], maxDistance = 3): string[] {
|
|
79
|
+
const q = input.toLowerCase();
|
|
80
|
+
return candidates
|
|
81
|
+
.map((c) => ({ value: c, dist: levenshtein(q, c.toLowerCase()) }))
|
|
82
|
+
.filter(({ dist }) => dist > 0 && dist <= maxDistance)
|
|
83
|
+
.sort((a, b) => a.dist - b.dist)
|
|
84
|
+
.map(({ value }) => value);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Build a suggestion hint from a path query by fuzzy-matching each segment
|
|
89
|
+
* against the docs index hierarchy.
|
|
90
|
+
*/
|
|
91
|
+
function buildSuggestionHint(segments: string[], categories: DocsCategory[]): string | undefined {
|
|
92
|
+
if (segments.length === 0) return undefined;
|
|
93
|
+
|
|
94
|
+
const suggestions: string[] = [];
|
|
95
|
+
|
|
96
|
+
// Try to fuzzy-match the first segment against category IDs
|
|
97
|
+
const categoryIds = categories.map((c) => c.id);
|
|
98
|
+
const similarCategories = findSimilar(segments[0], categoryIds);
|
|
99
|
+
|
|
100
|
+
if (similarCategories.length === 0) {
|
|
101
|
+
// No similar category — try to find similar full paths across everything
|
|
102
|
+
const allPaths = categories.flatMap((cat) =>
|
|
103
|
+
cat.sections.flatMap((sec) => sec.items.map((item) => `${cat.id}/${sec.id}/${item.id}`)),
|
|
104
|
+
);
|
|
105
|
+
const fullQuery = segments.join("/");
|
|
106
|
+
const similarPaths = findSimilar(fullQuery, allPaths, 5);
|
|
107
|
+
if (similarPaths.length > 0) {
|
|
108
|
+
suggestions.push(...similarPaths.slice(0, 3));
|
|
109
|
+
}
|
|
110
|
+
} else {
|
|
111
|
+
const bestCat = categories.find((c) => c.id === similarCategories[0]);
|
|
112
|
+
if (bestCat && segments.length >= 2) {
|
|
113
|
+
const sectionIds = bestCat.sections.map((s) => s.id);
|
|
114
|
+
const similarSections = findSimilar(segments[1], sectionIds);
|
|
115
|
+
|
|
116
|
+
if (similarSections.length > 0) {
|
|
117
|
+
const bestSec = bestCat.sections.find((s) => s.id === similarSections[0]);
|
|
118
|
+
if (bestSec && segments.length >= 3) {
|
|
119
|
+
const itemIds = bestSec.items.map((i) => i.id);
|
|
120
|
+
const similarItems = findSimilar(segments[2], itemIds);
|
|
121
|
+
for (const item of similarItems.slice(0, 3)) {
|
|
122
|
+
suggestions.push(`${bestCat.id}/${bestSec.id}/${item}`);
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
for (const sec of similarSections.slice(0, 3)) {
|
|
126
|
+
suggestions.push(`${bestCat.id}/${sec}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
// Section not found, search items within category
|
|
131
|
+
const allItemIds = bestCat.sections.flatMap((s) =>
|
|
132
|
+
s.items.map((i) => ({ path: `${bestCat.id}/${s.id}/${i.id}`, id: i.id })),
|
|
133
|
+
);
|
|
134
|
+
const similarItems = findSimilar(
|
|
135
|
+
segments[1],
|
|
136
|
+
allItemIds.map((x) => x.id),
|
|
137
|
+
);
|
|
138
|
+
for (const itemId of similarItems.slice(0, 3)) {
|
|
139
|
+
const found = allItemIds.find((x) => x.id === itemId);
|
|
140
|
+
if (found) suggestions.push(found.path);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
for (const cat of similarCategories.slice(0, 3)) {
|
|
145
|
+
suggestions.push(cat);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (suggestions.length === 0) return undefined;
|
|
151
|
+
|
|
152
|
+
const lines = ["", "💡 이것을 의미했나요?"];
|
|
153
|
+
for (const s of suggestions) {
|
|
154
|
+
lines.push(` - ${s}`);
|
|
155
|
+
}
|
|
156
|
+
return lines.join("\n");
|
|
157
|
+
}
|
|
158
|
+
|
|
52
159
|
/**
|
|
53
160
|
* Parse a path-style query into segments.
|
|
54
161
|
* e.g. "react/components/action-button" → ["react", "components", "action-button"]
|
|
@@ -126,15 +233,21 @@ export const docsCommand = (cli: CAC) => {
|
|
|
126
233
|
.option("-u, --baseUrl <baseUrl>", `레지스트리의 기본 URL (기본값: ${BASE_URL})`, {
|
|
127
234
|
default: BASE_URL,
|
|
128
235
|
})
|
|
236
|
+
.option("--raw", "llms.txt 내용을 직접 가져와 출력합니다. LLM 파이프에 유용합니다.", {
|
|
237
|
+
default: false,
|
|
238
|
+
})
|
|
129
239
|
.example("seed-design docs")
|
|
130
240
|
.example("seed-design docs action-button")
|
|
131
241
|
.example("seed-design docs react")
|
|
132
242
|
.example("seed-design docs react/components")
|
|
133
243
|
.example("seed-design docs react/components/action-button")
|
|
244
|
+
.example("seed-design docs react/updates/changelog --raw")
|
|
134
245
|
.action(async (query, opts) => {
|
|
135
246
|
const startTime = Date.now();
|
|
136
247
|
const verbose = isVerboseMode(opts);
|
|
137
|
-
|
|
248
|
+
const raw = opts.raw ?? false;
|
|
249
|
+
|
|
250
|
+
if (!raw) p.intro("seed-design docs");
|
|
138
251
|
|
|
139
252
|
try {
|
|
140
253
|
const parsed = docsOptionsSchema.safeParse({ query, ...opts });
|
|
@@ -145,10 +258,19 @@ export const docsCommand = (cli: CAC) => {
|
|
|
145
258
|
const { data: options } = parsed;
|
|
146
259
|
const baseUrl = options.baseUrl ?? BASE_URL;
|
|
147
260
|
|
|
148
|
-
|
|
149
|
-
|
|
261
|
+
if (options.raw && !options.query) {
|
|
262
|
+
throw new CliError({
|
|
263
|
+
message: "--raw 모드에서는 쿼리가 필요해요.",
|
|
264
|
+
hint: "예: `seed-design docs react/updates/changelog --raw`",
|
|
265
|
+
});
|
|
266
|
+
}
|
|
150
267
|
|
|
151
268
|
const docsIndex = await (async () => {
|
|
269
|
+
if (raw) {
|
|
270
|
+
return await fetchDocsIndex({ baseUrl });
|
|
271
|
+
}
|
|
272
|
+
const { start, stop } = p.spinner();
|
|
273
|
+
start("문서 목록을 가져오고 있어요...");
|
|
152
274
|
try {
|
|
153
275
|
const index = await fetchDocsIndex({ baseUrl });
|
|
154
276
|
stop("문서 목록을 가져왔어요.");
|
|
@@ -160,44 +282,62 @@ export const docsCommand = (cli: CAC) => {
|
|
|
160
282
|
})();
|
|
161
283
|
|
|
162
284
|
const { categories } = docsIndex;
|
|
163
|
-
let selectedItem: DocsItem;
|
|
285
|
+
let selectedItem: DocsItem | undefined;
|
|
286
|
+
|
|
287
|
+
// In --raw mode, wrap index resolution in try-catch to allow fallback to direct URL
|
|
288
|
+
const resolveFromIndex = async (): Promise<DocsItem | undefined> => {
|
|
289
|
+
if (options.query) {
|
|
290
|
+
const segments = parseQueryPath(options.query);
|
|
164
291
|
|
|
165
|
-
|
|
166
|
-
|
|
292
|
+
// Deep paths (more than category/section/item) can't be resolved from index
|
|
293
|
+
// e.g., react/updates/changelog/react/1.2.9 — skip to fallback in --raw mode
|
|
294
|
+
if (raw && segments.length > 3) {
|
|
295
|
+
return undefined;
|
|
296
|
+
}
|
|
167
297
|
|
|
168
|
-
|
|
169
|
-
|
|
298
|
+
// Try to resolve as path: category / section / item
|
|
299
|
+
const matchedCategory = categories.find((c) => c.id === segments[0]);
|
|
170
300
|
|
|
171
|
-
|
|
172
|
-
|
|
301
|
+
if (matchedCategory && segments.length >= 2) {
|
|
302
|
+
const matchedSection = matchedCategory.sections.find((s) => s.id === segments[1]);
|
|
173
303
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
304
|
+
if (matchedSection && segments.length >= 3) {
|
|
305
|
+
// Full path: category/section/item
|
|
306
|
+
const matchedItem = matchedSection.items.find((i) => i.id === segments[2]);
|
|
307
|
+
if (matchedItem) {
|
|
308
|
+
return matchedItem;
|
|
309
|
+
}
|
|
180
310
|
// Item not found in section — search within the section
|
|
181
311
|
const q = segments[2].toLowerCase();
|
|
182
312
|
const matched = matchedSection.items.filter(
|
|
183
313
|
(i) => i.id.toLowerCase().includes(q) || i.title.toLowerCase().includes(q),
|
|
184
314
|
);
|
|
185
315
|
if (matched.length === 0) {
|
|
316
|
+
const similarItems = findSimilar(
|
|
317
|
+
segments[2],
|
|
318
|
+
matchedSection.items.map((i) => i.id),
|
|
319
|
+
);
|
|
320
|
+
const suggestion =
|
|
321
|
+
similarItems.length > 0
|
|
322
|
+
? `\n\n💡 이것을 의미했나요?\n${similarItems
|
|
323
|
+
.slice(0, 3)
|
|
324
|
+
.map((s) => ` - ${matchedCategory.id}/${matchedSection.id}/${s}`)
|
|
325
|
+
.join("\n")}`
|
|
326
|
+
: "";
|
|
186
327
|
throw new CliError({
|
|
187
|
-
message: `${highlight(options.query)}: 문서를 찾을 수
|
|
328
|
+
message: `${highlight(options.query)}: 문서를 찾을 수 없어요.${suggestion}`,
|
|
188
329
|
hint: `\`seed-design docs ${matchedCategory.id}/${matchedSection.id}\`로 목록을 확인해보세요.`,
|
|
189
330
|
});
|
|
190
331
|
}
|
|
191
332
|
if (matched.length === 1) {
|
|
192
|
-
|
|
193
|
-
} else {
|
|
194
|
-
selectedItem = await selectItem(matched);
|
|
333
|
+
return matched[0];
|
|
195
334
|
}
|
|
335
|
+
return await selectItem(matched);
|
|
336
|
+
}
|
|
337
|
+
if (matchedSection) {
|
|
338
|
+
// category/section — select item within section
|
|
339
|
+
return await selectItem(matchedSection.items);
|
|
196
340
|
}
|
|
197
|
-
} else if (matchedSection) {
|
|
198
|
-
// category/section — select item within section
|
|
199
|
-
selectedItem = await selectItem(matchedSection.items);
|
|
200
|
-
} else {
|
|
201
341
|
// category/??? — search within category
|
|
202
342
|
const q = segments[1].toLowerCase();
|
|
203
343
|
const matched = matchedCategory.sections.flatMap((s) =>
|
|
@@ -209,61 +349,82 @@ export const docsCommand = (cli: CAC) => {
|
|
|
209
349
|
);
|
|
210
350
|
|
|
211
351
|
if (matched.length === 0) {
|
|
352
|
+
const sectionIds = matchedCategory.sections.map((s) => s.id);
|
|
353
|
+
const similarSections = findSimilar(segments[1], sectionIds);
|
|
354
|
+
const allItemIds = matchedCategory.sections.flatMap((s) =>
|
|
355
|
+
s.items.map((i) => ({
|
|
356
|
+
path: `${matchedCategory.id}/${s.id}/${i.id}`,
|
|
357
|
+
id: i.id,
|
|
358
|
+
})),
|
|
359
|
+
);
|
|
360
|
+
const similarItems = findSimilar(
|
|
361
|
+
segments[1],
|
|
362
|
+
allItemIds.map((x) => x.id),
|
|
363
|
+
);
|
|
364
|
+
const suggestions: string[] = [
|
|
365
|
+
...similarSections.slice(0, 2).map((s) => `${matchedCategory.id}/${s}`),
|
|
366
|
+
...similarItems
|
|
367
|
+
.slice(0, 2)
|
|
368
|
+
.map((id) => allItemIds.find((x) => x.id === id)?.path)
|
|
369
|
+
.filter((p): p is string => p != null),
|
|
370
|
+
];
|
|
371
|
+
const suggestion =
|
|
372
|
+
suggestions.length > 0
|
|
373
|
+
? `\n\n💡 이것을 의미했나요?\n${suggestions.map((s) => ` - ${s}`).join("\n")}`
|
|
374
|
+
: "";
|
|
212
375
|
throw new CliError({
|
|
213
|
-
message: `${highlight(options.query)}: 문서를 찾을 수
|
|
376
|
+
message: `${highlight(options.query)}: 문서를 찾을 수 없어요.${suggestion}`,
|
|
214
377
|
hint: `\`seed-design docs ${matchedCategory.id}\`로 목록을 확인해보세요.`,
|
|
215
378
|
});
|
|
216
379
|
}
|
|
217
380
|
if (matched.length === 1) {
|
|
218
|
-
|
|
219
|
-
} else {
|
|
220
|
-
const selected = await p.select({
|
|
221
|
-
message: `${highlight(segments[1])}에 해당하는 항목을 선택해주세요`,
|
|
222
|
-
options: matched.map(({ item, sectionLabel }) => ({
|
|
223
|
-
label: `[${sectionLabel}] ${item.title}`,
|
|
224
|
-
value: item,
|
|
225
|
-
hint: item.description,
|
|
226
|
-
})),
|
|
227
|
-
});
|
|
228
|
-
if (p.isCancel(selected)) throw new CliCancelError();
|
|
229
|
-
selectedItem = selected;
|
|
381
|
+
return matched[0].item;
|
|
230
382
|
}
|
|
383
|
+
const selected = await p.select({
|
|
384
|
+
message: `${highlight(segments[1])}에 해당하는 항목을 선택해주세요`,
|
|
385
|
+
options: matched.map(({ item, sectionLabel }) => ({
|
|
386
|
+
label: `[${sectionLabel}] ${item.title}`,
|
|
387
|
+
value: item,
|
|
388
|
+
hint: item.description,
|
|
389
|
+
})),
|
|
390
|
+
});
|
|
391
|
+
if (p.isCancel(selected)) throw new CliCancelError();
|
|
392
|
+
return selected;
|
|
231
393
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
394
|
+
if (matchedCategory) {
|
|
395
|
+
// Single segment matching a category — drill into it
|
|
396
|
+
if (matchedCategory.sections.length === 1) {
|
|
397
|
+
return await selectItem(matchedCategory.sections[0].items);
|
|
398
|
+
}
|
|
237
399
|
const section = await selectSection(matchedCategory.sections);
|
|
238
|
-
|
|
400
|
+
return await selectItem(section.items);
|
|
239
401
|
}
|
|
240
|
-
} else {
|
|
241
402
|
// No category match — global search
|
|
242
403
|
const matched = searchAllItems(categories, options.query);
|
|
243
404
|
|
|
244
405
|
if (matched.length === 0) {
|
|
406
|
+
const suggestion = buildSuggestionHint(segments, categories);
|
|
245
407
|
throw new CliError({
|
|
246
|
-
message: `${highlight(options.query)}: 문서를 찾을 수
|
|
408
|
+
message: `${highlight(options.query)}: 문서를 찾을 수 없어요.${suggestion ?? ""}`,
|
|
247
409
|
hint: "`seed-design docs`로 전체 목록을 확인해보세요.",
|
|
248
410
|
});
|
|
249
411
|
}
|
|
250
412
|
if (matched.length === 1) {
|
|
251
|
-
|
|
252
|
-
} else {
|
|
253
|
-
const selected = await p.select({
|
|
254
|
-
message: `${highlight(options.query)}에 해당하는 항목을 선택해주세요`,
|
|
255
|
-
options: matched.map(({ item, categoryLabel, sectionLabel }) => ({
|
|
256
|
-
label: `[${categoryLabel} > ${sectionLabel}] ${item.title}`,
|
|
257
|
-
value: item,
|
|
258
|
-
hint: item.description,
|
|
259
|
-
})),
|
|
260
|
-
});
|
|
261
|
-
if (p.isCancel(selected)) throw new CliCancelError();
|
|
262
|
-
selectedItem = selected;
|
|
413
|
+
return matched[0].item;
|
|
263
414
|
}
|
|
415
|
+
const selected = await p.select({
|
|
416
|
+
message: `${highlight(options.query)}에 해당하는 항목을 선택해주세요`,
|
|
417
|
+
options: matched.map(({ item, categoryLabel, sectionLabel }) => ({
|
|
418
|
+
label: `[${categoryLabel} > ${sectionLabel}] ${item.title}`,
|
|
419
|
+
value: item,
|
|
420
|
+
hint: item.description,
|
|
421
|
+
})),
|
|
422
|
+
});
|
|
423
|
+
if (p.isCancel(selected)) throw new CliCancelError();
|
|
424
|
+
return selected;
|
|
264
425
|
}
|
|
265
|
-
|
|
266
|
-
//
|
|
426
|
+
|
|
427
|
+
// No query — full interactive flow: category → section → item
|
|
267
428
|
const category = await selectCategory(categories);
|
|
268
429
|
|
|
269
430
|
let section: DocsSection;
|
|
@@ -273,11 +434,34 @@ export const docsCommand = (cli: CAC) => {
|
|
|
273
434
|
section = await selectSection(category.sections);
|
|
274
435
|
}
|
|
275
436
|
|
|
276
|
-
|
|
437
|
+
return await selectItem(section.items);
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
// In --raw mode, swallow index resolution errors and fall back to direct URL fetch
|
|
441
|
+
if (raw) {
|
|
442
|
+
try {
|
|
443
|
+
selectedItem = await resolveFromIndex();
|
|
444
|
+
} catch (error) {
|
|
445
|
+
if (isCliCancelError(error)) throw error;
|
|
446
|
+
// index miss in raw mode → will use fallback
|
|
447
|
+
}
|
|
448
|
+
} else {
|
|
449
|
+
selectedItem = await resolveFromIndex();
|
|
277
450
|
}
|
|
278
451
|
|
|
279
|
-
|
|
280
|
-
|
|
452
|
+
if (raw) {
|
|
453
|
+
let content: string;
|
|
454
|
+
if (selectedItem) {
|
|
455
|
+
const llmsUrl = `${baseUrl}/llms${selectedItem.docUrl}.txt`;
|
|
456
|
+
content = await fetchLlmsTxt({ url: llmsUrl });
|
|
457
|
+
} else {
|
|
458
|
+
content = await tryFetchLlmsTxt({ baseUrl, query: options.query! });
|
|
459
|
+
}
|
|
460
|
+
console.log(content);
|
|
461
|
+
} else {
|
|
462
|
+
printDocsResult(selectedItem!, baseUrl);
|
|
463
|
+
p.outro("완료했어요.");
|
|
464
|
+
}
|
|
281
465
|
|
|
282
466
|
const duration = Date.now() - startTime;
|
|
283
467
|
try {
|
|
@@ -285,8 +469,8 @@ export const docsCommand = (cli: CAC) => {
|
|
|
285
469
|
event: "docs",
|
|
286
470
|
properties: {
|
|
287
471
|
query: options.query ?? null,
|
|
288
|
-
item_id: selectedItem.
|
|
289
|
-
has_snippet: !!(selectedItem
|
|
472
|
+
item_id: selectedItem?.id ?? options.query ?? null,
|
|
473
|
+
has_snippet: !!(selectedItem?.snippets && selectedItem.snippets.length > 0),
|
|
290
474
|
duration_ms: duration,
|
|
291
475
|
},
|
|
292
476
|
});
|
|
@@ -297,10 +481,16 @@ export const docsCommand = (cli: CAC) => {
|
|
|
297
481
|
}
|
|
298
482
|
} catch (error) {
|
|
299
483
|
if (isCliCancelError(error)) {
|
|
300
|
-
p.outro(highlight(error.message));
|
|
484
|
+
if (!raw) p.outro(highlight(error.message));
|
|
301
485
|
process.exit(0);
|
|
302
486
|
}
|
|
303
487
|
|
|
488
|
+
if (raw) {
|
|
489
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
490
|
+
console.error(msg);
|
|
491
|
+
process.exit(1);
|
|
492
|
+
}
|
|
493
|
+
|
|
304
494
|
handleCliError(error, {
|
|
305
495
|
defaultMessage: "문서 조회에 실패했어요.",
|
|
306
496
|
defaultHint: "`--verbose` 옵션으로 상세 오류를 확인해보세요.",
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { addAllCommand } from "@/src/commands/add-all";
|
|
|
5
5
|
import { compatCommand } from "@/src/commands/compat";
|
|
6
6
|
import { docsCommand } from "@/src/commands/docs";
|
|
7
7
|
import { initCommand } from "@/src/commands/init";
|
|
8
|
+
|
|
8
9
|
import { getPackageInfo } from "@/src/utils/get-package-info";
|
|
9
10
|
import { cac } from "cac";
|
|
10
11
|
|
package/src/utils/fetch.ts
CHANGED
|
@@ -12,6 +12,26 @@ import {
|
|
|
12
12
|
} from "@/src/schema";
|
|
13
13
|
import { CliError } from "@/src/utils/error";
|
|
14
14
|
|
|
15
|
+
const FETCH_TIMEOUT_MS = 10_000;
|
|
16
|
+
|
|
17
|
+
async function fetchWithTimeout(url: string, timeoutMs = FETCH_TIMEOUT_MS): Promise<Response> {
|
|
18
|
+
const controller = new AbortController();
|
|
19
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
20
|
+
try {
|
|
21
|
+
return await fetch(url, { signal: controller.signal });
|
|
22
|
+
} catch (error) {
|
|
23
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
24
|
+
throw new CliError({
|
|
25
|
+
message: `요청 시간이 초과되었어요 (${timeoutMs}ms): ${url}`,
|
|
26
|
+
hint: "네트워크 상태를 확인하고 다시 시도해주세요.",
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
throw error;
|
|
30
|
+
} finally {
|
|
31
|
+
clearTimeout(timeout);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
15
35
|
export async function fetchDocsIndex({ baseUrl }: { baseUrl: string }): Promise<DocsIndex> {
|
|
16
36
|
const response = await fetch(`${baseUrl}/__docs__/index.json`);
|
|
17
37
|
|
|
@@ -101,6 +121,78 @@ async function fetchRegistryItem({
|
|
|
101
121
|
return parsedItem;
|
|
102
122
|
}
|
|
103
123
|
|
|
124
|
+
export async function fetchLlmsTxt({ url }: { url: string }): Promise<string> {
|
|
125
|
+
const response = await fetchWithTimeout(url);
|
|
126
|
+
|
|
127
|
+
if (!response.ok) {
|
|
128
|
+
throw new CliError({
|
|
129
|
+
message: `llms.txt를 가져오지 못했어요: ${response.status} ${response.statusText}`,
|
|
130
|
+
hint: `${url} 에 접근할 수 있는지 확인해주세요.`,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return response.text();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Try fetching llms.txt content with fallback URL patterns.
|
|
139
|
+
* 1. {baseUrl}/llms/{query}.txt
|
|
140
|
+
* 2. {baseUrl}/llms/{query}/llms.txt (for package changelog index)
|
|
141
|
+
*/
|
|
142
|
+
export async function tryFetchLlmsTxt({
|
|
143
|
+
baseUrl,
|
|
144
|
+
query,
|
|
145
|
+
}: {
|
|
146
|
+
baseUrl: string;
|
|
147
|
+
query: string;
|
|
148
|
+
}): Promise<string> {
|
|
149
|
+
const normalizedQuery = query.startsWith("/") ? query.slice(1) : query;
|
|
150
|
+
|
|
151
|
+
const urls = [
|
|
152
|
+
`${baseUrl}/llms/${normalizedQuery}.txt`,
|
|
153
|
+
`${baseUrl}/llms/${normalizedQuery}/llms.txt`,
|
|
154
|
+
];
|
|
155
|
+
|
|
156
|
+
let lastError: unknown;
|
|
157
|
+
|
|
158
|
+
for (const url of urls) {
|
|
159
|
+
let response: Response;
|
|
160
|
+
try {
|
|
161
|
+
response = await fetchWithTimeout(url);
|
|
162
|
+
} catch (error) {
|
|
163
|
+
lastError = error;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (response.ok) {
|
|
168
|
+
return response.text();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// 404 → try next URL candidate
|
|
172
|
+
if (response.status === 404) {
|
|
173
|
+
lastError = new CliError({
|
|
174
|
+
message: `llms.txt를 찾을 수 없어요: ${normalizedQuery}`,
|
|
175
|
+
hint: `다음 경로를 시도했어요:\n${urls.map((u) => ` - ${u}`).join("\n")}`,
|
|
176
|
+
});
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Non-404 errors (5xx, 401, etc.) — propagate immediately
|
|
181
|
+
throw new CliError({
|
|
182
|
+
message: `llms.txt 요청이 실패했어요: ${response.status} ${response.statusText}`,
|
|
183
|
+
hint: `URL: ${url}`,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
throw (
|
|
188
|
+
lastError ??
|
|
189
|
+
new CliError({
|
|
190
|
+
message: `llms.txt를 찾을 수 없어요: ${normalizedQuery}`,
|
|
191
|
+
hint: `다음 경로를 시도했어요:\n${urls.map((u) => ` - ${u}`).join("\n")}`,
|
|
192
|
+
})
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
104
196
|
export async function fetchRegistryItems({
|
|
105
197
|
baseUrl,
|
|
106
198
|
registryId,
|