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