@singhak/nodeui-core 0.1.0 → 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.
package/README.md CHANGED
@@ -1,82 +1,111 @@
1
- # @singhak/nodeui-core
2
-
3
- Framework-neutral engine for the NodeUI developer console: observability
4
- providers, the REST contract, the safety gate, and the static console server.
5
- The Express and NestJS adapters build on this package; you normally consume
6
- those instead of using `@singhak/nodeui-core` directly.
7
-
8
- ## Providers
9
-
10
- Each provider exposes one panel through `GET {path}/api/{id}`:
11
-
12
- | id | Panel | Notes |
13
- | --------------- | -------------- | ------------------------------------------------ |
14
- | `health` | Health | Derives status from event-loop + memory samples. |
15
- | `memory` | Memory | Samples process + OS memory on start. |
16
- | `cpu` | CPU | Process CPU percent from `/proc`-style clocks. |
17
- | `event-loop` | Event-loop lag | Drift vs. a 1ms `setInterval`, last 600 samples. |
18
- | `heap-snapshot` | Heap snapshot | Writes `nodeui-heap-<pid>-<ts>.heapsnapshot`. |
19
- | `startup` | Startup | Timing marks recorded via `server.mark(name)`. |
20
- | `requests` | Requests | Ring buffer of app HTTP requests (default 500). |
21
-
22
- ## API
23
-
24
- All endpoints live under `{path}/api` and return
25
- `{ ok: true, data } | { ok: false, error: { code, message } }`:
26
-
27
- - `GET /config` — effective configuration.
28
- - `GET /{provider-id}` — panel data for the seven ids above.
29
- - `POST /confirmations` — issue a single-use nonce.
30
- - `POST /heap-snapshot` — capture a snapshot; must send
31
- `x-nodeui-confirm: <nonce>` from a fresh confirmation. A missing, expired, or
32
- replayed nonce returns `409` with error code `confirmation-required`.
33
-
34
- `GET /` serves the bundled React console with an SPA fallback to `index.html`.
35
-
36
- ## Safety
37
-
38
- - **Activation:** active when `NODE_ENV` is non-production, or when
39
- `NODEUI_ENABLED=true` forces it; fail-closed in production.
40
- - **Loopback-only:** remote hosts are rejected with `403`.
41
- - **Secret masking:** keys matching `TOKEN|KEY|SECRET|PASSWORD` have their
42
- values replaced with `[REDACTED]` in every API payload.
43
- - **Read-only default:** the heap snapshot is the only mutating action and is
44
- gated behind a fresh nonce.
45
- - **Zero-cost when disabled:** the middleware is a pass-through; no timers or
46
- hooks are created.
47
-
48
- ## Configuration
49
-
50
- Environment variables are read at `createNodeUI()` time (overridable via the
51
- `options.env` map for tests):
52
-
53
- | Variable | Default | Description |
54
- | ------------------------------ | ----------- | --------------------------------- |
55
- | `NODEUI_ENABLED` | unset | Force activation (`true`). |
56
- | `NODEUI_HOST` | `127.0.0.1` | Loopback host the console trusts. |
57
- | `NODEUI_PATH` | `/nodeui` | URL prefix for console + API. |
58
- | `NODEUI_REQUEST_LOG_SIZE` | `500` | Request ring-buffer capacity. |
59
- | `NODEUI_POLL_INTERVAL_MS` | `2000` | Sampling interval. |
60
- | `NODEUI_INACTIVITY_TIMEOUT_MS` | `60000` | Provider idle timeout. |
61
- | `NODEUI_CONFIRM_TTL_MS` | `60000` | Nonce lifetime. |
62
- | `NODEUI_HEAP_SNAPSHOT_DIR` | OS tmpdir | Snapshot output directory. |
63
-
64
- ## Usage
65
-
66
- ```ts
67
- import { createNodeUI, type NodeUIServer } from '@singhak/nodeui-core';
68
-
69
- const server: NodeUIServer = createNodeUI();
70
- const middleware = server.middleware();
71
- // middleware is (req, res, next) => void; mount it before your routes.
72
- server.mark('listening');
73
- server.shutdown();
74
- ```
75
-
76
- ## Development
77
-
78
- ```bash
79
- npm run typecheck # tsc --noEmit
80
- npm test # vitest run (unit + e2e)
81
- npm run build # emit dist/
82
- ```
1
+ # @singhak/nodeui-core
2
+
3
+ Framework-neutral engine for the NodeUI developer console: observability
4
+ providers, the REST contract, the safety gate, and the static console server.
5
+ The Express, Fastify and NestJS adapters build on this package; you normally
6
+ consume those instead of using `@singhak/nodeui-core` directly. Use core
7
+ directly to integrate a framework without an adapter (Koa, Hono, plain `http`).
8
+
9
+ ## Providers
10
+
11
+ Each provider exposes one panel through `GET {path}/api/{id}`:
12
+
13
+ | id | Panel | Notes |
14
+ | --------------- | -------------- | ---------------------------------------------------------- |
15
+ | `health` | Health | Event-loop + memory status, plus your `healthChecks`. |
16
+ | `memory` | Memory | Samples process + OS memory on start. |
17
+ | `cpu` | CPU | Process CPU percent from `process.cpuUsage()`. |
18
+ | `event-loop` | Event-loop lag | Drift vs. a 1ms `setInterval`, last 600 samples. |
19
+ | `heap-snapshot` | Heap snapshot | Writes `nodeui-heap-<pid>-<ts>.heapsnapshot` (owner-only). |
20
+ | `startup` | Startup | Timing marks recorded via `server.mark(name)`. |
21
+ | `requests` | Requests | Ring buffer of app HTTP requests (default 500). |
22
+ | `metrics` | Metrics | Requests/errors per second for the last minute. |
23
+ | `env` | Environment | `process.env` + your `config`, masked. |
24
+ | `routes` | Routes | Express router introspection, or `server.setRoutes()`. |
25
+ | `logs` | Logs | `console.*` capture plus `server.addLogSource()`. |
26
+ | `outgoing` | Outgoing HTTP | `http`/`https`/`fetch` calls made by the app. |
27
+ | _your id_ | _your title_ | Custom panels via the `plugins` option (see below). |
28
+
29
+ ## API
30
+
31
+ All endpoints live under `{path}/api` and return
32
+ `{ ok: true, data } | { ok: false, error: { code, message } }`:
33
+
34
+ - `GET /config` — effective configuration, panel list and plugin titles.
35
+ - `GET /{panel-id}` — panel data for every id above.
36
+ - `GET /live?panels=a,b` — Server-Sent Events stream (capped by `maxSseClients`).
37
+ - `POST /confirmations` — issue a single-use nonce.
38
+ - `POST /heap-snapshot` — capture a snapshot; must send
39
+ `x-nodeui-confirm: <nonce>` from a fresh confirmation. A missing, expired, or
40
+ replayed nonce returns `409` with error code `confirmation-required`.
41
+
42
+ `GET /` serves the bundled React console with an SPA fallback to `index.html`.
43
+
44
+ ## Safety
45
+
46
+ - **Activation:** active when `NODE_ENV` is non-production, or when
47
+ `NODEUI_ENABLED=true` forces it; fail-closed in production (a warning is logged if forced on).
48
+ - **Loopback-only:** remote hosts are rejected with `403`. Extra clients can be allow-listed
49
+ (`allowedRemoteAddresses`, exact IPs or IPv4 CIDRs, e.g. the Docker bridge).
50
+ - **Host / Origin validation:** blocks DNS-rebinding and cross-site requests. Extra names via
51
+ `allowedHosts` / `allowedOrigins`. `X-Forwarded-*` requests are rejected unless `trustProxy`.
52
+ - **Access token (optional):** `authToken` / `NODEUI_TOKEN`; send `Authorization: Bearer <token>`,
53
+ or open `{path}/?token=<token>` once to get an HttpOnly cookie.
54
+ - **Secret masking:** values under keys such as `token`, `key`, `secret`, `password`, `auth`,
55
+ `cookie`, `dsn`, `database_url` are replaced with `[REDACTED]`; credentials inside text
56
+ (URLs, bearer tokens, JWTs, `password=...`) are scrubbed too, in REST and SSE. Disable with
57
+ `maskSecrets: false`.
58
+ - **Headers:** CSP, `X-Content-Type-Options`, `X-Frame-Options`, `Referrer-Policy` on every response.
59
+ - **Read-only default:** the heap snapshot is the only mutating action and is
60
+ gated behind a fresh nonce.
61
+ - **Zero-cost when disabled:** the middleware is a pass-through; no timers or
62
+ hooks are created.
63
+
64
+ ## Configuration
65
+
66
+ Environment variables are read at `createNodeUI()` time (overridable via the
67
+ `options.env` map for tests); each also has a typed option of the same meaning.
68
+
69
+ | Variable | Default | Description |
70
+ | ------------------------------ | ------------------- | ---------------------------------------- |
71
+ | `NODEUI_ENABLED` | unset | Force activation (`true`) / disable. |
72
+ | `NODEUI_HOST` | `127.0.0.1` | Loopback host the console trusts. |
73
+ | `NODEUI_PATH` | `/nodeui` | URL prefix for console + API. |
74
+ | `NODEUI_REQUEST_LOG_SIZE` | `500` | Request ring-buffer capacity. |
75
+ | `NODEUI_LOG_SIZE` | `500` | Log ring-buffer capacity. |
76
+ | `NODEUI_POLL_INTERVAL_MS` | `2000` | Sampling interval. |
77
+ | `NODEUI_INACTIVITY_TIMEOUT_MS` | `60000` | Provider idle timeout. |
78
+ | `NODEUI_CONFIRM_TTL_MS` | `60000` | Nonce lifetime. |
79
+ | `NODEUI_HEAP_SNAPSHOT_DIR` | `<tmp>/nodeui-heap` | Snapshot output directory. |
80
+ | `NODEUI_TOKEN` | unset | Require an access token. |
81
+ | `NODEUI_ALLOWED_HOSTS` | unset | Comma-separated extra `Host` names. |
82
+ | `NODEUI_ALLOWED_ORIGINS` | unset | Comma-separated extra `Origin` values. |
83
+ | `NODEUI_ALLOWED_REMOTE` | unset | Comma-separated client IPs / IPv4 CIDRs. |
84
+ | `NODEUI_TRUST_PROXY` | `false` | Accept `X-Forwarded-*` requests. |
85
+ | `NODEUI_MAX_SSE_CLIENTS` | `10` | Concurrent live streams. |
86
+
87
+ ## Usage
88
+
89
+ ```ts
90
+ import { createNodeUI, type NodeUIServer } from '@singhak/nodeui-core';
91
+
92
+ const server: NodeUIServer = createNodeUI({
93
+ plugins: [{ id: 'queues', title: 'Queues', get: async () => ({ ok: true, data: await jobs() }) }],
94
+ healthChecks: { db: () => pool.query('select 1') },
95
+ });
96
+ const middleware = server.middleware();
97
+ // middleware is (req, res, next) => void; mount it before your routes.
98
+ server.mark('listening');
99
+ server.shutdown();
100
+ ```
101
+
102
+ Plugin ids are lowercase letters, digits and `-`, and must not collide with a built-in panel.
103
+ Without an Express router, feed the routes panel with `server.setRoutes([...])`.
104
+
105
+ ## Development
106
+
107
+ ```bash
108
+ npm run typecheck # tsc --noEmit
109
+ npm test # vitest run (unit + e2e)
110
+ npm run build # emit dist/
111
+ ```