@aaronbassett/midnight-local-devnet 0.2.1 → 0.3.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 (88) hide show
  1. package/README.md +16 -26
  2. package/dist/cli/commands/dashboard.js +53 -14
  3. package/dist/cli/commands/dashboard.js.map +1 -1
  4. package/dist/cli/dashboard/html.d.ts +3 -0
  5. package/dist/cli/dashboard/html.js +1095 -0
  6. package/dist/cli/dashboard/html.js.map +1 -0
  7. package/dist/cli/dashboard/server.d.ts +17 -0
  8. package/dist/cli/dashboard/server.js +133 -0
  9. package/dist/cli/dashboard/server.js.map +1 -0
  10. package/dist/cli/dashboard/state-collector.d.ts +67 -0
  11. package/dist/cli/dashboard/state-collector.js +121 -0
  12. package/dist/cli/dashboard/state-collector.js.map +1 -0
  13. package/package.json +4 -5
  14. package/dist/cli/dashboard/app.d.ts +0 -9
  15. package/dist/cli/dashboard/app.js +0 -106
  16. package/dist/cli/dashboard/app.js.map +0 -1
  17. package/dist/cli/dashboard/components/gauge.d.ts +0 -9
  18. package/dist/cli/dashboard/components/gauge.js +0 -10
  19. package/dist/cli/dashboard/components/gauge.js.map +0 -1
  20. package/dist/cli/dashboard/components/panel-box.d.ts +0 -10
  21. package/dist/cli/dashboard/components/panel-box.js +0 -6
  22. package/dist/cli/dashboard/components/panel-box.js.map +0 -1
  23. package/dist/cli/dashboard/components/sparkline.d.ts +0 -9
  24. package/dist/cli/dashboard/components/sparkline.js +0 -25
  25. package/dist/cli/dashboard/components/sparkline.js.map +0 -1
  26. package/dist/cli/dashboard/components/status-badge.d.ts +0 -6
  27. package/dist/cli/dashboard/components/status-badge.js +0 -24
  28. package/dist/cli/dashboard/components/status-badge.js.map +0 -1
  29. package/dist/cli/dashboard/hooks/use-breakpoint.d.ts +0 -7
  30. package/dist/cli/dashboard/hooks/use-breakpoint.js +0 -15
  31. package/dist/cli/dashboard/hooks/use-breakpoint.js.map +0 -1
  32. package/dist/cli/dashboard/hooks/use-health.d.ts +0 -9
  33. package/dist/cli/dashboard/hooks/use-health.js +0 -35
  34. package/dist/cli/dashboard/hooks/use-health.js.map +0 -1
  35. package/dist/cli/dashboard/hooks/use-indexer-info.d.ts +0 -5
  36. package/dist/cli/dashboard/hooks/use-indexer-info.js +0 -19
  37. package/dist/cli/dashboard/hooks/use-indexer-info.js.map +0 -1
  38. package/dist/cli/dashboard/hooks/use-logs.d.ts +0 -19
  39. package/dist/cli/dashboard/hooks/use-logs.js +0 -55
  40. package/dist/cli/dashboard/hooks/use-logs.js.map +0 -1
  41. package/dist/cli/dashboard/hooks/use-node-info.d.ts +0 -21
  42. package/dist/cli/dashboard/hooks/use-node-info.js +0 -49
  43. package/dist/cli/dashboard/hooks/use-node-info.js.map +0 -1
  44. package/dist/cli/dashboard/hooks/use-polling.d.ts +0 -7
  45. package/dist/cli/dashboard/hooks/use-polling.js +0 -35
  46. package/dist/cli/dashboard/hooks/use-polling.js.map +0 -1
  47. package/dist/cli/dashboard/hooks/use-proof-server.d.ts +0 -7
  48. package/dist/cli/dashboard/hooks/use-proof-server.js +0 -14
  49. package/dist/cli/dashboard/hooks/use-proof-server.js.map +0 -1
  50. package/dist/cli/dashboard/hooks/use-services.d.ts +0 -3
  51. package/dist/cli/dashboard/hooks/use-services.js +0 -6
  52. package/dist/cli/dashboard/hooks/use-services.js.map +0 -1
  53. package/dist/cli/dashboard/hooks/use-terminal-size.d.ts +0 -5
  54. package/dist/cli/dashboard/hooks/use-terminal-size.js +0 -22
  55. package/dist/cli/dashboard/hooks/use-terminal-size.js.map +0 -1
  56. package/dist/cli/dashboard/hooks/use-wallet-state.d.ts +0 -10
  57. package/dist/cli/dashboard/hooks/use-wallet-state.js +0 -63
  58. package/dist/cli/dashboard/hooks/use-wallet-state.js.map +0 -1
  59. package/dist/cli/dashboard/layouts/large.d.ts +0 -7
  60. package/dist/cli/dashboard/layouts/large.js +0 -13
  61. package/dist/cli/dashboard/layouts/large.js.map +0 -1
  62. package/dist/cli/dashboard/layouts/medium.d.ts +0 -7
  63. package/dist/cli/dashboard/layouts/medium.js +0 -11
  64. package/dist/cli/dashboard/layouts/medium.js.map +0 -1
  65. package/dist/cli/dashboard/layouts/small.d.ts +0 -7
  66. package/dist/cli/dashboard/layouts/small.js +0 -11
  67. package/dist/cli/dashboard/layouts/small.js.map +0 -1
  68. package/dist/cli/dashboard/panels/indexer-panel.d.ts +0 -11
  69. package/dist/cli/dashboard/panels/indexer-panel.js +0 -17
  70. package/dist/cli/dashboard/panels/indexer-panel.js.map +0 -1
  71. package/dist/cli/dashboard/panels/log-panel.d.ts +0 -13
  72. package/dist/cli/dashboard/panels/log-panel.js +0 -27
  73. package/dist/cli/dashboard/panels/log-panel.js.map +0 -1
  74. package/dist/cli/dashboard/panels/node-panel.d.ts +0 -10
  75. package/dist/cli/dashboard/panels/node-panel.js +0 -17
  76. package/dist/cli/dashboard/panels/node-panel.js.map +0 -1
  77. package/dist/cli/dashboard/panels/proof-panel.d.ts +0 -10
  78. package/dist/cli/dashboard/panels/proof-panel.js +0 -20
  79. package/dist/cli/dashboard/panels/proof-panel.js.map +0 -1
  80. package/dist/cli/dashboard/panels/response-graph.d.ts +0 -10
  81. package/dist/cli/dashboard/panels/response-graph.js +0 -12
  82. package/dist/cli/dashboard/panels/response-graph.js.map +0 -1
  83. package/dist/cli/dashboard/panels/wallet-panel.d.ts +0 -9
  84. package/dist/cli/dashboard/panels/wallet-panel.js +0 -24
  85. package/dist/cli/dashboard/panels/wallet-panel.js.map +0 -1
  86. package/dist/cli/dashboard/types.d.ts +0 -39
  87. package/dist/cli/dashboard/types.js +0 -2
  88. package/dist/cli/dashboard/types.js.map +0 -1
package/README.md CHANGED
@@ -19,7 +19,7 @@ Start the network:
19
19
  npx @aaronbassett/midnight-local-devnet start
20
20
  ```
21
21
 
22
- Open the realtime dashboard in a second terminal pane to monitor your devnet:
22
+ Open the dashboard in your browser to monitor your devnet:
23
23
 
24
24
  ```bash
25
25
  npx @aaronbassett/midnight-local-devnet dashboard
@@ -58,48 +58,38 @@ All commands can be run via `npx @aaronbassett/midnight-local-devnet <command>`.
58
58
  | `fund <address>` | Fund a Bech32 address with NIGHT tokens | `--amount <n>` Amount in NIGHT (default: 50,000) |
59
59
  | `fund-file <path>` | Fund all accounts from an accounts.json file | |
60
60
  | `generate-accounts` | Generate random test accounts | `--count <n>`, `--format <mnemonic\|privateKey>`, `--output <path>`, `--fund`, `--register-dust` |
61
- | `dashboard` | Open realtime terminal dashboard | |
61
+ | `dashboard` | Open browser dashboard | `--port <n>` (default: 31780), `--no-open` Suppress auto-open |
62
62
  | `interactive` | Start interactive menu mode | |
63
63
 
64
64
  Running with no arguments displays help.
65
65
 
66
66
  ## Dashboard
67
67
 
68
- The `dashboard` command opens a realtime terminal UI that displays the state of all local devnet services. It's designed to run in a side terminal pane while you develop.
68
+ The `dashboard` command starts a local server and opens a browser-based dashboard that displays the state of all local devnet services in real time.
69
69
 
70
70
  ```bash
71
71
  npx @aaronbassett/midnight-local-devnet dashboard
72
72
  ```
73
73
 
74
+ This starts a server on `http://localhost:31780` and opens your default browser. Press Ctrl+C in the terminal to stop.
75
+
76
+ Options:
77
+
78
+ - `--port <n>` -- Use a specific port (default: 31780, auto-increments if in use)
79
+ - `--no-open` -- Start the server without opening the browser
80
+
74
81
  The dashboard shows:
75
82
 
76
83
  - **Node** -- Block height, average block time, chain, peers, sync status, version
77
- - **Indexer** -- Indexed block height, lag vs node, readiness
78
- - **Proof Server** -- Version, proof versions, job processing/pending/capacity
84
+ - **Indexer** -- Ready status, response time
85
+ - **Proof Server** -- Version, proof versions, job processing/pending/capacity gauge
79
86
  - **Wallet** -- Master wallet NIGHT (unshielded + shielded) and DUST balances
80
- - **Logs** -- Combined color-coded log stream from all services, filterable by service, level, or substring search
81
- - **Response Times** -- Sparkline charts of per-service response times (large terminals only)
87
+ - **Response Times** -- SVG sparkline charts of per-service response times
88
+ - **Logs** -- Combined color-coded log stream from all services, filterable by service, level, or text search
82
89
 
83
- The layout adapts to your terminal width:
90
+ The dashboard connects to the server via WebSocket for live updates. If the connection drops, it auto-reconnects. You can start and stop the network directly from the dashboard using the action buttons.
84
91
 
85
- | Terminal Width | Layout |
86
- |---|---|
87
- | < 40 columns | Single column, compact |
88
- | 40--119 columns | Two-column grid |
89
- | 120+ columns | Three-column with response time graphs |
90
-
91
- Keyboard shortcuts:
92
-
93
- | Key | Action |
94
- |---|---|
95
- | Tab | Cycle focus between panels |
96
- | Up/Down | Scroll logs (when focused) |
97
- | `s` | Cycle log service filter |
98
- | `l` | Cycle log level filter |
99
- | `/` | Enter log search mode |
100
- | `q` | Exit dashboard |
101
-
102
- The dashboard starts regardless of whether the network is running. Panels show "Connecting..." and update live when services come up.
92
+ The layout is responsive and adapts to your browser window width.
103
93
 
104
94
  ## MCP Tool Reference
105
95
 
@@ -1,20 +1,59 @@
1
+ import { createServer } from 'node:net';
2
+ async function findOpenPort(start, maxAttempts = 10) {
3
+ for (let i = 0; i < maxAttempts; i++) {
4
+ const port = start + i;
5
+ const available = await new Promise((resolve) => {
6
+ const server = createServer();
7
+ server.once('error', () => resolve(false));
8
+ server.once('listening', () => {
9
+ server.close(() => resolve(true));
10
+ });
11
+ server.listen(port, '127.0.0.1');
12
+ });
13
+ if (available)
14
+ return port;
15
+ }
16
+ throw new Error(`No open port found in range ${start}-${start + maxAttempts - 1}`);
17
+ }
1
18
  export function registerDashboardCommand(program, manager) {
2
19
  program
3
20
  .command('dashboard')
4
- .description('Open realtime terminal dashboard for the local devnet')
5
- .action(async () => {
6
- if (!process.stdin.isTTY) {
7
- console.error('Error: Dashboard requires an interactive terminal (TTY).');
8
- console.error('Run this command directly in a terminal, not through a pipe or script.');
9
- process.exit(1);
10
- }
11
- // Dynamic import to avoid loading React/ink for non-dashboard commands
12
- const { render } = await import('ink');
13
- const React = await import('react');
14
- const { App } = await import('../dashboard/app.js');
15
- const { waitUntilExit } = render(React.createElement(App, { manager, config: manager.config }));
16
- await waitUntilExit();
17
- await manager.shutdown();
21
+ .description('Open browser dashboard for the local devnet')
22
+ .option('--port <port>', 'Port to serve dashboard on', '31780')
23
+ .option('--no-open', 'Do not auto-open the browser')
24
+ .action(async (opts) => {
25
+ const { createDashboardApp } = await import('../dashboard/server.js');
26
+ const { serve } = await import('@hono/node-server');
27
+ const open = (await import('open')).default;
28
+ const preferredPort = parseInt(opts.port, 10);
29
+ const port = await findOpenPort(preferredPort);
30
+ const { app, setupWebSocket, startPolling, shutdown } = createDashboardApp({
31
+ config: manager.config,
32
+ manager,
33
+ port,
34
+ });
35
+ const server = serve({ fetch: app.fetch, port, hostname: '127.0.0.1' }, (info) => {
36
+ const url = `http://localhost:${info.port}`;
37
+ console.log(`Dashboard running at ${url}`);
38
+ console.log('Press Ctrl+C to stop\n');
39
+ if (opts.open !== false) {
40
+ open(url).catch(() => {
41
+ // Ignore browser open errors
42
+ });
43
+ }
44
+ });
45
+ const wss = setupWebSocket(server);
46
+ startPolling();
47
+ const gracefulShutdown = async () => {
48
+ console.log('\nShutting down dashboard...');
49
+ shutdown();
50
+ wss.close();
51
+ await new Promise((resolve) => server.close(() => resolve()));
52
+ await manager.shutdown();
53
+ process.exit(0);
54
+ };
55
+ process.on('SIGINT', gracefulShutdown);
56
+ process.on('SIGTERM', gracefulShutdown);
18
57
  });
19
58
  }
20
59
  //# sourceMappingURL=dashboard.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../../src/cli/commands/dashboard.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,wBAAwB,CAAC,OAAgB,EAAE,OAAuB;IAChF,OAAO;SACJ,OAAO,CAAC,WAAW,CAAC;SACpB,WAAW,CAAC,uDAAuD,CAAC;SACpE,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;YAC1E,OAAO,CAAC,KAAK,CAAC,wEAAwE,CAAC,CAAC;YACxF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,uEAAuE;QACvE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;QACpC,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;QAEpD,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,CAC9B,KAAK,CAAC,aAAa,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAC9D,CAAC;QAEF,MAAM,aAAa,EAAE,CAAC;QACtB,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC;IAC3B,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../../src/cli/commands/dashboard.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,KAAK,UAAU,YAAY,CAAC,KAAa,EAAE,WAAW,GAAG,EAAE;IACzD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC,CAAC;QACvB,MAAM,SAAS,GAAG,MAAM,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;YACvD,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;YAC3C,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;gBAC5B,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YACpC,CAAC,CAAC,CAAC;YACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QACH,IAAI,SAAS;YAAE,OAAO,IAAI,CAAC;IAC7B,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,+BAA+B,KAAK,IAAI,KAAK,GAAG,WAAW,GAAG,CAAC,EAAE,CAAC,CAAC;AACrF,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,OAAgB,EAAE,OAAuB;IAChF,OAAO;SACJ,OAAO,CAAC,WAAW,CAAC;SACpB,WAAW,CAAC,6CAA6C,CAAC;SAC1D,MAAM,CAAC,eAAe,EAAE,4BAA4B,EAAE,OAAO,CAAC;SAC9D,MAAM,CAAC,WAAW,EAAE,8BAA8B,CAAC;SACnD,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;QACtE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;QAE5C,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,aAAa,CAAC,CAAC;QAE/C,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,kBAAkB,CAAC;YACzE,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO;YACP,IAAI;SACL,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE;YAC/E,MAAM,GAAG,GAAG,oBAAoB,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,wBAAwB,GAAG,EAAE,CAAC,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;YAEtC,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBACxB,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;oBACnB,6BAA6B;gBAC/B,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,cAAc,CAAC,MAAa,CAAC,CAAC;QAC1C,YAAY,EAAE,CAAC;QAEf,MAAM,gBAAgB,GAAG,KAAK,IAAI,EAAE;YAClC,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;YAC5C,QAAQ,EAAE,CAAC;YACX,GAAG,CAAC,KAAK,EAAE,CAAC;YACZ,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAE,MAAc,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAC7E,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC;QAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;QACvC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function generateDashboardHtml({ wsUrl }: {
2
+ wsUrl: string;
3
+ }): string;