mekong-cli 1.1.0 → 1.2.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,8 +1,10 @@
1
1
  # mekong-cli
2
2
 
3
- Run your dev server and a [Mekong](https://mekongtunnel.dev) tunnel together in a single command — no separate terminal needed.
3
+ > Expose your Node.js dev server to the internet in one command.
4
+ > Works with Next.js, Vite, Nuxt, Angular, Astro, Svelte, Express, and more.
4
5
 
5
- Think of it as the glue between `next dev` / `vite` / `nuxt dev` and `mekong <port>`.
6
+ [![npm version](https://img.shields.io/npm/v/mekong-cli)](https://www.npmjs.com/package/mekong-cli)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
8
 
7
9
  ---
8
10
 
@@ -12,7 +14,7 @@ Think of it as the glue between `next dev` / `vite` / `nuxt dev` and `mekong <po
12
14
  npm install -g mekong-cli
13
15
  ```
14
16
 
15
- Or use it without installing:
17
+ Or use without installing:
16
18
 
17
19
  ```bash
18
20
  npx mekong-cli 3000
@@ -23,90 +25,133 @@ npx mekong-cli 3000
23
25
  ## Requirements
24
26
 
25
27
  - **Node.js 14+**
26
- - **mekong binary** installed separately (see below)
28
+ - **mekong binary** install separately (see below)
27
29
 
28
- ---
30
+ ### Install the mekong binary
29
31
 
30
- ## Install the mekong binary
32
+ ```bash
33
+ # macOS / Linux (auto-detect arch)
34
+ curl -fsSL https://github.com/MuyleangIng/MekongTunnel/releases/latest/download/mekong-$(uname -s | tr A-Z a-z)-$(uname -m) \
35
+ -o ~/.local/bin/mekong && chmod +x ~/.local/bin/mekong
31
36
 
32
- Download from the [GitHub releases page](https://github.com/MuyleangIng/MekongTunnel/releases/tag/v1.4.9).
37
+ # macOS Intel
38
+ curl -fsSL https://github.com/MuyleangIng/MekongTunnel/releases/latest/download/mekong-darwin-amd64 \
39
+ -o /usr/local/bin/mekong && chmod +x /usr/local/bin/mekong
33
40
 
34
- **Linux / macOS (amd64) — quick one-liner:**
41
+ # macOS Apple Silicon
42
+ curl -fsSL https://github.com/MuyleangIng/MekongTunnel/releases/latest/download/mekong-darwin-arm64 \
43
+ -o /usr/local/bin/mekong && chmod +x /usr/local/bin/mekong
35
44
 
36
- ```bash
37
- curl -sL https://github.com/MuyleangIng/MekongTunnel/releases/download/v1.4.9/mekong-linux-amd64 \
45
+ # Linux amd64
46
+ curl -fsSL https://github.com/MuyleangIng/MekongTunnel/releases/latest/download/mekong-linux-amd64 \
38
47
  -o /usr/local/bin/mekong && chmod +x /usr/local/bin/mekong
48
+
49
+ # Windows — download from:
50
+ # https://github.com/MuyleangIng/MekongTunnel/releases/latest
39
51
  ```
40
52
 
41
- **macOS (Apple Silicon):**
53
+ ---
54
+
55
+ ## Commands
56
+
57
+ ### 1. `mekong-cli <port>` — Tunnel an already-running server
58
+
59
+ Your server is already running. Just pass the port:
42
60
 
43
61
  ```bash
44
- curl -sL https://github.com/MuyleangIng/MekongTunnel/releases/download/v1.4.9/mekong-darwin-arm64 \
45
- -o /usr/local/bin/mekong && chmod +x /usr/local/bin/mekong
62
+ mekong-cli 3000
63
+ mekong-cli 5173
64
+ mekong-cli 8080
46
65
  ```
47
66
 
48
- **Windows:** Download `mekong-windows-amd64.exe`, rename it to `mekong.exe`, and place it somewhere on your `PATH` (e.g. `C:\Windows\System32\` or `%USERPROFILE%\AppData\Local\`).
67
+ > If nothing is listening on that port, mekong-cli will tell you clearly and exit it will **not** start the tunnel.
49
68
 
50
69
  ---
51
70
 
52
- ## Usage
71
+ ### 2. `mekong-cli` — Auto-detect port from package.json
53
72
 
54
- ### Tunnel an already-running server
73
+ No port needed if your `package.json` uses a known framework:
55
74
 
56
75
  ```bash
57
- mekong-cli 3000
76
+ mekong-cli
58
77
  ```
59
78
 
60
- ### Start server + tunnel together
79
+ mekong-cli reads your `package.json` and detects the port automatically:
80
+
81
+ | Framework | Detected port |
82
+ |---|---|
83
+ | Next.js | 3000 |
84
+ | Nuxt | 3000 |
85
+ | React (CRA) | 3000 |
86
+ | Remix | 3000 |
87
+ | Express / Fastify / Koa | 3000 |
88
+ | Vite | 5173 |
89
+ | SvelteKit | 5173 |
90
+ | Angular | 4200 |
91
+ | Astro | 4321 |
92
+ | Gatsby | 8000 |
93
+
94
+ ---
95
+
96
+ ### 3. `mekong-cli --with "<cmd>" --port <n>` — Start server + tunnel together
97
+
98
+ Start your dev server AND the tunnel at the same time — no separate terminals:
61
99
 
62
100
  ```bash
101
+ # Next.js
63
102
  mekong-cli --with "next dev" --port 3000
103
+
104
+ # Vite (React, Vue, Svelte, etc.)
64
105
  mekong-cli --with "vite" --port 5173
106
+
107
+ # Nuxt
65
108
  mekong-cli --with "nuxt dev" --port 3000
109
+
110
+ # Angular
66
111
  mekong-cli --with "ng serve" --port 4200
112
+
113
+ # Astro
67
114
  mekong-cli --with "astro dev" --port 4321
68
- ```
69
115
 
70
- ### Extra options
116
+ # SvelteKit
117
+ mekong-cli --with "vite dev" --port 5173
71
118
 
72
- ```bash
73
- # Set tunnel expiry
74
- mekong-cli --with "next dev" --port 3000 --expire 2h
119
+ # Express / Node server
120
+ mekong-cli --with "node server.js" --port 3000
75
121
 
76
- # Run mekong in background (daemon mode)
77
- mekong-cli --with "next dev" --port 3000 --daemon
122
+ # Any custom command
123
+ mekong-cli --with "npm run dev" --port 3000
124
+ ```
78
125
 
79
- # Suppress QR code
80
- mekong-cli --with "next dev" --port 3000 --no-qr
126
+ mekong-cli will:
127
+ 1. Start your dev server
128
+ 2. Wait for port to accept connections (up to 30s)
129
+ 3. Start the mekong tunnel
130
+ 4. Print the public URL banner
131
+ 5. On Ctrl+C — stop both cleanly
81
132
 
82
- # Use a custom mekong binary path
83
- mekong-cli --with "next dev" --port 3000 --mekong ~/bin/mekong
84
- ```
133
+ ---
85
134
 
86
- ### All options
135
+ ### 4. `mekong-cli init` — Auto-setup in your project
87
136
 
88
- ```
89
- --with <cmd> Shell command to start the dev server
90
- --port <n> Local port (auto-detected from package.json if omitted)
91
- --expire <val> Expiry duration passed to mekong (e.g. 2h, 30m)
92
- --daemon Run mekong in the background (-d flag)
93
- --no-qr Suppress QR code output
94
- --mekong <path> Custom path to the mekong binary
95
- --help Show help
96
- ```
137
+ Run this once in your project root:
97
138
 
98
- ---
139
+ ```bash
140
+ mekong-cli init
141
+ ```
99
142
 
100
- ## Add to package.json scripts
143
+ mekong-cli init will:
144
+ - Detect your framework (Next.js, Vite, Nuxt, etc.)
145
+ - Ask which port your server runs on
146
+ - Inject a `dev:tunnel` script into your `package.json`
101
147
 
102
- You can wire `mekong-cli` directly into your project's `package.json` so the whole team uses it consistently:
148
+ After running init, your `package.json` will have:
103
149
 
104
150
  ```json
105
151
  {
106
152
  "scripts": {
107
153
  "dev": "next dev",
108
- "tunnel": "mekong-cli --with \"next dev\" --port 3000",
109
- "tunnel:share": "mekong-cli --with \"next dev\" --port 3000 --expire 2h"
154
+ "dev:tunnel": "mekong-cli --with \"next dev\" --port 3000"
110
155
  }
111
156
  }
112
157
  ```
@@ -114,74 +159,99 @@ You can wire `mekong-cli` directly into your project's `package.json` so the who
114
159
  Then just run:
115
160
 
116
161
  ```bash
117
- npm run tunnel
162
+ npm run dev:tunnel
118
163
  ```
119
164
 
120
- ### Framework-specific examples
165
+ ---
121
166
 
122
- **Vite / SvelteKit:**
167
+ ## All options
123
168
 
124
- ```json
125
- {
126
- "scripts": {
127
- "dev": "vite",
128
- "tunnel": "mekong-cli --with \"vite\" --port 5173"
129
- }
130
- }
169
+ ```
170
+ mekong-cli [options] [port]
171
+
172
+ <port> Port of an already-running server to tunnel
173
+ --with <cmd> Start this dev server command first, then tunnel
174
+ --port <n> Explicit port (used with --with, or overrides auto-detect)
175
+ --expire <val> Tunnel expiry: 30m, 2h, 1d, 1w
176
+ --daemon Run mekong tunnel in background
177
+ --no-qr Suppress QR code in terminal
178
+ --mekong <path> Custom path to mekong binary
179
+ --help, -h Show help
180
+
181
+ init Auto-setup dev:tunnel script in your project
131
182
  ```
132
183
 
133
- **Nuxt:**
184
+ ---
134
185
 
135
- ```json
136
- {
137
- "scripts": {
138
- "dev": "nuxt dev",
139
- "tunnel": "mekong-cli --with \"nuxt dev\" --port 3000"
140
- }
141
- }
142
- ```
186
+ ## Framework quick reference
187
+
188
+ | Framework | Command |
189
+ |---|---|
190
+ | **Next.js** | `mekong-cli --with "next dev" --port 3000` |
191
+ | **Vite** | `mekong-cli --with "vite" --port 5173` |
192
+ | **Nuxt** | `mekong-cli --with "nuxt dev" --port 3000` |
193
+ | **Angular** | `mekong-cli --with "ng serve" --port 4200` |
194
+ | **Astro** | `mekong-cli --with "astro dev" --port 4321` |
195
+ | **SvelteKit** | `mekong-cli --with "vite dev" --port 5173` |
196
+ | **Remix** | `mekong-cli --with "remix dev" --port 3000` |
197
+ | **Gatsby** | `mekong-cli --with "gatsby develop" --port 8000` |
198
+ | **Express** | `mekong-cli --with "node server.js" --port 3000` |
199
+ | **Fastify** | `mekong-cli --with "node server.js" --port 3000` |
143
200
 
144
- **Angular:**
201
+ ---
145
202
 
146
- ```json
147
- {
148
- "scripts": {
149
- "start": "ng serve",
150
- "tunnel": "mekong-cli --with \"ng serve\" --port 4200"
151
- }
152
- }
203
+ ## With expiry and options
204
+
205
+ ```bash
206
+ # Expire tunnel after 2 hours
207
+ mekong-cli --with "next dev" --port 3000 --expire 2h
208
+
209
+ # Run tunnel in background (daemon mode)
210
+ mekong-cli --with "next dev" --port 3000 --daemon
211
+
212
+ # No QR code
213
+ mekong-cli --with "vite" --port 5173 --no-qr
214
+
215
+ # Custom mekong binary path
216
+ mekong-cli --with "next dev" --port 3000 --mekong ~/bin/mekong
153
217
  ```
154
218
 
155
- **Astro:**
219
+ ---
220
+
221
+ ## Add scripts to package.json manually
156
222
 
157
223
  ```json
158
224
  {
159
225
  "scripts": {
160
- "dev": "astro dev",
161
- "tunnel": "mekong-cli --with \"astro dev\" --port 4321"
226
+ "dev": "next dev",
227
+ "dev:tunnel": "mekong-cli --with \"next dev\" --port 3000",
228
+ "dev:tunnel:share": "mekong-cli --with \"next dev\" --port 3000 --expire 2h"
162
229
  }
163
230
  }
164
231
  ```
165
232
 
233
+ Or just run `mekong-cli init` and it does this for you automatically.
234
+
166
235
  ---
167
236
 
168
237
  ## How it works
169
238
 
170
- 1. Spawns your dev server (`--with`) with its stdout/stderr streamed to your terminal, prefixed with `[server]`.
171
- 2. Polls the local port every 500 ms until the server is accepting connections (up to 30 s).
172
- 3. Starts `mekong <port>` and streams its output prefixed with `[tunnel]`.
173
- 4. When the public URL appears in mekong's output, prints a banner:
174
-
175
239
  ```
176
- ╔══════════════════════════════════════════╗
240
+ mekong-cli --with "next dev" --port 3000
241
+
242
+ [server] ready - started server on 0.0.0.0:3000
243
+ [server] ...
244
+ ✔ Port 3000 is ready. Starting tunnel...
245
+ [tunnel] ✔ Tunnel is live!
246
+ [tunnel] URL https://happy-tiger-a1b2c3d4.mekongtunnel.dev
247
+
248
+ ╔══════════════════════════════════════════════════╗
177
249
  ║ Public URL: https://happy-tiger-a1b2c3d4.mekongtunnel.dev ║
178
- ╚══════════════════════════════════════════╝
250
+ ╚══════════════════════════════════════════════════╝
179
251
  ```
180
252
 
181
- 5. On `Ctrl+C` (or `SIGTERM`), kills the tunnel first, then the server, and exits cleanly.
182
-
183
253
  ---
184
254
 
185
255
  ## License
186
256
 
187
- MIT Author: Ing Muyleang
257
+ MIT © [Ing Muyleang](https://github.com/MuyleangIng) — KhmerStack
package/bin/mekong-cli.js CHANGED
@@ -4,9 +4,10 @@
4
4
  const { spawn } = require('child_process');
5
5
  const path = require('path');
6
6
 
7
- const { findMekong } = require('../lib/find-mekong');
8
- const { detectPort } = require('../lib/detect-port');
7
+ const { findMekong } = require('../lib/find-mekong');
8
+ const { detectPort } = require('../lib/detect-port');
9
9
  const { runWithServer } = require('../lib/runner');
10
+ const { checkPortOpen } = require('../lib/wait-for-port');
10
11
 
11
12
  const BOLD = '\x1b[1m';
12
13
  const DIM = '\x1b[2m';
@@ -23,37 +24,51 @@ const HELP = `
23
24
  ${BOLD}mekong-cli${RESET} — Run your dev server + Mekong tunnel in one command
24
25
 
25
26
  ${BOLD}USAGE${RESET}
26
- mekong-cli <port> Tunnel an already-running server
27
- mekong-cli --port <n> Tunnel only (auto-detect port)
27
+ mekong-cli <port> Tunnel an already-running server on <port>
28
+ mekong-cli Auto-detect port from package.json + tunnel
28
29
  mekong-cli --with "<cmd>" --port <n> Start server + tunnel together
30
+ mekong-cli init Auto-setup dev:tunnel script in your project
29
31
 
30
32
  ${BOLD}OPTIONS${RESET}
31
33
  --with <cmd> Shell command to start the dev server
32
34
  --port <n> Local port (auto-detected from package.json if omitted)
33
- --expire <val> Expiry duration passed to mekong (e.g. 2h, 30m)
35
+ --expire <val> Expiry duration passed to mekong (e.g. 2h, 30m, 1d, 1w)
34
36
  --daemon Run mekong in the background (-d flag)
35
37
  --no-qr Suppress QR code output
36
38
  --mekong <path> Custom path to the mekong binary
37
- --help Show this help message
39
+ --help, -h Show this help message
40
+
41
+ ${BOLD}SUBCOMMANDS${RESET}
42
+ init Auto-detect your framework, inject dev:tunnel into package.json
38
43
 
39
44
  ${BOLD}EXAMPLES${RESET}
45
+ ${DIM}# Tunnel a server already running on port 3000${RESET}
40
46
  mekong-cli 3000
47
+
48
+ ${DIM}# Auto-detect port from package.json and tunnel${RESET}
49
+ mekong-cli
50
+
51
+ ${DIM}# Start your dev server AND open a tunnel together${RESET}
41
52
  mekong-cli --with "next dev" --port 3000
42
53
  mekong-cli --with "vite" --port 5173
43
54
  mekong-cli --with "nuxt dev" --port 3000
44
55
  mekong-cli --with "ng serve" --port 4200
45
56
  mekong-cli --with "astro dev" --port 4321
57
+
58
+ ${DIM}# With options${RESET}
46
59
  mekong-cli --with "next dev" --port 3000 --expire 2h
47
- mekong-cli --with "next dev" --port 3000 --daemon
60
+ mekong-cli --with "vite" --port 5173 --daemon
61
+ mekong-cli --with "next dev" --port 3000 --no-qr
48
62
 
49
- ${BOLD}INSTALL MEKONG BINARY${RESET}
50
- Download from: https://github.com/MuyleangIng/MekongTunnel/releases/tag/v1.4.9
63
+ ${DIM}# Auto-setup script (run once in your project root)${RESET}
64
+ mekong-cli init
51
65
 
52
- Linux/macOS (quick install):
53
- curl -sL https://github.com/MuyleangIng/MekongTunnel/releases/download/v1.4.9/mekong-linux-amd64 \\
54
- -o /usr/local/bin/mekong && chmod +x /usr/local/bin/mekong
66
+ ${BOLD}INSTALL MEKONG BINARY${RESET}
67
+ Linux/macOS (auto-detect arch):
68
+ curl -fsSL https://github.com/MuyleangIng/MekongTunnel/releases/latest/download/mekong-\\$(uname -s | tr A-Z a-z)-\\$(uname -m) \\
69
+ -o ~/.local/bin/mekong && chmod +x ~/.local/bin/mekong
55
70
 
56
- Windows: download mekong-windows-amd64.exe and place in PATH
71
+ Windows: download from https://github.com/MuyleangIng/MekongTunnel/releases/latest
57
72
  `;
58
73
 
59
74
  // ---------------------------------------------------------------------------
@@ -179,7 +194,20 @@ async function main() {
179
194
  return;
180
195
  }
181
196
 
182
- // Tunnel-only mode: just proxy straight to mekong
197
+ // Tunnel-only mode: verify the port is actually listening before calling mekong
198
+ const isOpen = await checkPortOpen(port);
199
+ if (!isOpen) {
200
+ process.stderr.write(
201
+ `${RED}${BOLD}mekong-cli: nothing is listening on port ${port}.${RESET}\n\n` +
202
+ ` Start your server first, then run:\n` +
203
+ ` ${CYAN}mekong-cli ${port}${RESET}\n\n` +
204
+ ` Or let mekong-cli start it for you:\n` +
205
+ ` ${CYAN}mekong-cli --with "your-start-cmd" --port ${port}${RESET}\n\n` +
206
+ ` Or run ${CYAN}mekong-cli init${RESET} to set it up automatically.\n`
207
+ );
208
+ process.exit(1);
209
+ }
210
+
183
211
  const mekongArgs = [String(port)];
184
212
  if (opts.expire) mekongArgs.push('--expire', opts.expire);
185
213
  if (opts.daemon) mekongArgs.push('-d');
@@ -49,4 +49,27 @@ function waitForPort(port) {
49
49
  });
50
50
  }
51
51
 
52
- module.exports = { waitForPort };
52
+ /**
53
+ * Single immediate check — resolves true if port is open right now, false otherwise.
54
+ * @param {number} port
55
+ * @returns {Promise<boolean>}
56
+ */
57
+ function checkPortOpen(port) {
58
+ return new Promise((resolve) => {
59
+ const sock = new net.Socket();
60
+ let done = false;
61
+ function finish(open) {
62
+ if (done) return;
63
+ done = true;
64
+ sock.destroy();
65
+ resolve(open);
66
+ }
67
+ sock.setTimeout(1000);
68
+ sock.once('connect', () => finish(true));
69
+ sock.once('error', () => finish(false));
70
+ sock.once('timeout', () => finish(false));
71
+ sock.connect(port, '127.0.0.1');
72
+ });
73
+ }
74
+
75
+ module.exports = { waitForPort, checkPortOpen };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mekong-cli",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Run your dev server + Mekong tunnel in one command",
5
5
  "bin": {
6
6
  "mekong-cli": "bin/mekong-cli.js"