runlocal 0.5.0 → 0.6.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 (3) hide show
  1. package/index.js +2 -2
  2. package/lib.js +15 -7
  3. package/package.json +12 -3
package/index.js CHANGED
@@ -6,7 +6,7 @@ const { parseArgs, createConnection } = require("./lib");
6
6
  const BOLD = "\x1b[1m";
7
7
  const RESET = "\x1b[0m";
8
8
 
9
- const { port, host, apiKey } = parseArgs(process.argv.slice(2));
9
+ const { port, host, apiKey, subdomain } = parseArgs(process.argv.slice(2));
10
10
 
11
11
  console.log(`${BOLD}runlocal${RESET} — expose localhost:${port} to the internet`);
12
- createConnection({ host, port, apiKey, WebSocket });
12
+ createConnection({ host, port, apiKey, subdomain, WebSocket });
package/lib.js CHANGED
@@ -29,11 +29,14 @@ function parseArgs(argv) {
29
29
  let port = 3000;
30
30
  let host = process.env.RUNLOCAL_HOST || "wss://runlocal.eu";
31
31
  let apiKey = process.env.RUNLATER_API_KEY || readApiKeyFile();
32
+ let subdomain = null;
32
33
  for (let i = 0; i < argv.length; i++) {
33
34
  if (argv[i] === "--host" && argv[i + 1]) {
34
35
  host = argv[++i];
35
36
  } else if (argv[i] === "--api-key" && argv[i + 1]) {
36
37
  apiKey = argv[++i];
38
+ } else if (argv[i] === "--subdomain" && argv[i + 1]) {
39
+ subdomain = argv[++i];
37
40
  } else if (argv[i] === "--help" || argv[i] === "-h") {
38
41
  console.log("Usage: runlocal <port> [options]");
39
42
  console.log("");
@@ -42,6 +45,7 @@ function parseArgs(argv) {
42
45
  console.log("Options:");
43
46
  console.log(" --host <url> Server URL (default: wss://runlocal.eu)");
44
47
  console.log(" --api-key <key> Runlater API key for stable subdomain");
48
+ console.log(" --subdomain <name> Custom subdomain (Pro plan only)");
45
49
  console.log(" --help, -h Show this help");
46
50
  console.log("");
47
51
  console.log("API key (checked in order):");
@@ -50,17 +54,19 @@ function parseArgs(argv) {
50
54
  console.log(" 3. ~/.runlater/api-key file");
51
55
  console.log("");
52
56
  console.log("Examples:");
53
- console.log(" npx runlocal 3000 Random subdomain");
54
- console.log(" npx runlocal 3000 --api-key pk_xxx Stable subdomain");
57
+ console.log(" npx runlocal 3000 Random subdomain");
58
+ console.log(" npx runlocal 3000 --api-key pk_xxx Stable subdomain");
59
+ console.log(" npx runlocal 3000 --subdomain my-api Custom subdomain (Pro)");
55
60
  console.log("");
56
61
  console.log("A free runlater.eu account gives you a stable subdomain.");
62
+ console.log("Pro users can choose any available subdomain with --subdomain.");
57
63
  process.exit(0);
58
64
  } else if (!argv[i].startsWith("-")) {
59
65
  port = parseInt(argv[i], 10);
60
66
  }
61
67
  }
62
68
 
63
- return { port, host, apiKey };
69
+ return { port, host, apiKey, subdomain };
64
70
  }
65
71
 
66
72
  function filterHeaders(headers) {
@@ -75,9 +81,10 @@ function filterHeaders(headers) {
75
81
  return filtered;
76
82
  }
77
83
 
78
- function buildWsUrl(host, apiKey) {
84
+ function buildWsUrl(host, apiKey, subdomain) {
79
85
  const params = new URLSearchParams({ vsn: "2.0.0" });
80
86
  if (apiKey) params.set("api_key", apiKey);
87
+ if (subdomain) params.set("subdomain", subdomain);
81
88
  return `${host}/tunnel/websocket?${params.toString()}`;
82
89
  }
83
90
 
@@ -170,13 +177,14 @@ function createConnection(options) {
170
177
  host,
171
178
  port,
172
179
  apiKey,
180
+ subdomain,
173
181
  WebSocket,
174
182
  onTunnelCreated,
175
183
  onClose,
176
184
  log = console.log,
177
185
  logError = console.error,
178
186
  } = options;
179
- const wsUrl = buildWsUrl(host, apiKey);
187
+ const wsUrl = buildWsUrl(host, apiKey, subdomain);
180
188
 
181
189
  let refCounter = 0;
182
190
  const nextRef = () => String(++refCounter);
@@ -224,13 +232,13 @@ function createConnection(options) {
224
232
  if (event === "tunnel_created") {
225
233
  const inspectUrl = payload.url.replace(/^https?:\/\/[^/]+/, (origin) => {
226
234
  // Convert subdomain URL to main domain /inspect/ URL
227
- // e.g., https://fuzzy-tiger.runlocal.eu → https://runlocal.eu/inspect/fuzzy-tiger
235
+ // e.g., https://fuzzy-tiger.runlocal.eu → https://runlocal.eu/inspect/fuzzy-tiger/<token>
228
236
  const parts = new URL(origin);
229
237
  const hostParts = parts.hostname.split(".");
230
238
  if (hostParts.length > 2) {
231
239
  parts.hostname = hostParts.slice(1).join(".");
232
240
  }
233
- return `${parts.origin}/inspect/${payload.subdomain}`;
241
+ return `${parts.origin}/inspect/${payload.subdomain}/${payload.inspect_token}`;
234
242
  });
235
243
 
236
244
  log("");
package/package.json CHANGED
@@ -1,15 +1,24 @@
1
1
  {
2
2
  "name": "runlocal",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Expose localhost to the internet via runlocal.eu",
5
5
  "bin": {
6
6
  "runlocal": "./index.js"
7
7
  },
8
- "files": ["index.js", "lib.js"],
8
+ "files": [
9
+ "index.js",
10
+ "lib.js"
11
+ ],
9
12
  "scripts": {
10
13
  "test": "node --test test/*.test.js"
11
14
  },
12
- "keywords": ["tunnel", "localhost", "ngrok", "dev", "https"],
15
+ "keywords": [
16
+ "tunnel",
17
+ "localhost",
18
+ "ngrok",
19
+ "dev",
20
+ "https"
21
+ ],
13
22
  "license": "MIT",
14
23
  "dependencies": {
15
24
  "ws": "^8.0.0"