colorino 0.6.0 → 0.7.0

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/README.md CHANGED
@@ -1,334 +1,262 @@
1
- # <a id="0"></a>🎨 Colorino
2
-
3
- **The zero-configuration, context-aware `console` logger for Node.js and the browser.**
4
-
5
- Colorino automatically adapts its palette to your terminal or browser DevTools theme.
6
-
7
- # <a id="0"></a>
8
-
9
- - [Why use Colorino?](#1)
10
- - [Features](#2)
11
- - [Installation](#3)
12
- - [Usage](#4)
13
- - [Quick Start](#4-1)
14
- - [Creating a Custom Logger](#4-2)
15
- - [Options & Theme Overrides](#4-3)
16
- - [Available Theme Presets](#4-3-1)
17
- - [Examples](#4-3-2)
18
- - [Customization](#4-4)
19
- - [Supported Environment Variables](#4-5)
20
- - [Colorino vs. Chalk](#5)
21
- - [API Reference](#6)
22
- - [1. `colorino` (default instance)](#6-1)
23
- - [2. `createColorino(palette?, options?)` (factory)](#6-2)
24
- - [Extending Colorino](#7)
25
- - [Why This Pattern?](#7-1)
26
- - [Contributing](#8)
27
- - [License](#9)
28
-
29
- <!-- Table of contents is made with https://github.com/eugene-khyst/md-toc-cli -->
30
-
31
- ## <a id="1"></a>Why use Colorino?
32
-
33
- Plain `console.log` is colorless and inconsistent. Libraries like `chalk` let you style strings, but you have to decorate every message and manually manage color choices.
34
-
35
- Colorino is different: it’s a "batteries-included" logging facade with beautiful, theme-aware colors and a familiar API—no learning curve, no configuration. Instantly upgrade your logs everywhere.
36
-
37
- ## <a id="2"></a>Features
38
-
39
- - 🎨 **Smart Theming:** Automatically detects *dark/light* mode and uses a coordinated color palette.
40
- - 🤝 **Familiar API:** If you know `console.log`, you already know Colorino: all standard log levels are supported.
41
- - 🔀 **Environment-Aware:** Works in **Node.js** (ANSI color and truecolor) and all major **Browsers** (CSS styles).
42
- - ⚡️ **Fast, Lightweight:** Minimal dependencies, works great in modern frameworks and CLIs.
43
- - 🔒 **Robust:** Handles bad inputs and weird environments safely.
44
- - 🛠️ **Customizable:** Override individual log colors for your own branding.
45
-
46
- ## <a id="3"></a>Installation
47
-
48
- ```bash
49
- npm install colorino
50
- ```
51
-
52
- ## <a id="4"></a>Usage
53
-
54
- ### <a id="4-1"></a>Quick Start
55
-
56
- Just import the default instance and log away!
57
-
58
- ```typescript
59
- import { colorino } from 'colorino'
60
-
61
- // All log levels automatically themed
62
- colorino.error('A critical error!')
63
- colorino.warn('A warning message.')
64
- colorino.info('Useful info logging.')
65
- colorino.log('A plain log.')
66
- colorino.debug('Debug with objects:', { x: 5, y: 9 })
67
- colorino.trace('Tracing app start...')
68
- ```
69
-
70
- ### <a id="4-2"></a>Creating a Custom Logger
71
-
72
- Need your own colors or different settings?
73
- Use the factory to create as many loggers as you want (each with its own palette and options):
74
-
75
- ```typescript
76
- import { createColorino } from 'colorino'
77
-
78
- const myLogger = createColorino(
79
- { // Palette (partial)
80
- error: '#ff007b',
81
- info: '#3498db'
82
- },
83
- { disableWarnings: true } // Options (see below)
84
- )
85
- myLogger.error('Critical!')
86
- myLogger.info('Rebranded info!')
87
- ```
88
-
89
- ### <a id="4-3"></a>Options & Theme Overrides
90
-
91
- `createColorino(palette?, options?)` accepts:
92
-
93
- | Option | Type | Default | Description |
94
- |-------------------|--------------------------------|---------|--------------------------------------------------------------------------------|
95
- | `disableWarnings` | `boolean` | `false` | Suppress warnings when color support can't be detected or is disabled. |
96
- | `theme` | `ThemeOption` (see below) | `'auto'`| Control the active color theme or force a specific mode. |
97
-
98
- **`theme` accepts three types of values:**
99
-
100
- 1. **`'auto'`** (Default): Automatically detects your terminal or browser theme (dark/light) and applies the matching default preset.
101
- 2. **`'dark' | 'light'`**: Forces the logger into a specific mode using the default preset for that mode.
102
- 3. **`ThemeName`**: Forces a specific built-in palette (e.g., `'dracula'`).
103
-
104
- #### <a id="4-3-1"></a>Available Theme Presets
105
-
106
- Pass any of these names to the `theme` option to use a specific palette:
107
-
108
- | Theme Name | Type | Description |
109
- |----------------------|-----------------|--------------------------------------------------|
110
- | `'dracula'` | **Dark** (High) | Vibrant pinks, purples, and cyans. |
111
- | `'catppuccin-mocha'` | **Dark** (Low) | *Default Dark.* Soothing pastel colors. |
112
- | `'github-light'` | **Light** (High)| *Default Light.* Clean, sharp, high-contrast. |
113
- | `'catppuccin-latte'` | **Light** (Low) | Warm, cozy light mode with soft colors. |
114
-
115
- #### <a id="4-3-2"></a>Examples
116
-
117
- **1. Force a specific mode (uses defaults):**
118
- Useful for CI/CD or environments where detection fails.
119
-
120
- ```typescript
121
- // Forces the default dark theme (Catppuccin Mocha)
122
- const darkLogger = createColorino({}, { theme: 'dark' })
123
- ```
124
-
125
- **2. Use a specific preset:**
126
- Instant branding with zero configuration.
127
-
128
- ```typescript
129
- // Forces the Dracula palette
130
- const draculaLogger = createColorino({}, { theme: 'dracula' })
131
- ```
132
-
133
- **3. Customize a preset:**
134
- Overlay your own colors on top of a built-in theme.
135
-
136
- ```typescript
137
- // Use GitHub Light but with a custom error color
138
- const myLogger = createColorino(
139
- { error: '#ff007b' },
140
- { theme: 'github-light' }
141
- )
142
- ```
143
-
144
- > **Tip:**
145
- > Forcing `'dark'` or `'light'` bypasses automatic theming, ensuring predictable colors in environments with unknown or unsupported theme detection (like some CI pipelines, dumb terminals, or minimal browsers).
146
-
147
- ### <a id="4-4"></a>Customization
148
-
149
- Use your brand colors by passing a partial palette to the `createColorino` factory. Any log levels you don't specify will use the smart theme defaults.
150
-
151
- ```typescript
152
- import { createColorino } from 'colorino'
153
-
154
- // Custom error color; others use theme defaults
155
- const myLogger = createColorino({ error: '#ff007b' })
156
-
157
- myLogger.error('Oh no!') // Uses your custom color
158
- myLogger.info('Still styled by theme.') // Uses the default theme color
159
- ```
160
-
161
- ### <a id="4-5"></a>Supported Environment Variables
162
-
163
- Colorino auto-detects your environment and color support, but you can override behavior using these standard environment variables (compatible with Chalk):
164
-
165
- | Variable | Effect | Example |
166
- |------------------|---------------------------------------------------|--------------------------|
167
- | `NO_COLOR` | Forces *no color* output | `NO_COLOR=1 node app.js` |
168
- | `FORCE_COLOR` | Forces color (`1`=ANSI, `2`=256, `3`=truecolor) | `FORCE_COLOR=3 node app.js` |
169
- | `CLICOLOR` | `"0"` disables color | `CLICOLOR=0 node app.js` |
170
- | `CLICOLOR_FORCE` | Non-`"0"` value enables color even if not a TTY | `CLICOLOR_FORCE=1 node app.js` |
171
- | `TERM` | Terminal type, can increase/decrease support | `TERM=xterm-256color` |
172
- | `COLORTERM` | `'truecolor'` or `'24bit'` enables truecolor | `COLORTERM=truecolor` |
173
- | `WT_SESSION` | Detected for Windows Terminal (enables color) | |
174
- | `CI` | Many CI platforms default to *no color* | `CI=1 node app.js` |
175
-
176
- ## <a id="5"></a>Colorino vs. Chalk
177
-
178
- | Feature | 🎨 **Colorino** | 🖍️ **Chalk** |
179
- |--------------------------|----------------------------|-----------------|
180
- | Out-of-box logs | ✔ themed, all log levels | ✘ string styling|
181
- | Zero-config | ✔ | ✘ manual, per-use|
182
- | Node + browser | ✔ | ✘ (Node only) |
183
- | CSS console logs | ✔ | ✘ |
184
- | Extensible / Composable | ✔ (via factory) | ✘ |
185
-
186
- ## <a id="6"></a>API Reference
187
-
188
- The `colorino` package exports two main items:
189
-
190
- ### <a id="6-1"></a>1. `colorino` (default instance)
191
-
192
- A pre-configured, zero-setup logger instance. Just import and use.
193
-
194
- - `.log(...args)`
195
- - `.info(...args)`
196
- - `.warn(...args)`
197
- - `.error(...args)`
198
- - `.debug(...args)`
199
- - `.trace(...args)`
200
-
201
- ### <a id="6-2"></a>2. `createColorino(palette?, options?)` (factory)
202
-
203
- A factory function to create your own customized logger instances.
204
-
205
- - `palette` (`Partial<Palette>`): An object to override default colors for specific log levels (e.g., `{ error: '#ff007b' }`).
206
- - `options` (`ColorinoOptions`): An object to control behavior:
207
- - `disableWarnings: boolean` (default `false`): Suppress warnings on environments with no color support.
208
- - `theme: 'dark' | 'light'` (default `auto`): Force a specific theme instead of auto-detecting.
209
-
210
- ## <a id="7"></a>Extending Colorino
211
-
212
- Example: Add a `fatal()` logger for critical errors.
213
-
214
- Since colorino uses a factory pattern, extend it by creating your own factory that composes the base logger with additional methods:
215
-
216
- ```typescript
217
- import { createColorino, type ColorinoOptions, type Palette } from 'colorino'
218
-
219
- // Create a factory for your custom logger
220
- export function createMyLogger(palette?: Partial<Palette>, options?: ColorinoOptions) {
221
- // Get the base logger instance
222
- const baseLogger = createColorino(palette, options)
223
-
224
- // Define your custom method
225
- function fatal(...args: unknown[]): void {
226
- // Reuse the base logger's error method
227
- baseLogger.error(...args)
228
-
229
- // Add your custom behavior
230
- if (typeof process !== 'undefined' && process.exit) {
231
- process.exit(1)
232
- }
233
- }
234
-
235
- // Return a new object with all base methods + your custom ones
236
- // This preserves type safety and the original API
237
- return {
238
- ...baseLogger,
239
- fatal,
240
- }
241
- }
242
- ```
243
-
244
- Usage:
245
-
246
- ```typescript
247
- const logger = createMyLogger({ error: '#d92626' })
248
-
249
- logger.info('Starting!')
250
- logger.fatal('Missing config: Exiting')
251
- ```
252
-
253
- ### <a id="7-1"></a>Why This Pattern?
254
-
255
- - **Composition > Inheritance**: No fragile base class problems
256
- - **Type Safe**: TypeScript infers the return type correctly
257
- - **Future Proof**: Works even if colorino's internal implementation changes
258
- - **Clean**: No messing with `super()` or constructor parameters
259
- - **Composable**: You can layer multiple extensions
260
-
261
- ## <a id="8"></a>Contributing
262
-
263
- We welcome contributions! Here's exactly how to get started:
264
-
265
- 1. **Setup**
266
- Fork the repo and install dependencies. This will also set up Git hooks via `husky`.
267
-
268
- ```bash
269
- git clone https://github.com/simwai/colorino.git
270
- cd colorino
271
- npm install
272
- ```
273
-
274
- 2. **Development Workflow**
275
- Create a branch for your feature or fix.
276
-
277
- ```bash
278
- git checkout -b feat/my-cool-feature
279
- ```
280
-
281
- 3. **Running Tests**
282
- We use **Vitest** for testing. Please run the full suite to ensure compatibility with both Node.js and Browsers.
283
-
284
- ```bash
285
- # Run all tests (Node + Browser)
286
- npm run test:all
287
-
288
- # Run only Node.js tests
289
- npm run test:node
290
-
291
- # Run only Browser tests
292
- npm run test:browser
293
-
294
- # Watch mode with UI (great for dev!)
295
- npm run test:ui
296
- ```
297
-
298
- 4. **Linting & Formatting**
299
- We use **Oxlint** and **Oxfmt** for fast, robust linting.
300
-
301
- ```bash
302
- # Fix lint issues and format code
303
- npm run format
304
- ```
305
-
306
- 5. **Commit Changes**
307
- Commit your work. This triggers our `lint-staged` hooks to automatically lint, format, and run related tests on your staged files.
308
-
309
- ```bash
310
- git add .
311
- git commit -m "feat: ✨ Add amazing new feature"
312
- ```
313
-
314
- 6. **Building**
315
- To verify the build output (using `unbuild`):
316
-
317
- ```bash
318
- npm run build
319
- ```
320
-
321
- 7. **Submission**
322
- Push your branch and open a Pull Request.
323
-
324
- ```bash
325
- git push origin feat/my-cool-feature
326
- ```
327
-
328
- ## <a id="9"></a>License
329
-
330
- [MIT](LICENSE.md)
331
-
332
- ---
333
-
334
- > *Note:* When running tests, browser output is simulated. Visual styling only appears in real browsers/devtools, but Colorino always routes logs correctly for every environment.
1
+ # <a id="0"></a>🎨 Colorino
2
+
3
+ **The zero-configuration, context-aware `console` logger for Node.js and the browser.**
4
+
5
+ Colorino automatically adapts its palette to your terminal or browser DevTools theme.
6
+
7
+ # <a id="0"></a><a id="0"></a>
8
+
9
+ - [Why use Colorino?](#1)
10
+ - [Features](#2)
11
+ - [Installation](#3)
12
+ - [Usage](#4)
13
+ - [Quick Start](#4-1)
14
+ - [Creating a Custom Logger](#4-2)
15
+ - [Options & Theme Overrides](#4-3)
16
+ - [Available Theme Presets](#4-3-1)
17
+ - [Examples](#4-3-2)
18
+ - [Customization](#4-4)
19
+ - [Supported Environment Variables](#4-5)
20
+ - [Colorino vs. Chalk](#5)
21
+ - [API Reference](#6)
22
+ - [1. `colorino` (default instance)](#6-1)
23
+ - [2. `createColorino(palette?, options?)` (factory)](#6-2)
24
+ - [Extending Colorino](#7)
25
+ - [Why This Pattern?](#7-1)
26
+ - [License](#8)
27
+
28
+ <!-- Table of contents is made with https://github.com/eugene-khyst/md-toc-cli -->
29
+
30
+ ## <a id="1"></a>Why use Colorino?
31
+
32
+ Plain `console.log` is colorless and inconsistent. Libraries like `chalk` let you style strings, but you have to decorate every message and manually manage color choices.
33
+
34
+ Colorino is different: it’s a "batteries-included" logging facade with beautiful, theme-aware colors and a familiar API—no learning curve, no configuration. Instantly upgrade your logs everywhere.
35
+
36
+ ## <a id="2"></a>Features
37
+
38
+ - 🎨 **Smart Theming:** Automatically detects *dark/light* mode and uses a coordinated color palette.
39
+ - 🤝 **Familiar API:** If you know `console.log`, you already know Colorino: all standard log levels are supported.
40
+ - 🔀 **Environment-Aware:** Works in **Node.js** (ANSI color and truecolor) and all major **Browsers** (CSS styles).
41
+ - ⚡️ **Fast, Lightweight:** Minimal dependencies, works great in modern frameworks and CLIs.
42
+ - 🔒 **Robust:** Handles bad inputs and weird environments safely.
43
+ - 🛠️ **Customizable:** Override individual log colors for your own branding.
44
+
45
+ ## <a id="3"></a>Installation
46
+
47
+ ```bash
48
+ npm install colorino
49
+ ```
50
+
51
+ ## <a id="4"></a>Usage
52
+
53
+ ### <a id="4-1"></a>Quick Start
54
+
55
+ Just import the default instance and log away!
56
+
57
+ ```typescript
58
+ import { colorino } from 'colorino'
59
+
60
+ // All log levels automatically themed
61
+ colorino.error('A critical error!')
62
+ colorino.warn('A warning message.')
63
+ colorino.info('Useful info logging.')
64
+ colorino.log('A plain log.')
65
+ colorino.debug('Debug with objects:', { x: 5, y: 9 })
66
+ colorino.trace('Tracing app start...')
67
+ ```
68
+
69
+ ### <a id="4-2"></a>Creating a Custom Logger
70
+
71
+ Need your own colors or different settings?
72
+ Use the factory to create as many loggers as you want (each with its own palette and options):
73
+
74
+ ```typescript
75
+ import { createColorino } from 'colorino'
76
+
77
+ const myLogger = createColorino(
78
+ { // Palette (partial)
79
+ error: '#ff007b',
80
+ info: '#3498db'
81
+ },
82
+ { disableWarnings: true } // Options (see below)
83
+ )
84
+ myLogger.error('Critical!')
85
+ myLogger.info('Rebranded info!')
86
+ ```
87
+
88
+ ### <a id="4-3"></a>Options & Theme Overrides
89
+
90
+ `createColorino(palette?, options?)` accepts:
91
+
92
+ | Option | Type | Default | Description |
93
+ |-------------------|--------------------------------|---------|--------------------------------------------------------------------------------|
94
+ | `disableWarnings` | `boolean` | `false` | Suppress warnings when color support can't be detected or is disabled. |
95
+ | `theme` | `ThemeOption` (see below) | `'auto'`| Control the active color theme or force a specific mode. |
96
+
97
+ **`theme` accepts three types of values:**
98
+
99
+ 1. **`'auto'`** (Default): Automatically detects your terminal or browser theme (dark/light) and applies the matching default preset.
100
+ 2. **`'dark' | 'light'`**: Forces the logger into a specific mode using the default preset for that mode.
101
+ 3. **`ThemeName`**: Forces a specific built-in palette (e.g., `'dracula'`).
102
+
103
+ #### <a id="4-3-1"></a>Available Theme Presets
104
+
105
+ Pass any of these names to the `theme` option to use a specific palette:
106
+
107
+ | Theme Name | Type | Description |
108
+ |----------------------|-----------------|--------------------------------------------------|
109
+ | `'dracula'` | **Dark** (High) | Vibrant pinks, purples, and cyans. |
110
+ | `'catppuccin-mocha'` | **Dark** (Low) | *Default Dark.* Soothing pastel colors. |
111
+ | `'github-light'` | **Light** (High)| *Default Light.* Clean, sharp, high-contrast. |
112
+ | `'catppuccin-latte'` | **Light** (Low) | Warm, cozy light mode with soft colors. |
113
+
114
+ #### <a id="4-3-2"></a>Examples
115
+
116
+ **1. Force a specific mode (uses defaults):**
117
+ Useful for CI/CD or environments where detection fails.
118
+
119
+ ```typescript
120
+ // Forces the default dark theme (Catppuccin Mocha)
121
+ const darkLogger = createColorino({}, { theme: 'dark' })
122
+ ```
123
+
124
+ **2. Use a specific preset:**
125
+ Instant branding with zero configuration.
126
+
127
+ ```typescript
128
+ // Forces the Dracula palette
129
+ const draculaLogger = createColorino({}, { theme: 'dracula' })
130
+ ```
131
+
132
+ **3. Customize a preset:**
133
+ Overlay your own colors on top of a built-in theme.
134
+
135
+ ```typescript
136
+ // Use GitHub Light but with a custom error color
137
+ const myLogger = createColorino(
138
+ { error: '#ff007b' },
139
+ { theme: 'github-light' }
140
+ )
141
+ ```
142
+
143
+ > **Tip:**
144
+ > Forcing `'dark'` or `'light'` bypasses automatic theming, ensuring predictable colors in environments with unknown or unsupported theme detection (like some CI pipelines, dumb terminals, or minimal browsers).
145
+
146
+ ### <a id="4-4"></a>Customization
147
+
148
+ Use your brand colors by passing a partial palette to the `createColorino` factory. Any log levels you don't specify will use the smart theme defaults.
149
+
150
+ ```typescript
151
+ import { createColorino } from 'colorino'
152
+
153
+ // Custom error color; others use theme defaults
154
+ const myLogger = createColorino({ error: '#ff007b' })
155
+
156
+ myLogger.error('Oh no!') // Uses your custom color
157
+ myLogger.info('Still styled by theme.') // Uses the default theme color
158
+ ```
159
+
160
+ ### <a id="4-5"></a>Supported Environment Variables
161
+
162
+ Colorino auto-detects your environment and color support, but you can override behavior using these standard environment variables (compatible with Chalk):
163
+
164
+ | Variable | Effect | Example |
165
+ |------------------|---------------------------------------------------|--------------------------|
166
+ | `NO_COLOR` | Forces *no color* output | `NO_COLOR=1 node app.js` |
167
+ | `FORCE_COLOR` | Forces color (`1`=ANSI, `2`=256, `3`=truecolor) | `FORCE_COLOR=3 node app.js` |
168
+ | `CLICOLOR` | `"0"` disables color | `CLICOLOR=0 node app.js` |
169
+ | `CLICOLOR_FORCE` | Non-`"0"` value enables color even if not a TTY | `CLICOLOR_FORCE=1 node app.js` |
170
+ | `TERM` | Terminal type, can increase/decrease support | `TERM=xterm-256color` |
171
+ | `COLORTERM` | `'truecolor'` or `'24bit'` enables truecolor | `COLORTERM=truecolor` |
172
+ | `WT_SESSION` | Detected for Windows Terminal (enables color) | |
173
+ | `CI` | Many CI platforms default to *no color* | `CI=1 node app.js` |
174
+
175
+ ## <a id="5"></a>Colorino vs. Chalk
176
+
177
+ | Feature | 🎨 **Colorino** | 🖍️ **Chalk** |
178
+ |--------------------------|----------------------------|-----------------|
179
+ | Out-of-box logs | ✔ themed, all log levels | ✘ string styling|
180
+ | Zero-config | ✔ | ✘ manual, per-use|
181
+ | Node + browser | ✔ | ✘ (Node only) |
182
+ | CSS console logs | ✔ | ✘ |
183
+ | Extensible / Composable | ✔ (via factory) | ✘ |
184
+
185
+ ## <a id="6"></a>API Reference
186
+
187
+ The `colorino` package exports two main items:
188
+
189
+ ### <a id="6-1"></a>1. `colorino` (default instance)
190
+
191
+ A pre-configured, zero-setup logger instance. Just import and use.
192
+
193
+ - `.log(...args)`
194
+ - `.info(...args)`
195
+ - `.warn(...args)`
196
+ - `.error(...args)`
197
+ - `.debug(...args)`
198
+ - `.trace(...args)`
199
+
200
+ ### <a id="6-2"></a>2. `createColorino(palette?, options?)` (factory)
201
+
202
+ A factory function to create your own customized logger instances.
203
+
204
+ - `palette` (`Partial<Palette>`): An object to override default colors for specific log levels (e.g., `{ error: '#ff007b' }`).
205
+ - `options` (`ColorinoOptions`): An object to control behavior:
206
+ - `disableWarnings: boolean` (default `false`): Suppress warnings on environments with no color support.
207
+ - `theme: 'dark' | 'light'` (default `auto`): Force a specific theme instead of auto-detecting.
208
+
209
+ ## <a id="7"></a>Extending Colorino
210
+
211
+ Example: Add a `fatal()` logger for critical errors.
212
+
213
+ Since colorino uses a factory pattern, extend it by creating your own factory that composes the base logger with additional methods:
214
+
215
+ ```typescript
216
+ import { createColorino, type ColorinoOptions, type Palette } from 'colorino'
217
+
218
+ // Create a factory for your custom logger
219
+ export function createMyLogger(palette?: Partial<Palette>, options?: ColorinoOptions) {
220
+ // Get the base logger instance
221
+ const baseLogger = createColorino(palette, options)
222
+
223
+ // Define your custom method
224
+ function fatal(...args: unknown[]): void {
225
+ // Reuse the base logger's error method
226
+ baseLogger.error(...args)
227
+
228
+ // Add your custom behavior
229
+ if (typeof process !== 'undefined' && process.exit) {
230
+ process.exit(1)
231
+ }
232
+ }
233
+
234
+ // Return a new object with all base methods + your custom ones
235
+ // This preserves type safety and the original API
236
+ return {
237
+ ...baseLogger,
238
+ fatal,
239
+ }
240
+ }
241
+ ```
242
+
243
+ Usage:
244
+
245
+ ```typescript
246
+ const logger = createMyLogger({ error: '#d92626' })
247
+
248
+ logger.info('Starting!')
249
+ logger.fatal('Missing config: Exiting')
250
+ ```
251
+
252
+ ### <a id="7-1"></a>Why This Pattern?
253
+
254
+ - **Composition > Inheritance**: No fragile base class problems
255
+ - **Type Safe**: TypeScript infers the return type correctly
256
+ - **Future Proof**: Works even if colorino's internal implementation changes
257
+ - **Clean**: No messing with `super()` or constructor parameters
258
+ - **Composable**: You can layer multiple extensions
259
+
260
+ ## <a id="8"></a>License
261
+
262
+ [MIT](LICENSE.md)
package/dist/browser.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const determineBaseTheme = require('./shared/colorino.B9WUj1qg.cjs');
3
+ const determineBaseTheme = require('./shared/colorino.DZFkhcaF.cjs');
4
4
 
5
5
  class BrowserColorSupportDetector {
6
6
  constructor(_window, _navigator, _overrideTheme) {
@@ -1,5 +1,5 @@
1
- import { P as Palette, C as ColorinoOptions, a as Colorino } from './shared/colorino.DBw7jOfy.cjs';
2
- export { L as LogLevel, T as ThemeName, t as themePalettes } from './shared/colorino.DBw7jOfy.cjs';
1
+ import { P as Palette, C as ColorinoOptions, a as Colorino } from './shared/colorino.D5epIHWO.cjs';
2
+ export { L as LogLevel, T as ThemeName, t as themePalettes } from './shared/colorino.D5epIHWO.cjs';
3
3
 
4
4
  declare function createColorino(palette?: Partial<Palette>, options?: ColorinoOptions): Colorino;
5
5
 
@@ -1,5 +1,5 @@
1
- import { P as Palette, C as ColorinoOptions, a as Colorino } from './shared/colorino.DBw7jOfy.mjs';
2
- export { L as LogLevel, T as ThemeName, t as themePalettes } from './shared/colorino.DBw7jOfy.mjs';
1
+ import { P as Palette, C as ColorinoOptions, a as Colorino } from './shared/colorino.D5epIHWO.mjs';
2
+ export { L as LogLevel, T as ThemeName, t as themePalettes } from './shared/colorino.D5epIHWO.mjs';
3
3
 
4
4
  declare function createColorino(palette?: Partial<Palette>, options?: ColorinoOptions): Colorino;
5
5
 
package/dist/browser.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as Palette, C as ColorinoOptions, a as Colorino } from './shared/colorino.DBw7jOfy.js';
2
- export { L as LogLevel, T as ThemeName, t as themePalettes } from './shared/colorino.DBw7jOfy.js';
1
+ import { P as Palette, C as ColorinoOptions, a as Colorino } from './shared/colorino.D5epIHWO.js';
2
+ export { L as LogLevel, T as ThemeName, t as themePalettes } from './shared/colorino.D5epIHWO.js';
3
3
 
4
4
  declare function createColorino(palette?: Partial<Palette>, options?: ColorinoOptions): Colorino;
5
5
 
package/dist/browser.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { C as ColorLevel, t as themePalettes, a as Colorino, I as InputValidator, d as determineBaseTheme } from './shared/colorino.CsFoITs1.mjs';
1
+ import { C as ColorLevel, t as themePalettes, a as Colorino, I as InputValidator, d as determineBaseTheme } from './shared/colorino.Irp6M1AW.mjs';
2
2
 
3
3
  class BrowserColorSupportDetector {
4
4
  constructor(_window, _navigator, _overrideTheme) {
package/dist/node.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const determineBaseTheme = require('./shared/colorino.B9WUj1qg.cjs');
3
+ const determineBaseTheme = require('./shared/colorino.DZFkhcaF.cjs');
4
4
 
5
5
  class OscThemeQuerier {
6
6
  constructor(_stdin, _stdout, _timeout = 300, _cacheTtl = 36e5) {
package/dist/node.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as Palette, C as ColorinoOptions, a as Colorino } from './shared/colorino.DBw7jOfy.cjs';
2
- export { L as LogLevel, T as ThemeName, t as themePalettes } from './shared/colorino.DBw7jOfy.cjs';
1
+ import { P as Palette, C as ColorinoOptions, a as Colorino } from './shared/colorino.D5epIHWO.cjs';
2
+ export { L as LogLevel, T as ThemeName, t as themePalettes } from './shared/colorino.D5epIHWO.cjs';
3
3
 
4
4
  declare function createColorino(palette?: Partial<Palette>, options?: ColorinoOptions): Colorino;
5
5
 
package/dist/node.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as Palette, C as ColorinoOptions, a as Colorino } from './shared/colorino.DBw7jOfy.mjs';
2
- export { L as LogLevel, T as ThemeName, t as themePalettes } from './shared/colorino.DBw7jOfy.mjs';
1
+ import { P as Palette, C as ColorinoOptions, a as Colorino } from './shared/colorino.D5epIHWO.mjs';
2
+ export { L as LogLevel, T as ThemeName, t as themePalettes } from './shared/colorino.D5epIHWO.mjs';
3
3
 
4
4
  declare function createColorino(palette?: Partial<Palette>, options?: ColorinoOptions): Colorino;
5
5
 
package/dist/node.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as Palette, C as ColorinoOptions, a as Colorino } from './shared/colorino.DBw7jOfy.js';
2
- export { L as LogLevel, T as ThemeName, t as themePalettes } from './shared/colorino.DBw7jOfy.js';
1
+ import { P as Palette, C as ColorinoOptions, a as Colorino } from './shared/colorino.D5epIHWO.js';
2
+ export { L as LogLevel, T as ThemeName, t as themePalettes } from './shared/colorino.D5epIHWO.js';
3
3
 
4
4
  declare function createColorino(palette?: Partial<Palette>, options?: ColorinoOptions): Colorino;
5
5
 
package/dist/node.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { e as err, O as OscQueryError, o as ok, C as ColorLevel, d as determineBaseTheme, t as themePalettes, a as Colorino, I as InputValidator } from './shared/colorino.CsFoITs1.mjs';
1
+ import { e as err, O as OscQueryError, o as ok, C as ColorLevel, d as determineBaseTheme, t as themePalettes, a as Colorino, I as InputValidator } from './shared/colorino.Irp6M1AW.mjs';
2
2
 
3
3
  class OscThemeQuerier {
4
4
  constructor(_stdin, _stdout, _timeout = 300, _cacheTtl = 36e5) {
@@ -448,6 +448,7 @@ declare class Colorino {
448
448
  debug(...args: unknown[]): void;
449
449
  private _detectColorSupport;
450
450
  private _maybeWarnUser;
451
+ private _formatValue;
451
452
  private _out;
452
453
  }
453
454
 
@@ -448,6 +448,7 @@ declare class Colorino {
448
448
  debug(...args: unknown[]): void;
449
449
  private _detectColorSupport;
450
450
  private _maybeWarnUser;
451
+ private _formatValue;
451
452
  private _out;
452
453
  }
453
454
 
@@ -448,6 +448,7 @@ declare class Colorino {
448
448
  debug(...args: unknown[]): void;
449
449
  private _detectColorSupport;
450
450
  private _maybeWarnUser;
451
+ private _formatValue;
451
452
  private _out;
452
453
  }
453
454
 
@@ -115,19 +115,47 @@ class Colorino {
115
115
  "[Colorino] No ANSI color support detected in this terminal. See [https://github.com/chalk/supports-color#support-matrix](https://github.com/chalk/supports-color#support-matrix) to learn how to enable terminal color."
116
116
  );
117
117
  }
118
+ _formatValue(value, maxDepth = 3) {
119
+ const seen = /* @__PURE__ */ new WeakSet();
120
+ const sanitize = (val, currentDepth) => {
121
+ if (val === null || typeof val !== "object") return val;
122
+ if (seen.has(val)) return "[Circular]";
123
+ seen.add(val);
124
+ if (currentDepth >= maxDepth) return "[Object]";
125
+ if (Array.isArray(val)) {
126
+ return val.map((item) => sanitize(item, currentDepth + 1));
127
+ }
128
+ const result = {};
129
+ for (const key in val) {
130
+ result[key] = sanitize(val[key], currentDepth + 1);
131
+ }
132
+ return result;
133
+ };
134
+ return JSON.stringify(sanitize(value, 0), null, 2);
135
+ }
118
136
  _out(level, args) {
119
137
  const consoleMethod = isConsoleMethod(level) ? level : "log";
138
+ const processedArgs = args.map((arg) => {
139
+ if (arg !== null && typeof arg === "object" && typeof arg !== "string" && !(arg instanceof Error)) {
140
+ return this._formatValue(arg);
141
+ }
142
+ return arg;
143
+ });
120
144
  if (this._colorLevel === ColorLevel.NO_COLOR || this._colorLevel === "UnknownEnv") {
121
- if (level === "trace") console.trace(...args);
122
- else console[consoleMethod](...args);
145
+ if (level === "trace") console.trace(...processedArgs);
146
+ else console[consoleMethod](...processedArgs);
123
147
  return;
124
148
  }
125
149
  if (this.isBrowser) {
126
150
  const hex2 = this._palette[level];
127
- if (typeof args[0] === "string") {
128
- console[consoleMethod](`%c${args[0]}`, `color:${hex2}`, ...args.slice(1));
151
+ if (typeof processedArgs[0] === "string") {
152
+ console[consoleMethod](
153
+ `%c${processedArgs[0]}`,
154
+ `color:${hex2}`,
155
+ ...processedArgs.slice(1)
156
+ );
129
157
  } else {
130
- console[consoleMethod](...args);
158
+ console[consoleMethod](...processedArgs);
131
159
  }
132
160
  return;
133
161
  }
@@ -151,17 +179,17 @@ class Colorino {
151
179
  break;
152
180
  }
153
181
  }
154
- const processedArgs = [...args];
155
- const firstStringIndex = processedArgs.findIndex(
182
+ const coloredArgs = [...processedArgs];
183
+ const firstStringIndex = coloredArgs.findIndex(
156
184
  (arg) => typeof arg === "string"
157
185
  );
158
186
  if (firstStringIndex !== -1) {
159
- processedArgs[firstStringIndex] = `${ansiCode}${processedArgs[firstStringIndex]}\x1B[0m`;
187
+ coloredArgs[firstStringIndex] = `${ansiCode}${coloredArgs[firstStringIndex]}\x1B[0m`;
160
188
  }
161
189
  if (level === "trace") {
162
- console.trace(...processedArgs);
190
+ console.trace(...coloredArgs);
163
191
  } else {
164
- console[consoleMethod](...processedArgs);
192
+ console[consoleMethod](...coloredArgs);
165
193
  }
166
194
  }
167
195
  }
@@ -113,19 +113,47 @@ class Colorino {
113
113
  "[Colorino] No ANSI color support detected in this terminal. See [https://github.com/chalk/supports-color#support-matrix](https://github.com/chalk/supports-color#support-matrix) to learn how to enable terminal color."
114
114
  );
115
115
  }
116
+ _formatValue(value, maxDepth = 3) {
117
+ const seen = /* @__PURE__ */ new WeakSet();
118
+ const sanitize = (val, currentDepth) => {
119
+ if (val === null || typeof val !== "object") return val;
120
+ if (seen.has(val)) return "[Circular]";
121
+ seen.add(val);
122
+ if (currentDepth >= maxDepth) return "[Object]";
123
+ if (Array.isArray(val)) {
124
+ return val.map((item) => sanitize(item, currentDepth + 1));
125
+ }
126
+ const result = {};
127
+ for (const key in val) {
128
+ result[key] = sanitize(val[key], currentDepth + 1);
129
+ }
130
+ return result;
131
+ };
132
+ return JSON.stringify(sanitize(value, 0), null, 2);
133
+ }
116
134
  _out(level, args) {
117
135
  const consoleMethod = isConsoleMethod(level) ? level : "log";
136
+ const processedArgs = args.map((arg) => {
137
+ if (arg !== null && typeof arg === "object" && typeof arg !== "string" && !(arg instanceof Error)) {
138
+ return this._formatValue(arg);
139
+ }
140
+ return arg;
141
+ });
118
142
  if (this._colorLevel === ColorLevel.NO_COLOR || this._colorLevel === "UnknownEnv") {
119
- if (level === "trace") console.trace(...args);
120
- else console[consoleMethod](...args);
143
+ if (level === "trace") console.trace(...processedArgs);
144
+ else console[consoleMethod](...processedArgs);
121
145
  return;
122
146
  }
123
147
  if (this.isBrowser) {
124
148
  const hex2 = this._palette[level];
125
- if (typeof args[0] === "string") {
126
- console[consoleMethod](`%c${args[0]}`, `color:${hex2}`, ...args.slice(1));
149
+ if (typeof processedArgs[0] === "string") {
150
+ console[consoleMethod](
151
+ `%c${processedArgs[0]}`,
152
+ `color:${hex2}`,
153
+ ...processedArgs.slice(1)
154
+ );
127
155
  } else {
128
- console[consoleMethod](...args);
156
+ console[consoleMethod](...processedArgs);
129
157
  }
130
158
  return;
131
159
  }
@@ -149,17 +177,17 @@ class Colorino {
149
177
  break;
150
178
  }
151
179
  }
152
- const processedArgs = [...args];
153
- const firstStringIndex = processedArgs.findIndex(
180
+ const coloredArgs = [...processedArgs];
181
+ const firstStringIndex = coloredArgs.findIndex(
154
182
  (arg) => typeof arg === "string"
155
183
  );
156
184
  if (firstStringIndex !== -1) {
157
- processedArgs[firstStringIndex] = `${ansiCode}${processedArgs[firstStringIndex]}\x1B[0m`;
185
+ coloredArgs[firstStringIndex] = `${ansiCode}${coloredArgs[firstStringIndex]}\x1B[0m`;
158
186
  }
159
187
  if (level === "trace") {
160
- console.trace(...processedArgs);
188
+ console.trace(...coloredArgs);
161
189
  } else {
162
- console[consoleMethod](...processedArgs);
190
+ console[consoleMethod](...coloredArgs);
163
191
  }
164
192
  }
165
193
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "colorino",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "A super simple colorized logger that gets the most out of your terminal",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -50,6 +50,7 @@
50
50
  "test:watch": "vitest",
51
51
  "test:coverage": "vitest run --coverage",
52
52
  "test:ui": "vitest --ui",
53
+ "generate-readme-toc": "md-toc-cli -i README.md",
53
54
  "version:patch": "npm version patch",
54
55
  "version:minor": "npm version minor",
55
56
  "version:major": "npm version major",
@@ -69,6 +70,7 @@
69
70
  "@vitest/ui": "^4.0.15",
70
71
  "husky": "^9.0.0",
71
72
  "lint-staged": "^15.2.0",
73
+ "md-toc-cli": "^3.1.1",
72
74
  "oxfmt": "^0.9.0",
73
75
  "oxlint": "^0.2.0",
74
76
  "playwright": "^1.57.0",