@dpkrn/nodetunnel 1.0.10 → 1.1.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,63 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ Nothing unreleased yet.
10
+
11
+ ## [1.0.10] - 2026-04-12
12
+
13
+ ### Changed
14
+
15
+ - Expanded README with clearer coverage of what nodetunnel does and how to use it.
16
+
17
+ ## [1.0.9] - 2026-04-12
18
+
19
+ ### Added
20
+
21
+ - Makefile with `pkg` (publish) and `test` targets for maintainers.
22
+ - Contributor Covenant Code of Conduct.
23
+ - Local traffic inspector: HTTP UI plus WebSocket streaming of request/response logs (via `ws`).
24
+ - Structured logging store for tunneled HTTP exchanges.
25
+
26
+ ### Changed
27
+
28
+ - Refactor of the published tunnel package layout and dependencies.
29
+ - Clearer logging during tunnel setup and while forwarding requests.
30
+
31
+ ## [1.0.8] - 2026-04-12
32
+
33
+ ### Changed
34
+
35
+ - Maintenance release (version alignment).
36
+
37
+ ## [1.0.7] - 2026-04-12
38
+
39
+ ### Changed
40
+
41
+ - Default tunnel server host set to `clickly.cv`.
42
+ - Public URL string returned by the tunnel client updated for consistency with the server.
43
+ - Tunnel handshake and messaging updated (connection UUID and success-line formatting for the assigned URL).
44
+
45
+ ## [1.0.4] - 2026-04-03
46
+
47
+ ### Added
48
+
49
+ - Node.js tunnel library: expose a local HTTP server through a gotunnel/yamux-compatible remote (`startTunnel` and related APIs).
50
+
51
+ ## [1.0.2] - 2026-04-03
52
+
53
+ ### Added
54
+
55
+ - Initial `@dpkrn/nodetunnel` package scaffold.
56
+
57
+ [Unreleased]: https://github.com/DpkRn/nodetunnel/compare/v1.0.10...HEAD
58
+ [1.0.10]: https://github.com/DpkRn/nodetunnel/compare/v1.0.9...v1.0.10
59
+ [1.0.9]: https://github.com/DpkRn/nodetunnel/compare/v1.0.8...v1.0.9
60
+ [1.0.8]: https://github.com/DpkRn/nodetunnel/compare/v1.0.7...v1.0.8
61
+ [1.0.7]: https://github.com/DpkRn/nodetunnel/compare/v1.0.4...v1.0.7
62
+ [1.0.4]: https://github.com/DpkRn/nodetunnel/compare/v1.0.2...v1.0.4
63
+ [1.0.2]: https://github.com/DpkRn/nodetunnel/releases/tag/v1.0.2
package/README.md CHANGED
@@ -16,7 +16,7 @@ From **Node.js**, you get a **public URL** for webhooks, demos, sharing a dev se
16
16
  - No port forwarding or firewall configuration needed
17
17
  - Works behind NAT or private networks
18
18
  - Simple integration with existing Node.js HTTP servers (Express, Fastify, plain `http`, etc.)
19
- - Traffic inspector: capture traffic, replay, and modify requests as many times as you need
19
+ - Optional **traffic inspector**: local dashboard to capture tunneled requests, inspect them, and replay against your app
20
20
 
21
21
  Incoming traffic reaches the public URL, is forwarded through the tunnel, and is proxied to your local HTTP server (e.g., `localhost:8080`).
22
22
 
@@ -40,7 +40,7 @@ This enables exposing local development servers without port forwarding, firewal
40
40
  - **No separate tunnel process** — call one function from your app.
41
41
  - **Works with your existing server** — Express, Fastify, or plain `http`.
42
42
  - **Simple API** — you get a public `url` and a `stop()` when you are done.
43
- - **Optional traffic inspector** — local dashboard on loopback to browse captures, replay requests, modify and pick a theme (see below).
43
+ - **Optional traffic inspector** — pass `inspector: true` to start a local HTTP UI on loopback (captures, replay, headers/bodies). By default the inspector is **off**. Themes are chosen **inside the inspector UI** (not via `startTunnel` options).
44
44
 
45
45
  ---
46
46
 
@@ -54,8 +54,6 @@ This package is **ESM** (`import` / `export`).
54
54
 
55
55
  ---
56
56
 
57
-
58
-
59
57
  ## Quick Example
60
58
 
61
59
  ```js
@@ -69,8 +67,8 @@ app.get("/", (req, res) => res.send("OK"));
69
67
 
70
68
  app.listen(PORT, async () => {
71
69
  const { url, stop } = await startTunnel(String(PORT));
72
- //url is your public url using you can access publicly your server
73
- //stop() is method that will close your connection on error
70
+ // `url` public URL for your server
71
+ // `stop()` closes the tunnel connection
74
72
  });
75
73
  ```
76
74
 
@@ -107,29 +105,33 @@ Run with `node app.js`. Open the printed URL in a browser or share it for webhoo
107
105
 
108
106
  ---
109
107
 
110
- ## Traffic inspector (local dashboard)
108
+ ## Traffic inspector (optional local dashboard)
109
+
110
+ **Default:** `inspector` is **`false`** if you omit options or do not set `inspector`. No inspector server, no capture buffer, no extra listen port.
111
111
 
112
- When enabled (default), nodetunnel starts a small **HTTP server on your machine** (default `http://localhost:4040`) with:
112
+ When **`inspector: true`**:
113
113
 
114
- - **Live traffic** requests proxied through the tunnel appear in the UI (WebSocket updates).
115
- - **History** recent captures kept in memory (configurable count); reload the page to fetch `/logs`.
116
- - **Inspect** — request/response headers and bodies for each capture.
117
- - **Modify** — modify request header/path and can replay.
118
- - **Replay** — send a capture again to your local app, or edit method/path/headers/body and replay (aligned with the **gotunnel** inspector behavior).
114
+ 1. Starts a small **HTTP server on your machine** (default listen **`http://127.0.0.1:4040`**) that serves the inspector UI (override with `inspectorAddr`).
115
+ 2. **Captures** each tunneled request/response in memory (up to **`logs`** entries) so the UI can list them and push updates over WebSocket.
119
116
 
120
- The startup banner prints **Inspector →** with that URL. Set `inspector: false` if you do not want the UI or an extra listen port.
117
+ When **`inspector` stays false** (the default):
121
118
 
122
- ### Themes
119
+ - No inspector process runs — nothing listens on the inspector port.
120
+ - No traffic is stored for inspection (`logs` and `inspectorAddr` are ignored).
121
+ - The startup banner omits the **Inspector →** line.
123
122
 
124
- The UI supports three built-in palettes via `themes` in `startTunnel` options:
123
+ ### What you get with the inspector enabled
125
124
 
126
- | Value | Appearance |
127
- |--------|----------------|
128
- | **`"dark"`** (default) | Dark panels, blue accents — similar to GitHub-dark style. |
129
- | **`"terminal"`** | Green-on-black “CRT” / terminal aesthetic, monospace UI font. |
130
- | **`"light"`** | Light gray/white background, high-contrast text for bright environments. |
125
+ - **Live traffic** tunneled requests appear in the UI (WebSocket updates).
126
+ - **History** — recent captures in memory (size limited by `logs`).
127
+ - **Inspect** request/response headers and bodies (when captured).
128
+ - **Replay** send a capture again to your local app, or edit method/path/headers/body and replay.
131
129
 
132
- ### Example: themes and inspector options
130
+ ### Themes (inspector UI only)
131
+
132
+ Postman-style and Terminal-style palettes are available from the **Theme** dropdown in the inspector page; the choice is stored in the browser (localStorage). You do **not** configure themes on `startTunnel`.
133
+
134
+ ### Example: inspector enabled with custom port and log limit
133
135
 
134
136
  ```js
135
137
  import http from "node:http";
@@ -144,16 +146,11 @@ const server = http.createServer((req, res) => {
144
146
 
145
147
  server.listen(PORT, async () => {
146
148
  const { url, stop } = await startTunnel(String(PORT), {
147
- // Inspector (defaults: enabled, :4040, dark theme, 100 logs)
148
149
  inspector: true,
149
150
  inspectorAddr: ":4040",
150
- themes: "terminal", // try: "dark" | "terminal" | "light"
151
151
  logs: 100,
152
152
  });
153
153
 
154
- // console.log("Public:", url);
155
- // Open the Inspector URL from stderr in a browser (e.g. http://localhost:4040)
156
-
157
154
  process.once("SIGINT", () => {
158
155
  stop();
159
156
  server.close(() => process.exit(0));
@@ -161,14 +158,14 @@ server.listen(PORT, async () => {
161
158
  });
162
159
  ```
163
160
 
164
- ### Example: tunnel only (no inspector)
161
+ Open the **Inspector →** URL printed on startup (e.g. `http://127.0.0.1:4040`).
165
162
 
166
- ```js
167
- import { startTunnel } from "@dpkrn/nodetunnel";
163
+ ### Example: tunnel only (default — same as omitting options)
168
164
 
169
- const { url, stop } = await startTunnel("8080", {
170
- inspector: false,
171
- });
165
+ `startTunnel(port)` / `startTunnel(port, {})` already keeps the inspector off. You only need `inspector: false` if you merge options from elsewhere and want to force it off:
166
+
167
+ ```js
168
+ const { url, stop } = await startTunnel("8080"); // no inspector
172
169
  ```
173
170
 
174
171
  ---
@@ -207,27 +204,26 @@ app.listen(PORT, async () => {
207
204
  | Argument | Description |
208
205
  |----------|-------------|
209
206
  | `port` | String, e.g. `"8080"` — must match the port your HTTP server uses. |
210
- | `options` | Optional. Object — see **Options** below (tunnel server address, inspector, themes, etc.). |
207
+ | `options` | Optional. See **Options** below. |
211
208
 
212
209
  **Returns:** `{ url, stop }`
213
210
 
214
211
  | Field | Description |
215
212
  |-------|-------------|
216
213
  | `url` | Public URL people can hit. |
217
- | `stop` | Call to tear down the tunnel. |
214
+ | `stop` | Call to tear down the tunnel (and the inspector, if it was started). |
218
215
 
219
216
  Errors **reject** the promise — use `try/catch`.
220
217
 
221
218
  ### Options (`startTunnel` second argument)
222
219
 
223
- | Field | Type | Default | Description |
224
- |-------|------|---------|-------------|
225
- | `host` | `string` | `'clickly.cv'` | Hostname of the tunnel **control** server. |
226
- | `serverPort` | `number` | `9000` | TCP port of the tunnel server. |
227
- | `inspector` | `boolean` | `true` | If `true`, start the local traffic inspector UI (see [Traffic inspector](#traffic-inspector-local-dashboard)). If `false`, no extra HTTP server and no Inspector line in the banner. |
228
- | `themes` | `string` | `'dark'` | Inspector palette: `'dark'`, `'terminal'`, or `'light'`. |
229
- | `logs` | `number` | `100` | Maximum number of request/response captures kept in memory for the inspector. |
230
- | `inspectorAddr` | `string` | `':4040'` | Listen address for the inspector (e.g. `':4040'`, `'localhost:9090'`). Display URL follows the same rules as the public banner. |
220
+ | Field | Type | Default | Applies when |
221
+ |-------|------|---------|----------------|
222
+ | `host` | `string` | `'clickly.cv'` | Always tunnel control server hostname. |
223
+ | `serverPort` | `number` | `9000` | Always — TCP port of the tunnel server. |
224
+ | `inspector` | `boolean` | `false` | Always if `false` (default), no inspector UI, no capture store, and inspector-only options below are ignored. Set `true` to enable the local inspector. |
225
+ | `logs` | `number` | `100` | **`inspector: true` only** max request/response captures kept in memory. |
226
+ | `inspectorAddr` | `string` | `':4040'` | **`inspector: true` only** listen address for the inspector (e.g. `':4040'`, `'localhost:9090'`). |
231
227
 
232
228
  ---
233
229
 
@@ -4,6 +4,7 @@ import { startTunnel } from "../../pkg/tunnel/tunnel.js";
4
4
 
5
5
  const app = express();
6
6
  app.set("etag", false);
7
+ app.use(express.json());
7
8
  const PORT = process.env.PORT || 8080;
8
9
  /** Random id per process — if this doesn’t match your terminal on each restart, another process is bound to the port. */
9
10
  const INSTANCE = Math.random().toString(36).slice(2, 10);
@@ -26,10 +27,28 @@ app.get("/", async (req, res) => {
26
27
  res.send("Backend is running");
27
28
  });
28
29
 
30
+ /**
31
+ * POST echo: path params (`:category`, `:itemId`), query string, and JSON body.
32
+ * Example: POST /test/widgets/42?verbose=1&tag=a with body `{"name":"x"}`
33
+ */
34
+ app.post("/test/:category/:itemId", (req, res) => {
35
+ console.log("server received request");
36
+ console.log("req.body",req.body);
37
+ res.status(200).json({
38
+ pathParams: req.params,
39
+ query: req.query,
40
+ body: req.body,
41
+ });
42
+ });
43
+
29
44
  app.listen(PORT, async () => {
30
45
  console.log(`listening on http://localhost:${PORT}`);
31
46
  try {
32
- const { url, stop } = await startTunnel(String(PORT));
47
+ const { url, stop } = await startTunnel(String(PORT),{
48
+ inspector: true,
49
+ inspectorAddr: ':5040',
50
+ logs: 100,
51
+ });
33
52
  process.once("SIGINT", () => {
34
53
  stop();
35
54
  process.exit(0);