develog 1.0.2

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/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 전준연
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # develog
2
+
3
+ [![npm downloads](https://img.shields.io/npm/dt/develog.svg)](https://www.npmjs.com/package/develog)
4
+ [![GitHub repo size](https://img.shields.io/github/repo-size/junjuny0227/develog.svg)](https://github.com/junjuny0227/develog)
5
+ [![npm version](https://img.shields.io/npm/v/develog.svg)](https://www.npmjs.com/package/develog)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ > A lightweight frontend logger that runs only in local/dev environments
9
+
10
+ A smart logging library that automatically detects the environment based on the browser's hostname and outputs logs only in development environments.
11
+
12
+ ## Documentation
13
+
14
+ - [English Documentation](./docs/README.en.md)
15
+ - [한국어 문서](./docs/README.ko.md)
16
+
17
+ ## Quick Start
18
+
19
+ ### Installation
20
+
21
+ ```bash
22
+ # npm
23
+ npm install develog
24
+
25
+ # yarn
26
+ yarn add develog
27
+
28
+ # pnpm
29
+ pnpm add develog
30
+ ```
31
+
32
+ ### Basic Usage
33
+
34
+ ```typescript
35
+ import { develog } from 'develog';
36
+
37
+ develog.log('This log appears only in development environments');
38
+ develog.info('Info message');
39
+ develog.warn('Warning message');
40
+ develog.error('Error message');
41
+ ```
42
+
43
+ ## Features
44
+
45
+ - **Automatic Environment Detection** - Based on hostname patterns
46
+ - **Namespace Support** - Separate logs by module
47
+ - **Timestamp Support** - 4 format options
48
+ - **TypeScript Support** - Full type safety
49
+ - **Zero Dependencies** - Lightweight package
50
+ - **Production Safe** - Automatically disabled in production
51
+
52
+ ## Links
53
+
54
+ - [GitHub Repository](https://github.com/junjuny0227/develog)
55
+ - [npm Package](https://www.npmjs.com/package/develog)
56
+ - [Issues](https://github.com/junjuny0227/develog/issues)
57
+
58
+ ## License
59
+
60
+ MIT License - See [LICENSE.md](LICENSE.md)
61
+
62
+ ## Author
63
+
64
+ **junjuny** - [@junjuny0227](https://github.com/junjuny0227)
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ 'use strict';var v={local:/^(localhost|127\.0\.0\.1|0\.0\.0\.0|::1|\[::1\])/,dev:/(^|\.)(dev|development)\./,stage:/(^|\.)(stage|staging)\./,production:/(^|\.)(prod|production|www)\./,unknown:/.*/};function a(n){if(typeof window>"u"||!window.location)return "unknown";let e=window.location.hostname,t={...v,...n};return t.local.test(e)?"local":t.dev.test(e)?"dev":t.stage.test(e)?"stage":t.production.test(e)?"production":"unknown"}function p(n="time"){let e=new Date;switch(n){case "time":return m(e);case "datetime":return E(e);case "iso":return e.toISOString();case "ms":return e.getTime().toString();default:return m(e)}}function m(n){let e=o(n.getHours()),t=o(n.getMinutes()),s=o(n.getSeconds());return `${e}:${t}:${s}`}function E(n){let e=n.getFullYear(),t=o(n.getMonth()+1),s=o(n.getDate()),i=m(n);return `${e}-${t}-${s} ${i}`}function o(n){return n.toString().padStart(2,"0")}var r=class n{constructor(e={}){let{enabledEnvironments:t=["local","dev","stage"],customHostnamePatterns:s,prefix:i="[develog]",forceEnvironment:l,showTimestamp:c=false,timestampFormat:g="time",enabledNamespaces:d,_namespaceName:h}=e;this.environment=l||a(s),this.enabledEnvironments=new Set(t),this.prefix=i,this.showTimestamp=c,this.timestampFormat=g,this.namespaces=new Map,this.namespaceName=h,this.namespaceFilter=d;let u=this.enabledEnvironments.has(this.environment),f=this.isNamespaceEnabled();this.isEnabled=u&&f;}getEnvironment(){return this.environment}isLoggingEnabled(){return this.isEnabled}namespace(e){if(this.namespaces.has(e))return this.namespaces.get(e);let t=this.namespaceName?`${this.namespaceName}:${e}`:e,s=new n({enabledEnvironments:Array.from(this.enabledEnvironments),prefix:this.prefix,forceEnvironment:this.environment,showTimestamp:this.showTimestamp,timestampFormat:this.timestampFormat,enabledNamespaces:this.namespaceFilter,_namespaceName:t});return this.namespaces.set(e,s),s}isNamespaceEnabled(){if(!this.namespaceFilter||this.namespaceFilter.length===0||!this.namespaceName||this.namespaceFilter.includes("*")||this.namespaceFilter.includes(this.namespaceName))return true;for(let e of this.namespaceFilter)if(e.endsWith(":*")){let t=e.slice(0,-2);if(this.namespaceName===t||this.namespaceName.startsWith(`${t}:`))return true}return false}getLogPrefix(){let e=this.prefix;if(this.namespaceName&&(e=`${e}:${this.namespaceName}`),this.showTimestamp){let t=p(this.timestampFormat);e=`${e} [${t}]`;}return e}log(...e){this.logWithLevel("log",...e);}info(...e){this.logWithLevel("info",...e);}warn(...e){this.logWithLevel("warn",...e);}error(...e){this.logWithLevel("error",...e);}debug(...e){this.logWithLevel("debug",...e);}group(e){this.isEnabled&&(e?console.group(this.formatMessage(e)):console.group());}groupCollapsed(e){this.isEnabled&&(e?console.groupCollapsed(this.formatMessage(e)):console.groupCollapsed());}groupEnd(){this.isEnabled&&console.groupEnd();}table(e){this.isEnabled&&(console.log(this.getLogPrefix()),console.table(e));}time(e){this.isEnabled&&console.time(this.formatMessage(e));}timeEnd(e){this.isEnabled&&console.timeEnd(this.formatMessage(e));}count(e){this.isEnabled&&console.count(e?this.formatMessage(e):this.prefix);}countReset(e){this.isEnabled&&console.countReset(e?this.formatMessage(e):this.prefix);}clear(){this.isEnabled&&console.clear();}logWithLevel(e,...t){if(!this.isEnabled)return;let s=console[e]||console.log,i=this.getLogPrefix();s(i,...t);}formatMessage(e){return `${this.getLogPrefix()} ${e}`}},w=new r;exports.Develog=r;exports.detectEnvironment=a;exports.develog=w;exports.formatTimestamp=p;//# sourceMappingURL=index.cjs.map
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/environment.ts","../src/utils.ts","../src/logger.ts"],"names":["DEFAULT_HOSTNAME_PATTERNS","detectEnvironment","customPatterns","hostname","patterns","formatTimestamp","format","now","formatTime","formatDateTime","date","hours","padZero","minutes","seconds","year","month","day","timeStr","num","Develog","_Develog","options","enabledEnvironments","customHostnamePatterns","prefix","forceEnvironment","showTimestamp","timestampFormat","enabledNamespaces","_namespaceName","envEnabled","namespaceEnabled","name","fullNamespace","namespacedLogger","pattern","timestamp","args","label","data","level","consoleMethod","logPrefix","message","develog"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { Environment } from './types';\n\n/**\n * 기본 hostname 패턴 정의\n */\nconst DEFAULT_HOSTNAME_PATTERNS: Record<Environment, RegExp> = {\n local: /^(localhost|127\\.0\\.0\\.1|0\\.0\\.0\\.0|::1|\\[::1\\])/,\n dev: /(^|\\.)(dev|development)\\./,\n stage: /(^|\\.)(stage|staging)\\./,\n production: /(^|\\.)(prod|production|www)\\./,\n unknown: /.*/,\n};\n\n/**\n * 현재 브라우저의 hostname 또는 IP를 기반으로 실행 환경을 감지\n * @param customPatterns - 커스텀 hostname 패턴\n * @returns 감지된 환경\n */\nexport function detectEnvironment(\n customPatterns?: Partial<Record<Environment, RegExp>>,\n): Environment {\n // 브라우저 환경이 아닌 경우\n if (typeof window === 'undefined' || !window.location) {\n return 'unknown';\n }\n\n const hostname = window.location.hostname;\n const patterns = { ...DEFAULT_HOSTNAME_PATTERNS, ...customPatterns };\n\n // local 환경 체크 (최우선)\n if (patterns.local.test(hostname)) {\n return 'local';\n }\n\n // dev 환경 체크\n if (patterns.dev.test(hostname)) {\n return 'dev';\n }\n\n // stage 환경 체크\n if (patterns.stage.test(hostname)) {\n return 'stage';\n }\n\n // production 환경 체크\n if (patterns.production.test(hostname)) {\n return 'production';\n }\n\n // 매칭되지 않으면 unknown\n return 'unknown';\n}\n","import type { TimestampFormat } from './types';\n\n/**\n * 현재 시간을 지정된 포맷으로 변환\n * @param format - 타임스탬프 포맷\n * @returns 포맷된 타임스탬프 문자열\n */\nexport function formatTimestamp(format: TimestampFormat = 'time'): string {\n const now = new Date();\n\n switch (format) {\n case 'time':\n return formatTime(now);\n case 'datetime':\n return formatDateTime(now);\n case 'iso':\n return now.toISOString();\n case 'ms':\n return now.getTime().toString();\n default:\n return formatTime(now);\n }\n}\n\n/**\n * HH:MM:SS 포맷\n */\nfunction formatTime(date: Date): string {\n const hours = padZero(date.getHours());\n const minutes = padZero(date.getMinutes());\n const seconds = padZero(date.getSeconds());\n return `${hours}:${minutes}:${seconds}`;\n}\n\n/**\n * YYYY-MM-DD HH:MM:SS 포맷\n */\nfunction formatDateTime(date: Date): string {\n const year = date.getFullYear();\n const month = padZero(date.getMonth() + 1);\n const day = padZero(date.getDate());\n const timeStr = formatTime(date);\n return `${year}-${month}-${day} ${timeStr}`;\n}\n\n/**\n * 숫자를 두 자리로 패딩\n */\nfunction padZero(num: number): string {\n return num.toString().padStart(2, '0');\n}\n","import { detectEnvironment } from './environment';\nimport type { Environment, LoggerOptions, LogLevel, TimestampFormat } from './types';\nimport { formatTimestamp } from './utils';\n\n/**\n * develog - 브라우저 환경 기반 로거\n */\nexport class Develog {\n private readonly environment: Environment;\n private readonly enabledEnvironments: Set<Environment>;\n private readonly prefix: string;\n private readonly isEnabled: boolean;\n private readonly showTimestamp: boolean;\n private readonly timestampFormat: TimestampFormat;\n private readonly namespaces: Map<string, Develog>;\n private readonly namespaceName?: string;\n private readonly namespaceFilter?: string[];\n\n constructor(options: LoggerOptions = {}) {\n const {\n enabledEnvironments = ['local', 'dev', 'stage'],\n customHostnamePatterns,\n prefix = '[develog]',\n forceEnvironment,\n showTimestamp = false,\n timestampFormat = 'time',\n enabledNamespaces,\n _namespaceName,\n } = options;\n\n // 환경 감지\n this.environment = forceEnvironment || detectEnvironment(customHostnamePatterns);\n this.enabledEnvironments = new Set(enabledEnvironments);\n this.prefix = prefix;\n this.showTimestamp = showTimestamp;\n this.timestampFormat = timestampFormat;\n this.namespaces = new Map();\n this.namespaceName = _namespaceName;\n this.namespaceFilter = enabledNamespaces;\n\n // 환경 기반 활성화 체크\n const envEnabled = this.enabledEnvironments.has(this.environment);\n\n // 네임스페이스 필터링 체크\n const namespaceEnabled = this.isNamespaceEnabled();\n\n this.isEnabled = envEnabled && namespaceEnabled;\n }\n\n /**\n * 현재 감지된 환경을 반환\n */\n getEnvironment(): Environment {\n return this.environment;\n }\n\n /**\n * 로깅이 활성화되어 있는지 확인\n */\n isLoggingEnabled(): boolean {\n return this.isEnabled;\n }\n\n /**\n * 네임스페이스별 로거 인스턴스 생성\n * @param name - 네임스페이스 이름\n * @returns 네임스페이스 로거 인스턴스\n */\n namespace(name: string): Develog {\n // 이미 생성된 네임스페이스가 있으면 재사용\n if (this.namespaces.has(name)) {\n return this.namespaces.get(name)!;\n }\n\n // 계층 구조 지원: 부모 네임스페이스가 있으면 연결\n const fullNamespace = this.namespaceName ? `${this.namespaceName}:${name}` : name;\n\n // 새로운 네임스페이스 로거 생성\n const namespacedLogger = new Develog({\n enabledEnvironments: Array.from(this.enabledEnvironments),\n prefix: this.prefix,\n forceEnvironment: this.environment,\n showTimestamp: this.showTimestamp,\n timestampFormat: this.timestampFormat,\n enabledNamespaces: this.namespaceFilter,\n _namespaceName: fullNamespace,\n });\n\n this.namespaces.set(name, namespacedLogger);\n return namespacedLogger;\n }\n\n /**\n * 현재 네임스페이스가 활성화되어 있는지 확인\n */\n private isNamespaceEnabled(): boolean {\n // 네임스페이스 필터가 없으면 모두 활성화\n if (!this.namespaceFilter || this.namespaceFilter.length === 0) {\n return true;\n }\n\n // 네임스페이스가 없는 루트 로거는 항상 활성화\n if (!this.namespaceName) {\n return true;\n }\n\n // '*'는 모든 네임스페이스 활성화\n if (this.namespaceFilter.includes('*')) {\n return true;\n }\n\n // 정확한 매칭 확인\n if (this.namespaceFilter.includes(this.namespaceName)) {\n return true;\n }\n\n // 와일드카드 패턴 매칭\n for (const pattern of this.namespaceFilter) {\n if (pattern.endsWith(':*')) {\n const prefix = pattern.slice(0, -2);\n if (this.namespaceName === prefix || this.namespaceName.startsWith(`${prefix}:`)) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * 로그 출력 앞에 붙을 prefix 생성\n */\n private getLogPrefix(): string {\n let prefix = this.prefix;\n\n // 네임스페이스 추가\n if (this.namespaceName) {\n prefix = `${prefix}:${this.namespaceName}`;\n }\n\n // 타임스탬프 추가\n if (this.showTimestamp) {\n const timestamp = formatTimestamp(this.timestampFormat);\n prefix = `${prefix} [${timestamp}]`;\n }\n\n return prefix;\n }\n\n /**\n * 일반 로그 출력\n */\n log(...args: unknown[]): void {\n this.logWithLevel('log', ...args);\n }\n\n /**\n * 정보 로그 출력\n */\n info(...args: unknown[]): void {\n this.logWithLevel('info', ...args);\n }\n\n /**\n * 경고 로그 출력\n */\n warn(...args: unknown[]): void {\n this.logWithLevel('warn', ...args);\n }\n\n /**\n * 에러 로그 출력\n */\n error(...args: unknown[]): void {\n this.logWithLevel('error', ...args);\n }\n\n /**\n * 디버그 로그 출력\n */\n debug(...args: unknown[]): void {\n this.logWithLevel('debug', ...args);\n }\n\n /**\n * 그룹 시작\n */\n group(label?: string): void {\n if (!this.isEnabled) return;\n if (label) {\n console.group(this.formatMessage(label));\n } else {\n console.group();\n }\n }\n\n /**\n * 그룹 시작 (접혀있는 상태)\n */\n groupCollapsed(label?: string): void {\n if (!this.isEnabled) return;\n if (label) {\n console.groupCollapsed(this.formatMessage(label));\n } else {\n console.groupCollapsed();\n }\n }\n\n /**\n * 그룹 종료\n */\n groupEnd(): void {\n if (!this.isEnabled) return;\n console.groupEnd();\n }\n\n /**\n * 테이블 형태로 출력\n */\n table(data: unknown): void {\n if (!this.isEnabled) return;\n console.log(this.getLogPrefix());\n console.table(data);\n }\n\n /**\n * 시간 측정 시작\n */\n time(label: string): void {\n if (!this.isEnabled) return;\n console.time(this.formatMessage(label));\n }\n\n /**\n * 시간 측정 종료 및 출력\n */\n timeEnd(label: string): void {\n if (!this.isEnabled) return;\n console.timeEnd(this.formatMessage(label));\n }\n\n /**\n * 실행 횟수 카운트\n */\n count(label?: string): void {\n if (!this.isEnabled) return;\n if (label) {\n console.count(this.formatMessage(label));\n } else {\n console.count(this.prefix);\n }\n }\n\n /**\n * 카운트 초기화\n */\n countReset(label?: string): void {\n if (!this.isEnabled) return;\n if (label) {\n console.countReset(this.formatMessage(label));\n } else {\n console.countReset(this.prefix);\n }\n }\n\n /**\n * 콘솔 지우기\n */\n clear(): void {\n if (!this.isEnabled) return;\n console.clear();\n }\n\n /**\n * 레벨에 따른 로그 출력\n */\n private logWithLevel(level: LogLevel, ...args: unknown[]): void {\n if (!this.isEnabled) return;\n\n const consoleMethod = console[level] || console.log;\n const logPrefix = this.getLogPrefix();\n consoleMethod(logPrefix, ...args);\n }\n\n /**\n * 메시지에 prefix 추가\n */\n private formatMessage(message: string): string {\n const logPrefix = this.getLogPrefix();\n return `${logPrefix} ${message}`;\n }\n}\n\n/**\n * 기본 인스턴스 생성 및 export\n */\nexport const develog = new Develog();\n"]}
@@ -0,0 +1,186 @@
1
+ /**
2
+ * 실행 환경을 나타내는 타입
3
+ */
4
+ type Environment = 'local' | 'dev' | 'stage' | 'production' | 'unknown';
5
+ /**
6
+ * 타임스탬프 포맷 타입
7
+ */
8
+ type TimestampFormat = 'time' | 'datetime' | 'iso' | 'ms';
9
+ /**
10
+ * Logger 설정 옵션
11
+ */
12
+ interface LoggerOptions {
13
+ /**
14
+ * 로깅이 활성화될 환경 목록
15
+ * @default ['local', 'dev', 'stage']
16
+ */
17
+ enabledEnvironments?: Environment[];
18
+ /**
19
+ * 환경 감지에 사용할 커스텀 hostname 패턴
20
+ */
21
+ customHostnamePatterns?: {
22
+ [key in Environment]?: RegExp;
23
+ };
24
+ /**
25
+ * 로그 출력 앞에 붙을 prefix
26
+ * @default '[develog]'
27
+ */
28
+ prefix?: string;
29
+ /**
30
+ * 강제로 환경을 설정 (자동 감지 무시)
31
+ */
32
+ forceEnvironment?: Environment;
33
+ /**
34
+ * 타임스탬프 표시 여부
35
+ * @default false
36
+ */
37
+ showTimestamp?: boolean;
38
+ /**
39
+ * 타임스탬프 포맷
40
+ * - 'time': HH:MM:SS
41
+ * - 'datetime': YYYY-MM-DD HH:MM:SS
42
+ * - 'iso': ISO 8601 형식
43
+ * - 'ms': Unix timestamp (밀리초)
44
+ * @default 'time'
45
+ */
46
+ timestampFormat?: TimestampFormat;
47
+ /**
48
+ * 활성화할 네임스페이스 목록
49
+ * - 문자열 배열: 정확한 매칭 ['API', 'DB']
50
+ * - 와일드카드 지원: ['API:*', 'DB']
51
+ * - '*'는 모든 네임스페이스 활성화
52
+ * @default undefined (모든 네임스페이스 활성화)
53
+ */
54
+ enabledNamespaces?: string[];
55
+ /**
56
+ * 내부 전용: 현재 네임스페이스 이름
57
+ * @internal
58
+ */
59
+ _namespaceName?: string;
60
+ }
61
+ /**
62
+ * 로그 레벨
63
+ */
64
+ type LogLevel = 'log' | 'info' | 'warn' | 'error' | 'debug';
65
+
66
+ /**
67
+ * develog - 브라우저 환경 기반 로거
68
+ */
69
+ declare class Develog {
70
+ private readonly environment;
71
+ private readonly enabledEnvironments;
72
+ private readonly prefix;
73
+ private readonly isEnabled;
74
+ private readonly showTimestamp;
75
+ private readonly timestampFormat;
76
+ private readonly namespaces;
77
+ private readonly namespaceName?;
78
+ private readonly namespaceFilter?;
79
+ constructor(options?: LoggerOptions);
80
+ /**
81
+ * 현재 감지된 환경을 반환
82
+ */
83
+ getEnvironment(): Environment;
84
+ /**
85
+ * 로깅이 활성화되어 있는지 확인
86
+ */
87
+ isLoggingEnabled(): boolean;
88
+ /**
89
+ * 네임스페이스별 로거 인스턴스 생성
90
+ * @param name - 네임스페이스 이름
91
+ * @returns 네임스페이스 로거 인스턴스
92
+ */
93
+ namespace(name: string): Develog;
94
+ /**
95
+ * 현재 네임스페이스가 활성화되어 있는지 확인
96
+ */
97
+ private isNamespaceEnabled;
98
+ /**
99
+ * 로그 출력 앞에 붙을 prefix 생성
100
+ */
101
+ private getLogPrefix;
102
+ /**
103
+ * 일반 로그 출력
104
+ */
105
+ log(...args: unknown[]): void;
106
+ /**
107
+ * 정보 로그 출력
108
+ */
109
+ info(...args: unknown[]): void;
110
+ /**
111
+ * 경고 로그 출력
112
+ */
113
+ warn(...args: unknown[]): void;
114
+ /**
115
+ * 에러 로그 출력
116
+ */
117
+ error(...args: unknown[]): void;
118
+ /**
119
+ * 디버그 로그 출력
120
+ */
121
+ debug(...args: unknown[]): void;
122
+ /**
123
+ * 그룹 시작
124
+ */
125
+ group(label?: string): void;
126
+ /**
127
+ * 그룹 시작 (접혀있는 상태)
128
+ */
129
+ groupCollapsed(label?: string): void;
130
+ /**
131
+ * 그룹 종료
132
+ */
133
+ groupEnd(): void;
134
+ /**
135
+ * 테이블 형태로 출력
136
+ */
137
+ table(data: unknown): void;
138
+ /**
139
+ * 시간 측정 시작
140
+ */
141
+ time(label: string): void;
142
+ /**
143
+ * 시간 측정 종료 및 출력
144
+ */
145
+ timeEnd(label: string): void;
146
+ /**
147
+ * 실행 횟수 카운트
148
+ */
149
+ count(label?: string): void;
150
+ /**
151
+ * 카운트 초기화
152
+ */
153
+ countReset(label?: string): void;
154
+ /**
155
+ * 콘솔 지우기
156
+ */
157
+ clear(): void;
158
+ /**
159
+ * 레벨에 따른 로그 출력
160
+ */
161
+ private logWithLevel;
162
+ /**
163
+ * 메시지에 prefix 추가
164
+ */
165
+ private formatMessage;
166
+ }
167
+ /**
168
+ * 기본 인스턴스 생성 및 export
169
+ */
170
+ declare const develog: Develog;
171
+
172
+ /**
173
+ * 현재 브라우저의 hostname 또는 IP를 기반으로 실행 환경을 감지
174
+ * @param customPatterns - 커스텀 hostname 패턴
175
+ * @returns 감지된 환경
176
+ */
177
+ declare function detectEnvironment(customPatterns?: Partial<Record<Environment, RegExp>>): Environment;
178
+
179
+ /**
180
+ * 현재 시간을 지정된 포맷으로 변환
181
+ * @param format - 타임스탬프 포맷
182
+ * @returns 포맷된 타임스탬프 문자열
183
+ */
184
+ declare function formatTimestamp(format?: TimestampFormat): string;
185
+
186
+ export { Develog, type Environment, type LogLevel, type LoggerOptions, type TimestampFormat, detectEnvironment, develog, formatTimestamp };
@@ -0,0 +1,186 @@
1
+ /**
2
+ * 실행 환경을 나타내는 타입
3
+ */
4
+ type Environment = 'local' | 'dev' | 'stage' | 'production' | 'unknown';
5
+ /**
6
+ * 타임스탬프 포맷 타입
7
+ */
8
+ type TimestampFormat = 'time' | 'datetime' | 'iso' | 'ms';
9
+ /**
10
+ * Logger 설정 옵션
11
+ */
12
+ interface LoggerOptions {
13
+ /**
14
+ * 로깅이 활성화될 환경 목록
15
+ * @default ['local', 'dev', 'stage']
16
+ */
17
+ enabledEnvironments?: Environment[];
18
+ /**
19
+ * 환경 감지에 사용할 커스텀 hostname 패턴
20
+ */
21
+ customHostnamePatterns?: {
22
+ [key in Environment]?: RegExp;
23
+ };
24
+ /**
25
+ * 로그 출력 앞에 붙을 prefix
26
+ * @default '[develog]'
27
+ */
28
+ prefix?: string;
29
+ /**
30
+ * 강제로 환경을 설정 (자동 감지 무시)
31
+ */
32
+ forceEnvironment?: Environment;
33
+ /**
34
+ * 타임스탬프 표시 여부
35
+ * @default false
36
+ */
37
+ showTimestamp?: boolean;
38
+ /**
39
+ * 타임스탬프 포맷
40
+ * - 'time': HH:MM:SS
41
+ * - 'datetime': YYYY-MM-DD HH:MM:SS
42
+ * - 'iso': ISO 8601 형식
43
+ * - 'ms': Unix timestamp (밀리초)
44
+ * @default 'time'
45
+ */
46
+ timestampFormat?: TimestampFormat;
47
+ /**
48
+ * 활성화할 네임스페이스 목록
49
+ * - 문자열 배열: 정확한 매칭 ['API', 'DB']
50
+ * - 와일드카드 지원: ['API:*', 'DB']
51
+ * - '*'는 모든 네임스페이스 활성화
52
+ * @default undefined (모든 네임스페이스 활성화)
53
+ */
54
+ enabledNamespaces?: string[];
55
+ /**
56
+ * 내부 전용: 현재 네임스페이스 이름
57
+ * @internal
58
+ */
59
+ _namespaceName?: string;
60
+ }
61
+ /**
62
+ * 로그 레벨
63
+ */
64
+ type LogLevel = 'log' | 'info' | 'warn' | 'error' | 'debug';
65
+
66
+ /**
67
+ * develog - 브라우저 환경 기반 로거
68
+ */
69
+ declare class Develog {
70
+ private readonly environment;
71
+ private readonly enabledEnvironments;
72
+ private readonly prefix;
73
+ private readonly isEnabled;
74
+ private readonly showTimestamp;
75
+ private readonly timestampFormat;
76
+ private readonly namespaces;
77
+ private readonly namespaceName?;
78
+ private readonly namespaceFilter?;
79
+ constructor(options?: LoggerOptions);
80
+ /**
81
+ * 현재 감지된 환경을 반환
82
+ */
83
+ getEnvironment(): Environment;
84
+ /**
85
+ * 로깅이 활성화되어 있는지 확인
86
+ */
87
+ isLoggingEnabled(): boolean;
88
+ /**
89
+ * 네임스페이스별 로거 인스턴스 생성
90
+ * @param name - 네임스페이스 이름
91
+ * @returns 네임스페이스 로거 인스턴스
92
+ */
93
+ namespace(name: string): Develog;
94
+ /**
95
+ * 현재 네임스페이스가 활성화되어 있는지 확인
96
+ */
97
+ private isNamespaceEnabled;
98
+ /**
99
+ * 로그 출력 앞에 붙을 prefix 생성
100
+ */
101
+ private getLogPrefix;
102
+ /**
103
+ * 일반 로그 출력
104
+ */
105
+ log(...args: unknown[]): void;
106
+ /**
107
+ * 정보 로그 출력
108
+ */
109
+ info(...args: unknown[]): void;
110
+ /**
111
+ * 경고 로그 출력
112
+ */
113
+ warn(...args: unknown[]): void;
114
+ /**
115
+ * 에러 로그 출력
116
+ */
117
+ error(...args: unknown[]): void;
118
+ /**
119
+ * 디버그 로그 출력
120
+ */
121
+ debug(...args: unknown[]): void;
122
+ /**
123
+ * 그룹 시작
124
+ */
125
+ group(label?: string): void;
126
+ /**
127
+ * 그룹 시작 (접혀있는 상태)
128
+ */
129
+ groupCollapsed(label?: string): void;
130
+ /**
131
+ * 그룹 종료
132
+ */
133
+ groupEnd(): void;
134
+ /**
135
+ * 테이블 형태로 출력
136
+ */
137
+ table(data: unknown): void;
138
+ /**
139
+ * 시간 측정 시작
140
+ */
141
+ time(label: string): void;
142
+ /**
143
+ * 시간 측정 종료 및 출력
144
+ */
145
+ timeEnd(label: string): void;
146
+ /**
147
+ * 실행 횟수 카운트
148
+ */
149
+ count(label?: string): void;
150
+ /**
151
+ * 카운트 초기화
152
+ */
153
+ countReset(label?: string): void;
154
+ /**
155
+ * 콘솔 지우기
156
+ */
157
+ clear(): void;
158
+ /**
159
+ * 레벨에 따른 로그 출력
160
+ */
161
+ private logWithLevel;
162
+ /**
163
+ * 메시지에 prefix 추가
164
+ */
165
+ private formatMessage;
166
+ }
167
+ /**
168
+ * 기본 인스턴스 생성 및 export
169
+ */
170
+ declare const develog: Develog;
171
+
172
+ /**
173
+ * 현재 브라우저의 hostname 또는 IP를 기반으로 실행 환경을 감지
174
+ * @param customPatterns - 커스텀 hostname 패턴
175
+ * @returns 감지된 환경
176
+ */
177
+ declare function detectEnvironment(customPatterns?: Partial<Record<Environment, RegExp>>): Environment;
178
+
179
+ /**
180
+ * 현재 시간을 지정된 포맷으로 변환
181
+ * @param format - 타임스탬프 포맷
182
+ * @returns 포맷된 타임스탬프 문자열
183
+ */
184
+ declare function formatTimestamp(format?: TimestampFormat): string;
185
+
186
+ export { Develog, type Environment, type LogLevel, type LoggerOptions, type TimestampFormat, detectEnvironment, develog, formatTimestamp };
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ var v={local:/^(localhost|127\.0\.0\.1|0\.0\.0\.0|::1|\[::1\])/,dev:/(^|\.)(dev|development)\./,stage:/(^|\.)(stage|staging)\./,production:/(^|\.)(prod|production|www)\./,unknown:/.*/};function a(n){if(typeof window>"u"||!window.location)return "unknown";let e=window.location.hostname,t={...v,...n};return t.local.test(e)?"local":t.dev.test(e)?"dev":t.stage.test(e)?"stage":t.production.test(e)?"production":"unknown"}function p(n="time"){let e=new Date;switch(n){case "time":return m(e);case "datetime":return E(e);case "iso":return e.toISOString();case "ms":return e.getTime().toString();default:return m(e)}}function m(n){let e=o(n.getHours()),t=o(n.getMinutes()),s=o(n.getSeconds());return `${e}:${t}:${s}`}function E(n){let e=n.getFullYear(),t=o(n.getMonth()+1),s=o(n.getDate()),i=m(n);return `${e}-${t}-${s} ${i}`}function o(n){return n.toString().padStart(2,"0")}var r=class n{constructor(e={}){let{enabledEnvironments:t=["local","dev","stage"],customHostnamePatterns:s,prefix:i="[develog]",forceEnvironment:l,showTimestamp:c=false,timestampFormat:g="time",enabledNamespaces:d,_namespaceName:h}=e;this.environment=l||a(s),this.enabledEnvironments=new Set(t),this.prefix=i,this.showTimestamp=c,this.timestampFormat=g,this.namespaces=new Map,this.namespaceName=h,this.namespaceFilter=d;let u=this.enabledEnvironments.has(this.environment),f=this.isNamespaceEnabled();this.isEnabled=u&&f;}getEnvironment(){return this.environment}isLoggingEnabled(){return this.isEnabled}namespace(e){if(this.namespaces.has(e))return this.namespaces.get(e);let t=this.namespaceName?`${this.namespaceName}:${e}`:e,s=new n({enabledEnvironments:Array.from(this.enabledEnvironments),prefix:this.prefix,forceEnvironment:this.environment,showTimestamp:this.showTimestamp,timestampFormat:this.timestampFormat,enabledNamespaces:this.namespaceFilter,_namespaceName:t});return this.namespaces.set(e,s),s}isNamespaceEnabled(){if(!this.namespaceFilter||this.namespaceFilter.length===0||!this.namespaceName||this.namespaceFilter.includes("*")||this.namespaceFilter.includes(this.namespaceName))return true;for(let e of this.namespaceFilter)if(e.endsWith(":*")){let t=e.slice(0,-2);if(this.namespaceName===t||this.namespaceName.startsWith(`${t}:`))return true}return false}getLogPrefix(){let e=this.prefix;if(this.namespaceName&&(e=`${e}:${this.namespaceName}`),this.showTimestamp){let t=p(this.timestampFormat);e=`${e} [${t}]`;}return e}log(...e){this.logWithLevel("log",...e);}info(...e){this.logWithLevel("info",...e);}warn(...e){this.logWithLevel("warn",...e);}error(...e){this.logWithLevel("error",...e);}debug(...e){this.logWithLevel("debug",...e);}group(e){this.isEnabled&&(e?console.group(this.formatMessage(e)):console.group());}groupCollapsed(e){this.isEnabled&&(e?console.groupCollapsed(this.formatMessage(e)):console.groupCollapsed());}groupEnd(){this.isEnabled&&console.groupEnd();}table(e){this.isEnabled&&(console.log(this.getLogPrefix()),console.table(e));}time(e){this.isEnabled&&console.time(this.formatMessage(e));}timeEnd(e){this.isEnabled&&console.timeEnd(this.formatMessage(e));}count(e){this.isEnabled&&console.count(e?this.formatMessage(e):this.prefix);}countReset(e){this.isEnabled&&console.countReset(e?this.formatMessage(e):this.prefix);}clear(){this.isEnabled&&console.clear();}logWithLevel(e,...t){if(!this.isEnabled)return;let s=console[e]||console.log,i=this.getLogPrefix();s(i,...t);}formatMessage(e){return `${this.getLogPrefix()} ${e}`}},w=new r;export{r as Develog,a as detectEnvironment,w as develog,p as formatTimestamp};//# sourceMappingURL=index.js.map
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/environment.ts","../src/utils.ts","../src/logger.ts"],"names":["DEFAULT_HOSTNAME_PATTERNS","detectEnvironment","customPatterns","hostname","patterns","formatTimestamp","format","now","formatTime","formatDateTime","date","hours","padZero","minutes","seconds","year","month","day","timeStr","num","Develog","_Develog","options","enabledEnvironments","customHostnamePatterns","prefix","forceEnvironment","showTimestamp","timestampFormat","enabledNamespaces","_namespaceName","envEnabled","namespaceEnabled","name","fullNamespace","namespacedLogger","pattern","timestamp","args","label","data","level","consoleMethod","logPrefix","message","develog"],"mappings":"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","file":"index.js","sourcesContent":["import type { Environment } from './types';\n\n/**\n * 기본 hostname 패턴 정의\n */\nconst DEFAULT_HOSTNAME_PATTERNS: Record<Environment, RegExp> = {\n local: /^(localhost|127\\.0\\.0\\.1|0\\.0\\.0\\.0|::1|\\[::1\\])/,\n dev: /(^|\\.)(dev|development)\\./,\n stage: /(^|\\.)(stage|staging)\\./,\n production: /(^|\\.)(prod|production|www)\\./,\n unknown: /.*/,\n};\n\n/**\n * 현재 브라우저의 hostname 또는 IP를 기반으로 실행 환경을 감지\n * @param customPatterns - 커스텀 hostname 패턴\n * @returns 감지된 환경\n */\nexport function detectEnvironment(\n customPatterns?: Partial<Record<Environment, RegExp>>,\n): Environment {\n // 브라우저 환경이 아닌 경우\n if (typeof window === 'undefined' || !window.location) {\n return 'unknown';\n }\n\n const hostname = window.location.hostname;\n const patterns = { ...DEFAULT_HOSTNAME_PATTERNS, ...customPatterns };\n\n // local 환경 체크 (최우선)\n if (patterns.local.test(hostname)) {\n return 'local';\n }\n\n // dev 환경 체크\n if (patterns.dev.test(hostname)) {\n return 'dev';\n }\n\n // stage 환경 체크\n if (patterns.stage.test(hostname)) {\n return 'stage';\n }\n\n // production 환경 체크\n if (patterns.production.test(hostname)) {\n return 'production';\n }\n\n // 매칭되지 않으면 unknown\n return 'unknown';\n}\n","import type { TimestampFormat } from './types';\n\n/**\n * 현재 시간을 지정된 포맷으로 변환\n * @param format - 타임스탬프 포맷\n * @returns 포맷된 타임스탬프 문자열\n */\nexport function formatTimestamp(format: TimestampFormat = 'time'): string {\n const now = new Date();\n\n switch (format) {\n case 'time':\n return formatTime(now);\n case 'datetime':\n return formatDateTime(now);\n case 'iso':\n return now.toISOString();\n case 'ms':\n return now.getTime().toString();\n default:\n return formatTime(now);\n }\n}\n\n/**\n * HH:MM:SS 포맷\n */\nfunction formatTime(date: Date): string {\n const hours = padZero(date.getHours());\n const minutes = padZero(date.getMinutes());\n const seconds = padZero(date.getSeconds());\n return `${hours}:${minutes}:${seconds}`;\n}\n\n/**\n * YYYY-MM-DD HH:MM:SS 포맷\n */\nfunction formatDateTime(date: Date): string {\n const year = date.getFullYear();\n const month = padZero(date.getMonth() + 1);\n const day = padZero(date.getDate());\n const timeStr = formatTime(date);\n return `${year}-${month}-${day} ${timeStr}`;\n}\n\n/**\n * 숫자를 두 자리로 패딩\n */\nfunction padZero(num: number): string {\n return num.toString().padStart(2, '0');\n}\n","import { detectEnvironment } from './environment';\nimport type { Environment, LoggerOptions, LogLevel, TimestampFormat } from './types';\nimport { formatTimestamp } from './utils';\n\n/**\n * develog - 브라우저 환경 기반 로거\n */\nexport class Develog {\n private readonly environment: Environment;\n private readonly enabledEnvironments: Set<Environment>;\n private readonly prefix: string;\n private readonly isEnabled: boolean;\n private readonly showTimestamp: boolean;\n private readonly timestampFormat: TimestampFormat;\n private readonly namespaces: Map<string, Develog>;\n private readonly namespaceName?: string;\n private readonly namespaceFilter?: string[];\n\n constructor(options: LoggerOptions = {}) {\n const {\n enabledEnvironments = ['local', 'dev', 'stage'],\n customHostnamePatterns,\n prefix = '[develog]',\n forceEnvironment,\n showTimestamp = false,\n timestampFormat = 'time',\n enabledNamespaces,\n _namespaceName,\n } = options;\n\n // 환경 감지\n this.environment = forceEnvironment || detectEnvironment(customHostnamePatterns);\n this.enabledEnvironments = new Set(enabledEnvironments);\n this.prefix = prefix;\n this.showTimestamp = showTimestamp;\n this.timestampFormat = timestampFormat;\n this.namespaces = new Map();\n this.namespaceName = _namespaceName;\n this.namespaceFilter = enabledNamespaces;\n\n // 환경 기반 활성화 체크\n const envEnabled = this.enabledEnvironments.has(this.environment);\n\n // 네임스페이스 필터링 체크\n const namespaceEnabled = this.isNamespaceEnabled();\n\n this.isEnabled = envEnabled && namespaceEnabled;\n }\n\n /**\n * 현재 감지된 환경을 반환\n */\n getEnvironment(): Environment {\n return this.environment;\n }\n\n /**\n * 로깅이 활성화되어 있는지 확인\n */\n isLoggingEnabled(): boolean {\n return this.isEnabled;\n }\n\n /**\n * 네임스페이스별 로거 인스턴스 생성\n * @param name - 네임스페이스 이름\n * @returns 네임스페이스 로거 인스턴스\n */\n namespace(name: string): Develog {\n // 이미 생성된 네임스페이스가 있으면 재사용\n if (this.namespaces.has(name)) {\n return this.namespaces.get(name)!;\n }\n\n // 계층 구조 지원: 부모 네임스페이스가 있으면 연결\n const fullNamespace = this.namespaceName ? `${this.namespaceName}:${name}` : name;\n\n // 새로운 네임스페이스 로거 생성\n const namespacedLogger = new Develog({\n enabledEnvironments: Array.from(this.enabledEnvironments),\n prefix: this.prefix,\n forceEnvironment: this.environment,\n showTimestamp: this.showTimestamp,\n timestampFormat: this.timestampFormat,\n enabledNamespaces: this.namespaceFilter,\n _namespaceName: fullNamespace,\n });\n\n this.namespaces.set(name, namespacedLogger);\n return namespacedLogger;\n }\n\n /**\n * 현재 네임스페이스가 활성화되어 있는지 확인\n */\n private isNamespaceEnabled(): boolean {\n // 네임스페이스 필터가 없으면 모두 활성화\n if (!this.namespaceFilter || this.namespaceFilter.length === 0) {\n return true;\n }\n\n // 네임스페이스가 없는 루트 로거는 항상 활성화\n if (!this.namespaceName) {\n return true;\n }\n\n // '*'는 모든 네임스페이스 활성화\n if (this.namespaceFilter.includes('*')) {\n return true;\n }\n\n // 정확한 매칭 확인\n if (this.namespaceFilter.includes(this.namespaceName)) {\n return true;\n }\n\n // 와일드카드 패턴 매칭\n for (const pattern of this.namespaceFilter) {\n if (pattern.endsWith(':*')) {\n const prefix = pattern.slice(0, -2);\n if (this.namespaceName === prefix || this.namespaceName.startsWith(`${prefix}:`)) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * 로그 출력 앞에 붙을 prefix 생성\n */\n private getLogPrefix(): string {\n let prefix = this.prefix;\n\n // 네임스페이스 추가\n if (this.namespaceName) {\n prefix = `${prefix}:${this.namespaceName}`;\n }\n\n // 타임스탬프 추가\n if (this.showTimestamp) {\n const timestamp = formatTimestamp(this.timestampFormat);\n prefix = `${prefix} [${timestamp}]`;\n }\n\n return prefix;\n }\n\n /**\n * 일반 로그 출력\n */\n log(...args: unknown[]): void {\n this.logWithLevel('log', ...args);\n }\n\n /**\n * 정보 로그 출력\n */\n info(...args: unknown[]): void {\n this.logWithLevel('info', ...args);\n }\n\n /**\n * 경고 로그 출력\n */\n warn(...args: unknown[]): void {\n this.logWithLevel('warn', ...args);\n }\n\n /**\n * 에러 로그 출력\n */\n error(...args: unknown[]): void {\n this.logWithLevel('error', ...args);\n }\n\n /**\n * 디버그 로그 출력\n */\n debug(...args: unknown[]): void {\n this.logWithLevel('debug', ...args);\n }\n\n /**\n * 그룹 시작\n */\n group(label?: string): void {\n if (!this.isEnabled) return;\n if (label) {\n console.group(this.formatMessage(label));\n } else {\n console.group();\n }\n }\n\n /**\n * 그룹 시작 (접혀있는 상태)\n */\n groupCollapsed(label?: string): void {\n if (!this.isEnabled) return;\n if (label) {\n console.groupCollapsed(this.formatMessage(label));\n } else {\n console.groupCollapsed();\n }\n }\n\n /**\n * 그룹 종료\n */\n groupEnd(): void {\n if (!this.isEnabled) return;\n console.groupEnd();\n }\n\n /**\n * 테이블 형태로 출력\n */\n table(data: unknown): void {\n if (!this.isEnabled) return;\n console.log(this.getLogPrefix());\n console.table(data);\n }\n\n /**\n * 시간 측정 시작\n */\n time(label: string): void {\n if (!this.isEnabled) return;\n console.time(this.formatMessage(label));\n }\n\n /**\n * 시간 측정 종료 및 출력\n */\n timeEnd(label: string): void {\n if (!this.isEnabled) return;\n console.timeEnd(this.formatMessage(label));\n }\n\n /**\n * 실행 횟수 카운트\n */\n count(label?: string): void {\n if (!this.isEnabled) return;\n if (label) {\n console.count(this.formatMessage(label));\n } else {\n console.count(this.prefix);\n }\n }\n\n /**\n * 카운트 초기화\n */\n countReset(label?: string): void {\n if (!this.isEnabled) return;\n if (label) {\n console.countReset(this.formatMessage(label));\n } else {\n console.countReset(this.prefix);\n }\n }\n\n /**\n * 콘솔 지우기\n */\n clear(): void {\n if (!this.isEnabled) return;\n console.clear();\n }\n\n /**\n * 레벨에 따른 로그 출력\n */\n private logWithLevel(level: LogLevel, ...args: unknown[]): void {\n if (!this.isEnabled) return;\n\n const consoleMethod = console[level] || console.log;\n const logPrefix = this.getLogPrefix();\n consoleMethod(logPrefix, ...args);\n }\n\n /**\n * 메시지에 prefix 추가\n */\n private formatMessage(message: string): string {\n const logPrefix = this.getLogPrefix();\n return `${logPrefix} ${message}`;\n }\n}\n\n/**\n * 기본 인스턴스 생성 및 export\n */\nexport const develog = new Develog();\n"]}
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "develog",
3
+ "version": "1.0.2",
4
+ "description": "A lightweight frontend logger that runs only in local/dev environments.",
5
+ "license": "MIT",
6
+ "author": "junjuny",
7
+ "homepage": "https://github.com/junjuny0227/develog#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/junjuny0227/develog.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/junjuny0227/develog/issues"
14
+ },
15
+ "keywords": [
16
+ "logger",
17
+ "logging",
18
+ "frontend",
19
+ "console",
20
+ "debug",
21
+ "dev",
22
+ "development",
23
+ "local",
24
+ "browser",
25
+ "typescript"
26
+ ],
27
+ "type": "module",
28
+ "main": "./dist/index.cjs",
29
+ "module": "./dist/index.js",
30
+ "types": "./dist/index.d.ts",
31
+ "exports": {
32
+ ".": {
33
+ "import": {
34
+ "types": "./dist/index.d.ts",
35
+ "default": "./dist/index.js"
36
+ },
37
+ "require": {
38
+ "types": "./dist/index.d.cts",
39
+ "default": "./dist/index.cjs"
40
+ }
41
+ }
42
+ },
43
+ "files": [
44
+ "dist",
45
+ "README.md",
46
+ "LICENSE.md"
47
+ ],
48
+ "devDependencies": {
49
+ "@eslint/js": "^9.39.2",
50
+ "@types/node": "^25.0.3",
51
+ "@vitest/coverage-v8": "^4.0.16",
52
+ "@vitest/ui": "^4.0.16",
53
+ "eslint": "^9.39.2",
54
+ "eslint-config-prettier": "^10.1.8",
55
+ "eslint-plugin-prettier": "^5.5.4",
56
+ "happy-dom": "^20.0.11",
57
+ "prettier": "^3.7.4",
58
+ "tsup": "^8.5.1",
59
+ "typescript": "^5.9.3",
60
+ "typescript-eslint": "^8.50.1",
61
+ "vitest": "^4.0.16"
62
+ },
63
+ "scripts": {
64
+ "build": "tsup",
65
+ "dev": "tsup --watch",
66
+ "test": "vitest run",
67
+ "test:watch": "vitest",
68
+ "test:ui": "vitest --ui",
69
+ "test:coverage": "vitest run --coverage",
70
+ "lint": "eslint .",
71
+ "lint:fix": "eslint . --fix",
72
+ "type-check": "tsc --noEmit",
73
+ "format": "prettier --write .",
74
+ "format:check": "prettier --check ."
75
+ }
76
+ }