@axis-ds/cli 1.6.2 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -45,7 +45,7 @@ axis list
45
45
 
46
46
  - `axis.config.json` 과 `cn()` 을 담은 `utils.ts` 를 만들고, `clsx` · `tailwind-merge` 가 `package.json` 에 없으면 `dependencies` 에 더합니다. 설치는 실행하지 않고 명령만 안내합니다.
47
47
  - `axis.config.json` 의 `registry` 는 기본값(`https://axis-design-system.pages.dev/r`)이거나, 이미 있던 config 의 값입니다. 종전 기본값 `https://axis.minu.best/r` 는 Cloudflare 403 이라 바꿨습니다. add · list 는 그 값을 새 기본값으로 바꿔 읽으며 한 줄 알립니다(위 「컴포넌트 추가」, 파일은 고치지 않음). init 을 다시 실행하면 그 값을 새 기본값으로 바꿔 쓰고 「registry 를 새 기본 주소로 갱신」으로 알립니다. 사용자가 지정한 다른 값은 init 도 그대로 둡니다.
48
- - `utils.ts` 가 이미 있으면 같은 내용이면 「유지(이미 같은 내용)」(다시 쓰지 않음), 다르면 init 의 utils 로 덮어쓰고 「덮어씀」으로 알립니다. `utils.ts` 쓰기는 `axis add` 와 같은 규칙입니다: 심볼릭 링크면 같은 내용일 때 「유지(이미 같은 내용, 링크)」로 두고, 내용이 다른 링크(프로젝트 안 · 밖) · 깨진 링크 · 디렉터리 · 읽을 수 없는 파일 · 다른 경로와 하드링크로 이어진 파일은 쓰지 않고 그 사실을 알린 뒤 rc 1 입니다. 이 판정은 쓰기 전에 하므로 이때는 `axis.config.json` · `package.json` 도 쓰지 않습니다. 다른 경로와 하드링크로 이어진 `axis.config.json` 을 다시 써야 할 때도 같습니다.
48
+ - `utils.ts` 가 이미 있으면 같은 내용이면 「유지(이미 같은 내용)」(다시 쓰지 않음), 다르면 init 의 utils 로 덮어쓰고 「덮어씀」으로 알립니다(터미널이 아닌 곳에서 `-y` 없이 실행하면 덮어쓰지 않고 rc 1, 아래 「터미널이 아닌 곳에서 실행」). `utils.ts` 쓰기는 `axis add` 와 같은 규칙입니다: 심볼릭 링크면 같은 내용일 때 「유지(이미 같은 내용, 링크)」로 두고, 내용이 다른 링크(프로젝트 안 · 밖) · 깨진 링크 · 디렉터리 · 읽을 수 없는 파일 · 다른 경로와 하드링크로 이어진 파일은 쓰지 않고 그 사실을 알린 뒤 rc 1 입니다. 이 판정은 쓰기 전에 하므로 이때는 `axis.config.json` · `package.json` 도 쓰지 않습니다. 다른 경로와 하드링크로 이어진 `axis.config.json` 을 다시 써야 할 때도 같습니다.
49
49
  - 경로 기본값(`-y` 값 · 대화형 초기값)은 실제 프로젝트를 보고 정합니다(1.6.0 부터). `componentsDir` 는 `src/` 가 있으면 `./src/components/ui`, 없으면 `./components/ui` 이고 `src/` 를 새로 만들지 않습니다. `globalCss` 는 `app/globals.css` · `src/app/globals.css` · `styles/globals.css` · `src/styles/globals.css` · `globals.css` 가운데 실제로 있는 첫 파일, `tailwindConfig` 는 있는 `tailwind.config.{ts,js,mjs,cjs}` 가운데 첫 파일입니다. 찾지 못하면 기본값을 기록하고 그 사실을 한 줄 알립니다. Tailwind 4 안내 제목도 이 경로를 씁니다.
50
50
  - config 가 이미 있으면 출력이 「생성 완료」가 아니라 사실대로 「유지(이미 같은 내용)」 또는 「갱신」입니다. 갱신은 init 이 다루는 키(`$schema` · `componentsDir` · `tailwindConfig` · `globalCss` · `registry`)만 바꾸고, 그 밖의 키(`brand` · `monetDir` · `template` · `agenticDir` 등)는 값과 순서를 그대로 둡니다(1.6.0 부터, 이전에는 빠졌음). 들여쓰기도 기존 파일을 따릅니다. 기존 `componentsDir` 는 그대로 두고, `globalCss` · `tailwindConfig` 는 가리키는 파일이 있으면 그대로, 없으면 찾은 파일로 바꾸고 알립니다(찾지 못하면 그대로 두고 알림). Tailwind 4 이상이면 `tailwindConfig` 를 지우고 알립니다. `registry` 가 종전 기본값이면 위처럼 새 기본값으로 바꿉니다. `AXIS_REGISTRY_URL` 은 config 에 기록하지 않고 add · list 를 실행할 때만 우선합니다.
51
51
  - 애니메이션 플러그인(`tailwindcss-animate` · `tw-animate-css`)이 `package.json` 에 없으면, Dialog · Select 등의 열고 닫는 애니메이션에 필요하다는 안내 한 줄을 냅니다(Tailwind 3 은 plugins, Tailwind 4 는 `@import "tw-animate-css";`).
@@ -112,6 +112,24 @@ axis theme add ontology
112
112
  - FAIL 이 하나라도 있으면 종료 코드 1 로 끝납니다. WARN 만 있으면 0 입니다(1.3.0 부터, 이전에는 결과와 관계없이 0).
113
113
  - MCP `axis.check_project` 도 같은 항목 · 문구를 냅니다.
114
114
 
115
+ ## 터미널이 아닌 곳에서 실행 (CI · 파이프 · `</dev/null`)
116
+
117
+ stdin 이 터미널이 아니면 질문을 띄우지 않습니다(1.7.0 부터). 이전에는 `axis add` 말고는 입력이 닫힌 곳(`</dev/null` · 빈 파이프)에서 질문 한 줄만 찍고 아무것도 하지 않은 채 rc 0 으로 끝났고, 파이프로 응답을 넣으면 그 값으로 동작했습니다. 질문의 성격에 따라 이렇게 합니다.
118
+
119
+ | 명령 | 터미널이 아닐 때 |
120
+ |---|---|
121
+ | `axis init`(`-y` 없음) | `-y` 와 같은 기본값으로 진행하고 쓴 값을 한 줄 알림. 단 내용이 다른 기존 `utils.ts` 가 있으면 덮어쓰지 않고 rc 1, 아무것도 쓰지 않음(`-y` 면 덮어씀) |
122
+ | `axis template init <name>`(`--dir` 없음) | 템플릿 이름 디렉터리(`./<name>`)로 진행하고 한 줄 알림 |
123
+ | `axis template init`(이름 없음) | rc 1, 템플릿 이름 안내(템플릿 선택에는 기본값이 없음) |
124
+ | `axis template init` 대상이 비어 있지 않음 | rc 1, 아무것도 쓰지 않음. `-y` 면 진행(템플릿과 같은 경로의 파일은 덮어씀) |
125
+ | `axis template apply` 충돌 파일 있음 | rc 1, 아무것도 쓰지 않음. `-y` 면 덮어씀, `--dry-run` 으로 미리보기 |
126
+ | `axis add` 내용이 다른 기존 파일 | `-y` 와 같이 건너뛰고 목록을 알림(종전과 같음) |
127
+ | `axis v0 import` · `axis monet import` | rc 1, 대화형 터미널에서 실행하라는 안내(`v0` 는 `axis v0 convert <file>` 도 안내) |
128
+
129
+ - `axis template init -y` 는 질문을 기본값으로 답하고, 비어 있지 않은 디렉터리도 진행합니다(`template apply -y` 와 같은 뜻). 터미널에서도 같습니다.
130
+ - 판정은 stdin 이 터미널인지 하나로 합니다. 그래서 `printf '\n' | axis template init dashboard` 처럼 파이프로 응답을 넣던 스크립트도 이제는 묻지 않고 위 표대로 동작합니다. 값은 `--dir` · `-y` 같은 옵션으로 주세요.
131
+ - Windows Git Bash(mintty)처럼 사람이 앞에 있어도 stdin 이 터미널로 잡히지 않는 환경에서는 질문 없이 위 표대로 동작할 수 있습니다(실측 전). 질문이 뜨지 않으면 `winpty npx axis ...` 로 실행하거나, PowerShell · Windows Terminal 에서 실행하거나, `--dir` · `-y` 같은 옵션으로 값을 주세요.
132
+
115
133
  ## 문서
116
134
 
117
135
  자세한 사용법은 [AXIS Design System 문서](https://axis-design-system.pages.dev)를 참고하세요.
@@ -1,8 +1,13 @@
1
+ import {
2
+ ask,
3
+ failNonInteractive,
4
+ isInteractive
5
+ } from "./chunk-HFMMK6R4.js";
6
+
1
7
  // src/v0.ts
2
8
  import chalk from "chalk";
3
9
  import fs from "fs-extra";
4
10
  import path from "path";
5
- import prompts from "prompts";
6
11
  var V0_CONVERSION_RULES = [
7
12
  // import 경로 변환
8
13
  { from: /@\/components\/ui\//g, to: "@/components/ui/" },
@@ -69,7 +74,8 @@ ${result}`;
69
74
  console.log(chalk.gray(" - \uD658\uACBD \uBCC0\uC218 \uBC0F API \uC5D4\uB4DC\uD3EC\uC778\uD2B8\n"));
70
75
  }
71
76
  // V0 URL에서 가져오기 안내
72
- async importFromUrl() {
77
+ async importFromUrl(opts = {}) {
78
+ const interactive = opts.interactive ?? isInteractive();
73
79
  console.log(chalk.blue("\n\u{1F517} V0 URL\uC5D0\uC11C \uCEF4\uD3EC\uB10C\uD2B8 \uAC00\uC838\uC624\uAE30\n"));
74
80
  console.log(chalk.yellow("V0\uB294 \uC9C1\uC811 API\uB97C \uC81C\uACF5\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4."));
75
81
  console.log(chalk.gray("\uB2E4\uC74C \uBC29\uBC95\uC73C\uB85C \uCF54\uB4DC\uB97C \uAC00\uC838\uC62C \uC218 \uC788\uC2B5\uB2C8\uB2E4:\n"));
@@ -85,26 +91,36 @@ ${result}`;
85
91
  console.log(chalk.gray(" 1. v0.app\uC5D0\uC11C \uCF54\uB4DC \uD0ED \uC5F4\uAE30"));
86
92
  console.log(chalk.gray(" 2. \uD30C\uC77C\uBCC4\uB85C \uCF54\uB4DC \uBCF5\uC0AC"));
87
93
  console.log(chalk.gray(" 3. npx @axis-ds/cli v0 convert\uB85C \uBCC0\uD658\n"));
88
- const { method } = await prompts({
89
- type: "select",
90
- name: "method",
91
- message: "\uC5B4\uB5A4 \uBC29\uBC95\uC744 \uC0AC\uC6A9\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
92
- choices: [
93
- { title: "GitHub\uC5D0\uC11C \uD074\uB860", value: "github" },
94
- { title: "\uB2E4\uC6B4\uB85C\uB4DC\uD55C ZIP \uD30C\uC77C \uBCC0\uD658", value: "zip" },
95
- { title: "\uD074\uB9BD\uBCF4\uB4DC\uC5D0\uC11C \uBCC0\uD658", value: "clipboard" },
96
- { title: "\uCDE8\uC18C", value: "cancel" }
97
- ]
98
- });
94
+ if (!interactive) {
95
+ failNonInteractive("\uBC29\uBC95\uC744 \uACE0\uB97C \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.", [
96
+ "\uC704 \uBC29\uBC95 1~3 \uC744 \uC9C1\uC811 \uB530\uB974\uAC70\uB098 \uB300\uD654\uD615 \uD130\uBBF8\uB110\uC5D0\uC11C \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.",
97
+ "\uD30C\uC77C\uC774 \uC788\uC73C\uBA74: axis v0 convert <file> [-o <path>]"
98
+ ]);
99
+ return;
100
+ }
101
+ const { method } = await ask(
102
+ {
103
+ type: "select",
104
+ name: "method",
105
+ message: "\uC5B4\uB5A4 \uBC29\uBC95\uC744 \uC0AC\uC6A9\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
106
+ choices: [
107
+ { title: "GitHub\uC5D0\uC11C \uD074\uB860", value: "github" },
108
+ { title: "\uB2E4\uC6B4\uB85C\uB4DC\uD55C ZIP \uD30C\uC77C \uBCC0\uD658", value: "zip" },
109
+ { title: "\uD074\uB9BD\uBCF4\uB4DC\uC5D0\uC11C \uBCC0\uD658", value: "clipboard" },
110
+ { title: "\uCDE8\uC18C", value: "cancel" }
111
+ ]
112
+ },
113
+ interactive
114
+ );
99
115
  switch (method) {
100
116
  case "github":
101
117
  await this.setupGitHubSync();
102
118
  break;
103
119
  case "zip":
104
- await this.convertFromZip();
120
+ await this.convertFromZip({ interactive });
105
121
  break;
106
122
  case "clipboard":
107
- await this.convertFromClipboard();
123
+ await this.convertFromClipboard({ interactive });
108
124
  break;
109
125
  }
110
126
  }
@@ -122,14 +138,24 @@ ${result}`;
122
138
  console.log(chalk.gray("\uD301: GitHub Actions\uB85C \uC790\uB3D9 \uBCC0\uD658 \uC6CC\uD06C\uD50C\uB85C\uB3C4 \uC124\uC815 \uAC00\uB2A5\uD569\uB2C8\uB2E4.\n"));
123
139
  }
124
140
  // ZIP 파일에서 변환
125
- async convertFromZip() {
141
+ async convertFromZip(opts = {}) {
126
142
  console.log(chalk.blue("\n\u{1F4E6} ZIP \uD30C\uC77C\uC5D0\uC11C \uBCC0\uD658\n"));
127
- const { zipPath } = await prompts({
128
- type: "text",
129
- name: "zipPath",
130
- message: "\uB2E4\uC6B4\uB85C\uB4DC\uD55C ZIP \uD30C\uC77C \uACBD\uB85C:",
131
- validate: (v) => v.length > 0 ? true : "\uACBD\uB85C\uB97C \uC785\uB825\uD558\uC138\uC694"
132
- });
143
+ const interactive = opts.interactive ?? isInteractive();
144
+ if (!interactive) {
145
+ failNonInteractive("ZIP \uD30C\uC77C \uACBD\uB85C\uB97C \uBB3C\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.", [
146
+ "\uC555\uCD95\uC744 \uD47C \uB4A4: axis v0 convert <file> [-o <path>]"
147
+ ]);
148
+ return;
149
+ }
150
+ const { zipPath } = await ask(
151
+ {
152
+ type: "text",
153
+ name: "zipPath",
154
+ message: "\uB2E4\uC6B4\uB85C\uB4DC\uD55C ZIP \uD30C\uC77C \uACBD\uB85C:",
155
+ validate: (v) => v.length > 0 ? true : "\uACBD\uB85C\uB97C \uC785\uB825\uD558\uC138\uC694"
156
+ },
157
+ interactive
158
+ );
133
159
  if (!zipPath) return;
134
160
  console.log(chalk.yellow("\nZIP \uBCC0\uD658 \uAE30\uB2A5\uC740 \uCD94\uD6C4 \uAD6C\uD604 \uC608\uC815\uC785\uB2C8\uB2E4."));
135
161
  console.log(chalk.gray("\uD604\uC7AC\uB294 \uC218\uB3D9\uC73C\uB85C \uC555\uCD95 \uD574\uC81C \uD6C4 convert \uBA85\uB839\uC5B4\uB97C \uC0AC\uC6A9\uD558\uC138\uC694:\n"));
@@ -137,22 +163,35 @@ ${result}`;
137
163
  console.log(chalk.cyan(" npx @axis-ds/cli v0 convert ./v0-project/components/*.tsx\n"));
138
164
  }
139
165
  // 클립보드에서 변환
140
- async convertFromClipboard() {
166
+ async convertFromClipboard(opts = {}) {
141
167
  console.log(chalk.blue("\n\u{1F4CB} \uD074\uB9BD\uBCF4\uB4DC\uC5D0\uC11C V0 \uCF54\uB4DC \uBCC0\uD658\n"));
142
- const { componentName } = await prompts({
143
- type: "text",
144
- name: "componentName",
145
- message: "\uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984 (\uC608: hero-section):",
146
- validate: (v) => v.length > 0 ? true : "\uC774\uB984\uC744 \uC785\uB825\uD558\uC138\uC694"
147
- });
168
+ const interactive = opts.interactive ?? isInteractive();
169
+ if (!interactive) {
170
+ failNonInteractive("\uBD99\uC5EC \uB123\uC744 \uCF54\uB4DC\uC640 \uC774\uB984\uC744 \uBB3C\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.", [
171
+ "\uCF54\uB4DC\uB97C \uD30C\uC77C\uB85C \uC800\uC7A5\uD55C \uB4A4: axis v0 convert <file> [-o <path>]"
172
+ ]);
173
+ return;
174
+ }
175
+ const { componentName } = await ask(
176
+ {
177
+ type: "text",
178
+ name: "componentName",
179
+ message: "\uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984 (\uC608: hero-section):",
180
+ validate: (v) => v.length > 0 ? true : "\uC774\uB984\uC744 \uC785\uB825\uD558\uC138\uC694"
181
+ },
182
+ interactive
183
+ );
148
184
  if (!componentName) return;
149
185
  console.log(chalk.gray("\nV0\uC5D0\uC11C \uBCF5\uC0AC\uD55C \uCF54\uB4DC\uB97C \uBD99\uC5EC\uB123\uC73C\uC138\uC694."));
150
186
  console.log(chalk.gray("(\uC785\uB825 \uC644\uB8CC \uD6C4 \uBE48 \uC904\uC5D0\uC11C Enter \uB450 \uBC88)\n"));
151
- const { code } = await prompts({
152
- type: "text",
153
- name: "code",
154
- message: "\uCF54\uB4DC:"
155
- });
187
+ const { code } = await ask(
188
+ {
189
+ type: "text",
190
+ name: "code",
191
+ message: "\uCF54\uB4DC:"
192
+ },
193
+ interactive
194
+ );
156
195
  if (!code) {
157
196
  console.log(chalk.yellow("\n\uCF54\uB4DC\uAC00 \uC785\uB825\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4."));
158
197
  return;
@@ -0,0 +1,35 @@
1
+ // src/interactive.ts
2
+ import chalk from "chalk";
3
+ import prompts from "prompts";
4
+ var isInteractive = () => process.stdin.isTTY === true;
5
+ var NonInteractiveError = class extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = "NonInteractiveError";
9
+ }
10
+ };
11
+ async function ask(questions, interactive) {
12
+ if (!interactive) {
13
+ const list = Array.isArray(questions) ? questions : [questions];
14
+ const first = list.find((q) => q.type !== null);
15
+ const message = typeof first?.message === "string" ? first.message : String(first?.name ?? "");
16
+ throw new NonInteractiveError(`\uBE44\uB300\uD654\uD615 \uC2E4\uD589\uC774\uB77C \uC9C8\uBB38(${message})\uC5D0 \uB2F5\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uB300\uD654\uD615 \uD130\uBBF8\uB110\uC5D0\uC11C \uC2E4\uD589\uD558\uAC70\uB098 \uD544\uC694\uD55C \uC635\uC158\uC744 \uC8FC\uC138\uC694.`);
17
+ }
18
+ return prompts(questions);
19
+ }
20
+ function noteDefault(message) {
21
+ console.log(chalk.gray(`\uBE44\uB300\uD654\uD615 \uC2E4\uD589\uC774\uB77C ${message}`));
22
+ }
23
+ function failNonInteractive(reason, hints) {
24
+ console.error(chalk.red(`\uBE44\uB300\uD654\uD615 \uC2E4\uD589\uC774\uB77C ${reason}`));
25
+ for (const hint of hints) console.error(chalk.yellow(` ${hint}`));
26
+ process.exitCode = 1;
27
+ }
28
+
29
+ export {
30
+ isInteractive,
31
+ NonInteractiveError,
32
+ ask,
33
+ noteDefault,
34
+ failNonInteractive
35
+ };
@@ -1,8 +1,13 @@
1
+ import {
2
+ ask,
3
+ failNonInteractive,
4
+ isInteractive
5
+ } from "./chunk-HFMMK6R4.js";
6
+
1
7
  // src/monet.ts
2
8
  import chalk from "chalk";
3
9
  import fs from "fs-extra";
4
10
  import path from "path";
5
- import prompts from "prompts";
6
11
  var MONET_CATEGORIES = [
7
12
  { id: "hero", name: "Hero Sections", count: 120 },
8
13
  { id: "feature", name: "Feature Sections", count: 191 },
@@ -111,24 +116,38 @@ var MonetClient = class {
111
116
  return examples[category] || [{ id: `${category}-basic`, desc: "\uAE30\uBCF8 \uD15C\uD50C\uB9BF" }];
112
117
  }
113
118
  // 클립보드에서 Monet 코드 가져오기
114
- async importFromClipboard() {
119
+ /** opts.interactive: 질문을 띄울 수 있는지(WI-0075). 없으면 stdin 이 TTY 인지로 정합니다 */
120
+ async importFromClipboard(opts = {}) {
115
121
  console.log(chalk.blue("\n\u{1F4CB} \uD074\uB9BD\uBCF4\uB4DC\uC5D0\uC11C Monet \uCEF4\uD3EC\uB10C\uD2B8 \uAC00\uC838\uC624\uAE30\n"));
116
122
  console.log(chalk.yellow("\uC900\uBE44 \uB2E8\uACC4:"));
117
123
  console.log(chalk.gray(" 1. monet.design\uC5D0\uC11C \uCEF4\uD3EC\uB10C\uD2B8 \uC120\uD0DD"));
118
124
  console.log(chalk.gray(" 2. 'Copy Code' \uBC84\uD2BC\uC73C\uB85C \uCF54\uB4DC \uBCF5\uC0AC"));
119
125
  console.log(chalk.gray(" 3. \uC774 \uBA85\uB839\uC5B4 \uC2E4\uD589\n"));
120
- const { componentName } = await prompts({
121
- type: "text",
122
- name: "componentName",
123
- message: "\uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984 (\uC608: hero-section):",
124
- validate: (v) => v.length > 0 ? true : "\uC774\uB984\uC744 \uC785\uB825\uD558\uC138\uC694"
125
- });
126
+ const interactive = opts.interactive ?? isInteractive();
127
+ if (!interactive) {
128
+ failNonInteractive("\uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984\uACFC \uBD99\uC5EC \uB123\uC744 \uCF54\uB4DC\uB97C \uBB3C\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.", [
129
+ "\uB300\uD654\uD615 \uD130\uBBF8\uB110\uC5D0\uC11C \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694: axis monet import"
130
+ ]);
131
+ return;
132
+ }
133
+ const { componentName } = await ask(
134
+ {
135
+ type: "text",
136
+ name: "componentName",
137
+ message: "\uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984 (\uC608: hero-section):",
138
+ validate: (v) => v.length > 0 ? true : "\uC774\uB984\uC744 \uC785\uB825\uD558\uC138\uC694"
139
+ },
140
+ interactive
141
+ );
126
142
  if (!componentName) return;
127
- const { componentCode } = await prompts({
128
- type: "text",
129
- name: "componentCode",
130
- message: "\uBCF5\uC0AC\uD55C \uCF54\uB4DC\uB97C \uBD99\uC5EC\uB123\uC73C\uC138\uC694 (\uD55C \uC904\uB85C):"
131
- });
143
+ const { componentCode } = await ask(
144
+ {
145
+ type: "text",
146
+ name: "componentCode",
147
+ message: "\uBCF5\uC0AC\uD55C \uCF54\uB4DC\uB97C \uBD99\uC5EC\uB123\uC73C\uC138\uC694 (\uD55C \uC904\uB85C):"
148
+ },
149
+ interactive
150
+ );
132
151
  if (!componentCode) {
133
152
  console.log(chalk.yellow("\n\uCF54\uB4DC\uAC00 \uC785\uB825\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4."));
134
153
  return;
package/dist/index.js CHANGED
@@ -1,10 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  MonetClient
4
- } from "./chunk-ZVVACWEW.js";
4
+ } from "./chunk-LVMDBOXD.js";
5
5
  import {
6
6
  V0Client
7
- } from "./chunk-NNFSJISD.js";
7
+ } from "./chunk-2PNCUPCG.js";
8
+ import {
9
+ NonInteractiveError,
10
+ ask,
11
+ failNonInteractive,
12
+ isInteractive,
13
+ noteDefault
14
+ } from "./chunk-HFMMK6R4.js";
8
15
  import {
9
16
  registerSyncCommand
10
17
  } from "./chunk-7CDXEBEE.js";
@@ -1806,7 +1813,6 @@ import fs8 from "fs-extra";
1806
1813
  import path9 from "path";
1807
1814
  import chalk5 from "chalk";
1808
1815
  import ora3 from "ora";
1809
- import prompts from "prompts";
1810
1816
 
1811
1817
  // src/template/post-install.ts
1812
1818
  import fs6 from "fs-extra";
@@ -2125,22 +2131,17 @@ function majorFromVersion(version) {
2125
2131
  }
2126
2132
  function detectTailwind(baseDirInput, pkg) {
2127
2133
  const baseDir = resolve(baseDirInput);
2128
- const installedFile = join(baseDir, "node_modules", "tailwindcss", "package.json");
2129
2134
  const declared = pkg ? hasDependency2(pkg, "tailwindcss") : void 0;
2130
2135
  const bounds = declared !== void 0 ? tailwindMajorBounds(declared) : void 0;
2131
2136
  const declaredMajor = bounds?.lower;
2132
- try {
2133
- const installed = JSON.parse(readFileSync2(installedFile, "utf8"));
2134
- const version = isPlainObject2(installed) ? installed.version : void 0;
2135
- const major = majorFromVersion(version);
2136
- if (major !== void 0) {
2137
- const found = { major, source: "installed", value: String(version) };
2138
- if (declared !== void 0 && bounds !== void 0 && !majorWithin(major, bounds)) {
2139
- found.mismatch = { declared, declaredMajor: bounds.lower };
2140
- }
2141
- return found;
2137
+ const version = isPnpProject(baseDir) ? void 0 : findInstalledPackage(baseDir, "tailwindcss")?.version;
2138
+ const major = majorFromVersion(version);
2139
+ if (version !== void 0 && major !== void 0) {
2140
+ const found = { major, source: "installed", value: version };
2141
+ if (declared !== void 0 && bounds !== void 0 && !majorWithin(major, bounds)) {
2142
+ found.mismatch = { declared, declaredMajor: bounds.lower };
2142
2143
  }
2143
- } catch {
2144
+ return found;
2144
2145
  }
2145
2146
  if (declared !== void 0) {
2146
2147
  if (declaredMajor !== void 0) return { major: declaredMajor, source: "declared", value: declared };
@@ -2283,19 +2284,9 @@ function rangeLowerAtLeast(range, min) {
2283
2284
  if (!lower || !target) return void 0;
2284
2285
  return compareLower(lower, target) >= 0;
2285
2286
  }
2286
- function exactVersion(version) {
2287
- if (typeof version !== "string") return void 0;
2288
- const v = version.trim();
2289
- if (!/^v?\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(v) || /^v?0\.0\.0-/.test(v)) return void 0;
2290
- return v;
2291
- }
2292
- function installedVersion(baseDir, name) {
2293
- try {
2294
- const parsed = JSON.parse(readFileSync2(join(baseDir, "node_modules", ...name.split("/"), "package.json"), "utf8"));
2295
- return isPlainObject2(parsed) ? exactVersion(parsed.version) : void 0;
2296
- } catch {
2297
- return void 0;
2298
- }
2287
+ function installedAxisVersion(baseDir, name) {
2288
+ if (isPnpProject(baseDir)) return void 0;
2289
+ return findInstalledPackage(baseDir, name)?.version;
2299
2290
  }
2300
2291
  function axisPackagesBelowTailwind4(pkg, baseDirInput) {
2301
2292
  if (!pkg) return [];
@@ -2305,7 +2296,7 @@ function axisPackagesBelowTailwind4(pkg, baseDirInput) {
2305
2296
  for (const name of TAILWIND4_AXIS_PACKAGES) {
2306
2297
  const range = hasDependency2(pkg, name);
2307
2298
  if (range === void 0 || range.trim().startsWith("workspace:")) continue;
2308
- const installed = baseDir !== void 0 ? installedVersion(baseDir, name) : void 0;
2299
+ const installed = baseDir !== void 0 ? installedAxisVersion(baseDir, name) : void 0;
2309
2300
  const installedLower = installed !== void 0 ? lowerOf(installed) : void 0;
2310
2301
  if (installed !== void 0 && installedLower !== void 0) {
2311
2302
  if (compareLower(installedLower, min) < 0) out.push({ name, range, status: "below", source: "installed", installed });
@@ -2892,12 +2883,23 @@ async function applyTemplate(slug, options) {
2892
2883
  for (const c of conflicts) {
2893
2884
  console.log(chalk5.gray(` - ${c}`));
2894
2885
  }
2895
- const { proceed } = await prompts({
2896
- type: "confirm",
2897
- name: "proceed",
2898
- message: "\uCDA9\uB3CC \uD30C\uC77C\uC744 \uB36E\uC5B4\uC4F0\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
2899
- initial: false
2900
- });
2886
+ const interactive = options.interactive ?? isInteractive();
2887
+ if (!interactive) {
2888
+ failNonInteractive("\uCDA9\uB3CC \uD30C\uC77C\uC744 \uB36E\uC5B4\uC4F8\uC9C0 \uBB3C\uC744 \uC218 \uC5C6\uC5B4 \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.", [
2889
+ `\uB36E\uC5B4\uC4F0\uB824\uBA74: axis template apply ${slug} -y`,
2890
+ `\uBBF8\uB9AC\uBCF4\uAE30: axis template apply ${slug} --dry-run`
2891
+ ]);
2892
+ return;
2893
+ }
2894
+ const { proceed } = await ask(
2895
+ {
2896
+ type: "confirm",
2897
+ name: "proceed",
2898
+ message: "\uCDA9\uB3CC \uD30C\uC77C\uC744 \uB36E\uC5B4\uC4F0\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
2899
+ initial: false
2900
+ },
2901
+ interactive
2902
+ );
2901
2903
  if (!proceed) {
2902
2904
  console.log(chalk5.gray("\uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4."));
2903
2905
  return;
@@ -2949,20 +2951,31 @@ async function applyTemplate(slug, options) {
2949
2951
  '${detail.name}' \uD15C\uD50C\uB9BF \uC801\uC6A9 \uC644\uB8CC!`));
2950
2952
  }
2951
2953
  async function initTemplate(slug, options) {
2954
+ const interactive = options.interactive ?? isInteractive();
2952
2955
  let selectedSlug = slug;
2953
2956
  if (!selectedSlug) {
2957
+ if (!interactive) {
2958
+ failNonInteractive("\uD15C\uD50C\uB9BF\uC744 \uACE0\uB97C \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uD15C\uD50C\uB9BF \uC774\uB984\uC744 \uC8FC\uC138\uC694.", [
2959
+ "\uC0AC\uC6A9\uBC95: axis template init <name> [--dir <path>] [-y]",
2960
+ "\uBAA9\uB85D: axis template list"
2961
+ ]);
2962
+ return;
2963
+ }
2954
2964
  const { fetchTemplateIndex: fetchTemplateIndex2 } = await import("./registry-client-6WSGKPF2.js");
2955
2965
  const index = await fetchTemplateIndex2();
2956
- const { choice } = await prompts({
2957
- type: "select",
2958
- name: "choice",
2959
- message: "\uC0AC\uC6A9\uD560 \uD15C\uD50C\uB9BF\uC744 \uC120\uD0DD\uD558\uC138\uC694:",
2960
- choices: index.templates.map((t) => ({
2961
- title: `${t.name} (${t.category})`,
2962
- description: t.description,
2963
- value: t.slug
2964
- }))
2965
- });
2966
+ const { choice } = await ask(
2967
+ {
2968
+ type: "select",
2969
+ name: "choice",
2970
+ message: "\uC0AC\uC6A9\uD560 \uD15C\uD50C\uB9BF\uC744 \uC120\uD0DD\uD558\uC138\uC694:",
2971
+ choices: index.templates.map((t) => ({
2972
+ title: `${t.name} (${t.category})`,
2973
+ description: t.description,
2974
+ value: t.slug
2975
+ }))
2976
+ },
2977
+ interactive
2978
+ );
2966
2979
  if (!choice) {
2967
2980
  console.log(chalk5.gray("\uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4."));
2968
2981
  return;
@@ -2970,13 +2983,22 @@ async function initTemplate(slug, options) {
2970
2983
  selectedSlug = choice;
2971
2984
  }
2972
2985
  let targetDir = options.dir;
2986
+ if (!targetDir && (!interactive || options.yes)) {
2987
+ targetDir = selectedSlug;
2988
+ const msg = `\uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD1A0\uB9AC\uB97C \uAE30\uBCF8\uAC12 '${targetDir}' \uB85C \uC815\uD588\uC2B5\uB2C8\uB2E4(\uBC14\uAFB8\uB824\uBA74 --dir <path>).`;
2989
+ if (interactive) console.log(chalk5.gray(`-y \uB77C ${msg}`));
2990
+ else noteDefault(msg);
2991
+ }
2973
2992
  if (!targetDir) {
2974
- const { dir } = await prompts({
2975
- type: "text",
2976
- name: "dir",
2977
- message: "\uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD1A0\uB9AC:",
2978
- initial: selectedSlug
2979
- });
2993
+ const { dir } = await ask(
2994
+ {
2995
+ type: "text",
2996
+ name: "dir",
2997
+ message: "\uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD1A0\uB9AC:",
2998
+ initial: selectedSlug
2999
+ },
3000
+ interactive
3001
+ );
2980
3002
  if (!dir) {
2981
3003
  console.log(chalk5.gray("\uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4."));
2982
3004
  return;
@@ -2987,13 +3009,26 @@ async function initTemplate(slug, options) {
2987
3009
  if (await fs8.pathExists(resolved)) {
2988
3010
  const entries = await fs8.readdir(resolved);
2989
3011
  if (entries.length > 0) {
2990
- const { proceed } = await prompts({
2991
- type: "confirm",
2992
- name: "proceed",
2993
- message: `'${targetDir}'\uC5D0 \uC774\uBBF8 \uD30C\uC77C\uC774 \uC788\uC2B5\uB2C8\uB2E4. \uACC4\uC18D\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?`,
2994
- initial: false
2995
- });
2996
- if (!proceed) return;
3012
+ if (options.yes) {
3013
+ console.log(chalk5.yellow(`! '${targetDir}'\uC5D0 \uC774\uBBF8 \uD30C\uC77C\uC774 \uC788\uC9C0\uB9CC -y \uB77C \uC9C4\uD589\uD569\uB2C8\uB2E4(\uD15C\uD50C\uB9BF\uACFC \uAC19\uC740 \uACBD\uB85C\uC758 \uD30C\uC77C\uC740 \uB36E\uC5B4\uC500).`));
3014
+ } else if (!interactive) {
3015
+ failNonInteractive(`'${targetDir}'\uC5D0 \uC774\uBBF8 \uD30C\uC77C\uC774 \uC788\uC5B4 \uACC4\uC18D\uD560\uC9C0 \uBB3C\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.`, [
3016
+ `\uBE48 \uB514\uB809\uD130\uB9AC\uB97C \uC8FC\uC138\uC694: axis template init ${selectedSlug} --dir <path>`,
3017
+ `\uADF8\uB300\uB85C \uC9C4\uD589\uD558\uB824\uBA74(\uAC19\uC740 \uACBD\uB85C\uC758 \uD30C\uC77C\uC740 \uB36E\uC5B4\uC500): axis template init ${selectedSlug} --dir ${targetDir} -y`
3018
+ ]);
3019
+ return;
3020
+ } else {
3021
+ const { proceed } = await ask(
3022
+ {
3023
+ type: "confirm",
3024
+ name: "proceed",
3025
+ message: `'${targetDir}'\uC5D0 \uC774\uBBF8 \uD30C\uC77C\uC774 \uC788\uC2B5\uB2C8\uB2E4. \uACC4\uC18D\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?`,
3026
+ initial: false
3027
+ },
3028
+ interactive
3029
+ );
3030
+ if (!proceed) return;
3031
+ }
2997
3032
  }
2998
3033
  } else {
2999
3034
  await fs8.ensureDir(resolved);
@@ -3632,7 +3667,8 @@ function brandActivationResult(check) {
3632
3667
  }
3633
3668
 
3634
3669
  // src/template/index.ts
3635
- function registerTemplateCommand(program2) {
3670
+ function registerTemplateCommand(program2, deps = {}) {
3671
+ const interactive = () => (deps.isInteractive ?? isInteractive)();
3636
3672
  const tplCmd = program2.command("template").alias("tpl").description("\uD504\uB85C\uC81D\uD2B8 \uD15C\uD50C\uB9BF \uAD00\uB9AC");
3637
3673
  tplCmd.command("list").alias("ls").description("\uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uD15C\uD50C\uB9BF \uBAA9\uB85D").option("--category <type>", "\uCE74\uD14C\uACE0\uB9AC \uD544\uD130").action(async (options) => {
3638
3674
  const spinner = ora5("\uD15C\uD50C\uB9BF \uBAA9\uB85D \uAC00\uC838\uC624\uB294 \uC911...").start();
@@ -3698,12 +3734,12 @@ function registerTemplateCommand(program2) {
3698
3734
  for (const f of detail.files) {
3699
3735
  console.log(` ${chalk8.cyan(f.path)} ${chalk8.gray(`(${f.type})`)}`);
3700
3736
  }
3701
- const deps = Object.keys(detail.dependencies || {});
3737
+ const deps2 = Object.keys(detail.dependencies || {});
3702
3738
  const devDeps = Object.keys(detail.devDependencies || {});
3703
- if (deps.length > 0 || devDeps.length > 0) {
3739
+ if (deps2.length > 0 || devDeps.length > 0) {
3704
3740
  console.log(chalk8.bold("\n \uC758\uC874\uC131:"));
3705
- if (deps.length > 0) {
3706
- console.log(` dependencies: ${deps.join(", ")}`);
3741
+ if (deps2.length > 0) {
3742
+ console.log(` dependencies: ${deps2.join(", ")}`);
3707
3743
  }
3708
3744
  if (devDeps.length > 0) {
3709
3745
  console.log(` devDependencies: ${devDeps.join(", ")}`);
@@ -3718,10 +3754,10 @@ function registerTemplateCommand(program2) {
3718
3754
  }
3719
3755
  });
3720
3756
  tplCmd.command("apply <name>").description("\uD15C\uD50C\uB9BF\uC744 \uD604\uC7AC \uD504\uB85C\uC81D\uD2B8\uC5D0 \uC801\uC6A9").option("-y, --yes", "\uD655\uC778 \uC5C6\uC774 \uB36E\uC5B4\uC4F0\uAE30").option("--dry-run", "\uC2E4\uC81C \uD30C\uC77C \uC0DD\uC131 \uC5C6\uC774 \uBBF8\uB9AC\uBCF4\uAE30").option("--skip-deps", "\uC758\uC874\uC131 \uC548\uB0B4 \uC0DD\uB7B5").option("-d, --dir <path>", "\uB300\uC0C1 \uB514\uB809\uD1A0\uB9AC").action(async (name, options) => {
3721
- await applyTemplate(name, options);
3757
+ await applyTemplate(name, { ...options, interactive: interactive() });
3722
3758
  });
3723
- tplCmd.command("init [name]").description("\uC0C8 \uD504\uB85C\uC81D\uD2B8\uB97C \uD15C\uD50C\uB9BF\uC73C\uB85C \uCD08\uAE30\uD654").option("-d, --dir <path>", "\uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD1A0\uB9AC").action(async (name, options) => {
3724
- await initTemplate(name, options);
3759
+ tplCmd.command("init [name]").description("\uC0C8 \uD504\uB85C\uC81D\uD2B8\uB97C \uD15C\uD50C\uB9BF\uC73C\uB85C \uCD08\uAE30\uD654").option("-d, --dir <path>", "\uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD1A0\uB9AC(\uC5C6\uC73C\uBA74 \uD15C\uD50C\uB9BF \uC774\uB984)").option("-y, --yes", "\uC9C8\uBB38\uC744 \uAE30\uBCF8\uAC12\uC73C\uB85C \uB2F5\uD558\uACE0, \uBE44\uC5B4 \uC788\uC9C0 \uC54A\uC740 \uB514\uB809\uD1A0\uB9AC\uB3C4 \uC9C4\uD589(\uAC19\uC740 \uACBD\uB85C\uC758 \uD30C\uC77C\uC740 \uB36E\uC5B4\uC500)").action(async (name, options) => {
3760
+ await initTemplate(name, { ...options, interactive: interactive() });
3725
3761
  });
3726
3762
  tplCmd.command("diff <name>").description("\uB85C\uCEEC \uD504\uB85C\uC81D\uD2B8\uC640 \uD15C\uD50C\uB9BF\uC758 \uCC28\uC774 \uBE44\uAD50").option("--verbose", "\uB85C\uCEEC \uC804\uC6A9 \uD30C\uC77C\uB3C4 \uD45C\uC2DC").option("-d, --dir <path>", "\uB300\uC0C1 \uB514\uB809\uD1A0\uB9AC").action(async (name, options) => {
3727
3763
  await diffTemplate(name, options);
@@ -4428,7 +4464,6 @@ function registerThemeCommand(program2) {
4428
4464
 
4429
4465
  // src/init/index.ts
4430
4466
  import chalk11 from "chalk";
4431
- import prompts2 from "prompts";
4432
4467
 
4433
4468
  // ../axis-registry-core/src/registry/schema.ts
4434
4469
  import { createHash } from "crypto";
@@ -5286,7 +5321,7 @@ function planUtilsWrite(baseDirInput, utilsPath) {
5286
5321
  }
5287
5322
  return { action: "overwrite" };
5288
5323
  }
5289
- async function runInit(baseDirInput, answers, registryUrl, log = console.log) {
5324
+ async function runInit(baseDirInput, answers, registryUrl, log = console.log, options = {}) {
5290
5325
  const baseDir = path15.resolve(baseDirInput);
5291
5326
  const current = await existingConfig(baseDir);
5292
5327
  const existingRegistry = nonEmptyString(current?.registry);
@@ -5333,6 +5368,12 @@ async function runInit(baseDirInput, answers, registryUrl, log = console.log) {
5333
5368
  const utilsPath = path15.resolve(baseDir, answers.componentsDir, "utils.ts");
5334
5369
  const utilsPlan = planUtilsWrite(baseDir, utilsPath);
5335
5370
  if (utilsPlan.action === "reject") rejects.push(utilsPlan.reason);
5371
+ if (utilsPlan.action === "overwrite" && options.allowOverwrite === false) {
5372
+ const shown = path15.relative(baseDir, utilsPath).split(path15.sep).join("/") || utilsPath;
5373
+ rejects.push(
5374
+ `\uBE44\uB300\uD654\uD615 \uC2E4\uD589\uC774\uB77C \uB0B4\uC6A9\uC774 \uB2E4\uB978 \uAE30\uC874 ${shown} \uB97C \uB36E\uC5B4\uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uB36E\uC5B4\uC368\uB3C4 \uB418\uBA74 axis init -y \uB85C \uB2E4\uC2DC \uC2E4\uD589\uD558\uAC70\uB098 \uB300\uD654\uD615 \uD130\uBBF8\uB110\uC5D0\uC11C \uC2E4\uD589\uD558\uC138\uC694`
5375
+ );
5376
+ }
5336
5377
  if (rejects.length > 0) {
5337
5378
  log(chalk10.red("\u2717 \uC4F8 \uC218 \uC5C6\uB294 \uD30C\uC77C\uC774 \uC788\uC5B4 \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4(axis.config.json \xB7 utils.ts \xB7 package.json \uADF8\uB300\uB85C)."));
5338
5379
  for (const r of rejects) log(chalk10.red(` - ${r}`));
@@ -5437,14 +5478,20 @@ ${head}`));
5437
5478
  }
5438
5479
 
5439
5480
  // src/init/index.ts
5440
- function registerInitCommand(program2, registryUrl = DEFAULT_REGISTRY_URL) {
5481
+ function registerInitCommand(program2, registryUrl = DEFAULT_REGISTRY_URL, deps = {}) {
5441
5482
  program2.command("init").description("\uD504\uB85C\uC81D\uD2B8\uC5D0 AXIS Design System \uCD08\uAE30\uD654").option("-y, --yes", "\uAE30\uBCF8\uAC12\uC73C\uB85C \uC790\uB3D9 \uC124\uC815").action(async (options) => {
5442
5483
  console.log(chalk11.blue("\n\u{1F3A8} AXIS Design System \uCD08\uAE30\uD654\n"));
5443
5484
  const baseDir = process.cwd();
5444
5485
  const tailwind4 = isTailwind4(planUtilsDependencies(baseDir).tailwind);
5445
5486
  const resolved = await resolveInitAnswers(baseDir, tailwind4);
5446
5487
  for (const note of resolved.notes) console.log(note.startsWith("!") ? chalk11.yellow(note) : chalk11.gray(note));
5447
- const config = options.yes ? { ...resolved.answers } : await prompts2([
5488
+ const interactive = (deps.isInteractive ?? isInteractive)();
5489
+ if (!options.yes && !interactive) {
5490
+ const a = resolved.answers;
5491
+ const values = [`componentsDir=${a.componentsDir}`, ...tailwind4 ? [] : [`tailwindConfig=${a.tailwindConfig}`], `globalCss=${a.globalCss}`];
5492
+ noteDefault(`\uAE30\uBCF8\uAC12\uC73C\uB85C \uC9C4\uD589\uD569\uB2C8\uB2E4(-y \uC640 \uAC19\uC74C): ${values.join(", ")}`);
5493
+ }
5494
+ const config = options.yes || !interactive ? { ...resolved.answers } : await ask([
5448
5495
  {
5449
5496
  type: "text",
5450
5497
  name: "componentsDir",
@@ -5463,14 +5510,13 @@ function registerInitCommand(program2, registryUrl = DEFAULT_REGISTRY_URL) {
5463
5510
  message: "\uAE00\uB85C\uBC8C CSS \uD30C\uC77C:",
5464
5511
  initial: resolved.answers.globalCss
5465
5512
  }
5466
- ]);
5467
- await runInit(baseDir, config, registryUrl);
5513
+ ], interactive);
5514
+ await runInit(baseDir, config, registryUrl, console.log, { allowOverwrite: options.yes === true || interactive });
5468
5515
  });
5469
5516
  }
5470
5517
 
5471
5518
  // src/add/index.ts
5472
5519
  import chalk12 from "chalk";
5473
- import prompts3 from "prompts";
5474
5520
 
5475
5521
  // ../axis-registry-core/src/add/add.ts
5476
5522
  import { existsSync as existsSync8, readFileSync as readFileSync8, statSync as statSync5 } from "fs";
@@ -6535,7 +6581,7 @@ function configRegistryRejectedMessage(url, problem) {
6535
6581
  function createConfirm(interactive) {
6536
6582
  if (!interactive) return void 0;
6537
6583
  return async (message) => {
6538
- const { overwrite } = await prompts3({ type: "confirm", name: "overwrite", message, initial: false });
6584
+ const { overwrite } = await ask({ type: "confirm", name: "overwrite", message, initial: false }, interactive);
6539
6585
  return overwrite === true;
6540
6586
  };
6541
6587
  }
@@ -6543,7 +6589,7 @@ var defaultCreateClient = (cwd) => createClientFor(cwd, (m) => console.warn(chal
6543
6589
  function registerAddCommand(program2, deps = {}) {
6544
6590
  program2.command("add <components...>").description("\uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC758 \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uD504\uB85C\uC81D\uD2B8\uC5D0 \uBCF5\uC0AC(registryDependencies \uD3EC\uD568)").option("--agentic", "\uC774\uB984 \uC55E\uC5D0 agentic- \uB97C \uBD99\uC5EC \uCC3E\uC74C(\uC804\uCCB4 \uC774\uB984\uB3C4 \uD5C8\uC6A9)").option("-y, --yes", "\uBB3B\uC9C0 \uC54A\uACE0 \uC9C4\uD589. \uB0B4\uC6A9\uC774 \uB2E4\uB978 \uAE30\uC874 \uD30C\uC77C\uC740 \uAC74\uB108\uB700").option("--overwrite", "\uB0B4\uC6A9\uC774 \uB2E4\uB978 \uAE30\uC874 \uD30C\uC77C\uC744 \uB36E\uC5B4\uC500").action(async (components, options) => {
6545
6591
  const client = await (deps.createClient ?? defaultCreateClient)(process.cwd());
6546
- const confirm = createConfirm((deps.isInteractive ?? (() => process.stdin.isTTY === true))());
6592
+ const confirm = createConfirm((deps.isInteractive ?? isInteractive)());
6547
6593
  const result = await runAdd(process.cwd(), components, options, {
6548
6594
  client,
6549
6595
  log: (...a) => console.log(...a),
@@ -6786,4 +6832,10 @@ registerSyncCommand(program);
6786
6832
  registerTemplateCommand(program);
6787
6833
  registerCheckCommand(program);
6788
6834
  registerThemeCommand(program);
6789
- program.parse();
6835
+ try {
6836
+ await program.parseAsync();
6837
+ } catch (err) {
6838
+ if (!(err instanceof NonInteractiveError)) throw err;
6839
+ console.error(chalk13.red(err.message));
6840
+ process.exitCode = 1;
6841
+ }
package/dist/monet.d.ts CHANGED
@@ -82,7 +82,10 @@ declare class MonetClient {
82
82
  searchComponents(query: string): Promise<void>;
83
83
  browseCategory(category: string): Promise<void>;
84
84
  private getCategoryExamples;
85
- importFromClipboard(): Promise<void>;
85
+ /** opts.interactive: 질문을 띄울 수 있는지(WI-0075). 없으면 stdin 이 TTY 인지로 정합니다 */
86
+ importFromClipboard(opts?: {
87
+ interactive?: boolean;
88
+ }): Promise<void>;
86
89
  }
87
90
  declare function getMonetUrl(path: string): string;
88
91
  declare function getMonetMcpConfig(): object;
package/dist/monet.js CHANGED
@@ -3,7 +3,8 @@ import {
3
3
  MonetClient,
4
4
  getMonetMcpConfig,
5
5
  getMonetUrl
6
- } from "./chunk-ZVVACWEW.js";
6
+ } from "./chunk-LVMDBOXD.js";
7
+ import "./chunk-HFMMK6R4.js";
7
8
  export {
8
9
  MONET_CATEGORIES,
9
10
  MonetClient,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "axis",
3
3
  "homepage": "https://axis-design-system.pages.dev",
4
- "version": "1.8.0",
4
+ "version": "1.8.1",
5
5
  "items": [
6
6
  {
7
7
  "name": "utils",
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://ui.shadcn.com/schema/registry.json",
3
3
  "name": "axis",
4
4
  "homepage": "https://axis-design-system.pages.dev",
5
- "version": "1.8.0",
5
+ "version": "1.8.1",
6
6
  "items": [
7
7
  {
8
8
  "name": "utils",
package/dist/v0.d.ts CHANGED
@@ -8,19 +8,23 @@
8
8
  * npx @axis-ds/cli v0 import <url> # V0 URL에서 가져오기
9
9
  * npx @axis-ds/cli v0 setup # GitHub 연동 안내
10
10
  */
11
+ /** 질문을 띄울 수 있는지(WI-0075). 없으면 stdin 이 TTY 인지로 정합니다 */
12
+ interface V0PromptOptions {
13
+ interactive?: boolean;
14
+ }
11
15
  declare class V0Client {
12
16
  convertCode(code: string, options?: {
13
17
  preserveImports?: boolean;
14
18
  }): Promise<string>;
15
19
  convertFile(filePath: string, outputPath?: string): Promise<void>;
16
20
  private showConversionSummary;
17
- importFromUrl(): Promise<void>;
21
+ importFromUrl(opts?: V0PromptOptions): Promise<void>;
18
22
  setupGitHubSync(): Promise<void>;
19
- convertFromZip(): Promise<void>;
20
- convertFromClipboard(): Promise<void>;
23
+ convertFromZip(opts?: V0PromptOptions): Promise<void>;
24
+ convertFromClipboard(opts?: V0PromptOptions): Promise<void>;
21
25
  showGuide(): void;
22
26
  }
23
27
  declare function getV0Url(path?: string): string;
24
28
  declare function isV0Code(code: string): boolean;
25
29
 
26
- export { V0Client, getV0Url, isV0Code };
30
+ export { V0Client, type V0PromptOptions, getV0Url, isV0Code };
package/dist/v0.js CHANGED
@@ -2,7 +2,8 @@ import {
2
2
  V0Client,
3
3
  getV0Url,
4
4
  isV0Code
5
- } from "./chunk-NNFSJISD.js";
5
+ } from "./chunk-2PNCUPCG.js";
6
+ import "./chunk-HFMMK6R4.js";
6
7
  export {
7
8
  V0Client,
8
9
  getV0Url,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axis-ds/cli",
3
- "version": "1.6.2",
3
+ "version": "1.7.0",
4
4
  "type": "module",
5
5
  "description": "AXIS Design System - CLI for adding components (shadcn compatible)",
6
6
  "publishConfig": {