@kood/claude-code 0.5.8 → 0.5.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 CHANGED
@@ -854,7 +854,7 @@ var init = async (options) => {
854
854
 
855
855
  // src/index.ts
856
856
  var program = new Command();
857
- program.name("claude-code").description("Claude Code documentation installer for projects").version("0.5.8");
857
+ program.name("claude-code").description("Claude Code documentation installer for projects").version("0.5.9");
858
858
  program.option(
859
859
  "-t, --template <names>",
860
860
  "template names (comma-separated: tanstack-start,hono)"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kood/claude-code",
3
- "version": "0.5.8",
3
+ "version": "0.5.9",
4
4
  "description": "Claude Code documentation installer for projects",
5
5
  "type": "module",
6
6
  "bin": "./dist/index.js",
@@ -0,0 +1,687 @@
1
+ # Consola
2
+
3
+ > **Version 3.x** | Elegant Console Logger for Node.js & Browser
4
+
5
+ ---
6
+
7
+ <context>
8
+
9
+ **Purpose:** 타입 안전하고 우아한 콘솔 로깅 라이브러리
10
+
11
+ **Key Features:**
12
+ - 우아한 콘솔 출력 (색상, 아이콘, 포맷팅)
13
+ - 로그 레벨 관리 (0-5, Silent, Verbose)
14
+ - 커스텀 리포터 지원
15
+ - 테스트 환경 Mock 지원
16
+ - 타입스크립트 완벽 지원
17
+ - 작은 번들 크기 (`consola/basic`, `consola/core` - 80% 크기 감소)
18
+
19
+ **Bundle Size:**
20
+ - `consola`: ~8KB (전체 기능)
21
+ - `consola/basic`: ~2KB (기본 로깅)
22
+ - `consola/core`: ~1KB (최소 기능)
23
+
24
+ </context>
25
+
26
+ ---
27
+
28
+ <forbidden>
29
+
30
+ | 분류 | 금지 |
31
+ |------|------|
32
+ | **로깅** | ❌ `console.log()` 직접 사용 (consola 사용) |
33
+ | **로그 레벨** | ❌ 프로덕션 환경에서 로그 레벨 미설정 |
34
+ | **에러 핸들링** | ❌ 에러를 `console.error()` 직접 출력 |
35
+ | **테스트** | ❌ 테스트에서 실제 콘솔 출력 (Mock 사용) |
36
+
37
+ </forbidden>
38
+
39
+ ---
40
+
41
+ <required>
42
+
43
+ | 분류 | 필수 |
44
+ |------|------|
45
+ | **환경 변수** | ✅ `CONSOLA_LEVEL` 설정 (프로덕션) |
46
+ | **로그 레벨** | ✅ 프로덕션: 3 (log) 이하, 개발: 4 (debug) 이상 |
47
+ | **에러 처리** | ✅ `consola.error()` 사용 |
48
+ | **테스트** | ✅ `mockTypes()` 또는 `pauseLogs()` 사용 |
49
+ | **Hono** | ✅ Middleware 및 Route Handler에서 consola 사용 |
50
+
51
+ </required>
52
+
53
+ ---
54
+
55
+ <installation>
56
+
57
+ ## 설치
58
+
59
+ ```bash
60
+ npm install consola@^3.0.0
61
+ ```
62
+
63
+ ## Bundle 최적화
64
+
65
+ ```typescript
66
+ // ✅ 전체 기능 (8KB)
67
+ import { consola } from 'consola'
68
+
69
+ // ✅ 기본 로깅 (2KB, 80% 크기 감소)
70
+ import { consola } from 'consola/basic'
71
+
72
+ // ✅ 최소 기능 (1KB)
73
+ import { consola } from 'consola/core'
74
+ ```
75
+
76
+ **권장사항:**
77
+ - 서버: `consola` (전체 기능) 또는 `consola/basic` (크기 최적화)
78
+
79
+ </installation>
80
+
81
+ ---
82
+
83
+ <basic_usage>
84
+
85
+ ## 기본 사용법
86
+
87
+ ```typescript
88
+ import { consola } from 'consola'
89
+
90
+ // 기본 로그 레벨 (0-5)
91
+ consola.fatal('Fatal error!') // 0: 치명적 에러
92
+ consola.error('Error occurred!') // 1: 에러
93
+ consola.warn('Warning message') // 2: 경고
94
+ consola.log('Log message') // 3: 일반 로그 (기본값)
95
+ consola.info('Info message') // 4: 정보
96
+ consola.debug('Debug message') // 5: 디버그
97
+ consola.trace('Trace message') // 5: 추적
98
+ consola.verbose('Verbose message') // +999: 상세 로그
99
+ consola.silent('Silent message') // -999: 출력 안 됨
100
+
101
+ // 성공/시작/준비 메시지
102
+ consola.success('Task completed!') // ✅ 성공
103
+ consola.start('Starting task...') // ⏳ 시작
104
+ consola.ready('Server is ready!') // ✅ 준비 완료
105
+
106
+ // 박스 출력
107
+ consola.box('Important Message') // 박스로 감싸서 출력
108
+ ```
109
+
110
+ ## 로거 생성
111
+
112
+ ```typescript
113
+ import { createConsola } from 'consola'
114
+
115
+ // 커스텀 태그
116
+ const logger = createConsola({
117
+ level: 4, // info 레벨까지 출력
118
+ fancy: true, // 색상 및 아이콘 사용
119
+ formatOptions: {
120
+ date: true, // 타임스탬프 표시
121
+ },
122
+ })
123
+
124
+ // 태그 추가
125
+ const apiLogger = logger.withTag('API')
126
+ apiLogger.info('Request received') // [API] Request received
127
+ ```
128
+
129
+ ## 환경 변수
130
+
131
+ ```bash
132
+ # 로그 레벨 설정
133
+ CONSOLA_LEVEL=3 # 0: fatal, 1: error, 2: warn, 3: log, 4: info, 5: debug/trace
134
+
135
+ # 프로덕션
136
+ CONSOLA_LEVEL=3 # log까지만 출력
137
+
138
+ # 개발
139
+ CONSOLA_LEVEL=5 # 모든 로그 출력
140
+ ```
141
+
142
+ </basic_usage>
143
+
144
+ ---
145
+
146
+ <log_levels>
147
+
148
+ ## 로그 레벨
149
+
150
+ | 레벨 | 값 | 메서드 | 사용 |
151
+ |------|------|--------|------|
152
+ | **fatal** | 0 | `consola.fatal()` | 치명적 에러 (프로세스 종료) |
153
+ | **error** | 1 | `consola.error()` | 에러 발생 |
154
+ | **warn** | 2 | `consola.warn()` | 경고 메시지 |
155
+ | **log** | 3 | `consola.log()` | 일반 로그 (기본값) |
156
+ | **info** | 4 | `consola.info()` | 정보성 메시지 |
157
+ | **debug** | 5 | `consola.debug()` | 디버그 정보 |
158
+ | **trace** | 5 | `consola.trace()` | 추적 정보 |
159
+ | **verbose** | +999 | `consola.verbose()` | 상세 로그 |
160
+ | **silent** | -999 | `consola.silent()` | 출력 안 됨 |
161
+
162
+ ### 로그 레벨 설정
163
+
164
+ ```typescript
165
+ import { consola } from 'consola'
166
+
167
+ // 레벨 설정
168
+ consola.level = 3 // log까지만 출력
169
+ consola.level = 5 // 모든 로그 출력 (debug/trace 포함)
170
+
171
+ // 환경별 설정
172
+ if (process.env.NODE_ENV === 'production') {
173
+ consola.level = 2 // warn, error, fatal만 출력
174
+ } else {
175
+ consola.level = 5 // 개발 환경: 모든 로그 출력
176
+ }
177
+ ```
178
+
179
+ ### 환경 변수로 제어
180
+
181
+ ```bash
182
+ # .env.production
183
+ CONSOLA_LEVEL=2 # warn, error, fatal
184
+
185
+ # .env.development
186
+ CONSOLA_LEVEL=5 # 모든 로그
187
+ ```
188
+
189
+ </log_levels>
190
+
191
+ ---
192
+
193
+ <custom_reporters>
194
+
195
+ ## 커스텀 리포터
196
+
197
+ ```typescript
198
+ import { consola, createConsola, type ConsolaReporter } from 'consola'
199
+
200
+ // 파일 리포터
201
+ const fileReporter: ConsolaReporter = {
202
+ log(logObj) {
203
+ const message = `[${logObj.date.toISOString()}] ${logObj.type}: ${logObj.args.join(' ')}`
204
+ fs.appendFileSync('app.log', message + '\n')
205
+ },
206
+ }
207
+
208
+ // Sentry 리포터
209
+ const sentryReporter: ConsolaReporter = {
210
+ log(logObj) {
211
+ if (logObj.level <= 1) { // error, fatal
212
+ Sentry.captureException(new Error(logObj.args.join(' ')))
213
+ }
214
+ },
215
+ }
216
+
217
+ // 리포터 추가
218
+ const logger = createConsola({
219
+ reporters: [
220
+ consola.options.reporters[0], // 기본 콘솔 리포터
221
+ fileReporter,
222
+ sentryReporter,
223
+ ],
224
+ })
225
+
226
+ logger.error('This will be logged to console, file, and Sentry')
227
+ ```
228
+
229
+ ## 프로덕션 리포터 패턴
230
+
231
+ ```typescript
232
+ import { createConsola } from 'consola'
233
+
234
+ // 환경별 리포터 설정
235
+ const reporters = [consola.options.reporters[0]] // 기본 콘솔
236
+
237
+ if (process.env.NODE_ENV === 'production') {
238
+ // 프로덕션: 파일 + 외부 로깅 서비스
239
+ reporters.push(fileReporter, sentryReporter)
240
+ } else {
241
+ // 개발: 콘솔만
242
+ }
243
+
244
+ export const logger = createConsola({
245
+ level: process.env.NODE_ENV === 'production' ? 2 : 5,
246
+ reporters,
247
+ })
248
+ ```
249
+
250
+ </custom_reporters>
251
+
252
+ ---
253
+
254
+ <testing>
255
+
256
+ ## 테스트 통합
257
+
258
+ ### Mock 사용
259
+
260
+ ```typescript
261
+ import { consola } from 'consola'
262
+
263
+ describe('User Service', () => {
264
+ beforeEach(() => {
265
+ // 모든 로그 Mock
266
+ consola.mockTypes(() => vi.fn())
267
+ })
268
+
269
+ afterEach(() => {
270
+ // Mock 복원
271
+ consola.restoreAll()
272
+ })
273
+
274
+ it('should log user creation', async () => {
275
+ const spy = vi.fn()
276
+ consola.mockTypes((type) => spy)
277
+
278
+ await createUser({ name: 'Alice' })
279
+
280
+ expect(spy).toHaveBeenCalledWith('User created:', 'Alice')
281
+ })
282
+ })
283
+ ```
284
+
285
+ ### Pause/Resume
286
+
287
+ ```typescript
288
+ import { consola } from 'consola'
289
+
290
+ describe('API Tests', () => {
291
+ beforeAll(() => {
292
+ // 테스트 중 로그 일시 중지
293
+ consola.pauseLogs()
294
+ })
295
+
296
+ afterAll(() => {
297
+ // 로그 재개
298
+ consola.resumeLogs()
299
+ })
300
+
301
+ it('should not log during test', () => {
302
+ consola.log('This will not be printed')
303
+ })
304
+ })
305
+ ```
306
+
307
+ ### Vitest 통합
308
+
309
+ ```typescript
310
+ import { consola } from 'consola'
311
+ import { beforeEach, afterEach, vi } from 'vitest'
312
+
313
+ beforeEach(() => {
314
+ consola.mockTypes(() => vi.fn())
315
+ })
316
+
317
+ afterEach(() => {
318
+ consola.restoreAll()
319
+ })
320
+ ```
321
+
322
+ </testing>
323
+
324
+ ---
325
+
326
+ <advanced>
327
+
328
+ ## 고급 기능
329
+
330
+ ### Console Redirect
331
+
332
+ ```typescript
333
+ import { consola } from 'consola'
334
+
335
+ // console.log를 consola로 리다이렉트
336
+ consola.wrapConsole()
337
+
338
+ console.log('This uses consola now!') // consola.log()로 출력됨
339
+
340
+ // 복원
341
+ consola.restoreConsole()
342
+ ```
343
+
344
+ **Pause/Resume, Mock 기능:** 자세한 내용은 `<testing>` 및 `<utilities>` 섹션을 참고하세요.
345
+
346
+ </advanced>
347
+
348
+ ---
349
+
350
+ <utilities>
351
+
352
+ ## 유틸리티
353
+
354
+ ### withTag
355
+
356
+ ```typescript
357
+ import { consola } from 'consola'
358
+
359
+ // 태그 추가
360
+ const apiLogger = consola.withTag('API')
361
+ apiLogger.info('Request received') // [API] Request received
362
+
363
+ const dbLogger = consola.withTag('DB')
364
+ dbLogger.warn('Connection slow') // [DB] Connection slow
365
+
366
+ // 다중 태그
367
+ const authLogger = consola.withTag('API').withTag('Auth')
368
+ authLogger.info('User logged in') // [API] [Auth] User logged in
369
+ ```
370
+
371
+ ### wrapConsole
372
+
373
+ ```typescript
374
+ import { consola } from 'consola'
375
+
376
+ // console.* 메서드를 consola로 래핑
377
+ consola.wrapConsole()
378
+
379
+ console.log('Uses consola') // consola.log()
380
+ console.error('Uses consola') // consola.error()
381
+
382
+ // 복원
383
+ consola.restoreConsole()
384
+ ```
385
+
386
+ ### wrapStd
387
+
388
+ ```typescript
389
+ import { consola } from 'consola'
390
+
391
+ // process.stdout/stderr를 consola로 래핑
392
+ consola.wrapStd()
393
+
394
+ process.stdout.write('Uses consola\n') // consola.log()
395
+ process.stderr.write('Uses consola\n') // consola.error()
396
+
397
+ // 복원
398
+ consola.restoreStd()
399
+ ```
400
+
401
+ ### wrapAll
402
+
403
+ ```typescript
404
+ import { consola } from 'consola'
405
+
406
+ // console + process.std* 모두 래핑
407
+ consola.wrapAll()
408
+
409
+ console.log('Uses consola')
410
+ process.stdout.write('Uses consola\n')
411
+
412
+ // 복원
413
+ consola.restoreAll()
414
+ ```
415
+
416
+ </utilities>
417
+
418
+ ---
419
+
420
+ <patterns>
421
+
422
+ ## Hono 패턴
423
+
424
+ ### Middleware에서 consola 사용
425
+
426
+ ```typescript
427
+ import { createMiddleware } from 'hono/factory'
428
+ import { logger } from '@/lib/logger'
429
+
430
+ // ✅ 요청 로깅 미들웨어
431
+ export const requestLogger = createMiddleware(async (c, next) => {
432
+ const start = Date.now()
433
+ logger.info(`→ ${c.req.method} ${c.req.path}`)
434
+
435
+ await next()
436
+
437
+ const ms = Date.now() - start
438
+ logger.success(`← ${c.req.method} ${c.req.path} - ${ms}ms`)
439
+ })
440
+ ```
441
+
442
+ ### Route Handler에서 consola 사용
443
+
444
+ ```typescript
445
+ import { Hono } from 'hono'
446
+ import { zValidator } from '@hono/zod-validator'
447
+ import { logger } from '@/lib/logger'
448
+ import { createUserSchema } from '@/schemas/user'
449
+
450
+ const app = new Hono()
451
+
452
+ // ✅ GET 요청 로깅
453
+ app.get('/users', async (c) => {
454
+ logger.debug('Fetching users...')
455
+ const users = await prisma.user.findMany()
456
+ logger.info(`Found ${users.length} users`)
457
+ return c.json(users)
458
+ })
459
+
460
+ // ✅ POST 요청 로깅 (zValidator + consola)
461
+ app.post('/users', zValidator('json', createUserSchema), async (c) => {
462
+ const data = c.req.valid('json')
463
+
464
+ logger.info('Creating user:', data.email)
465
+
466
+ try {
467
+ const user = await prisma.user.create({ data })
468
+ logger.success('User created:', user.id)
469
+ return c.json(user, 201)
470
+ } catch (error) {
471
+ logger.error('Failed to create user:', error)
472
+ throw error
473
+ }
474
+ })
475
+ ```
476
+
477
+ ### Error Handler에서 consola 사용
478
+
479
+ ```typescript
480
+ import { Hono } from 'hono'
481
+ import { HTTPException } from 'hono/http-exception'
482
+ import { logger } from '@/lib/logger'
483
+
484
+ const app = new Hono()
485
+
486
+ // ✅ 에러 핸들러
487
+ app.onError((err, c) => {
488
+ // HTTPException 처리
489
+ if (err instanceof HTTPException) {
490
+ logger.warn('HTTP Exception:', err.status, err.message)
491
+ return c.json({ error: err.message }, err.status)
492
+ }
493
+
494
+ // 일반 에러
495
+ logger.error('Unhandled error:', err)
496
+ return c.json({ error: 'Internal Server Error' }, 500)
497
+ })
498
+ ```
499
+
500
+ ### 환경별 로거 설정
501
+
502
+ ```typescript
503
+ // lib/logger.ts
504
+ import { createConsola } from 'consola'
505
+
506
+ export const logger = createConsola({
507
+ level: process.env.NODE_ENV === 'production' ? 2 : 5, // prod: warn, dev: trace
508
+ fancy: process.env.NODE_ENV !== 'production', // 개발 환경에서만 색상/아이콘
509
+ formatOptions: {
510
+ date: true, // 타임스탬프
511
+ },
512
+ })
513
+
514
+ // 사용
515
+ import { logger } from '@/lib/logger'
516
+
517
+ logger.info('Application started')
518
+ ```
519
+
520
+ ### Sentry 통합 (서버용)
521
+
522
+ ```typescript
523
+ import { createConsola, type ConsolaReporter } from 'consola'
524
+ import * as Sentry from '@sentry/node'
525
+
526
+ // Sentry 리포터
527
+ const sentryReporter: ConsolaReporter = {
528
+ log(logObj) {
529
+ if (logObj.level <= 1) { // error, fatal
530
+ Sentry.captureException(new Error(logObj.args.join(' ')), {
531
+ level: logObj.level === 0 ? 'fatal' : 'error',
532
+ tags: {
533
+ type: logObj.type,
534
+ },
535
+ })
536
+ }
537
+ },
538
+ }
539
+
540
+ export const logger = createConsola({
541
+ level: 2, // warn, error, fatal
542
+ reporters: [
543
+ consola.options.reporters[0], // 콘솔
544
+ sentryReporter, // Sentry
545
+ ],
546
+ })
547
+ ```
548
+
549
+ ### 라우트별 로거 생성
550
+
551
+ ```typescript
552
+ import { Hono } from 'hono'
553
+ import { logger } from '@/lib/logger'
554
+
555
+ const app = new Hono()
556
+
557
+ // ✅ 라우트별 태그 로거
558
+ app.get('/api/posts', async (c) => {
559
+ const postLogger = logger.withTag('Post')
560
+
561
+ postLogger.debug('Fetching posts...')
562
+ const posts = await prisma.post.findMany()
563
+ postLogger.info(`Found ${posts.length} posts`)
564
+
565
+ return c.json(posts)
566
+ })
567
+
568
+ app.get('/api/users', async (c) => {
569
+ const userLogger = logger.withTag('User')
570
+
571
+ userLogger.debug('Fetching users...')
572
+ const users = await prisma.user.findMany()
573
+ userLogger.info(`Found ${users.length} users`)
574
+
575
+ return c.json(users)
576
+ })
577
+ ```
578
+
579
+ </patterns>
580
+
581
+ ---
582
+
583
+ <dos_and_donts>
584
+
585
+ ## Do's & Don'ts
586
+
587
+ ### ✅ Do
588
+
589
+ | 상황 | 방법 |
590
+ |------|------|
591
+ | **로깅** | `consola.log()` 사용 |
592
+ | **에러** | `consola.error()` 사용 |
593
+ | **성공** | `consola.success()` 사용 |
594
+ | **태그** | `.withTag()` 사용 |
595
+ | **환경별** | `CONSOLA_LEVEL` 환경 변수 설정 |
596
+ | **테스트** | `mockTypes()` 또는 `pauseLogs()` 사용 |
597
+ | **프로덕션** | 로그 레벨 2 이하 (warn, error, fatal) |
598
+ | **개발** | 로그 레벨 5 (debug/trace 포함) |
599
+
600
+ ### ❌ Don't
601
+
602
+ | 상황 | 이유 |
603
+ |------|------|
604
+ | **console.log** | ❌ 직접 사용 금지 → `consola.log()` 사용 |
605
+ | **프로덕션 로그** | ❌ 로그 레벨 미설정 → 불필요한 로그 출력 |
606
+ | **테스트 출력** | ❌ 실제 콘솔 출력 → Mock 사용 |
607
+ | **에러 무시** | ❌ `console.error()` 직접 사용 → `consola.error()` + 리포터 |
608
+
609
+ ### 환경별 패턴
610
+
611
+ ```typescript
612
+ // ❌ 로그 레벨 미설정
613
+ import { consola } from 'consola'
614
+ consola.debug('This will be printed in production!') // 불필요한 로그
615
+
616
+ // ✅ 환경별 로그 레벨 설정
617
+ import { createConsola } from 'consola'
618
+
619
+ export const logger = createConsola({
620
+ level: process.env.NODE_ENV === 'production' ? 2 : 5,
621
+ })
622
+
623
+ logger.debug('This is only printed in development')
624
+ ```
625
+
626
+ ### 테스트 패턴
627
+
628
+ ```typescript
629
+ // ❌ 테스트 중 콘솔 출력
630
+ describe('Test', () => {
631
+ it('should work', () => {
632
+ consola.log('This will clutter test output') // 출력됨
633
+ })
634
+ })
635
+
636
+ // ✅ Mock 사용
637
+ describe('Test', () => {
638
+ beforeEach(() => consola.mockTypes(() => vi.fn()))
639
+ afterEach(() => consola.restoreAll())
640
+
641
+ it('should work', () => {
642
+ consola.log('This will not clutter test output') // Mock됨
643
+ })
644
+ })
645
+ ```
646
+
647
+ </dos_and_donts>
648
+
649
+ ---
650
+
651
+ <quick_reference>
652
+
653
+ ## Quick Reference
654
+
655
+ ```typescript
656
+ // 설치
657
+ import { consola } from 'consola'
658
+ import { consola } from 'consola/basic' // 80% 크기 감소
659
+
660
+ // 기본 로깅
661
+ consola.log('Log')
662
+ consola.info('Info')
663
+ consola.warn('Warning')
664
+ consola.error('Error')
665
+ consola.success('Success')
666
+
667
+ // 태그
668
+ const logger = consola.withTag('API')
669
+ logger.info('Request') // [API] Request
670
+
671
+ // 로그 레벨
672
+ consola.level = 3 // log까지만 출력
673
+ CONSOLA_LEVEL=3 # 환경 변수
674
+
675
+ // 테스트
676
+ consola.mockTypes(() => vi.fn())
677
+ consola.pauseLogs()
678
+ consola.resumeLogs()
679
+ consola.restoreAll()
680
+
681
+ // 커스텀 리포터
682
+ const logger = createConsola({
683
+ reporters: [consola.options.reporters[0], customReporter],
684
+ })
685
+ ```
686
+
687
+ </quick_reference>