sh-ui-cli 0.21.0 → 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,6 +2,18 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$description": "sh-ui 릴리즈 노트 단일 소스. docs(React)와 showcase(Flutter)가 함께 읽는다. 새 릴리즈마다 맨 앞에 추가.",
4
4
  "versions": [
5
+ {
6
+ "version": "0.21.1",
7
+ "date": "2026-04-27",
8
+ "title": "외부 패키지 자동 설치 버전 해석",
9
+ "type": "patch",
10
+ "highlights": [
11
+ "registry/react/peer-versions.json — registry.json deps 의 패키지명을 실제 버전 범위로 매핑하는 단일 출처 추가",
12
+ "sh-ui add 가 npm install <name>@<range> 로 호출 — RC 만 있는 패키지(@base-ui-components/react 등) 자동 설치 시 latest 못 찾아 ETARGET 으로 실패하던 사전 이슈 수정",
13
+ "패키지명에 이미 @version 이 포함돼 있거나 peer-versions 맵에 없는 경우는 그대로 통과 (Flutter·기타 platform 호환)"
14
+ ],
15
+ "url": "https://github.com/sanghyeonKim0201/sh-ui/releases/tag/v0.21.1"
16
+ },
5
17
  {
6
18
  "version": "0.21.0",
7
19
  "date": "2026-04-27",
@@ -0,0 +1,10 @@
1
+ {
2
+ "$description": "registry.json 의 dependencies 에 등장하는 npm 패키지의 버전 범위. CLI 가 add 시 npm install <name>@<range> 로 호출하기 위함.",
3
+ "versions": {
4
+ "@base-ui-components/react": "^1.0.0-rc.0",
5
+ "@tanstack/react-form": "^1.29.1",
6
+ "lucide-react": "^1.11.0",
7
+ "react-hook-form": "^7.74.0",
8
+ "shiki": "^4.0.2"
9
+ }
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sh-ui-cli",
3
- "version": "0.21.0",
3
+ "version": "0.21.1",
4
4
  "description": "sh-ui CLI — 디자인 시스템 컴포넌트를 프로젝트로 복사하는 CLI (sh-ui init / add / list / remove)",
5
5
  "license": "MIT",
6
6
  "repository": {
package/src/add.mjs CHANGED
@@ -4,7 +4,30 @@ import { dirname, resolve, relative } from "node:path";
4
4
  import { pathToFileURL } from "node:url";
5
5
  import { spawn } from "node:child_process";
6
6
  import { formatUnifiedDiff } from "./diff.mjs";
7
- import { getRegistryRoot, getTokensRoot } from "./paths.mjs";
7
+ import { getRegistryRoot, getTokensRoot, getPeerVersionsPath } from "./paths.mjs";
8
+
9
+ /**
10
+ * `dependencies` 에 적힌 패키지명을 peer-versions.json 의 버전 범위와 결합.
11
+ * 패키지 자체에 이미 `@version` 이 붙어 있거나 맵에 없으면 그대로 둔다.
12
+ *
13
+ * 왜: registry.json 은 deps 를 패키지명만 적어 두고, 실제 호환 버전은
14
+ * peer-versions.json 가 단일 출처로 관리한다. 이게 없으면 npm install 이
15
+ * latest 태그를 찾는데, RC 만 있는 패키지(@base-ui-components/react 등)
16
+ * 에서 ETARGET 으로 실패한다.
17
+ */
18
+ async function resolveDepVersions(deps, platform) {
19
+ let map = {};
20
+ try {
21
+ const data = JSON.parse(await readFile(getPeerVersionsPath(platform), "utf8"));
22
+ map = data.versions ?? {};
23
+ } catch {
24
+ // peer-versions.json 이 없는 platform 은 그대로 패스 (Flutter 등)
25
+ }
26
+ return deps.map((d) => {
27
+ if (d.includes("@", 1)) return d; // 이미 name@range 형식
28
+ return map[d] ? `${d}@${map[d]}` : d;
29
+ });
30
+ }
8
31
 
9
32
  // tokens/build.mjs 는 모노레포·출고 모드에 따라 위치가 달라서 동적 import.
10
33
  async function loadTokensBuilder() {
@@ -209,22 +232,24 @@ export async function add({ cwd, names, skipInstall = false, diffMode = false })
209
232
  return;
210
233
  }
211
234
 
235
+ const versioned = await resolveDepVersions(missing, config.platform);
236
+
212
237
  if (skipInstall) {
213
238
  const pm = detectPackageManager(cwd);
214
239
  const addCmd = pm === "npm" ? "install" : "add";
215
240
  console.log(
216
- `\n ⚠ 외부 패키지 필요. 다음을 실행하세요:\n ${pm} ${addCmd} ${missing.join(" ")}`,
241
+ `\n ⚠ 외부 패키지 필요. 다음을 실행하세요:\n ${pm} ${addCmd} ${versioned.join(" ")}`,
217
242
  );
218
243
  return;
219
244
  }
220
245
 
221
246
  const pm = detectPackageManager(cwd);
222
247
  try {
223
- await runInstall(pm, missing, cwd);
248
+ await runInstall(pm, versioned, cwd);
224
249
  } catch (err) {
225
250
  const addCmd = pm === "npm" ? "install" : "add";
226
251
  console.error(
227
- `\n✗ 자동 설치 실패 (${err.message}). 수동으로 실행하세요:\n ${pm} ${addCmd} ${missing.join(" ")}`,
252
+ `\n✗ 자동 설치 실패 (${err.message}). 수동으로 실행하세요:\n ${pm} ${addCmd} ${versioned.join(" ")}`,
228
253
  );
229
254
  throw err;
230
255
  }
package/src/mcp.mjs CHANGED
@@ -102,7 +102,7 @@ function resolveCwd(input) {
102
102
 
103
103
  export async function startMcpServer() {
104
104
  const server = new McpServer(
105
- { name: "sh-ui", version: "0.21.0" },
105
+ { name: "sh-ui", version: "0.21.1" },
106
106
  { capabilities: { tools: {} } },
107
107
  );
108
108
 
package/src/paths.mjs CHANGED
@@ -33,6 +33,13 @@ export function getTokensRoot() {
33
33
  : resolve(MONOREPO_PACKAGES, "tokens");
34
34
  }
35
35
 
36
+ /** registry.json deps 에 등장하는 npm 패키지의 버전 범위 맵 */
37
+ export function getPeerVersionsPath(platform) {
38
+ return isBundled
39
+ ? resolve(BUNDLED_DATA, "registry", platform, "peer-versions.json")
40
+ : resolve(MONOREPO_PACKAGES, "registry", platform, "peer-versions.json");
41
+ }
42
+
36
43
  /** llms 요약 JSON (platform별) */
37
44
  export function getSummariesPath(platform) {
38
45
  return isBundled