@kood/claude-code 0.5.7 → 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,673 @@
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
+ | **TanStack Start** | ✅ Server Function에서 `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
+ ## TanStack Start 패턴
461
+
462
+ ### Server Functions
463
+
464
+ ```typescript
465
+ import { createServerFn } from '@tanstack/start'
466
+ import { consola } from 'consola'
467
+
468
+ // ✅ Server Function 로깅
469
+ export const createUser = createServerFn({ method: 'POST' })
470
+ .inputValidator(createUserSchema)
471
+ .handler(async ({ data }) => {
472
+ const logger = consola.withTag('API').withTag('User')
473
+
474
+ logger.info('Creating user:', data.email)
475
+
476
+ try {
477
+ const user = await prisma.user.create({ data })
478
+ logger.success('User created:', user.id)
479
+ return user
480
+ } catch (error) {
481
+ logger.error('Failed to create user:', error)
482
+ throw error
483
+ }
484
+ })
485
+ ```
486
+
487
+ ### Middleware
488
+
489
+ ```typescript
490
+ import { createMiddleware } from '@tanstack/start'
491
+ import { consola } from 'consola'
492
+
493
+ // ✅ 요청 로깅 미들웨어
494
+ export const loggingMiddleware = createMiddleware()
495
+ .server(async ({ next, data }) => {
496
+ const logger = consola.withTag('Middleware')
497
+
498
+ logger.info('Request:', data.method, data.url)
499
+
500
+ try {
501
+ const result = await next()
502
+ logger.success('Response:', result.status)
503
+ return result
504
+ } catch (error) {
505
+ logger.error('Error:', error)
506
+ throw error
507
+ }
508
+ })
509
+ ```
510
+
511
+ ### 환경별 로거 설정
512
+
513
+ ```typescript
514
+ // lib/logger.ts
515
+ import { createConsola } from 'consola'
516
+
517
+ export const logger = createConsola({
518
+ level: process.env.NODE_ENV === 'production' ? 2 : 5, // prod: warn, dev: trace
519
+ fancy: process.env.NODE_ENV !== 'production', // 개발 환경에서만 색상/아이콘
520
+ formatOptions: {
521
+ date: true, // 타임스탬프
522
+ },
523
+ })
524
+
525
+ // 사용
526
+ import { logger } from '@/lib/logger'
527
+
528
+ logger.info('Application started')
529
+ ```
530
+
531
+ ### 프로덕션 에러 리포터
532
+
533
+ ```typescript
534
+ import { createConsola, type ConsolaReporter } from 'consola'
535
+ import * as Sentry from '@sentry/node'
536
+
537
+ // Sentry 리포터
538
+ const sentryReporter: ConsolaReporter = {
539
+ log(logObj) {
540
+ if (logObj.level <= 1) { // error, fatal
541
+ Sentry.captureException(new Error(logObj.args.join(' ')), {
542
+ level: logObj.level === 0 ? 'fatal' : 'error',
543
+ tags: {
544
+ type: logObj.type,
545
+ },
546
+ })
547
+ }
548
+ },
549
+ }
550
+
551
+ export const logger = createConsola({
552
+ level: 2, // warn, error, fatal
553
+ reporters: [
554
+ consola.options.reporters[0], // 콘솔
555
+ sentryReporter, // Sentry
556
+ ],
557
+ })
558
+ ```
559
+
560
+ </patterns>
561
+
562
+ ---
563
+
564
+ <dos_and_donts>
565
+
566
+ ## Do's & Don'ts
567
+
568
+ ### ✅ Do
569
+
570
+ | 상황 | 방법 |
571
+ |------|------|
572
+ | **로깅** | `consola.log()` 사용 |
573
+ | **에러** | `consola.error()` 사용 |
574
+ | **성공** | `consola.success()` 사용 |
575
+ | **태그** | `.withTag()` 사용 |
576
+ | **환경별** | `CONSOLA_LEVEL` 환경 변수 설정 |
577
+ | **테스트** | `mockTypes()` 또는 `pauseLogs()` 사용 |
578
+ | **프로덕션** | 로그 레벨 2 이하 (warn, error, fatal) |
579
+ | **개발** | 로그 레벨 5 (debug/trace 포함) |
580
+
581
+ ### ❌ Don't
582
+
583
+ | 상황 | 이유 |
584
+ |------|------|
585
+ | **console.log** | ❌ 직접 사용 금지 → `consola.log()` 사용 |
586
+ | **프로덕션 로그** | ❌ 로그 레벨 미설정 → 불필요한 로그 출력 |
587
+ | **테스트 출력** | ❌ 실제 콘솔 출력 → Mock 사용 |
588
+ | **에러 무시** | ❌ `console.error()` 직접 사용 → `consola.error()` + 리포터 |
589
+ | **번들 크기** | ❌ 클라이언트에서 전체 패키지 사용 → `consola/basic` 사용 |
590
+
591
+ ### 환경별 패턴
592
+
593
+ ```typescript
594
+ // ❌ 로그 레벨 미설정
595
+ import { consola } from 'consola'
596
+ consola.debug('This will be printed in production!') // 불필요한 로그
597
+
598
+ // ✅ 환경별 로그 레벨 설정
599
+ import { createConsola } from 'consola'
600
+
601
+ export const logger = createConsola({
602
+ level: process.env.NODE_ENV === 'production' ? 2 : 5,
603
+ })
604
+
605
+ logger.debug('This is only printed in development')
606
+ ```
607
+
608
+ ### 테스트 패턴
609
+
610
+ ```typescript
611
+ // ❌ 테스트 중 콘솔 출력
612
+ describe('Test', () => {
613
+ it('should work', () => {
614
+ consola.log('This will clutter test output') // 출력됨
615
+ })
616
+ })
617
+
618
+ // ✅ Mock 사용
619
+ describe('Test', () => {
620
+ beforeEach(() => consola.mockTypes(() => vi.fn()))
621
+ afterEach(() => consola.restoreAll())
622
+
623
+ it('should work', () => {
624
+ consola.log('This will not clutter test output') // Mock됨
625
+ })
626
+ })
627
+ ```
628
+
629
+ </dos_and_donts>
630
+
631
+ ---
632
+
633
+ <quick_reference>
634
+
635
+ ## Quick Reference
636
+
637
+ ```typescript
638
+ // 설치
639
+ import { consola } from 'consola'
640
+ import { consola } from 'consola/basic' // 80% 크기 감소
641
+
642
+ // 기본 로깅
643
+ consola.log('Log')
644
+ consola.info('Info')
645
+ consola.warn('Warning')
646
+ consola.error('Error')
647
+ consola.success('Success')
648
+
649
+ // 태그
650
+ const logger = consola.withTag('API')
651
+ logger.info('Request') // [API] Request
652
+
653
+ // 로그 레벨
654
+ consola.level = 3 // log까지만 출력
655
+ CONSOLA_LEVEL=3 # 환경 변수
656
+
657
+ // 테스트
658
+ consola.mockTypes(() => vi.fn())
659
+ consola.pauseLogs()
660
+ consola.resumeLogs()
661
+ consola.restoreAll()
662
+
663
+ // 프롬프트
664
+ const name = await consola.prompt('Name?', { type: 'text' })
665
+ const ok = await consola.prompt('Sure?', { type: 'confirm' })
666
+
667
+ // 커스텀 리포터
668
+ const logger = createConsola({
669
+ reporters: [consola.options.reporters[0], customReporter],
670
+ })
671
+ ```
672
+
673
+ </quick_reference>