termpainter 2.0.0 → 2.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.
Files changed (2) hide show
  1. package/README.md +127 -72
  2. package/package.json +1 -4
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # termpainter
2
2
 
3
- tired of staring at walls of plain `console.log`? termpainter gives your terminal output actual structure. colors, boxes, badges, tables, timestamps. zero dependencies, works in Node 18+ and Bun.
3
+ Build clean, structured CLI output with zero dependencies.
4
+
5
+ termpainter gives you semantic styles, boxes, tables, spinners, layouts and more. works in Node 18+ and Bun. full TypeScript support.
4
6
  ```sh
5
7
  npm install termpainter
6
8
  ```
@@ -9,6 +11,73 @@ npm install termpainter
9
11
 
10
12
  ---
11
13
 
14
+ ## real world examples
15
+
16
+ ### deploy pipeline
17
+ ```ts
18
+ import { style, box, columns } from 'termpainter'
19
+
20
+ console.log(box(
21
+ style.group('Deploy', [
22
+ style.success('Dependencies installed'),
23
+ style.success('TypeScript compiled'),
24
+ style.success('22/22 tests passed'),
25
+ style.success('Bundle created (10.5 kB)'),
26
+ ]),
27
+ { color: 'green', title: 'CI/CD' }
28
+ ))
29
+
30
+ console.log(columns(
31
+ style.group('Services', [
32
+ style.success('API'),
33
+ style.success('Auth'),
34
+ style.error('Database'),
35
+ style.warn('Cache'),
36
+ ]),
37
+ style.group('Stats', [
38
+ style.info('Uptime: 3d 2h'),
39
+ style.info('Memory: 512 MB'),
40
+ style.warn('CPU: 87%'),
41
+ style.info('Port: 3000'),
42
+ ])
43
+ ))
44
+ ```
45
+
46
+ <img src="https://raw.githubusercontent.com/abd105/termpainter/main/assets/example-deploy.png" width="500" alt="deploy pipeline example" />
47
+
48
+ ### structured logging
49
+ ```ts
50
+ import { style } from 'termpainter'
51
+
52
+ style.success('User created', { id: 847, role: 'admin', plan: 'pro' })
53
+ style.error('Request failed', { status: 503, path: '/api/checkout', retries: 3 })
54
+ style.warn('Rate limit approaching', { limit: 1000, current: 847, reset: '60s' })
55
+ style.info('Deploy started', { env: 'production', version: 'v2.0.0', region: 'us-east-1' })
56
+ ```
57
+
58
+ <img src="https://raw.githubusercontent.com/abd105/termpainter/main/assets/example-logs.png" width="400" alt="structured logging example" />
59
+
60
+ ### CLI status dashboard
61
+ ```ts
62
+ import { style, badge, columns } from 'termpainter'
63
+
64
+ console.log(columns(
65
+ style.table({ Status: 'Running', Uptime: '3d 2h', Memory: '512 MB', CPU: '12%' }),
66
+ style.table({ Region: 'us-east-1', Version: 'v2.0.0', Node: '22.x', Port: '3000' })
67
+ ))
68
+
69
+ console.log(
70
+ badge('production', 'green') + ' ' +
71
+ badge('v2.0.0', 'cyan') + ' ' +
72
+ badge('0 deps', 'magenta') + ' ' +
73
+ badge('TypeScript', 'blue')
74
+ )
75
+ ```
76
+
77
+ <img src="https://raw.githubusercontent.com/abd105/termpainter/main/assets/example-dashboard.png" width="500" alt="status dashboard example" />
78
+
79
+ ---
80
+
12
81
  ## usage
13
82
  ```ts
14
83
  import { style, badge, box, paint, spin, strip, columns, truncate,
@@ -30,14 +99,12 @@ style.highlight('termpainter') // cyan
30
99
 
31
100
  ### structured log output
32
101
 
33
- any `style.*` method accepts an optional second argument a plain object whose keys and values are printed below the message, indented and with keys in cyan.
102
+ any `style.*` method accepts an optional second argument. a plain object whose keys and values are printed below the message, indented with keys in cyan.
34
103
  ```ts
35
104
  style.info('User created', { id: 123, role: 'admin' })
36
105
  // ℹ User created
37
106
  // id 123
38
107
  // role admin
39
-
40
- style.error('Request failed', { status: 503, path: '/api/data' })
41
108
  ```
42
109
 
43
110
  ### debug
@@ -70,7 +137,7 @@ style.list(items, { bullet: '-', color: 'gray', indent: 2 })
70
137
 
71
138
  inline labels. good for status, versions, environments.
72
139
  ```ts
73
- badge('v1.0.0', 'cyan')
140
+ badge('v2.0.0', 'cyan')
74
141
  badge('PASS', 'green')
75
142
  badge('FAIL', 'red')
76
143
  badge('production', 'green')
@@ -79,13 +146,12 @@ badge('offline', 'red')
79
146
 
80
147
  ### boxes
81
148
 
82
- draws a clean unicode border around anything. multiline works fine. fully composable — pass styled strings directly. supports an optional title in the top border.
149
+ draws a clean unicode border around anything. multiline works fine. fully composable. supports an optional title in the top border.
83
150
  ```ts
84
151
  box('Deploy complete\n3 services restarted\nAll checks passed', 'green')
85
152
  box('Critical error\nProcess exited with code 1', 'red')
86
153
  box(style.success('done')) // styled content inside a box
87
154
 
88
- // with title
89
155
  box('Deploy complete\n3 services restarted', { color: 'green', title: 'Deploy' })
90
156
  // ╭ Deploy ──────────────────╮
91
157
  // │ Deploy complete │
@@ -123,15 +189,6 @@ style.timestamp('Deploy complete', 'green') // timestamp in green
123
189
  style.timestamp('Connection failed', 'red') // timestamp in red
124
190
  ```
125
191
 
126
- ### paint
127
-
128
- low level, for when you need something the presets don't cover.
129
- ```ts
130
- paint('custom text', { color: 'magenta', bold: true })
131
- paint('highlighted', { color: 'white', bg: 'blue' })
132
- paint('soft note', { color: 'gray', italic: true, dim: true })
133
- ```
134
-
135
192
  ### group
136
193
 
137
194
  groups a list of already-styled lines under a labeled header.
@@ -152,34 +209,30 @@ renders two strings side by side, ANSI-aware. falls back to two lines in non-int
152
209
  columns('Left content', 'Right content')
153
210
  columns(style.success('Build passed'), style.info('Tests: 22/22'))
154
211
  columns(badge('production', 'green'), badge('v2.0.0', 'cyan'))
155
-
156
212
  columns(left, right, { width: 100, gap: 6 })
157
213
  ```
158
214
 
159
215
  ### truncate
160
216
 
161
- truncates a string to a maximum visible length and appends `…`. uses `strip()` internally so ANSI codes don't count toward the length.
217
+ truncates a string to a maximum visible length and appends `...`. uses `strip()` internally so ANSI codes don't count toward the length.
162
218
  ```ts
163
219
  truncate('very long string that overflows', 20)
164
- // => 'very long string tha'
220
+ // => 'very long string tha...'
165
221
 
166
222
  truncate(style.success('Build complete'), 10)
167
- // => truncated styled string with ANSI codes preserved
168
223
  ```
169
224
 
170
225
  ### spinner
171
226
 
172
- animated terminal spinner. returns a handle with `succeed`, `fail`, and `update`. no external dependencies. automatically degrades to static line-by-line output when not in a TTY.
227
+ animated terminal spinner. returns a handle with `succeed`, `fail`, and `update`. no external dependencies. automatically degrades to static output when not in a TTY.
173
228
  ```ts
174
229
  const s = spin('Deploying...')
175
230
 
176
- s.update('Still working...') // update message while spinning
231
+ s.update('Still working...')
177
232
  s.update('Almost done...')
178
233
 
179
- s.succeed('Deploy complete') // stops spinner, shows style.success
180
- s.fail('Deploy failed') // stops spinner, shows style.error
181
-
182
- s.succeed() // reuse current message
234
+ s.succeed('Deploy complete')
235
+ s.fail('Deploy failed')
183
236
  ```
184
237
 
185
238
  ### strip
@@ -192,71 +245,73 @@ const raw = strip(style.success('Build complete'))
192
245
  fs.appendFileSync('app.log', strip(style.info('Server started')) + '\n')
193
246
  ```
194
247
 
195
- ### themes
248
+ ### paint
196
249
 
197
- globally override colors and icons for all `style.*` methods. all keys are optional — unspecified entries fall back to defaults. call `resetTheme()` to restore factory defaults.
250
+ low level, for when you need something the presets don't cover.
198
251
  ```ts
199
- import { setTheme, resetTheme } from 'termpainter'
252
+ paint('custom text', { color: 'magenta', bold: true })
253
+ paint('highlighted', { color: 'white', bg: 'blue' })
254
+ paint('soft note', { color: 'gray', italic: true, dim: true })
255
+ ```
256
+
257
+ ### themes
200
258
 
259
+ globally override colors and icons for all `style.*` methods. all keys are optional. call `resetTheme()` to restore defaults.
260
+ ```ts
201
261
  setTheme({
202
262
  success: { color: 'cyan', icon: '✓' },
203
263
  error: { color: 'magenta', icon: '✕' },
204
264
  warn: { color: 'yellow' },
205
- info: { color: 'blue', icon: '' },
206
- debug: { color: 'gray', dim: true },
207
- muted: { color: 'gray', dim: true },
208
- highlight: { color: 'green' },
265
+ info: { color: 'blue', icon: '>' },
209
266
  })
210
267
 
211
- style.success('done') // ✓ done (cyan, custom icon)
212
- style.error('oops') // ✕ oops (magenta)
268
+ style.success('done') // ✓ done (cyan, custom icon)
269
+ style.error('oops') // ✕ oops (magenta)
213
270
 
214
- resetTheme() // back to defaults
271
+ resetTheme() // back to defaults
215
272
  ```
216
273
 
217
- ### test mode
274
+ ### custom icons
218
275
 
219
- makes output deterministic for snapshot testing. `style.timestamp()` omits the time prefix, `spin()` renders statically without animation, `isInteractive()` returns `false`.
276
+ override the default icons for any or all style methods. unspecified keys fall back to defaults.
220
277
  ```ts
221
- import { setTestMode } from 'termpainter'
222
-
223
- setTestMode(true)
224
-
225
- style.timestamp('Server started') // => 'Server started' (no [HH:MM:SS])
226
- const s = spin('Loading...') // prints once, no animation
227
- s.succeed('Done') // prints style.success line
278
+ setIcons({ success: '✓', error: '' })
228
279
 
229
- setTestMode(false) // restore normal behavior
280
+ style.success('done') // done
281
+ style.warn('careful') // ⚠ careful (default unchanged)
230
282
  ```
231
283
 
284
+ available keys: `success`, `error`, `warn`, `info`, `debug`
285
+
232
286
  ### silent mode
233
287
 
234
288
  suppress all output globally. every function returns an empty string and produces no side effects. useful for tests, CI, and benchmarks.
235
289
  ```ts
236
290
  setSilent(true)
237
291
 
238
- style.success('done') // ''
239
- badge('v1.0.0', 'cyan') // ''
240
- box('hello') // ''
292
+ style.success('done') // ''
293
+ badge('v2.0.0', 'cyan') // ''
294
+ box('hello') // ''
241
295
 
242
- setSilent(false) // restore normal output
296
+ setSilent(false) // restore normal output
243
297
  ```
244
298
 
245
- ### custom icons
299
+ ### test mode
246
300
 
247
- override the default icons for any or all style methods. unspecified keys fall back to defaults.
301
+ makes output deterministic for snapshot testing. `style.timestamp()` omits the time prefix, `spin()` renders statically, `isInteractive()` returns `false`.
248
302
  ```ts
249
- setIcons({ success: '✓', error: '✕' })
303
+ setTestMode(true)
250
304
 
251
- style.success('done') // done
252
- style.warn('careful') // careful (default unchanged)
253
- ```
305
+ style.timestamp('Server started') // 'Server started' (no [HH:MM:SS])
306
+ const s = spin('Loading...') // prints once, no animation
307
+ s.succeed('Done')
254
308
 
255
- available keys: `success`, `error`, `warn`, `info`, `debug`
309
+ setTestMode(false)
310
+ ```
256
311
 
257
312
  ### isInteractive
258
313
 
259
- returns `true` if stdout is an interactive TTY. always `false` in test mode.
314
+ returns `true` if stdout is a TTY. always `false` in test mode.
260
315
  ```ts
261
316
  if (isInteractive()) {
262
317
  const s = spin('Loading...')
@@ -284,32 +339,32 @@ isColorEnabled() // true in an interactive terminal, false everywhere else
284
339
  | `style.success(msg, meta?)` | green, prepends ✔ |
285
340
  | `style.warn(msg, meta?)` | yellow, prepends ⚠ |
286
341
  | `style.info(msg, meta?)` | blue, prepends ℹ |
287
- | `style.debug(msg, meta?)` | gray+dim, 🔍 prefix, only when `DEBUG` is set |
342
+ | `style.debug(msg, meta?)` | gray+dim, 🔍 prefix, only when DEBUG is set |
288
343
  | `style.muted(msg)` | gray, dimmed |
289
344
  | `style.bold(msg)` | bold white |
290
345
  | `style.highlight(msg)` | cyan |
291
346
  | `style.divider(color?)` | 40 char horizontal rule, default gray |
292
347
  | `style.table(data, color?)` | aligned key-value table, keys in cyan |
293
- | `style.timestamp(msg, color?)` | prepends [HH:MM:SS], default gray; omitted in test mode |
294
- | `style.group(label, lines[])` | label in cyan, lines indented 2 spaces |
348
+ | `style.timestamp(msg, color?)` | prepends [HH:MM:SS], omitted in test mode |
349
+ | `style.group(label, lines[])` | labeled indented section |
295
350
  | `style.list(items, options?)` | bulleted list, options: bullet, color, indent |
296
351
  | `badge(text, color?)` | [text] in chosen color, default white |
297
- | `box(text, color\|options?)` | unicode border box; options: color, title |
298
- | `columns(left, right, options?)` | two columns side by side; options: width, gap |
299
- | `truncate(str, maxLength)` | truncate to maxLength visible chars, append … |
300
- | `spin(msg)` | animated spinner; returns `{ succeed, fail, update }` |
352
+ | `box(text, color or options?)` | unicode border box with optional title |
353
+ | `columns(left, right, options?)` | side by side output, options: width, gap |
354
+ | `truncate(str, maxLength)` | truncate preserving ANSI codes |
355
+ | `spin(msg)` | animated spinner, returns succeed, fail, update |
301
356
  | `strip(str)` | removes all ANSI escape codes |
357
+ | `paint(text, options?)` | raw ANSI composer |
302
358
  | `setTheme(theme)` | override colors and icons globally |
303
359
  | `resetTheme()` | restore default theme |
304
- | `setIcons(icons)` | override icons for error, success, warn, info, debug |
305
- | `setSilent(mode)` | suppress all output globally when `true` |
306
- | `setTestMode(mode)` | deterministic output for snapshot testing |
307
- | `isInteractive()` | returns `true` if stdout is a TTY (false in test mode) |
308
- | `paint(text, options?)` | raw ANSI composer |
309
- | `isColorEnabled()` | returns true if colors are active |
360
+ | `setIcons(icons)` | override icons for success, error, warn, info, debug |
361
+ | `setSilent(bool)` | suppress all output globally |
362
+ | `setTestMode(bool)` | deterministic output for snapshot testing |
363
+ | `isColorEnabled()` | true if colors are active |
364
+ | `isInteractive()` | true if stdout is a TTY, false in test mode |
310
365
 
311
366
  ---
312
367
 
313
368
  ## license
314
369
 
315
- MIT © Abdullah Hashmi
370
+ MIT © Abdullah Hashmi
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "termpainter",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "Zero-dependency terminal styling toolkit for Node.js and Bun",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",
@@ -54,8 +54,5 @@
54
54
  "devDependencies": {
55
55
  "@types/node": "^25.5.0",
56
56
  "typescript": "^6.0.2"
57
- },
58
- "dependencies": {
59
- "termpainter": "^1.0.1"
60
57
  }
61
58
  }