tuimon 0.2.0 → 0.3.1

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 (45) hide show
  1. package/README.md +191 -181
  2. package/dist/browser.d.ts.map +1 -1
  3. package/dist/browser.js +4 -1
  4. package/dist/browser.js.map +1 -1
  5. package/dist/cli.js +67 -2
  6. package/dist/cli.js.map +1 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +22 -6
  9. package/dist/index.js.map +1 -1
  10. package/dist/quick/presets/coverage.d.ts +3 -0
  11. package/dist/quick/presets/coverage.d.ts.map +1 -0
  12. package/dist/quick/presets/coverage.js +362 -0
  13. package/dist/quick/presets/coverage.js.map +1 -0
  14. package/dist/quick/presets/deps.d.ts +3 -0
  15. package/dist/quick/presets/deps.d.ts.map +1 -0
  16. package/dist/quick/presets/deps.js +194 -0
  17. package/dist/quick/presets/deps.js.map +1 -0
  18. package/dist/quick/presets/docker.d.ts +3 -0
  19. package/dist/quick/presets/docker.d.ts.map +1 -0
  20. package/dist/quick/presets/docker.js +100 -0
  21. package/dist/quick/presets/docker.js.map +1 -0
  22. package/dist/quick/presets/git.d.ts +3 -0
  23. package/dist/quick/presets/git.d.ts.map +1 -0
  24. package/dist/quick/presets/git.js +116 -0
  25. package/dist/quick/presets/git.js.map +1 -0
  26. package/dist/quick/presets/ps.d.ts +3 -0
  27. package/dist/quick/presets/ps.d.ts.map +1 -0
  28. package/dist/quick/presets/ps.js +168 -0
  29. package/dist/quick/presets/ps.js.map +1 -0
  30. package/dist/quick/presets/runner.d.ts +3 -0
  31. package/dist/quick/presets/runner.d.ts.map +1 -0
  32. package/dist/quick/presets/runner.js +20 -0
  33. package/dist/quick/presets/runner.js.map +1 -0
  34. package/dist/quick/presets/types.d.ts +7 -0
  35. package/dist/quick/presets/types.d.ts.map +1 -0
  36. package/dist/quick/presets/types.js +2 -0
  37. package/dist/quick/presets/types.js.map +1 -0
  38. package/dist/types.d.ts +1 -1
  39. package/dist/types.d.ts.map +1 -1
  40. package/examples/preset-deps.png +0 -0
  41. package/examples/preset-docker.png +0 -0
  42. package/examples/preset-git.png +0 -0
  43. package/examples/preset-ps.png +0 -0
  44. package/examples/test-presets.ts +91 -0
  45. package/package.json +2 -1
package/README.md CHANGED
@@ -1,145 +1,114 @@
1
1
  # TuiMon
2
2
 
3
- > Render beautiful dashboards directly in your terminal. Zero config required.
3
+ > Your HTML, CSS, and JavaScript, rendered directly in the terminal.
4
4
 
5
- ## The Simplest Way to Visualize Data in Your Terminal
5
+ ## What Is TuiMon?
6
6
 
7
- ```bash
8
- # Visualize any data file instantly
9
- tuimon data.json
10
- tuimon users.csv
11
- tuimon /var/log/nginx/access.log
12
-
13
- # Live monitoring from a data function
14
- tuimon watch metrics.js
7
+ TuiMon takes any HTML page and renders it live in your terminal. Write your dashboard with HTML, CSS flexbox, Chart.js, D3, or whatever you already know, and TuiMon turns it into a real-time terminal application.
15
8
 
16
- # Poll a JSON API
17
- tuimon watch --url http://localhost:3000/metrics
9
+ No curses. No blessed. No terminal UI framework. Just the web tech you already use.
18
10
 
19
- # Full custom dashboard (HTML/CSS/JS)
20
- tuimon start
11
+ ```
12
+ Your HTML/CSS/JS > Headless Chromium > Screenshot > Terminal Graphics > Your Terminal
21
13
  ```
22
14
 
23
- No HTML. No config files. No charting libraries. Just point TuiMon at your data.
24
-
25
- ## Terminal Support
26
-
27
- | Terminal | Protocol | Status |
28
- |----------|----------|--------|
29
- | Kitty | Kitty | Supported |
30
- | Ghostty | Kitty | Supported |
31
- | WezTerm | Kitty | Supported |
32
- | iTerm2 | iTerm2 | Supported |
33
- | **VSCode** | Sixel | **Supported** (requires one setting) |
34
- | mlterm | Sixel | Supported |
35
-
36
- ### VSCode Setup
15
+ If it works in a browser, it works in TuiMon.
37
16
 
38
- VSCode supports terminal images but it's **off by default**. Running `tuimon init` enables it automatically by creating `.vscode/settings.json` with:
39
-
40
- ```json
41
- { "terminal.integrated.enableImages": true }
42
- ```
17
+ But you don't have to write HTML if you don't want to. TuiMon also comes with a beautiful built-in theme and a set of zero-config CLI tools that let you visualize files, databases, and live data without writing a single line of HTML.
43
18
 
44
19
  ## Quick Start
45
20
 
46
21
  ```bash
47
22
  npm install -g tuimon
48
- tuimon check # verify your terminal supports graphics
23
+ tuimon init # scaffolds a starter dashboard
24
+ tuimon start # renders it in your terminal
49
25
  ```
50
26
 
51
- ## 1. Instant File Visualization
52
-
53
- Point TuiMon at any data file — it auto-detects the format, picks the right charts, and renders a dashboard:
54
-
55
- ```bash
56
- # JSON array → table + charts
57
- tuimon users.json
58
-
59
- # CSV → table + charts
60
- tuimon sales.csv
27
+ ---
61
28
 
62
- # Nginx access log request stats + table
63
- tuimon /var/log/nginx/access.log
29
+ ## 1. Build Your Own Dashboard with HTML
64
30
 
65
- # ModSecurity audit log security dashboard
66
- tuimon /var/log/modsec_audit.log
31
+ This is what TuiMon was built for. You write your dashboard as a normal HTML page. Use CSS flexbox, grid, animations, whatever. Use any charting library. TuiMon renders it in your terminal.
67
32
 
68
- # Filter columns
69
- tuimon access.log --columns "Timestamp,IP,Path,Status"
33
+ ```html
34
+ <!-- pages/dashboard.html -->
35
+ <div style="display: flex; gap: 20px; padding: 20px; background: #0a0e1a; color: white; height: 100vh;">
36
+ <div style="flex: 1; background: #0f1629; border-radius: 8px; padding: 16px;">
37
+ <h3>CPU Usage</h3>
38
+ <canvas id="cpuChart"></canvas>
39
+ </div>
40
+ <div style="flex: 1; background: #0f1629; border-radius: 8px; padding: 16px;">
41
+ <h3>Memory</h3>
42
+ <div id="memValue" style="font-size: 48px; color: #00e5ff;">--</div>
43
+ </div>
44
+ </div>
45
+ <script src="https://cdn.jsdelivr.net/npm/chart.js@4"></script>
46
+ <script>
47
+ TuiMon.onUpdate(function(data) {
48
+ TuiMon.set('#memValue', data.memory + '%')
49
+ // update your charts, DOM, anything you want
50
+ })
51
+ </script>
70
52
  ```
71
53
 
72
- **Auto-detected formats:**
73
- - **JSON/JSONL** — arrays of objects → table + stat cards + charts
74
- - **CSV/TSV** auto-detects delimiter, header row, column types
75
- - **Nginx combined log** — request stats, status codes, top endpoints/IPs, browsable request table
76
- - **ModSecurity audit log** — security events, severity distribution, attack categories, top attacker IPs
77
- - **JSON logs** — level distribution, latest entries
78
- - **Plain text** — live tail
79
-
80
- **Features:**
81
- - Press **D** to switch to full-screen data table view, **ESC** to go back
82
- - Arrow keys / PgUp / PgDn to navigate table pages
83
- - **F5** to reload file, **F10** to quit
84
- - File is **watched** — dashboard updates when the file changes on disk
54
+ ```typescript
55
+ // tuimon.config.ts
56
+ import tuimon from 'tuimon'
85
57
 
86
- ## 2. Live Data Monitoring
58
+ const dash = await tuimon.start({
59
+ pages: {
60
+ main: {
61
+ html: './pages/dashboard.html',
62
+ default: true,
63
+ keys: {
64
+ F5: { label: 'Refresh', action: async () => dash.render(await getData()) },
65
+ F10: { label: 'Quit', action: () => process.exit(0) },
66
+ },
67
+ },
68
+ },
69
+ refresh: 1000,
70
+ data: getData,
71
+ })
72
+ ```
87
73
 
88
- Create a JS file that exports a data function — TuiMon handles the rest:
74
+ ### Multiple Pages
89
75
 
90
- ```js
91
- // metrics.js
92
- const os = require('os')
76
+ You can define multiple HTML pages and let users switch between them with keyboard shortcuts. Press a letter to jump to a detail page, ESC to go back.
93
77
 
94
- module.exports = () => ({
95
- cpu: Math.round(100 - (os.cpus().reduce((a,c) => a + c.times.idle, 0) / os.cpus().reduce((a,c) => a + Object.values(c.times).reduce((x,y) => x+y, 0), 0)) * 100),
96
- memory: Math.round((1 - os.freemem() / os.totalmem()) * 100),
97
- uptime: Math.round(process.uptime()) + 's',
98
- })
78
+ ```typescript
79
+ pages: {
80
+ overview: { html: './pages/overview.html', default: true },
81
+ cpu: { html: './pages/cpu-detail.html', shortcut: 'g', label: 'CPU Detail' },
82
+ memory: { html: './pages/memory-detail.html', shortcut: 'm', label: 'Memory' },
83
+ }
99
84
  ```
100
85
 
101
- ```bash
102
- tuimon watch metrics.js
103
- ```
86
+ ### Client Library
104
87
 
105
- TuiMon inspects the returned data and auto-creates the right widgets:
88
+ TuiMon automatically injects a small client script into your HTML pages. You use it to receive data updates:
106
89
 
107
- | Data type | Widget |
108
- |-----------|--------|
109
- | Number (0-100 + name like cpu/mem) | Gauge |
110
- | Number (other) | Stat card |
111
- | String | Stat card |
112
- | `{ key: number, ... }` (2+ keys) | Line chart (auto-accumulates history) |
113
- | `{ key: number }` | Bar chart |
114
- | `['string', ...]` | Event log (auto-timestamped) |
115
- | `[{ label, status }, ...]` | Status grid (colored dots) |
90
+ - `TuiMon.onUpdate(callback)` receives data whenever `dash.render(data)` is called
91
+ - `TuiMon.set(selector, value)` is a shortcut to update text content or styles
92
+ - `TuiMon.notify(message)` dispatches a notification event
116
93
 
117
- **Export options:**
94
+ ### Shortcut Badges
118
95
 
119
- ```js
120
- module.exports = () => ({ ... }) // data function (required)
121
- module.exports.refresh = 500 // refresh interval in ms (default: 1000)
122
- module.exports.title = 'My App' // dashboard title
123
- module.exports.layout = { ... } // override auto-detected layout
124
- ```
96
+ Add `data-tm-key="g"` to any element and TuiMon automatically renders a `[G]` badge in the corner. Users immediately know they can press G to navigate there.
125
97
 
126
- ### Poll a JSON API
98
+ ### F-Key Bar
127
99
 
128
- ```bash
129
- tuimon watch --url http://localhost:3000/metrics
130
- tuimon watch --url http://localhost:3000/metrics --interval 2000
131
- ```
100
+ Each page can define its own F-key bindings. The bar at the bottom of the terminal always shows the active page's keys.
132
101
 
133
- ## 3. Zero-HTML Declarative Dashboard
102
+ ---
134
103
 
135
- For more control without writing HTML, define widgets in a layout config:
104
+ ## 2. Use the Built-in Theme (No HTML Needed)
136
105
 
137
- ```typescript
138
- import tuimon from 'tuimon'
106
+ If you don't want to design anything, TuiMon comes with a built-in dark neon theme. Just define your widgets and push data. TuiMon generates the HTML for you behind the scenes.
139
107
 
108
+ ```typescript
140
109
  const dash = await tuimon.start({
141
110
  pages: {
142
- overview: {
111
+ main: {
143
112
  default: true,
144
113
  layout: {
145
114
  title: 'My App',
@@ -158,8 +127,8 @@ const dash = await tuimon.start({
158
127
  },
159
128
  refresh: 500,
160
129
  data: () => ({
161
- users: getOnlineCount(),
162
- cpu: getCpuPercent(),
130
+ users: 42,
131
+ cpu: 73,
163
132
  traffic: { Requests: 340, Errors: 12 },
164
133
  services: { Web: 47, API: 27 },
165
134
  events: ['Deploy completed'],
@@ -168,121 +137,162 @@ const dash = await tuimon.start({
168
137
  })
169
138
  ```
170
139
 
171
- **8 widget types:** `stat`, `gauge`, `line`, `doughnut`, `bar`, `event-log`, `status-grid`, `table`
140
+ ### Widget Types
172
141
 
173
- **Per-widget throttle:** Each widget can have its own update rate — charts update every frame while event logs and status grids update less frequently.
142
+ There are 8 built-in widget types: `stat`, `gauge`, `line`, `doughnut`, `bar`, `event-log`, `status-grid`, and `table`.
174
143
 
175
- **Lazy data format:** Every widget accepts the simplest possible data. Just send numbers — TuiMon figures out the rest:
144
+ ### Just Send Numbers
176
145
 
177
- ```typescript
178
- dash.render({
179
- users: 42, // number → stat
180
- cpu: 73, // number → gauge (0-100)
181
- traffic: { Requests: 340, Errors: 12 }, // object → line chart (history auto-accumulated)
182
- services: { Web: 47, API: 27 }, // object → doughnut
183
- events: ['Deploy completed'], // string[] → event-log (auto-timestamped)
184
- health: ['Node-1', 'Node-2'], // string[] → status-grid (all "ok")
185
- })
186
- ```
146
+ You don't need to learn a data format. Just send the simplest thing and TuiMon figures it out:
187
147
 
188
- ## 4. Full Custom HTML Dashboard
148
+ | What you send | What TuiMon shows |
149
+ |---------------|-------------------|
150
+ | `42` | Stat card with the number |
151
+ | `73` (for something named cpu or mem) | Gauge bar showing 73% |
152
+ | `{ Requests: 340, Errors: 12 }` | Line chart that builds up over time |
153
+ | `['Deploy completed']` | Event log with automatic timestamps |
154
+ | `['Node-1', 'Node-2']` | Status grid with green dots |
189
155
 
190
- For complete control, write your dashboard as normal HTML/CSS/JS:
156
+ For line charts, you don't manage history. Each render call sends the current values and TuiMon accumulates the history automatically.
157
+
158
+ ### Per-Widget Throttle
159
+
160
+ Each widget can update at its own speed. Your charts can update every frame while your event log only updates every 2 seconds and your status grid every 5 seconds. Just add `throttle: 2000` to any widget config.
161
+
162
+ ---
163
+
164
+ ## 3. Instant Visualization (Zero Setup)
165
+
166
+ Sometimes you just need to quickly look at some data. TuiMon can do that too.
167
+
168
+ ### View a File
191
169
 
192
170
  ```bash
193
- tuimon init # scaffolds starter project
194
- tuimon start # runs it
171
+ tuimon data.json # JSON array of objects, shown as table + charts
172
+ tuimon users.csv # CSV file, auto-detects delimiter
173
+ tuimon access.log # Nginx access log, shows request stats
174
+ tuimon modsec_audit.log # ModSecurity log, shows security dashboard
175
+ tuimon data.json -c "name,age" # Only show specific columns
195
176
  ```
196
177
 
197
- TuiMon renders your HTML pages in a headless Chromium browser via Playwright, screenshots them as PNG, and streams the images to your terminal. Any charting library works Chart.js, D3, ECharts, anything.
178
+ TuiMon auto-detects the file format, picks the right widgets, and builds a dashboard. It also watches the file for changes so the dashboard updates if the file is modified.
198
179
 
199
- ### Multi-Page Navigation
180
+ Press D to switch to a full-screen data table. Use arrow keys to page through the data. ESC goes back.
200
181
 
201
- ```typescript
202
- const dash = await tuimon.start({
203
- pages: {
204
- overview: {
205
- html: './pages/overview.html',
206
- default: true,
207
- label: 'Overview',
208
- },
209
- cpu: {
210
- html: './pages/cpu-detail.html',
211
- shortcut: 'g',
212
- label: 'CPU Detail',
213
- },
214
- },
182
+ ### Watch Live Data
183
+
184
+ Create a JS file that exports a function returning your data:
185
+
186
+ ```js
187
+ // metrics.js
188
+ const os = require('os')
189
+ module.exports = () => ({
190
+ cpu: getCpuPercent(),
191
+ memory: getMemPercent(),
192
+ uptime: process.uptime(),
215
193
  })
216
194
  ```
217
195
 
218
- - Press a shortcut key to jump to a detail page
219
- - **ESC** on detail page returns to overview
220
- - **ESC** on overview shows quit confirmation
221
- - **Ctrl+C** exits immediately from anywhere
196
+ ```bash
197
+ tuimon watch metrics.js
198
+ ```
199
+
200
+ TuiMon calls your function every second, auto-detects the data shape, and builds a dashboard.
222
201
 
223
- ### Per-Page F-Key Bindings
202
+ You can also poll an HTTP endpoint that returns JSON:
224
203
 
225
- ```typescript
226
- keys: {
227
- F5: { label: 'Refresh', action: async () => dash.render(await getData()) },
228
- F10: { label: 'Quit', action: () => process.exit(0) },
229
- }
204
+ ```bash
205
+ tuimon watch --url http://localhost:3000/metrics
206
+ tuimon watch --url http://localhost:3000/metrics --interval 5000
230
207
  ```
231
208
 
232
- ### Client Library
209
+ ### View a Database Table
233
210
 
234
- In your HTML pages, the injected `TuiMon` object receives data:
211
+ If you are working on a project that already has a database driver installed and a connection string in `.env`, you can view your data directly:
235
212
 
236
- ```javascript
237
- TuiMon.onUpdate(function(data) {
238
- TuiMon.set('#cpu', data.cpu)
239
- TuiMon.set('#memory', data.memory + '%')
240
- })
213
+ ```bash
214
+ tuimon db users # view a table or collection
215
+ tuimon db users --watch # re-query every 2 seconds
216
+ tuimon db "SELECT * FROM orders" # run a custom query
217
+ tuimon db users --query '{"active":true}' # MongoDB filter
218
+ tuimon db users --env MY_DB_URI # use a specific env variable
219
+ tuimon db users -c "name,email,role" # only show these columns
241
220
  ```
242
221
 
243
- Add shortcut badges to panels with data attributes:
222
+ TuiMon finds the database driver in your project's `node_modules/` folder and reads the connection string from your `.env` file. It supports MongoDB, PostgreSQL, MySQL, and SQLite.
244
223
 
245
- ```html
246
- <div class="panel" data-tm-key="g" data-tm-label="CPU Detail">
224
+ No new dependencies are installed. TuiMon uses whatever driver your project already has.
225
+
226
+ ---
227
+
228
+ ## Terminal Support
229
+
230
+ | Terminal | Protocol | Status |
231
+ |----------|----------|--------|
232
+ | Kitty | Kitty | Supported |
233
+ | Ghostty | Kitty | Supported |
234
+ | WezTerm | Kitty | Supported |
235
+ | iTerm2 | iTerm2 | Supported |
236
+ | VSCode | Sixel | Supported |
237
+ | mlterm | Sixel | Supported |
238
+
239
+ ### VSCode
240
+
241
+ Running `tuimon init` automatically enables terminal images in VSCode. It creates a `.vscode/settings.json` file with:
242
+
243
+ ```json
244
+ { "terminal.integrated.enableImages": true }
245
+ ```
246
+
247
+ If you are adding TuiMon to an existing project, add that setting manually or run `tuimon init`.
248
+
249
+ ---
250
+
251
+ ## Global Config
252
+
253
+ You can set preferences once so you don't have to repeat them:
254
+
255
+ ```bash
256
+ tuimon config db.envVar MONGODB_URI # which env var holds your DB connection
257
+ tuimon config db.defaultLimit 500 # how many rows to show by default
258
+ tuimon config refresh 250 # default refresh rate in ms
259
+ tuimon config # show current config
260
+ tuimon config --reset # reset everything to defaults
247
261
  ```
248
262
 
263
+ Config is stored in `~/.tuimon/config.json`.
264
+
265
+ ---
266
+
249
267
  ## CLI Reference
250
268
 
251
- | Command | Description |
252
- |---------|-------------|
269
+ | Command | What it does |
270
+ |---------|--------------|
253
271
  | `tuimon <file>` | Visualize a JSON, CSV, or log file |
254
- | `tuimon watch <file.js>` | Live dashboard from a data module |
272
+ | `tuimon watch <file.js>` | Live dashboard from a JS data module |
255
273
  | `tuimon watch --url <url>` | Poll a JSON endpoint |
256
- | `tuimon start` | Run from tuimon.config.ts |
257
- | `tuimon init` | Scaffold a starter project + enable VSCode |
258
- | `tuimon check` | Check terminal graphics support |
274
+ | `tuimon db <table or query>` | View a database table or run a query |
275
+ | `tuimon start` | Run a custom HTML dashboard from tuimon.config.ts |
276
+ | `tuimon init` | Scaffold a starter project and enable VSCode |
277
+ | `tuimon check` | Check if your terminal supports graphics |
278
+ | `tuimon config` | View or set global preferences |
279
+ | `tuimon ai` | Print the AI integration guide |
259
280
 
260
- **Options:**
261
- - `-c, --columns <cols>` — comma-separated list of columns to display
262
- - `--interval <ms>` — poll interval for URL watch mode (default: 1000)
281
+ Set `TUIMON_DEBUG=1` to print per-frame timing to stderr.
263
282
 
264
- **Environment:**
265
- - `TUIMON_DEBUG=1` — print per-frame timing to stderr
283
+ ---
266
284
 
267
285
  ## How It Works
268
286
 
269
- ```
270
- Your data → TuiMon → Headless Chromium → Screenshot → Kitty/Sixel → Terminal
271
- ```
287
+ TuiMon runs a headless Chromium browser via Playwright. Your HTML page loads in the browser. TuiMon pushes data into the page, takes a PNG screenshot, encodes it using the Kitty graphics protocol (or Sixel for terminals that need it), and writes it to stdout. The F-key bar and keyboard input run natively in the terminal.
272
288
 
273
- 1. Your data is pushed to an HTML page running in headless Chromium
274
- 2. Playwright takes a PNG screenshot
275
- 3. The image is encoded as Kitty graphics protocol (or Sixel fallback)
276
- 4. Written directly to your terminal's stdout
289
+ A typical frame takes about 50ms from data push to pixels on screen.
277
290
 
278
- Typical frame time: **~50ms** (at 250ms refresh = 4 FPS with headroom to spare).
291
+ ---
279
292
 
280
293
  ## Contributing
281
294
 
282
- - **TDD required** write tests first, implementation second
283
- - Coverage thresholds: 80% lines, 80% functions, 75% branches
284
- - `npm test` must pass before any PR
285
- - Strict TypeScript — `strict: true`, `noUncheckedIndexedAccess`, no `any`
295
+ Tests first, implementation second. Coverage thresholds are 80% lines, 80% functions, and 75% branches. TypeScript is strict with no exceptions.
286
296
 
287
297
  ## License
288
298
 
@@ -1 +1 @@
1
- {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,wBAAsB,aAAa,CAAC,EAClC,GAAG,EACH,KAAK,EACL,MAAM,GACP,EAAE;IACD,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,GAAG,OAAO,CAAC,aAAa,CAAC,CAkEzB"}
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,wBAAsB,aAAa,CAAC,EAClC,GAAG,EACH,KAAK,EACL,MAAM,GACP,EAAE;IACD,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,GAAG,OAAO,CAAC,aAAa,CAAC,CAqEzB"}
package/dist/browser.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import { chromium } from 'playwright';
2
2
  export async function createBrowser({ url, width, height, }) {
3
- const browser = await chromium.launch({ headless: true });
3
+ const browser = await chromium.launch({
4
+ headless: true,
5
+ timeout: 30000,
6
+ });
4
7
  const context = await browser.newContext();
5
8
  const page = await context.newPage();
6
9
  await page.setViewportSize({ width, height });
@@ -1 +1 @@
1
- {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAGrC,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,EAClC,GAAG,EACH,KAAK,EACL,MAAM,GAKP;IACC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;QACpC,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,KAAK;KACf,CAAC,CAAA;IACF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,CAAA;IAC1C,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAA;IAEpC,MAAM,IAAI,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;IAC7C,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,CAAA;IAEvD,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE;QAC1B,UAAU,EAAE,CAAA;QACZ,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;YACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAA;YAChF,OAAM;QACR,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,UAAU,kBAAkB,CAAC,CAAA;QACpF,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,EAAE,CAAA;QACrB,CAAC;QAAC,MAAM,CAAC;YACP,yBAAyB;QAC3B,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,GAAG,EAAE,EAAE;QAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,GAAG,CAAC,OAAO,IAAI,CAAC,CAAA;IAC9D,CAAC,CAAC,CAAA;IAEF,OAAO;QACL,KAAK,CAAC,UAAU;YACd,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;YAClD,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACzB,CAAC;QAED,KAAK,CAAC,QAAQ,CAAC,IAA6B;YAC1C,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,CAA0B,EAAE,EAAE;gBACjD,MAAM,GAAG,GAAG,UAAqC,CAAA;gBACjD,IAAI,OAAO,GAAG,CAAC,mBAAmB,CAAC,KAAK,UAAU,EAAE,CAAC;oBACnD,CAAC;oBAAC,GAAG,CAAC,mBAAmB,CAA0C,CAAC,CAAC,CAAC,CAAA;gBACxE,CAAC;YACH,CAAC,EAAE,IAAI,CAAC,CAAA;YACR,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,eAAe,CACxB,GAAG,EAAE,CAAE,UAAsC,CAAC,kBAAkB,CAAC,KAAK,IAAI,EAC1E,EAAE,OAAO,EAAE,IAAI,EAAE,CAClB,CAAA;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,kEAAkE;YACpE,CAAC;QACH,CAAC;QAED,KAAK,CAAC,QAAQ,CAAC,MAAc;YAC3B,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,CAAA;QAC5D,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,CAAS,EAAE,CAAS;YAC/B,MAAM,IAAI,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;QACrD,CAAC;QAED,KAAK,CAAC,QAAQ,CAAC,UAAkB;YAC/B,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;QACjC,CAAC;QAED,KAAK,CAAC,KAAK;YACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAA;QACvB,CAAC;KACF,CAAA;AACH,CAAC"}
package/dist/cli.js CHANGED
@@ -18,7 +18,7 @@ const program = new Command();
18
18
  program
19
19
  .name('tuimon')
20
20
  .description('Render beautiful HTML dashboards directly in your terminal.')
21
- .version('0.1.0');
21
+ .version('0.3.0');
22
22
  // ─── Default command: tuimon <file> ──────────────────────────────────────────
23
23
  program
24
24
  .argument('[file]', 'JSON, CSV, or log file to visualize')
@@ -48,6 +48,34 @@ program
48
48
  return;
49
49
  }
50
50
  const columns = opts.columns ? opts.columns.split(',').map((c) => c.trim()).filter(Boolean) : undefined;
51
+ // Check for preset file patterns first
52
+ const basename = file.split('/').pop()?.split('\\').pop() ?? '';
53
+ if (basename === 'package-lock.json' || basename === 'yarn.lock' || basename === 'pnpm-lock.yaml') {
54
+ if (!existsSync(file)) {
55
+ console.error(`[tuimon] File not found: ${file}`);
56
+ process.exit(1);
57
+ }
58
+ const { depsPreset } = await import('./quick/presets/deps.js');
59
+ const { runPreset } = await import('./quick/presets/runner.js');
60
+ await runPreset(depsPreset(file));
61
+ return;
62
+ }
63
+ if (basename.includes('coverage') || basename.endsWith('.lcov') || (basename.endsWith('.xml') && existsSync(file))) {
64
+ if (!existsSync(file)) {
65
+ console.error(`[tuimon] File not found: ${file}`);
66
+ process.exit(1);
67
+ }
68
+ // Check if it's a coverage/junit file
69
+ try {
70
+ const { coveragePreset } = await import('./quick/presets/coverage.js');
71
+ const { runPreset } = await import('./quick/presets/runner.js');
72
+ await runPreset(coveragePreset(file));
73
+ return;
74
+ }
75
+ catch {
76
+ // Not a coverage file, fall through to normal detection
77
+ }
78
+ }
51
79
  // Quick mode: detect file type and visualize
52
80
  const { detectInputType } = await import('./quick/detect.js');
53
81
  const inputType = detectInputType(file);
@@ -96,6 +124,31 @@ program
96
124
  }
97
125
  }
98
126
  });
127
+ // ─── Preset subcommands ──────────────────────────────────────────────────────
128
+ program
129
+ .command('docker')
130
+ .description('Live Docker container dashboard')
131
+ .action(async () => {
132
+ const { dockerPreset } = await import('./quick/presets/docker.js');
133
+ const { runPreset } = await import('./quick/presets/runner.js');
134
+ await runPreset(dockerPreset());
135
+ });
136
+ program
137
+ .command('git')
138
+ .description('Git repository dashboard')
139
+ .action(async () => {
140
+ const { gitPreset } = await import('./quick/presets/git.js');
141
+ const { runPreset } = await import('./quick/presets/runner.js');
142
+ await runPreset(gitPreset());
143
+ });
144
+ program
145
+ .command('ps')
146
+ .description('Live process monitor')
147
+ .action(async () => {
148
+ const { psPreset } = await import('./quick/presets/ps.js');
149
+ const { runPreset } = await import('./quick/presets/runner.js');
150
+ await runPreset(psPreset());
151
+ });
99
152
  // ─── Start command: tuimon start (full config mode) ──────────────────────────
100
153
  program
101
154
  .command('start')
@@ -177,11 +230,23 @@ program
177
230
  }
178
231
  if (process.env['TERM_PROGRAM'] === 'vscode') {
179
232
  console.log('');
180
- console.log(' VSCode detected \u2014 make sure this setting is enabled:');
233
+ console.log(' VSCode detected. Make sure this setting is enabled:');
181
234
  console.log(' "terminal.integrated.enableImages": true');
182
235
  console.log('');
183
236
  console.log(' Run "tuimon init" to configure this automatically.');
184
237
  }
238
+ // Check if Playwright browser is installed
239
+ console.log('');
240
+ try {
241
+ const { chromium } = await import('playwright');
242
+ const browser = await chromium.launch({ headless: true, timeout: 10000 });
243
+ await browser.close();
244
+ console.log('\u2713 Chromium browser: installed');
245
+ }
246
+ catch {
247
+ console.log('\u2717 Chromium browser: not found');
248
+ console.log(' Run: npx playwright install chromium');
249
+ }
185
250
  console.log('');
186
251
  process.exit(support.protocol ? 0 : 1);
187
252
  });