sh-ui-cli 0.96.3 → 0.98.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
@@ -22,7 +22,7 @@ npx sh-ui-cli create
22
22
 
23
23
  # 비대화형 (에이전트 / CI)
24
24
  npx sh-ui-cli create my-app --platform next --structure standalone --yes
25
- npx sh-ui-cli create my-app --platform next --structure monorepo --plugins sentry,next-intl,auth-jwt --yes
25
+ npx sh-ui-cli create my-app --platform next --structure monorepo --plugins next-intl --yes
26
26
  npx sh-ui-cli create my-app --platform flutter --yes
27
27
  ```
28
28
 
@@ -2,6 +2,32 @@
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.98.0",
7
+ "date": "2026-05-16",
8
+ "title": "auth-jwt · sentry 플러그인 제거 — 스캐폴더에서 두 통합 완전 삭제 (breaking)",
9
+ "type": "minor",
10
+ "highlights": [
11
+ "**`sentry` 플러그인 + `--observability` 옵션 제거 (breaking)** — Next 의 `--plugins sentry` 와 vite 전용 `--observability sentry` 를 둘 다 삭제. `sh_ui_create_project` · `sh_ui_add_app` · `sh_ui_describe_template` 의 `observability` 인자, `DescribeTemplateOptions.observability` 타입, `emitSentry()` 도 함께 제거. 이제 `--observability` 는 '알 수 없는 플래그', `--plugins sentry` 는 '알 수 없는 플러그인' 으로 거부된다.",
12
+ "**`auth-jwt` 플러그인 제거 (breaking)** — `--plugins auth-jwt` 및 auth-jwt+next-intl proxy.ts 병합 로직 삭제. `next-intl` 단독 scaffold 는 자체 proxy.ts 를 그대로 emit (회귀 가드 smoke 유지).",
13
+ "**유지: i18n / next-intl** — `--plugins next-intl` 과 vite `--i18n react-i18next` / `--locales` 는 그대로. 스캐폴더 플러그인은 이제 `next-intl` 단일. Sentry/JWT 는 프로젝트마다 설정이 갈려 baked-in scaffold 가치가 낮고, 특히 Sentry 의 Next 통합은 버전 churn 유지보수 부채라 의도적으로 축소.",
14
+ "**마이그레이션** — Sentry 가 필요하면 생성 후 공식 `@sentry/nextjs` 또는 `@sentry/react` 를 직접 추가. 인증은 프로젝트 백엔드 명세에 맞춰 직접 구성. docs `/plugins/sentry`·`/plugins/auth-jwt` 페이지 및 `/create` UI 토글 제거, smoke 시나리오 정리."
15
+ ],
16
+ "url": "https://github.com/sanghyeonKim0201/sh-ui/releases/tag/v0.98.0"
17
+ },
18
+ {
19
+ "version": "0.97.0",
20
+ "date": "2026-05-16",
21
+ "title": "Tauri 통합 제거 — 스캐폴더에서 src-tauri/ shell 및 --tauri 옵션 삭제 (breaking)",
22
+ "type": "minor",
23
+ "highlights": [
24
+ "**`--tauri` / MCP `tauri` 옵션 제거 (breaking)** — `sh-ui-cli create` / `add-app` 의 `--tauri` 플래그, `sh_ui_create_project` · `sh_ui_add_app` · `sh_ui_describe_template` 의 `tauri` 인자, `DescribeTemplateOptions.tauri` 타입을 모두 삭제. 이제 `--tauri` 는 '알 수 없는 플래그' 에러로 거부된다.",
25
+ "**`tauri-shell` 템플릿 + `emitTauri`/`patchViteForTauri` 삭제** — `src-tauri/` (Cargo.toml·tauri.conf.json·Rust 소스) 를 더 이상 emit 하지 않는다. `@tauri-apps/*` 의존성·`tauri:dev`/`tauri:build` scripts·`src-tauri/target/` gitignore 주입도 제거. Tauri 가 필요하면 공식 `@tauri-apps/cli init` 을 직접 쓰면 된다 (vite 의 `dist/` 표준 산출물과 그대로 호환).",
26
+ "**docs `/create` UI 정리** — Tauri 데스크탑 셸 토글 제거, `/api/template-content` 의 src-tauri resolve 분기 삭제. vite 의 mobile/PWA 친화 디폴트(`viewport-fit=cover`·`theme-color`·webview reset)는 그대로 유지 — Tauri 전용이 아니라 일반 모바일 하드닝이라 보존.",
27
+ "**smoke 정리** — tauri 전용 시나리오(V7a–f, V12–14) 삭제, all-options 가드(V20a)는 i18n+sentry 조합으로 축소 유지. 마이그레이션: `--tauri` 쓰던 사용자는 플래그를 빼고 생성 후 `@tauri-apps/cli init` 으로 desktop shell 을 별도 추가."
28
+ ],
29
+ "url": "https://github.com/sanghyeonKim0201/sh-ui/releases/tag/v0.97.0"
30
+ },
5
31
  {
6
32
  "version": "0.96.3",
7
33
  "date": "2026-05-16",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sh-ui-cli",
3
- "version": "0.96.3",
3
+ "version": "0.98.0",
4
4
  "description": "sh-ui CLI — 프로젝트 스캐폴드(create) + 컴포넌트 추가(add/list/remove) + IDE-내 AI용 MCP 서버",
5
5
  "license": "MIT",
6
6
  "repository": {
package/src/api.d.ts CHANGED
@@ -139,14 +139,10 @@ export interface DescribeTemplateOptions {
139
139
  projectName?: string;
140
140
  /** monorepo 첫 앱 이름. 기본 'web'. */
141
141
  appName?: string;
142
- /** platform=vite + structure=standalone 일 때 Tauri 2.x 셸(`src-tauri/`) 동시 emit. */
143
- tauri?: boolean;
144
142
  /** vite 전용 — react-i18next opt-in. v0.92.0+ */
145
143
  i18n?: 'none' | 'react-i18next';
146
144
  /** i18n 활성화 시 생성할 locale 코드 (comma-separated). 기본 'ko,en' */
147
145
  locales?: string;
148
- /** vite 전용 — Sentry observability opt-in. v0.93.0+ */
149
- observability?: 'none' | 'sentry';
150
146
  }
151
147
 
152
148
  export interface DescribeTemplateGroup {
package/src/constants.js CHANGED
@@ -60,8 +60,3 @@ export const INIT_DEFAULTS = {
60
60
  export const I18N_LIBRARIES = ['none', 'react-i18next'];
61
61
  export const I18N_DEFAULT = 'none';
62
62
  export const I18N_DEFAULT_LOCALES = 'ko,en';
63
-
64
- // ─── observability (vite preset 전용 — v0.93.0+) ───
65
- // 'none' 디폴트 — opt-in 으로 @sentry/react + @sentry/vite-plugin 설치 + 셋업.
66
- // GlitchTip self-hosted 도 같은 SDK — DSN 만 변경. 향후 bugsnag 등 추가 시 enum 확장.
67
- export const OBSERVABILITY_PROVIDERS = ['none', 'sentry'];
@@ -4,7 +4,6 @@ import {
4
4
  CSS_FRAMEWORKS_SUPPORTED,
5
5
  CSS_FRAMEWORKS_PLANNED,
6
6
  I18N_LIBRARIES,
7
- OBSERVABILITY_PROVIDERS,
8
7
  } from '../constants.js';
9
8
  import { allPlugins } from './plugins/index.js';
10
9
  import { allArchitectures } from './architectures/index.js';
@@ -14,8 +13,8 @@ const VALID_STRUCTURES = CREATE_STRUCTURES;
14
13
  const VALID_PLUGINS = allPlugins.map((p) => p.name);
15
14
  const VALID_ARCHES = allArchitectures.map((a) => a.name);
16
15
 
17
- const VALUE_FLAGS = ['platform', 'structure', 'plugins', 'theme', 'app', 'css', 'arch', 'port', 'i18n', 'locales', 'observability'];
18
- const BOOL_FLAGS = ['yes', 'help', 'dry-run', 'tauri'];
16
+ const VALUE_FLAGS = ['platform', 'structure', 'plugins', 'theme', 'app', 'css', 'arch', 'port', 'i18n', 'locales'];
17
+ const BOOL_FLAGS = ['yes', 'help', 'dry-run'];
19
18
 
20
19
  const SUBCOMMANDS = ['add-app', 'add-component'];
21
20
 
@@ -80,9 +79,6 @@ export const parseArgs = (argv) => {
80
79
  if (name === 'i18n' && !I18N_LIBRARIES.includes(value)) {
81
80
  throw new Error(`--i18n 은 ${I18N_LIBRARIES.join('/')} 중 하나여야 함 (받은 값: ${value})`);
82
81
  }
83
- if (name === 'observability' && !OBSERVABILITY_PROVIDERS.includes(value)) {
84
- throw new Error(`--observability 는 ${OBSERVABILITY_PROVIDERS.join('/')} 중 하나여야 함 (받은 값: ${value})`);
85
- }
86
82
  if (name === 'css' && !CSS_FRAMEWORKS_SUPPORTED.includes(value)) {
87
83
  // planned 값은 '곧 옵니다' 신호로 분기 — 사용자 의도가 더 명확히 전달.
88
84
  if (CSS_FRAMEWORKS_PLANNED.includes(value)) {
@@ -31,14 +31,12 @@ import { CSS_FRAMEWORK_DEFAULT } from '../constants.js';
31
31
  * @property {'next'|'flutter'|'vite'} [platform]
32
32
  * @property {'standalone'|'monorepo'} [structure] next/vite 일 때만 의미
33
33
  * @property {string} [arch] next 일 때 'fsd'|'flat'|'mes'
34
- * @property {string[]} [plugins] ['sentry', 'next-intl', 'auth-jwt']
34
+ * @property {string[]} [plugins] ['next-intl']
35
35
  * @property {'tailwind'|'plain'|'css-modules'} [cssFramework]
36
36
  * @property {string} [projectName]
37
37
  * @property {string} [appName] monorepo 첫 앱 이름. 기본 'web'
38
- * @property {boolean} [tauri] platform=vite (standalone/monorepo 둘 다) 일 때 Tauri 2.x 셸 같이 emit
39
38
  * @property {'none'|'react-i18next'} [i18n] vite 전용 — react-i18next 셋업
40
39
  * @property {string} [locales] i18n 활성화 시 생성할 locale 코드 (comma-separated, default 'ko,en')
41
- * @property {'none'|'sentry'} [observability] vite 전용 — Sentry 셋업 (v0.93.0+)
42
40
  */
43
41
 
44
42
  /**
@@ -66,10 +64,8 @@ export function describeTemplate(opts = {}) {
66
64
  plugins: pluginNames = [],
67
65
  cssFramework = CSS_FRAMEWORK_DEFAULT,
68
66
  appName: rawAppName = 'web',
69
- tauri = false,
70
67
  i18n = 'none',
71
68
  locales = 'ko,en',
72
- observability = 'none',
73
69
  } = opts;
74
70
 
75
71
  if (platform === 'flutter') {
@@ -97,14 +93,6 @@ export function describeTemplate(opts = {}) {
97
93
  makeGroup('base', '베이스 (vite-standalone)', baseFiles),
98
94
  makeGroup('arch', `Arch (${safeArchName})`, archFiles),
99
95
  ];
100
- if (tauri) {
101
- const tauriTpl = TEMPLATE_MANIFEST['tauri-shell'];
102
- if (!tauriTpl) {
103
- throw new Error("Template manifest missing entry for 'tauri-shell'.");
104
- }
105
- const tauriFiles = tauriTpl.base.map((p) => `src-tauri/${p}`);
106
- groups.push(makeGroup('tauri', 'Tauri 셸 (src-tauri/)', tauriFiles));
107
- }
108
96
  if (i18n === 'react-i18next') {
109
97
  const isFsd = safeArchName === 'fsd';
110
98
  const i18nBase = isFsd ? 'src/shared/i18n' : 'src/lib/i18n';
@@ -118,17 +106,6 @@ export function describeTemplate(opts = {}) {
118
106
  ];
119
107
  groups.push(makeGroup('i18n', `i18n (${i18n})`, i18nFiles));
120
108
  }
121
- if (observability === 'sentry') {
122
- const isFsd = safeArchName === 'fsd';
123
- const obsBase = isFsd ? 'src/shared/observability' : 'src/lib/observability';
124
- const providersBase = isFsd ? 'src/app/providers' : 'src/components/providers';
125
- groups.push(makeGroup('sentry', `Sentry observability`, [
126
- `${obsBase}/sentry.ts`,
127
- `${obsBase}/index.ts`,
128
- `${providersBase}/SentryProvider.tsx`,
129
- '.env.example',
130
- ]));
131
- }
132
109
  return finalize(groups);
133
110
  }
134
111
 
@@ -170,15 +147,6 @@ export function describeTemplate(opts = {}) {
170
147
  ),
171
148
  ));
172
149
 
173
- if (tauri) {
174
- const tauriTpl = TEMPLATE_MANIFEST['tauri-shell'];
175
- if (!tauriTpl) {
176
- throw new Error("Template manifest missing entry for 'tauri-shell'.");
177
- }
178
- const tauriFiles = tauriTpl.base.map((p) => `apps/${appName}/src-tauri/${p}`);
179
- groups.push(makeGroup('tauri', `Tauri 셸 (apps/${appName}/src-tauri/)`, tauriFiles));
180
- }
181
-
182
150
  if (i18n === 'react-i18next') {
183
151
  const isFsd = safeArchName === 'fsd';
184
152
  const i18nBase = isFsd ? 'src/shared/i18n' : 'src/lib/i18n';
@@ -193,18 +161,6 @@ export function describeTemplate(opts = {}) {
193
161
  groups.push(makeGroup('i18n', `i18n (${i18n}, apps/${appName}/)`, i18nFiles));
194
162
  }
195
163
 
196
- if (observability === 'sentry') {
197
- const isFsd = safeArchName === 'fsd';
198
- const obsBase = isFsd ? 'src/shared/observability' : 'src/lib/observability';
199
- const providersBase = isFsd ? 'src/app/providers' : 'src/components/providers';
200
- groups.push(makeGroup('sentry', `Sentry observability (apps/${appName}/)`, [
201
- `apps/${appName}/${obsBase}/sentry.ts`,
202
- `apps/${appName}/${obsBase}/index.ts`,
203
- `apps/${appName}/${providersBase}/SentryProvider.tsx`,
204
- `apps/${appName}/.env.example`,
205
- ]));
206
- }
207
-
208
164
  return finalize(groups);
209
165
  }
210
166
 
@@ -299,13 +255,9 @@ function buildNextGroups({ prefix, templateKey, arch, plugins, cssFramework }) {
299
255
  // generator.js applyCssFrameworkVariant 와 동일한 분기 — intl 활성 시 [locale]/, 아니면 app/.
300
256
  if (cssFramework === 'css-modules') {
301
257
  const intlActive = plugins.some((p) => p.name === 'next-intl');
302
- const sentryActive = plugins.some((p) => p.name === 'sentry');
303
258
  const cssPaths = [];
304
259
  const pageDir = intlActive ? 'app/[locale]' : 'app';
305
260
  cssPaths.push(`${prefix}${pageDir}/page.module.css`);
306
- if (sentryActive) {
307
- cssPaths.push(`${prefix}${pageDir}/error.module.css`);
308
- }
309
261
  groups.push(makeGroup(
310
262
  'css',
311
263
  'CSS: css-modules 변종',
@@ -356,7 +308,7 @@ function applyMovesAndDeletes(groups, moves, deletes) {
356
308
  const added = [];
357
309
  for (const { from, to } of moves) {
358
310
  const removed = removeFromAllGroups(groups, from);
359
- // 원본이 어디에도 없었다면 (예: sentry 비활성 상태에서 error.tsx 이동) — 새로
311
+ // 원본이 어디에도 없었다면 (move 소스가 현재 file-plan 없음) — 새로
360
312
  // 추가하지 않는다. generator.js 의 `if (await fs.pathExists(fromPath))` 시맨틱.
361
313
  if (removed) added.push(to);
362
314
  }
@@ -426,7 +378,7 @@ function finalize(groups) {
426
378
  * 현재 규칙:
427
379
  * - basename 이 정확히 'gitignore' 인 경로 → '.gitignore' 로 prefix dot 추가.
428
380
  * (npm publish 가 .gitignore 를 strip 하므로 템플릿엔 점 없이 두고 emit 후 dot-prefix.)
429
- * - 이미 '.gitignore' 인 경로 (예: tauri-shell 의 src-tauri/.gitignore) 는 그대로.
381
+ * - 이미 '.gitignore' 인 경로는 그대로.
430
382
  *
431
383
  * 미래에 다른 fs-level rename 이 추가되면 여기에 같이 등록 (describeTemplate 의
432
384
  * file-plan ↔ create_project 의 실제 emit 1:1 정합성 유지).