@kood/claude-code 0.1.6 → 0.1.9
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/dist/index.js +109 -216
- package/package.json +8 -2
- package/templates/hono/CLAUDE.md +59 -328
- package/templates/hono/docs/architecture/architecture.md +93 -747
- package/templates/hono/docs/deployment/cloudflare.md +59 -513
- package/templates/hono/docs/deployment/docker.md +41 -356
- package/templates/hono/docs/deployment/index.md +54 -190
- package/templates/hono/docs/deployment/railway.md +36 -306
- package/templates/hono/docs/deployment/vercel.md +49 -434
- package/templates/hono/docs/library/ai-sdk/index.md +53 -290
- package/templates/hono/docs/library/ai-sdk/openrouter.md +19 -387
- package/templates/hono/docs/library/ai-sdk/providers.md +28 -394
- package/templates/hono/docs/library/ai-sdk/streaming.md +52 -353
- package/templates/hono/docs/library/ai-sdk/structured-output.md +63 -395
- package/templates/hono/docs/library/ai-sdk/tools.md +62 -431
- package/templates/hono/docs/library/hono/env-setup.md +24 -313
- package/templates/hono/docs/library/hono/error-handling.md +34 -295
- package/templates/hono/docs/library/hono/index.md +29 -121
- package/templates/hono/docs/library/hono/middleware.md +21 -188
- package/templates/hono/docs/library/hono/rpc.md +40 -341
- package/templates/hono/docs/library/hono/validation.md +35 -195
- package/templates/hono/docs/library/pino/index.md +42 -333
- package/templates/hono/docs/library/prisma/cloudflare-d1.md +64 -367
- package/templates/hono/docs/library/prisma/config.md +19 -260
- package/templates/hono/docs/library/prisma/index.md +67 -320
- package/templates/hono/docs/library/zod/index.md +53 -257
- package/templates/npx/CLAUDE.md +62 -274
- package/templates/npx/docs/references/patterns.md +160 -0
- package/templates/tanstack-start/CLAUDE.md +100 -256
- package/templates/tanstack-start/docs/architecture/architecture.md +44 -589
- package/templates/tanstack-start/docs/deployment/cloudflare.md +37 -424
- package/templates/tanstack-start/docs/deployment/index.md +57 -286
- package/templates/tanstack-start/docs/deployment/nitro.md +36 -318
- package/templates/tanstack-start/docs/deployment/railway.md +40 -409
- package/templates/tanstack-start/docs/deployment/vercel.md +43 -465
- package/templates/tanstack-start/docs/design/components.md +77 -311
- package/templates/tanstack-start/docs/design/index.md +113 -69
- package/templates/tanstack-start/docs/design/safe-area.md +51 -250
- package/templates/tanstack-start/docs/design/tailwind-setup.md +45 -359
- package/templates/tanstack-start/docs/guides/conventions.md +103 -0
- package/templates/tanstack-start/docs/guides/env-setup.md +34 -340
- package/templates/tanstack-start/docs/guides/getting-started.md +22 -209
- package/templates/tanstack-start/docs/guides/hooks.md +166 -0
- package/templates/tanstack-start/docs/guides/routes.md +166 -0
- package/templates/tanstack-start/docs/guides/services.md +143 -0
- package/templates/tanstack-start/docs/library/better-auth/2fa.md +27 -115
- package/templates/tanstack-start/docs/library/better-auth/advanced.md +22 -105
- package/templates/tanstack-start/docs/library/better-auth/index.md +17 -66
- package/templates/tanstack-start/docs/library/better-auth/plugins.md +11 -88
- package/templates/tanstack-start/docs/library/better-auth/session.md +12 -92
- package/templates/tanstack-start/docs/library/better-auth/setup.md +9 -91
- package/templates/tanstack-start/docs/library/prisma/cloudflare-d1.md +30 -358
- package/templates/tanstack-start/docs/library/prisma/config.md +27 -327
- package/templates/tanstack-start/docs/library/prisma/crud.md +46 -174
- package/templates/tanstack-start/docs/library/prisma/index.md +23 -113
- package/templates/tanstack-start/docs/library/prisma/relations.md +31 -153
- package/templates/tanstack-start/docs/library/prisma/schema.md +40 -217
- package/templates/tanstack-start/docs/library/prisma/setup.md +12 -112
- package/templates/tanstack-start/docs/library/prisma/transactions.md +20 -110
- package/templates/tanstack-start/docs/library/tanstack-query/index.md +26 -97
- package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +28 -107
- package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +44 -146
- package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +33 -127
- package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +49 -149
- package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +19 -112
- package/templates/tanstack-start/docs/library/tanstack-start/index.md +33 -80
- package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +28 -106
- package/templates/tanstack-start/docs/library/tanstack-start/routing.md +21 -118
- package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +34 -246
- package/templates/tanstack-start/docs/library/tanstack-start/setup.md +6 -39
- package/templates/tanstack-start/docs/library/zod/complex-types.md +32 -156
- package/templates/tanstack-start/docs/library/zod/index.md +31 -144
- package/templates/tanstack-start/docs/library/zod/transforms.md +20 -129
- package/templates/tanstack-start/docs/library/zod/validation.md +39 -155
- package/templates/hono/docs/commands/git.md +0 -145
- package/templates/hono/docs/mcp/context7.md +0 -106
- package/templates/hono/docs/mcp/index.md +0 -176
- package/templates/hono/docs/mcp/sequential-thinking.md +0 -101
- package/templates/hono/docs/mcp/serena.md +0 -269
- package/templates/hono/docs/mcp/sgrep.md +0 -105
- package/templates/hono/docs/skills/gemini-review/SKILL.md +0 -220
- package/templates/hono/docs/skills/gemini-review/references/checklists.md +0 -136
- package/templates/hono/docs/skills/gemini-review/references/prompt-templates.md +0 -303
- package/templates/npx/docs/commands/git.md +0 -145
- package/templates/npx/docs/mcp/index.md +0 -60
- package/templates/npx/docs/skills/gemini-review/SKILL.md +0 -220
- package/templates/npx/docs/skills/gemini-review/references/checklists.md +0 -134
- package/templates/npx/docs/skills/gemini-review/references/prompt-templates.md +0 -301
- package/templates/tanstack-start/docs/commands/git.md +0 -145
- package/templates/tanstack-start/docs/design/accessibility.md +0 -433
- package/templates/tanstack-start/docs/design/color.md +0 -235
- package/templates/tanstack-start/docs/design/spacing.md +0 -341
- package/templates/tanstack-start/docs/design/typography.md +0 -324
- package/templates/tanstack-start/docs/guides/best-practices.md +0 -950
- package/templates/tanstack-start/docs/guides/husky-lint-staged.md +0 -303
- package/templates/tanstack-start/docs/guides/prettier.md +0 -189
- package/templates/tanstack-start/docs/guides/project-templates.md +0 -710
- package/templates/tanstack-start/docs/library/tanstack-query/setup.md +0 -107
- package/templates/tanstack-start/docs/library/zod/basic-types.md +0 -186
- package/templates/tanstack-start/docs/mcp/context7.md +0 -204
- package/templates/tanstack-start/docs/mcp/index.md +0 -177
- package/templates/tanstack-start/docs/mcp/sequential-thinking.md +0 -180
- package/templates/tanstack-start/docs/mcp/serena.md +0 -269
- package/templates/tanstack-start/docs/mcp/sgrep.md +0 -174
- package/templates/tanstack-start/docs/skills/gemini-review/SKILL.md +0 -220
- package/templates/tanstack-start/docs/skills/gemini-review/references/checklists.md +0 -144
- package/templates/tanstack-start/docs/skills/gemini-review/references/prompt-templates.md +0 -292
package/templates/npx/CLAUDE.md
CHANGED
|
@@ -1,309 +1,97 @@
|
|
|
1
|
-
# CLAUDE.md -
|
|
1
|
+
# CLAUDE.md - NPX CLI 프로젝트
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Node.js CLI 도구 개발 지침
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## 🚨 STOP - 작업 전 필수 확인
|
|
5
|
+
## Instructions
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
│ 특히 ⛔ NEVER DO 섹션의 규칙은 절대 위반하지 마세요. │
|
|
13
|
-
│ │
|
|
14
|
-
│ 📖 작업 유형별 상세 문서: docs/ 폴더 참조 │
|
|
15
|
-
└─────────────────────────────────────────────────────────────┘
|
|
16
|
-
```
|
|
7
|
+
@docs/library/commander/index.md
|
|
8
|
+
@docs/library/fs-extra/index.md
|
|
9
|
+
@docs/library/prompts/index.md
|
|
17
10
|
|
|
18
11
|
---
|
|
19
12
|
|
|
20
|
-
##
|
|
13
|
+
## 금지 사항
|
|
21
14
|
|
|
22
|
-
### Git 커밋
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
❌ AI/봇이 작성했다는 어떤 표시도 금지
|
|
28
|
-
❌ 커밋 메시지 여러 줄 작성 금지
|
|
29
|
-
❌ 커밋 메시지에 이모지 사용 금지
|
|
30
|
-
```
|
|
15
|
+
### Git 커밋
|
|
16
|
+
- `Generated with Claude Code` 포함 금지
|
|
17
|
+
- AI 관련 이모지/표시 금지
|
|
18
|
+
- `Co-Authored-By:` 헤더 금지
|
|
19
|
+
- 여러 줄 커밋 메시지 금지
|
|
31
20
|
|
|
32
|
-
### CLI 구현
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
❌ 사용자 입력 검증 없이 처리 금지
|
|
39
|
-
```
|
|
21
|
+
### CLI 구현
|
|
22
|
+
- `process.exit()` 없이 에러 종료 금지
|
|
23
|
+
- `console.log` 직접 사용 금지 (logger 사용)
|
|
24
|
+
- 동기 파일 작업 (`fs.readFileSync` 등) 금지
|
|
25
|
+
- hardcoded 경로 금지 (`path.join` 사용)
|
|
26
|
+
- 사용자 입력 미검증 처리 금지
|
|
40
27
|
|
|
41
|
-
### 코드 검색
|
|
42
|
-
|
|
43
|
-
❌ grep, rg 등 기본 검색 도구 사용 금지
|
|
44
|
-
❌ find 명령어로 코드 검색 금지
|
|
45
|
-
✅ 코드베이스 검색 시 sgrep 사용 필수
|
|
46
|
-
```
|
|
28
|
+
### 코드 검색
|
|
29
|
+
- `grep`, `rg` 사용 금지 → `ast-grep` 필수
|
|
47
30
|
|
|
48
31
|
---
|
|
49
32
|
|
|
50
|
-
##
|
|
33
|
+
## 필수 사항
|
|
51
34
|
|
|
52
|
-
###
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
35
|
+
### 작업 전
|
|
36
|
+
| 작업 | 참조 문서 |
|
|
37
|
+
|------|----------|
|
|
38
|
+
| CLI 작업 | `docs/library/commander/` |
|
|
39
|
+
| 파일 작업 | `docs/library/fs-extra/` |
|
|
40
|
+
| 사용자 입력 | `docs/library/prompts/` |
|
|
58
41
|
|
|
59
|
-
###
|
|
42
|
+
### 커밋 형식
|
|
60
43
|
```
|
|
61
|
-
|
|
62
|
-
복잡한 분석/디버깅 → Sequential Thinking 사용
|
|
63
|
-
라이브러리 문서 → Context7 사용
|
|
44
|
+
<prefix>: <설명>
|
|
64
45
|
```
|
|
65
|
-
**상세**: `docs/mcp/` 참고
|
|
66
|
-
|
|
67
|
-
### 3. 작업 완료 후: Git 커밋
|
|
68
|
-
```bash
|
|
69
|
-
git add .
|
|
70
|
-
git commit -m "<prefix>: <설명>"
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
**커밋 형식**: `<prefix>: <설명>` (한 줄, 본문 없음)
|
|
74
46
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
```
|
|
47
|
+
| Prefix | 용도 |
|
|
48
|
+
|--------|------|
|
|
49
|
+
| feat | 새 기능 |
|
|
50
|
+
| fix | 버그 수정 |
|
|
51
|
+
| refactor | 리팩토링 |
|
|
52
|
+
| docs | 문서 수정 |
|
|
53
|
+
| chore | 빌드/설정 |
|
|
83
54
|
|
|
84
55
|
---
|
|
85
56
|
|
|
86
|
-
##
|
|
57
|
+
## Tech Stack
|
|
87
58
|
|
|
88
|
-
|
|
|
89
|
-
|
|
90
|
-
|
|
|
91
|
-
| **MCP 도구** | `docs/mcp/` | 🔴 필수 |
|
|
92
|
-
| **Commander** | `docs/library/commander/` | 🔴 필수 |
|
|
93
|
-
| **fs-extra** | `docs/library/fs-extra/` | 🔴 필수 |
|
|
94
|
-
| **prompts** | `docs/library/prompts/` | 🔴 필수 |
|
|
95
|
-
|
|
96
|
-
---
|
|
97
|
-
|
|
98
|
-
## 🛠 Tech Stack (버전 주의)
|
|
99
|
-
|
|
100
|
-
| 기술 | 버전 | 주의사항 |
|
|
101
|
-
|------|------|----------|
|
|
102
|
-
| Node.js | >= 18 | ESM 모듈 사용 |
|
|
59
|
+
| 기술 | 버전 | 비고 |
|
|
60
|
+
|------|------|------|
|
|
61
|
+
| Node.js | >= 18 | ESM 모듈 |
|
|
103
62
|
| TypeScript | 5.x | strict mode |
|
|
104
63
|
| Commander | 12.x | CLI 프레임워크 |
|
|
105
|
-
| fs-extra | 11.x | 파일 시스템
|
|
106
|
-
| prompts | 2.x | Interactive
|
|
107
|
-
| picocolors | 1.x | 터미널 색상
|
|
108
|
-
| tsup | 8.x |
|
|
64
|
+
| fs-extra | 11.x | 파일 시스템 |
|
|
65
|
+
| prompts | 2.x | Interactive prompts |
|
|
66
|
+
| picocolors | 1.x | 터미널 색상 |
|
|
67
|
+
| tsup | 8.x | 번들러 |
|
|
109
68
|
|
|
110
69
|
---
|
|
111
70
|
|
|
112
|
-
##
|
|
71
|
+
## Directory Structure
|
|
113
72
|
|
|
114
73
|
```
|
|
115
74
|
src/
|
|
116
|
-
├── index.ts
|
|
117
|
-
├── commands/
|
|
118
|
-
│ └── init.ts
|
|
119
|
-
├── utils/
|
|
120
|
-
│ ├── copy.ts
|
|
121
|
-
│ └── logger.ts
|
|
122
|
-
└── types/
|
|
123
|
-
└── index.ts # 공통 타입
|
|
124
|
-
|
|
125
|
-
templates/ # 템플릿 파일 (빌드 시 복사)
|
|
126
|
-
scripts/ # 빌드 스크립트
|
|
127
|
-
dist/ # 빌드 결과물
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
---
|
|
131
|
-
|
|
132
|
-
## 🔧 Code Conventions
|
|
133
|
-
|
|
134
|
-
### File Naming
|
|
135
|
-
- **kebab-case**: `copy-template.ts`, `file-utils.ts`
|
|
136
|
-
- **index.ts**: 모듈 진입점
|
|
137
|
-
|
|
138
|
-
### TypeScript
|
|
139
|
-
- `const` 선언 사용 (function 대신)
|
|
140
|
-
- 명시적 return type
|
|
141
|
-
- `interface` (객체) / `type` (유니온)
|
|
142
|
-
- `any` 금지 → `unknown` 사용
|
|
143
|
-
|
|
144
|
-
### ESM Module
|
|
145
|
-
```typescript
|
|
146
|
-
// ✅ ESM import
|
|
147
|
-
import fs from 'fs-extra';
|
|
148
|
-
import path from 'path';
|
|
149
|
-
import { fileURLToPath } from 'url';
|
|
150
|
-
|
|
151
|
-
// __dirname 대체
|
|
152
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
153
|
-
const __dirname = path.dirname(__filename);
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
---
|
|
157
|
-
|
|
158
|
-
## 📝 Quick Patterns (복사용)
|
|
159
|
-
|
|
160
|
-
### CLI Entry Point
|
|
161
|
-
```typescript
|
|
162
|
-
#!/usr/bin/env node
|
|
163
|
-
import { Command } from 'commander';
|
|
164
|
-
|
|
165
|
-
const program = new Command();
|
|
166
|
-
|
|
167
|
-
program
|
|
168
|
-
.name('my-cli')
|
|
169
|
-
.description('CLI description')
|
|
170
|
-
.version('1.0.0');
|
|
171
|
-
|
|
172
|
-
program
|
|
173
|
-
.option('-t, --template <name>', 'template name')
|
|
174
|
-
.option('-f, --force', 'overwrite existing files')
|
|
175
|
-
.action(async (options) => {
|
|
176
|
-
// 명령어 실행
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
program.parse();
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
### Logger 유틸
|
|
183
|
-
```typescript
|
|
184
|
-
import pc from 'picocolors';
|
|
185
|
-
|
|
186
|
-
export const logger = {
|
|
187
|
-
info: (msg: string) => console.log(pc.blue('ℹ'), msg),
|
|
188
|
-
success: (msg: string) => console.log(pc.green('✔'), msg),
|
|
189
|
-
warn: (msg: string) => console.log(pc.yellow('⚠'), msg),
|
|
190
|
-
error: (msg: string) => console.log(pc.red('✖'), msg),
|
|
191
|
-
step: (msg: string) => console.log(pc.gray(' →'), msg),
|
|
192
|
-
blank: () => console.log(),
|
|
193
|
-
};
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### Interactive Prompts
|
|
197
|
-
```typescript
|
|
198
|
-
import prompts from 'prompts';
|
|
199
|
-
|
|
200
|
-
// Select (단일 선택)
|
|
201
|
-
const { template } = await prompts({
|
|
202
|
-
type: 'select',
|
|
203
|
-
name: 'template',
|
|
204
|
-
message: 'Select a template:',
|
|
205
|
-
choices: [
|
|
206
|
-
{ title: 'Template A', value: 'a' },
|
|
207
|
-
{ title: 'Template B', value: 'b' },
|
|
208
|
-
],
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
// Multiselect (다중 선택)
|
|
212
|
-
const { templates } = await prompts({
|
|
213
|
-
type: 'multiselect',
|
|
214
|
-
name: 'templates',
|
|
215
|
-
message: 'Select templates:',
|
|
216
|
-
choices: [
|
|
217
|
-
{ title: 'Template A', value: 'a' },
|
|
218
|
-
{ title: 'Template B', value: 'b' },
|
|
219
|
-
],
|
|
220
|
-
min: 1,
|
|
221
|
-
hint: '- Space to select. Return to submit',
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
// Confirm
|
|
225
|
-
const { confirmed } = await prompts({
|
|
226
|
-
type: 'confirm',
|
|
227
|
-
name: 'confirmed',
|
|
228
|
-
message: 'Overwrite existing files?',
|
|
229
|
-
initial: false,
|
|
230
|
-
});
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
### File Copy 유틸
|
|
234
|
-
```typescript
|
|
235
|
-
import fs from 'fs-extra';
|
|
236
|
-
import path from 'path';
|
|
237
|
-
|
|
238
|
-
export const copyRecursive = async (
|
|
239
|
-
src: string,
|
|
240
|
-
dest: string,
|
|
241
|
-
): Promise<{ files: number; directories: number }> => {
|
|
242
|
-
const counter = { files: 0, directories: 0 };
|
|
243
|
-
|
|
244
|
-
const copy = async (s: string, d: string): Promise<void> => {
|
|
245
|
-
const stat = await fs.stat(s);
|
|
246
|
-
|
|
247
|
-
if (stat.isDirectory()) {
|
|
248
|
-
await fs.ensureDir(d);
|
|
249
|
-
counter.directories++;
|
|
250
|
-
|
|
251
|
-
const items = await fs.readdir(s);
|
|
252
|
-
for (const item of items) {
|
|
253
|
-
await copy(path.join(s, item), path.join(d, item));
|
|
254
|
-
}
|
|
255
|
-
} else {
|
|
256
|
-
await fs.copy(s, d);
|
|
257
|
-
counter.files++;
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
await copy(src, dest);
|
|
262
|
-
return counter;
|
|
263
|
-
};
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
### Package.json 설정
|
|
267
|
-
```json
|
|
268
|
-
{
|
|
269
|
-
"name": "@scope/my-cli",
|
|
270
|
-
"version": "1.0.0",
|
|
271
|
-
"type": "module",
|
|
272
|
-
"bin": "./dist/index.js",
|
|
273
|
-
"files": ["dist", "templates"],
|
|
274
|
-
"scripts": {
|
|
275
|
-
"build": "tsup",
|
|
276
|
-
"dev": "tsup --watch",
|
|
277
|
-
"prepublishOnly": "npm run build"
|
|
278
|
-
},
|
|
279
|
-
"engines": {
|
|
280
|
-
"node": ">=18"
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
### tsup.config.ts
|
|
286
|
-
```typescript
|
|
287
|
-
import { defineConfig } from 'tsup';
|
|
75
|
+
├── index.ts # CLI 진입점
|
|
76
|
+
├── commands/ # 명령어 모듈
|
|
77
|
+
│ └── init.ts
|
|
78
|
+
├── utils/ # 유틸리티
|
|
79
|
+
│ ├── copy.ts
|
|
80
|
+
│ └── logger.ts
|
|
81
|
+
└── types/ # 타입 정의
|
|
288
82
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
target: 'node18',
|
|
293
|
-
clean: true,
|
|
294
|
-
dts: true,
|
|
295
|
-
banner: {
|
|
296
|
-
js: '#!/usr/bin/env node',
|
|
297
|
-
},
|
|
298
|
-
});
|
|
83
|
+
templates/ # 템플릿 (빌드 시 복사)
|
|
84
|
+
scripts/ # 빌드 스크립트
|
|
85
|
+
dist/ # 빌드 결과물
|
|
299
86
|
```
|
|
300
87
|
|
|
301
88
|
---
|
|
302
89
|
|
|
303
|
-
##
|
|
90
|
+
## 참조
|
|
304
91
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
- [
|
|
309
|
-
|
|
92
|
+
| 문서 | 경로 |
|
|
93
|
+
|------|------|
|
|
94
|
+
| Commander 가이드 | [docs/library/commander/](docs/library/commander/index.md) |
|
|
95
|
+
| fs-extra 가이드 | [docs/library/fs-extra/](docs/library/fs-extra/index.md) |
|
|
96
|
+
| prompts 가이드 | [docs/library/prompts/](docs/library/prompts/index.md) |
|
|
97
|
+
| 코드 패턴 | [docs/references/patterns.md](docs/references/patterns.md) |
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# NPX CLI Patterns
|
|
2
|
+
|
|
3
|
+
> 복사용 코드 패턴 모음
|
|
4
|
+
|
|
5
|
+
## CLI Entry Point
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
#!/usr/bin/env node
|
|
9
|
+
import { Command } from 'commander';
|
|
10
|
+
|
|
11
|
+
const program = new Command();
|
|
12
|
+
|
|
13
|
+
program
|
|
14
|
+
.name('my-cli')
|
|
15
|
+
.description('CLI description')
|
|
16
|
+
.version('1.0.0');
|
|
17
|
+
|
|
18
|
+
program
|
|
19
|
+
.option('-t, --template <name>', 'template name')
|
|
20
|
+
.option('-f, --force', 'overwrite existing files')
|
|
21
|
+
.action(async (options) => {
|
|
22
|
+
// 명령어 실행
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
program.parse();
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Logger 유틸
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import pc from 'picocolors';
|
|
32
|
+
|
|
33
|
+
export const logger = {
|
|
34
|
+
info: (msg: string): void => console.log(pc.blue('ℹ'), msg),
|
|
35
|
+
success: (msg: string): void => console.log(pc.green('✔'), msg),
|
|
36
|
+
warn: (msg: string): void => console.log(pc.yellow('⚠'), msg),
|
|
37
|
+
error: (msg: string): void => console.log(pc.red('✖'), msg),
|
|
38
|
+
step: (msg: string): void => console.log(pc.gray(' →'), msg),
|
|
39
|
+
blank: (): void => console.log(),
|
|
40
|
+
};
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Interactive Prompts
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import prompts from 'prompts';
|
|
47
|
+
|
|
48
|
+
// Select (단일 선택)
|
|
49
|
+
const { template } = await prompts({
|
|
50
|
+
type: 'select',
|
|
51
|
+
name: 'template',
|
|
52
|
+
message: 'Select a template:',
|
|
53
|
+
choices: [
|
|
54
|
+
{ title: 'Template A', value: 'a' },
|
|
55
|
+
{ title: 'Template B', value: 'b' },
|
|
56
|
+
],
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Multiselect (다중 선택)
|
|
60
|
+
const { templates } = await prompts({
|
|
61
|
+
type: 'multiselect',
|
|
62
|
+
name: 'templates',
|
|
63
|
+
message: 'Select templates:',
|
|
64
|
+
choices: [
|
|
65
|
+
{ title: 'Template A', value: 'a' },
|
|
66
|
+
{ title: 'Template B', value: 'b' },
|
|
67
|
+
],
|
|
68
|
+
min: 1,
|
|
69
|
+
hint: '- Space to select. Return to submit',
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Confirm
|
|
73
|
+
const { confirmed } = await prompts({
|
|
74
|
+
type: 'confirm',
|
|
75
|
+
name: 'confirmed',
|
|
76
|
+
message: 'Overwrite existing files?',
|
|
77
|
+
initial: false,
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## File Copy 유틸
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import fs from 'fs-extra';
|
|
85
|
+
import path from 'path';
|
|
86
|
+
|
|
87
|
+
export const copyRecursive = async (
|
|
88
|
+
src: string,
|
|
89
|
+
dest: string,
|
|
90
|
+
): Promise<{ files: number; directories: number }> => {
|
|
91
|
+
const counter = { files: 0, directories: 0 };
|
|
92
|
+
|
|
93
|
+
const copy = async (s: string, d: string): Promise<void> => {
|
|
94
|
+
const stat = await fs.stat(s);
|
|
95
|
+
|
|
96
|
+
if (stat.isDirectory()) {
|
|
97
|
+
await fs.ensureDir(d);
|
|
98
|
+
counter.directories++;
|
|
99
|
+
|
|
100
|
+
const items = await fs.readdir(s);
|
|
101
|
+
for (const item of items) {
|
|
102
|
+
await copy(path.join(s, item), path.join(d, item));
|
|
103
|
+
}
|
|
104
|
+
} else {
|
|
105
|
+
await fs.copy(s, d);
|
|
106
|
+
counter.files++;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
await copy(src, dest);
|
|
111
|
+
return counter;
|
|
112
|
+
};
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## ESM __dirname
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
import { fileURLToPath } from 'url';
|
|
119
|
+
import path from 'path';
|
|
120
|
+
|
|
121
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
122
|
+
const __dirname = path.dirname(__filename);
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Package.json
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"name": "@scope/my-cli",
|
|
130
|
+
"version": "1.0.0",
|
|
131
|
+
"type": "module",
|
|
132
|
+
"bin": "./dist/index.js",
|
|
133
|
+
"files": ["dist", "templates"],
|
|
134
|
+
"scripts": {
|
|
135
|
+
"build": "tsup",
|
|
136
|
+
"dev": "tsup --watch",
|
|
137
|
+
"prepublishOnly": "npm run build"
|
|
138
|
+
},
|
|
139
|
+
"engines": {
|
|
140
|
+
"node": ">=18"
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## tsup.config.ts
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
import { defineConfig } from 'tsup';
|
|
149
|
+
|
|
150
|
+
export default defineConfig({
|
|
151
|
+
entry: ['src/index.ts'],
|
|
152
|
+
format: ['esm'],
|
|
153
|
+
target: 'node18',
|
|
154
|
+
clean: true,
|
|
155
|
+
dts: true,
|
|
156
|
+
banner: {
|
|
157
|
+
js: '#!/usr/bin/env node',
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
```
|