sh-ui-cli 0.40.0 → 0.41.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.
@@ -2,6 +2,19 @@
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.41.0",
7
+ "date": "2026-04-30",
8
+ "title": "sh-ui create — git 자동 초기화 + .gitignore 자동 생성",
9
+ "type": "minor",
10
+ "highlights": [
11
+ "**`sh-ui create` 직후 `git init` 자동 실행** — 별도 명령 없이 바로 첫 커밋 가능한 상태. git 미설치 등 실패 시는 조용히 스킵 (스캐폴드 자체는 성공)",
12
+ "**`.gitignore` 자동 생성** — Next.js standalone / monorepo / Flutter 각 템플릿에 맞는 ignore 패턴 동봉. 모노레포는 `.turbo` `.vercel`, Flutter 는 `.dart_tool/` `**/ios/Flutter/.last_build_id` 등 플랫폼 표준 패턴 + `.claude/settings.local.json` 공통",
13
+ "**npm strip 우회** — npm publish 가 패키지 내 `.gitignore` 를 자동 strip 하던 이슈를 템플릿 파일명 `gitignore` (no-dot) → 스캐폴드 시 `.gitignore` 로 리네이밍하는 방식으로 해결",
14
+ "dry-run 모드는 git init / 파일 쓰기 모두 우회 (기존 동작 유지)"
15
+ ],
16
+ "url": "https://github.com/sanghyeonKim0201/sh-ui/releases/tag/v0.41.0"
17
+ },
5
18
  {
6
19
  "version": "0.40.0",
7
20
  "date": "2026-04-29",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sh-ui-cli",
3
- "version": "0.40.0",
3
+ "version": "0.41.0",
4
4
  "description": "sh-ui CLI — 프로젝트 스캐폴드(create) + 컴포넌트 추가(add/list/remove) + IDE-내 AI용 MCP 서버",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -115,6 +115,7 @@ export async function createProject(options = {}) {
115
115
 
116
116
  if (platform === 'flutter') {
117
117
  await generateFlutter(targetDir, projectName, theme);
118
+ await finalizeProject(targetDir, { dryRun: options.dryRun });
118
119
  console.log(`\n✅ ${projectName} Flutter 프로젝트가 생성되었습니다!`);
119
120
  console.log(`\n cd ${projectName}`);
120
121
  console.log(' flutter pub get');
@@ -144,6 +145,8 @@ export async function createProject(options = {}) {
144
145
  await generateMonorepo(targetDir, projectName, plugins, { yes: options.yes, theme });
145
146
  }
146
147
 
148
+ await finalizeProject(targetDir, { dryRun: options.dryRun });
149
+
147
150
  if (options.dryRun) {
148
151
  const files = await listAllFiles(targetDir);
149
152
  console.log(`\n[DRY RUN] ${projectName} 스캐폴드 시 작성될 파일 (${files.length}개):\n`);
@@ -416,6 +419,31 @@ async function generateApp(targetDir, appName, port, plugins) {
416
419
 
417
420
  // ─── Helpers ───
418
421
 
422
+ /**
423
+ * 스캐폴드 마무리 — `gitignore` 파일을 `.gitignore` 로 되돌리고 `git init` 실행.
424
+ *
425
+ * 왜 이름을 우회하는가: npm publish 는 패키지 안의 `.gitignore` 를 자동으로
426
+ * strip 한다(없으면 `.npmignore` fallback 으로 사용). 사용자에게 도착하지 않으니
427
+ * 템플릿엔 `gitignore` 로 두고 복사 직후 dot-prefix 를 붙인다.
428
+ *
429
+ * git init 은 dry-run 에서는 스킵하고, 실패해도(git 미설치 등) 조용히 넘어간다.
430
+ */
431
+ async function finalizeProject(targetDir, { dryRun = false } = {}) {
432
+ const noDot = path.join(targetDir, 'gitignore');
433
+ const withDot = path.join(targetDir, '.gitignore');
434
+ if (await fs.pathExists(noDot)) {
435
+ await fs.move(noDot, withDot, { overwrite: true });
436
+ }
437
+
438
+ if (dryRun) return;
439
+
440
+ try {
441
+ execSync('git init -q', { cwd: targetDir, stdio: 'ignore' });
442
+ } catch {
443
+ // git 미설치 / 권한 문제 — 스캐폴드 자체는 성공이므로 조용히 넘어간다.
444
+ }
445
+ }
446
+
419
447
  async function replaceInAllFiles(dir, search, replace) {
420
448
  const entries = await fs.readdir(dir, { withFileTypes: true });
421
449
  for (const entry of entries) {
@@ -0,0 +1,47 @@
1
+ # Miscellaneous
2
+ *.class
3
+ *.log
4
+ *.pyc
5
+ *.swp
6
+ .DS_Store
7
+ .atom/
8
+ .build/
9
+ .buildlog/
10
+ .history
11
+ .svn/
12
+ .swiftpm/
13
+ migrate_working_dir/
14
+
15
+ # IntelliJ related
16
+ *.iml
17
+ *.ipr
18
+ *.iws
19
+ .idea/
20
+
21
+ # VS Code
22
+ #.vscode/
23
+
24
+ # Flutter/Dart/Pub related
25
+ **/doc/api/
26
+ **/ios/Flutter/.last_build_id
27
+ .dart_tool/
28
+ .flutter-plugins
29
+ .flutter-plugins-dependencies
30
+ .pub-cache/
31
+ .pub/
32
+ /build/
33
+ /coverage/
34
+
35
+ # Symbolication
36
+ app.*.symbols
37
+
38
+ # Obfuscation
39
+ app.*.map.json
40
+
41
+ # Android build artifacts
42
+ /android/app/debug
43
+ /android/app/profile
44
+ /android/app/release
45
+
46
+ # Claude Code (개인 설정 제외, rules/는 공유)
47
+ .claude/settings.local.json
@@ -0,0 +1,44 @@
1
+ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2
+
3
+ # Dependencies
4
+ node_modules
5
+ .pnp
6
+ .pnp.js
7
+
8
+ # Local env files
9
+ .env
10
+ .env.local
11
+ .env.development.local
12
+ .env.test.local
13
+ .env.production.local
14
+
15
+ # Testing
16
+ coverage
17
+
18
+ # Turbo
19
+ .turbo
20
+
21
+ # Vercel
22
+ .vercel
23
+
24
+ # Build Outputs
25
+ .next/
26
+ out/
27
+ build
28
+ dist
29
+
30
+ # Debug
31
+ npm-debug.log*
32
+
33
+ # Sentry
34
+ .env.sentry-build-plugin
35
+
36
+ # Misc
37
+ .DS_Store
38
+ *.pem
39
+
40
+ # IDE
41
+ .idea/
42
+
43
+ # Claude Code (개인 설정 제외, rules/는 공유)
44
+ .claude/settings.local.json
@@ -0,0 +1,42 @@
1
+ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2
+
3
+ # Dependencies
4
+ node_modules
5
+ .pnp
6
+ .pnp.js
7
+
8
+ # Local env files
9
+ .env
10
+ .env.local
11
+ .env.development.local
12
+ .env.test.local
13
+ .env.production.local
14
+
15
+ # Testing
16
+ coverage
17
+
18
+ # Vercel
19
+ .vercel
20
+
21
+ # Build Outputs
22
+ .next/
23
+ out/
24
+ build
25
+ dist
26
+
27
+ # Debug
28
+ npm-debug.log*
29
+
30
+ # Sentry
31
+ .env.sentry-build-plugin
32
+
33
+ # Misc
34
+ .DS_Store
35
+ *.pem
36
+
37
+ # IDE
38
+ .idea/
39
+ .vscode/
40
+
41
+ # Claude Code (개인 설정 제외, rules/는 공유)
42
+ .claude/settings.local.json