tuimon 0.1.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.
Files changed (50) hide show
  1. package/CLAUDE.md +80 -0
  2. package/README.md +153 -0
  3. package/client/tuimon-client.js +44 -0
  4. package/dist/browser.d.ts +7 -0
  5. package/dist/browser.d.ts.map +1 -0
  6. package/dist/browser.js +57 -0
  7. package/dist/browser.js.map +1 -0
  8. package/dist/cli.d.ts +3 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +87 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/detect.d.ts +8 -0
  13. package/dist/detect.d.ts.map +1 -0
  14. package/dist/detect.js +141 -0
  15. package/dist/detect.js.map +1 -0
  16. package/dist/encoder.d.ts +4 -0
  17. package/dist/encoder.d.ts.map +1 -0
  18. package/dist/encoder.js +115 -0
  19. package/dist/encoder.js.map +1 -0
  20. package/dist/fkeybar.d.ts +5 -0
  21. package/dist/fkeybar.d.ts.map +1 -0
  22. package/dist/fkeybar.js +89 -0
  23. package/dist/fkeybar.js.map +1 -0
  24. package/dist/index.d.ts +7 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +166 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/keyhandler.d.ts +5 -0
  29. package/dist/keyhandler.d.ts.map +1 -0
  30. package/dist/keyhandler.js +20 -0
  31. package/dist/keyhandler.js.map +1 -0
  32. package/dist/router.d.ts +10 -0
  33. package/dist/router.d.ts.map +1 -0
  34. package/dist/router.js +154 -0
  35. package/dist/router.js.map +1 -0
  36. package/dist/server.d.ts +5 -0
  37. package/dist/server.d.ts.map +1 -0
  38. package/dist/server.js +142 -0
  39. package/dist/server.js.map +1 -0
  40. package/dist/types.d.ts +108 -0
  41. package/dist/types.d.ts.map +1 -0
  42. package/dist/types.js +3 -0
  43. package/dist/types.js.map +1 -0
  44. package/package.json +44 -0
  45. package/templates/internal/confirm-quit.html +94 -0
  46. package/templates/starter/pages/cpu-detail.html +176 -0
  47. package/templates/starter/pages/memory-detail.html +166 -0
  48. package/templates/starter/pages/overview.html +186 -0
  49. package/templates/starter/tuimon.config.ts +87 -0
  50. package/tsconfig.json +23 -0
@@ -0,0 +1,115 @@
1
+ import sharp from 'sharp';
2
+ const CHUNK_SIZE = 4096;
3
+ const MAX_PALETTE_COLORS = 256;
4
+ export async function encodeAndRender(buffer, opts) {
5
+ if (opts.protocol === 'kitty') {
6
+ renderKitty(buffer);
7
+ }
8
+ else {
9
+ await renderSixel(buffer);
10
+ }
11
+ }
12
+ function renderKitty(buffer) {
13
+ process.stdout.write('\x1b[H');
14
+ const b64 = buffer.toString('base64');
15
+ const chunks = [];
16
+ for (let i = 0; i < b64.length; i += CHUNK_SIZE) {
17
+ chunks.push(b64.slice(i, i + CHUNK_SIZE));
18
+ }
19
+ for (let i = 0; i < chunks.length; i++) {
20
+ const hasMore = i < chunks.length - 1;
21
+ if (i === 0) {
22
+ process.stdout.write(`\x1b_Ga=T,f=100,m=${hasMore ? 1 : 0};${chunks[i]}\x1b\\`);
23
+ }
24
+ else {
25
+ process.stdout.write(`\x1b_Gm=${hasMore ? 1 : 0};${chunks[i]}\x1b\\`);
26
+ }
27
+ }
28
+ }
29
+ async function renderSixel(buffer) {
30
+ process.stdout.write('\x1b[H');
31
+ let image;
32
+ try {
33
+ image = sharp(buffer);
34
+ }
35
+ catch (err) {
36
+ console.error('[tuimon] encoder: invalid image buffer', err);
37
+ return;
38
+ }
39
+ const meta = await image.metadata();
40
+ const width = meta.width ?? 1;
41
+ const height = meta.height ?? 1;
42
+ const { data, info } = await image
43
+ .raw()
44
+ .ensureAlpha()
45
+ .toBuffer({ resolveWithObject: true });
46
+ // Build color palette (up to 256 colors)
47
+ const colorMap = new Map();
48
+ let nextColor = 0;
49
+ let paletteOverflow = false;
50
+ const pixels = new Array(width * height);
51
+ for (let i = 0; i < width * height; i++) {
52
+ const offset = i * info.channels;
53
+ const r = data[offset] ?? 0;
54
+ const g = data[offset + 1] ?? 0;
55
+ const b = data[offset + 2] ?? 0;
56
+ const key = `${r},${g},${b}`;
57
+ if (!colorMap.has(key) && nextColor < MAX_PALETTE_COLORS) {
58
+ colorMap.set(key, nextColor++);
59
+ }
60
+ else if (!colorMap.has(key) && !paletteOverflow) {
61
+ paletteOverflow = true;
62
+ console.error(`[tuimon] sixel: image has >256 colors — some colors will be approximated`);
63
+ }
64
+ pixels[i] = colorMap.get(key) ?? 0;
65
+ }
66
+ // Write DCS header and raster attributes
67
+ process.stdout.write(`\x1bP0;0;0q"1;1;${width};${height}`);
68
+ // Write color definitions
69
+ for (const [key, idx] of colorMap.entries()) {
70
+ const parts = key.split(',').map(Number);
71
+ const r = parts[0] ?? 0;
72
+ const g = parts[1] ?? 0;
73
+ const b = parts[2] ?? 0;
74
+ const rp = Math.round((r / 255) * 100);
75
+ const gp = Math.round((g / 255) * 100);
76
+ const bp = Math.round((b / 255) * 100);
77
+ process.stdout.write(`#${idx};2;${rp};${gp};${bp}`);
78
+ }
79
+ // Write sixel rows in chunks (groups of 6 vertical pixels)
80
+ for (let y = 0; y < height; y += 6) {
81
+ const rowColors = new Map();
82
+ for (let x = 0; x < width; x++) {
83
+ const sixelByte = new Map();
84
+ for (let dy = 0; dy < 6; dy++) {
85
+ const py = y + dy;
86
+ if (py >= height)
87
+ break;
88
+ const colorIdx = pixels[py * width + x] ?? 0;
89
+ sixelByte.set(colorIdx, (sixelByte.get(colorIdx) ?? 0) | (1 << dy));
90
+ }
91
+ for (const [colorIdx, bits] of sixelByte.entries()) {
92
+ if (!rowColors.has(colorIdx)) {
93
+ rowColors.set(colorIdx, new Array(width).fill(0));
94
+ }
95
+ rowColors.get(colorIdx)[x] = bits;
96
+ }
97
+ }
98
+ let bandData = '';
99
+ let first = true;
100
+ for (const [colorIdx, row] of rowColors.entries()) {
101
+ if (!first)
102
+ bandData += '$';
103
+ first = false;
104
+ bandData += `#${colorIdx}`;
105
+ for (let x = 0; x < width; x++) {
106
+ bandData += String.fromCharCode(63 + (row[x] ?? 0));
107
+ }
108
+ }
109
+ bandData += '-';
110
+ process.stdout.write(bandData);
111
+ }
112
+ // String terminator
113
+ process.stdout.write('\x1b\\');
114
+ }
115
+ //# sourceMappingURL=encoder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encoder.js","sourceRoot":"","sources":["../src/encoder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { FKeyMap, FKeyBarHandle } from './types.js';
2
+ export declare function renderFKeyBar({ keys }: {
3
+ keys: FKeyMap;
4
+ }): FKeyBarHandle;
5
+ //# sourceMappingURL=fkeybar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fkeybar.d.ts","sourceRoot":"","sources":["../src/fkeybar.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAkD9D,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,aAAa,CAsDxE"}
@@ -0,0 +1,89 @@
1
+ const ALL_FKEYS = ['F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12'];
2
+ const BG = '\x1b[48;5;236m';
3
+ const CYAN = '\x1b[96m';
4
+ const WHITE = '\x1b[97m';
5
+ const RESET = '\x1b[0m';
6
+ const HIDE_CURSOR = '\x1b[?25l';
7
+ const SHOW_CURSOR = '\x1b[?25h';
8
+ function buildBar(keys, cols) {
9
+ const segments = [];
10
+ for (const fk of ALL_FKEYS) {
11
+ const binding = keys[fk];
12
+ if (!binding)
13
+ continue;
14
+ segments.push(`${CYAN}${fk}${WHITE} ${binding.label}`);
15
+ }
16
+ // Build the full rendered line
17
+ let rendered = segments.join(' ');
18
+ // Calculate visible length (strip ANSI)
19
+ const visibleLength = rendered.replace(/\x1b\[[0-9;]*m/g, '').length;
20
+ if (visibleLength > cols) {
21
+ // Truncate: rebuild with fewer segments
22
+ rendered = '';
23
+ let currentLen = 0;
24
+ for (let i = 0; i < segments.length; i++) {
25
+ const segVisible = (segments[i] ?? '').replace(/\x1b\[[0-9;]*m/g, '').length;
26
+ const sepLen = rendered.length > 0 ? 2 : 0;
27
+ if (currentLen + segVisible + sepLen > cols)
28
+ break;
29
+ rendered += (rendered.length > 0 ? ' ' : '') + (segments[i] ?? '');
30
+ currentLen += segVisible + sepLen;
31
+ }
32
+ }
33
+ // Pad to full width
34
+ const finalVisible = rendered.replace(/\x1b\[[0-9;]*m/g, '').length;
35
+ const padding = Math.max(0, cols - finalVisible);
36
+ return `${BG}${rendered}${' '.repeat(padding)}${RESET}`;
37
+ }
38
+ function renderLine(content, rows) {
39
+ process.stdout.write(`\x1b[${rows};0H${content}`);
40
+ }
41
+ export function renderFKeyBar({ keys }) {
42
+ let currentKeys = keys;
43
+ let notifyTimer = null;
44
+ process.stdout.write(HIDE_CURSOR);
45
+ function draw() {
46
+ const cols = process.stdout.columns || 80;
47
+ const rows = process.stdout.rows || 24;
48
+ const bar = buildBar(currentKeys, cols);
49
+ renderLine(bar, rows);
50
+ }
51
+ function onResize() {
52
+ draw();
53
+ }
54
+ process.stdout.on('resize', onResize);
55
+ draw();
56
+ return {
57
+ setKeys(newKeys) {
58
+ currentKeys = newKeys;
59
+ if (notifyTimer) {
60
+ clearTimeout(notifyTimer);
61
+ notifyTimer = null;
62
+ }
63
+ draw();
64
+ },
65
+ notify(message, duration = 3000) {
66
+ const cols = process.stdout.columns || 80;
67
+ const rows = process.stdout.rows || 24;
68
+ const visible = message.slice(0, cols);
69
+ const padding = Math.max(0, cols - visible.length);
70
+ const line = `${BG}${WHITE}${visible}${' '.repeat(padding)}${RESET}`;
71
+ renderLine(line, rows);
72
+ if (notifyTimer)
73
+ clearTimeout(notifyTimer);
74
+ notifyTimer = setTimeout(() => {
75
+ notifyTimer = null;
76
+ draw();
77
+ }, duration);
78
+ },
79
+ stop() {
80
+ if (notifyTimer) {
81
+ clearTimeout(notifyTimer);
82
+ notifyTimer = null;
83
+ }
84
+ process.stdout.removeListener('resize', onResize);
85
+ process.stdout.write(SHOW_CURSOR);
86
+ },
87
+ };
88
+ }
89
+ //# sourceMappingURL=fkeybar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fkeybar.js","sourceRoot":"","sources":["../src/fkeybar.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { TuiMonOptions, TuiMonDashboard } from './types.js';
2
+ declare function start(options: TuiMonOptions): Promise<TuiMonDashboard>;
3
+ declare const _default: {
4
+ start: typeof start;
5
+ };
6
+ export default _default;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EAEhB,MAAM,YAAY,CAAA;AAWnB,iBAAe,KAAK,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,CA2KrE;;;;AAED,wBAAwB"}
package/dist/index.js ADDED
@@ -0,0 +1,166 @@
1
+ import path from 'node:path';
2
+ import { detectGraphicsSupport, getTerminalDimensions } from './detect.js';
3
+ import { startServer } from './server.js';
4
+ import { createBrowser } from './browser.js';
5
+ import { encodeAndRender } from './encoder.js';
6
+ import { startKeyHandler } from './keyhandler.js';
7
+ import { renderFKeyBar } from './fkeybar.js';
8
+ import { createRouter } from './router.js';
9
+ const MAX_REFRESH_FAILURES = 5;
10
+ async function start(options) {
11
+ const { pages } = options;
12
+ const renderDelay = options.renderDelay ?? 50;
13
+ // Validate pages is not empty
14
+ const pageEntries = Object.entries(pages);
15
+ if (pageEntries.length === 0) {
16
+ throw new Error('[tuimon] At least one page must be defined');
17
+ }
18
+ // Detect terminal capabilities
19
+ const graphics = await detectGraphicsSupport();
20
+ const dims = await getTerminalDimensions();
21
+ if (!graphics.protocol) {
22
+ console.error('[tuimon] No supported graphics protocol detected. Falling back to kitty.');
23
+ }
24
+ // iterm2 uses kitty-compatible rendering for our purposes
25
+ const protocol = (graphics.protocol === 'sixel') ? 'sixel' : 'kitty';
26
+ // Resolve all page html paths and find common root
27
+ const resolvedPages = new Map();
28
+ const allDirs = [];
29
+ for (const [id, page] of pageEntries) {
30
+ const resolved = path.resolve(process.cwd(), page.html);
31
+ resolvedPages.set(id, resolved);
32
+ allDirs.push(path.dirname(resolved));
33
+ }
34
+ // Find common parent directory
35
+ let rootDir = allDirs[0] ?? process.cwd();
36
+ if (allDirs.length > 1) {
37
+ const parts = rootDir.split(path.sep);
38
+ for (const dir of allDirs) {
39
+ const dirParts = dir.split(path.sep);
40
+ let common = 0;
41
+ while (common < parts.length && common < dirParts.length && parts[common] === dirParts[common]) {
42
+ common++;
43
+ }
44
+ parts.length = common;
45
+ }
46
+ rootDir = parts.join(path.sep) || '/';
47
+ }
48
+ // Start server
49
+ const server = await startServer({ rootDir });
50
+ // Calculate viewport dimensions (reserve 1 row for F-key bar)
51
+ const cellPixelHeight = Math.floor(dims.pixelHeight / dims.rows);
52
+ const viewportHeight = dims.pixelHeight - cellPixelHeight;
53
+ const viewportWidth = dims.pixelWidth;
54
+ // Start browser
55
+ const browser = await createBrowser({
56
+ url: server.url,
57
+ width: viewportWidth,
58
+ height: viewportHeight,
59
+ });
60
+ // Enter alt screen + hide cursor
61
+ process.stdout.write('\x1b[?1049h\x1b[?25l');
62
+ // Track last data for re-rendering after navigation
63
+ let lastData = {};
64
+ let refreshInterval;
65
+ let stopped = false;
66
+ let rendering = false;
67
+ // Render function with concurrency guard
68
+ async function renderFrame(data) {
69
+ if (stopped || rendering)
70
+ return;
71
+ rendering = true;
72
+ try {
73
+ if (data)
74
+ lastData = data;
75
+ await browser.pushData(lastData);
76
+ await new Promise((resolve) => setTimeout(resolve, renderDelay));
77
+ const screenshot = await browser.screenshot();
78
+ await encodeAndRender(screenshot, { protocol });
79
+ }
80
+ finally {
81
+ rendering = false;
82
+ }
83
+ }
84
+ // F-key bar
85
+ const defaultPageId = pageEntries.find(([, p]) => p.default)?.[0] ?? pageEntries[0][0];
86
+ const defaultPage = pages[defaultPageId];
87
+ const fkeyBar = renderFKeyBar({ keys: defaultPage.keys ?? {} });
88
+ // Router navigate helper
89
+ async function navigateToPage(htmlPath) {
90
+ // Internal paths (e.g., /tuimon/confirm-quit.html) are served as-is
91
+ // Page paths are resolved to their filename
92
+ const url = htmlPath.startsWith('/tuimon/')
93
+ ? `${server.url}${htmlPath}`
94
+ : server.urlFor(path.basename(htmlPath));
95
+ await browser.navigate(url);
96
+ }
97
+ // Router
98
+ const router = createRouter({
99
+ pages,
100
+ navigate: navigateToPage,
101
+ render: async () => { await renderFrame(); },
102
+ setKeys: (keys) => { fkeyBar.setKeys(keys); },
103
+ confirmQuitHtml: '/tuimon/confirm-quit.html',
104
+ });
105
+ // Key handler — catch unhandled rejections from handleKey
106
+ const keyHandler = startKeyHandler({
107
+ onKey: (key) => {
108
+ router.handleKey(key).catch((err) => {
109
+ console.error('[tuimon] key handler error:', err);
110
+ });
111
+ },
112
+ });
113
+ // Auto-refresh with circuit breaker
114
+ if (options.refresh && options.data) {
115
+ const dataFn = options.data;
116
+ let consecutiveFailures = 0;
117
+ refreshInterval = setInterval(async () => {
118
+ try {
119
+ const data = await dataFn();
120
+ await renderFrame(data);
121
+ consecutiveFailures = 0;
122
+ }
123
+ catch (err) {
124
+ consecutiveFailures++;
125
+ console.error('[tuimon] refresh error:', err);
126
+ if (consecutiveFailures >= MAX_REFRESH_FAILURES) {
127
+ console.error(`[tuimon] ${MAX_REFRESH_FAILURES} consecutive refresh failures — disabling auto-refresh`);
128
+ if (refreshInterval)
129
+ clearInterval(refreshInterval);
130
+ }
131
+ }
132
+ }, options.refresh);
133
+ refreshInterval.unref();
134
+ }
135
+ // Navigate to the default page
136
+ const defaultHtml = defaultPage.html;
137
+ const defaultFilename = path.basename(path.resolve(process.cwd(), defaultHtml));
138
+ await browser.navigate(server.urlFor(defaultFilename));
139
+ // Stop function
140
+ async function stop() {
141
+ if (stopped)
142
+ return;
143
+ stopped = true;
144
+ if (refreshInterval)
145
+ clearInterval(refreshInterval);
146
+ keyHandler.stop();
147
+ fkeyBar.stop();
148
+ await browser.close();
149
+ await server.close();
150
+ // Restore terminal: show cursor + exit alt screen
151
+ process.stdout.write('\x1b[?25h\x1b[?1049l');
152
+ }
153
+ // Await stop on SIGINT to ensure cleanup completes
154
+ process.once('SIGINT', () => {
155
+ stop().catch((err) => {
156
+ console.error('[tuimon] shutdown error:', err);
157
+ process.exit(1);
158
+ });
159
+ });
160
+ return {
161
+ render: async (data) => { await renderFrame(data); },
162
+ stop,
163
+ };
164
+ }
165
+ export default { start };
166
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { KeyHandlerHandle } from './types.js';
2
+ export declare function startKeyHandler({ onKey }: {
3
+ onKey: (key: string) => void;
4
+ }): KeyHandlerHandle;
5
+ //# sourceMappingURL=keyhandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyhandler.d.ts","sourceRoot":"","sources":["../src/keyhandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD,wBAAgB,eAAe,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,GAAG,gBAAgB,CAoB7F"}
@@ -0,0 +1,20 @@
1
+ export function startKeyHandler({ onKey }) {
2
+ const onData = (buffer) => {
3
+ onKey(buffer.toString());
4
+ };
5
+ if (process.stdin.isTTY) {
6
+ process.stdin.setRawMode(true);
7
+ }
8
+ process.stdin.resume();
9
+ process.stdin.on('data', onData);
10
+ return {
11
+ stop() {
12
+ process.stdin.removeListener('data', onData);
13
+ if (process.stdin.isTTY) {
14
+ process.stdin.setRawMode(false);
15
+ }
16
+ process.stdin.pause();
17
+ },
18
+ };
19
+ }
20
+ //# sourceMappingURL=keyhandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyhandler.js","sourceRoot":"","sources":["../src/keyhandler.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAAC,EAAE,KAAK,EAAoC;IACzE,MAAM,MAAM,GAAG,CAAC,MAAc,EAAQ,EAAE;QACtC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC1B,CAAC,CAAA;IAED,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;IAChC,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAA;IACtB,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEhC,OAAO;QACL,IAAI;YACF,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;YAC5C,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;gBACxB,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;YACjC,CAAC;YACD,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;QACvB,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { PageMap, FKeyMap, RouterHandle } from './types.js';
2
+ export interface RouterDeps {
3
+ pages: PageMap;
4
+ navigate: (url: string) => Promise<void>;
5
+ render: (data?: Record<string, unknown>) => Promise<void>;
6
+ setKeys: (keys: FKeyMap) => void;
7
+ confirmQuitHtml: string;
8
+ }
9
+ export declare function createRouter(deps: RouterDeps): RouterHandle;
10
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAa,OAAO,EAAQ,YAAY,EAAE,MAAM,YAAY,CAAA;AAEjF,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,OAAO,CAAA;IACd,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACxC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACzD,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IAChC,eAAe,EAAE,MAAM,CAAA;CACxB;AA0BD,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,YAAY,CAsK3D"}
package/dist/router.js ADDED
@@ -0,0 +1,154 @@
1
+ // ─── Key sequence → FKey mapping ─────────────────────────────────────────────
2
+ const SEQ_TO_FKEY = {
3
+ '\x1bOP': 'F1', '\x1b[11~': 'F1',
4
+ '\x1bOQ': 'F2', '\x1b[12~': 'F2',
5
+ '\x1bOR': 'F3', '\x1b[13~': 'F3',
6
+ '\x1bOS': 'F4', '\x1b[14~': 'F4',
7
+ '\x1b[15~': 'F5',
8
+ '\x1b[17~': 'F6',
9
+ '\x1b[18~': 'F7',
10
+ '\x1b[19~': 'F8',
11
+ '\x1b[20~': 'F9',
12
+ '\x1b[21~': 'F10',
13
+ '\x1b[23~': 'F11',
14
+ '\x1b[24~': 'F12',
15
+ };
16
+ const RESERVED_SHORTCUTS = new Set(['y', 'n', '\x1b', '\x03']);
17
+ const ESC = '\x1b';
18
+ const CTRL_C = '\x03';
19
+ // ─── createRouter ────────────────────────────────────────────────────────────
20
+ export function createRouter(deps) {
21
+ const { pages, navigate, render, setKeys, confirmQuitHtml } = deps;
22
+ // ── Validation ──────────────────────────────────────────────────────────
23
+ // Exactly one default page
24
+ const defaultEntries = Object.entries(pages).filter(([, cfg]) => cfg.default);
25
+ if (defaultEntries.length !== 1) {
26
+ throw new Error(`Exactly one page must have default: true, found ${defaultEntries.length}`);
27
+ }
28
+ const [defaultPageId, defaultPageConfig] = defaultEntries[0];
29
+ // Shortcut uniqueness and reserved check
30
+ const seenShortcuts = new Map();
31
+ for (const [id, cfg] of Object.entries(pages)) {
32
+ if (cfg.shortcut != null) {
33
+ if (RESERVED_SHORTCUTS.has(cfg.shortcut)) {
34
+ throw new Error(`Page "${id}" uses reserved shortcut '${cfg.shortcut}'`);
35
+ }
36
+ if (seenShortcuts.has(cfg.shortcut)) {
37
+ throw new Error(`Duplicate shortcut '${cfg.shortcut}' on pages "${seenShortcuts.get(cfg.shortcut)}" and "${id}"`);
38
+ }
39
+ seenShortcuts.set(cfg.shortcut, id);
40
+ }
41
+ // Warn if ESC or Ctrl+C defined in page keys
42
+ if (cfg.keys) {
43
+ for (const key of Object.keys(cfg.keys)) {
44
+ if (key === 'ESC' || key === 'Escape' || key === CTRL_C) {
45
+ console.warn(`[tuimon] Page "${id}" defines reserved key "${key}" in its key map — it will be ignored`);
46
+ }
47
+ }
48
+ }
49
+ }
50
+ // ── Shortcut → pageId lookup ────────────────────────────────────────────
51
+ const shortcutToPageId = new Map();
52
+ for (const [id, cfg] of Object.entries(pages)) {
53
+ if (cfg.shortcut) {
54
+ shortcutToPageId.set(cfg.shortcut, id);
55
+ }
56
+ }
57
+ // ── State ───────────────────────────────────────────────────────────────
58
+ let state = { type: 'overview', pageId: defaultPageId };
59
+ // Set initial keys
60
+ setKeys(defaultPageConfig.keys ?? {});
61
+ // ── Confirm-quit keys ───────────────────────────────────────────────────
62
+ const confirmQuitKeys = {};
63
+ // ── Helpers ─────────────────────────────────────────────────────────────
64
+ function getPageKeys(pageId) {
65
+ return pages[pageId]?.keys ?? {};
66
+ }
67
+ function getPageHtml(pageId) {
68
+ const page = pages[pageId];
69
+ if (!page)
70
+ throw new Error(`[tuimon] Unknown page: "${pageId}"`);
71
+ return page.html;
72
+ }
73
+ async function goToPage(pageState) {
74
+ state = pageState;
75
+ const pageId = pageState.type === 'confirm-quit'
76
+ ? null
77
+ : pageState.pageId;
78
+ if (pageState.type === 'confirm-quit') {
79
+ await navigate(confirmQuitHtml);
80
+ setKeys(confirmQuitKeys);
81
+ }
82
+ else {
83
+ await navigate(getPageHtml(pageId));
84
+ setKeys(getPageKeys(pageId));
85
+ await render();
86
+ }
87
+ }
88
+ // ── handleKey ───────────────────────────────────────────────────────────
89
+ async function handleKey(key) {
90
+ // Ctrl+C always exits immediately
91
+ if (key === CTRL_C) {
92
+ process.exit(0);
93
+ return;
94
+ }
95
+ // ── confirm-quit state ────────────────────────────────────────────────
96
+ if (state.type === 'confirm-quit') {
97
+ const lower = key.toLowerCase();
98
+ if (lower === 'y') {
99
+ process.exit(0);
100
+ return;
101
+ }
102
+ if (lower === 'n' || key === ESC) {
103
+ await goToPage(state.returnTo);
104
+ return;
105
+ }
106
+ // Ignore everything else (including F-keys) on confirm-quit
107
+ return;
108
+ }
109
+ // ── Check for F-key sequences ─────────────────────────────────────────
110
+ const fkey = SEQ_TO_FKEY[key];
111
+ if (fkey) {
112
+ const currentPageId = state.pageId;
113
+ const binding = getPageKeys(currentPageId)[fkey];
114
+ if (binding) {
115
+ try {
116
+ await Promise.resolve(binding.action());
117
+ }
118
+ catch (err) {
119
+ console.error('[tuimon]', err);
120
+ }
121
+ }
122
+ return;
123
+ }
124
+ // ── ESC ───────────────────────────────────────────────────────────────
125
+ if (key === ESC) {
126
+ if (state.type === 'detail') {
127
+ // Back to overview
128
+ await goToPage({ type: 'overview', pageId: defaultPageId });
129
+ }
130
+ else if (state.type === 'overview') {
131
+ // Show confirm-quit
132
+ const returnTo = { ...state };
133
+ state = { type: 'confirm-quit', returnTo };
134
+ await navigate(confirmQuitHtml);
135
+ setKeys(confirmQuitKeys);
136
+ }
137
+ return;
138
+ }
139
+ // ── Shortcut keys (only from overview) ────────────────────────────────
140
+ if (state.type === 'overview') {
141
+ const targetPageId = shortcutToPageId.get(key);
142
+ if (targetPageId) {
143
+ await goToPage({ type: 'detail', pageId: targetPageId });
144
+ }
145
+ }
146
+ // detail state ignores shortcut keys — no action needed
147
+ }
148
+ // ── Public API ──────────────────────────────────────────────────────────
149
+ return {
150
+ handleKey,
151
+ getState: () => state,
152
+ };
153
+ }
154
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAUA,gFAAgF;AAEhF,MAAM,WAAW,GAAyB;IACxC,QAAQ,EAAI,IAAI,EAAG,UAAU,EAAE,IAAI;IACnC,QAAQ,EAAI,IAAI,EAAG,UAAU,EAAE,IAAI;IACnC,QAAQ,EAAI,IAAI,EAAG,UAAU,EAAE,IAAI;IACnC,QAAQ,EAAI,IAAI,EAAG,UAAU,EAAE,IAAI;IACnC,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,KAAK;CAClB,CAAA;AAED,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;AAE9D,MAAM,GAAG,GAAG,MAAM,CAAA;AAClB,MAAM,MAAM,GAAG,MAAM,CAAA;AAErB,gFAAgF;AAEhF,MAAM,UAAU,YAAY,CAAC,IAAgB;IAC3C,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,GAAG,IAAI,CAAA;IAElE,2EAA2E;IAE3E,2BAA2B;IAC3B,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAC7E,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CACb,mDAAmD,cAAc,CAAC,MAAM,EAAE,CAC3E,CAAA;IACH,CAAC;IACD,MAAM,CAAC,aAAa,EAAE,iBAAiB,CAAC,GAAG,cAAc,CAAC,CAAC,CAAE,CAAA;IAE7D,yCAAyC;IACzC,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAA;IAC/C,KAAK,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9C,IAAI,GAAG,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;YACzB,IAAI,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACzC,MAAM,IAAI,KAAK,CACb,SAAS,EAAE,6BAA6B,GAAG,CAAC,QAAQ,GAAG,CACxD,CAAA;YACH,CAAC;YACD,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACpC,MAAM,IAAI,KAAK,CACb,uBAAuB,GAAG,CAAC,QAAQ,eAAe,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,CACjG,CAAA;YACH,CAAC;YACD,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;QACrC,CAAC;QAED,6CAA6C;QAC7C,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YACb,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxC,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;oBACxD,OAAO,CAAC,IAAI,CACV,kBAAkB,EAAE,2BAA2B,GAAG,uCAAuC,CAC1F,CAAA;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,2EAA2E;IAE3E,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAkB,CAAA;IAClD,KAAK,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9C,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;YACjB,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;QACxC,CAAC;IACH,CAAC;IAED,2EAA2E;IAE3E,IAAI,KAAK,GAAc,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,CAAA;IAElE,mBAAmB;IACnB,OAAO,CAAC,iBAAiB,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;IAErC,2EAA2E;IAE3E,MAAM,eAAe,GAAY,EAAE,CAAA;IAEnC,2EAA2E;IAE3E,SAAS,WAAW,CAAC,MAAc;QACjC,OAAO,KAAK,CAAC,MAAM,CAAC,EAAE,IAAI,IAAI,EAAE,CAAA;IAClC,CAAC;IAED,SAAS,WAAW,CAAC,MAAc;QACjC,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAA;QAC1B,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,MAAM,GAAG,CAAC,CAAA;QAChE,OAAO,IAAI,CAAC,IAAI,CAAA;IAClB,CAAC;IAED,KAAK,UAAU,QAAQ,CAAC,SAAoB;QAC1C,KAAK,GAAG,SAAS,CAAA;QACjB,MAAM,MAAM,GACV,SAAS,CAAC,IAAI,KAAK,cAAc;YAC/B,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,SAAS,CAAC,MAAM,CAAA;QAEtB,IAAI,SAAS,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YACtC,MAAM,QAAQ,CAAC,eAAe,CAAC,CAAA;YAC/B,OAAO,CAAC,eAAe,CAAC,CAAA;QAC1B,CAAC;aAAM,CAAC;YACN,MAAM,QAAQ,CAAC,WAAW,CAAC,MAAO,CAAC,CAAC,CAAA;YACpC,OAAO,CAAC,WAAW,CAAC,MAAO,CAAC,CAAC,CAAA;YAC7B,MAAM,MAAM,EAAE,CAAA;QAChB,CAAC;IACH,CAAC;IAED,2EAA2E;IAE3E,KAAK,UAAU,SAAS,CAAC,GAAW;QAClC,kCAAkC;QAClC,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACf,OAAM;QACR,CAAC;QAED,yEAAyE;QACzE,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAA;YAE/B,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;gBAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;gBACf,OAAM;YACR,CAAC;YAED,IAAI,KAAK,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;gBACjC,MAAM,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;gBAC9B,OAAM;YACR,CAAC;YAED,4DAA4D;YAC5D,OAAM;QACR,CAAC;QAED,yEAAyE;QACzE,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAA;QAC7B,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAA;YAClC,MAAM,OAAO,GAAG,WAAW,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAA;YAChD,IAAI,OAAO,EAAE,CAAC;gBACZ,IAAI,CAAC;oBACH,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;gBACzC,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,GAAG,CAAC,CAAA;gBAChC,CAAC;YACH,CAAC;YACD,OAAM;QACR,CAAC;QAED,yEAAyE;QACzE,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;YAChB,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC5B,mBAAmB;gBACnB,MAAM,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAA;YAC7D,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBACrC,oBAAoB;gBACpB,MAAM,QAAQ,GAAG,EAAE,GAAG,KAAK,EAAE,CAAA;gBAC7B,KAAK,GAAG,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAA;gBAC1C,MAAM,QAAQ,CAAC,eAAe,CAAC,CAAA;gBAC/B,OAAO,CAAC,eAAe,CAAC,CAAA;YAC1B,CAAC;YACD,OAAM;QACR,CAAC;QAED,yEAAyE;QACzE,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC9B,MAAM,YAAY,GAAG,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YAC9C,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAA;YAC1D,CAAC;QACH,CAAC;QAED,wDAAwD;IAC1D,CAAC;IAED,2EAA2E;IAE3E,OAAO;QACL,SAAS;QACT,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK;KACtB,CAAA;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { ServerHandle } from './types.js';
2
+ export declare function startServer({ rootDir }: {
3
+ rootDir: string;
4
+ }): Promise<ServerHandle>;
5
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAqI9C,wBAAsB,WAAW,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAgCzF"}