connectbase-client 0.3.0 → 0.3.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.
Files changed (3) hide show
  1. package/README.md +15 -0
  2. package/dist/cli.js +49 -7
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -98,6 +98,8 @@ npx connectbase-client deploy ./dist -s <storage-id> -k <api-key>
98
98
  | `--storage <id>` | `-s` | Storage ID |
99
99
  | `--api-key <key>` | `-k` | API Key |
100
100
  | `--base-url <url>` | `-u` | Custom server URL |
101
+ | `--timeout <sec>` | `-t` | Tunnel request timeout in seconds (tunnel only) |
102
+ | `--max-body <MB>` | | Tunnel max body size in MB (tunnel only) |
101
103
  | `--help` | `-h` | Show help |
102
104
  | `--version` | `-v` | Show version |
103
105
 
@@ -112,11 +114,24 @@ npx connectbase-client tunnel 8084 -k <api-key>
112
114
  # With environment variable
113
115
  export CONNECTBASE_API_KEY=your-api-key
114
116
  npx connectbase-client tunnel 8084
117
+
118
+ # For GPU servers or long-running tasks (e.g., image generation)
119
+ npx connectbase-client tunnel 7860 --timeout 300 --max-body 50
115
120
  ```
116
121
 
117
122
  The tunnel creates a public URL like `https://tunnel.connectbase.world/<tunnel-id>/` that proxies all HTTP requests to your local service.
118
123
 
124
+ **Plan-based limits:** Timeout and body size are clamped to your plan's maximum:
125
+
126
+ | Plan | Max Timeout | Max Body |
127
+ |------|-------------|----------|
128
+ | Free | 60s | 10MB |
129
+ | Starter | 120s | 25MB |
130
+ | Pro | 300s | 50MB |
131
+ | Business | 600s | 100MB |
132
+
119
133
  Features:
134
+ - Per-tunnel timeout and body size configuration
120
135
  - Automatic reconnection with exponential backoff
121
136
  - Request/response logging in terminal
122
137
  - Graceful shutdown with Ctrl+C
package/dist/cli.js CHANGED
@@ -470,6 +470,13 @@ function createWsCloseFrame(code) {
470
470
  header[1] = 128 | 2;
471
471
  return Buffer.concat([header, maskKey, masked]);
472
472
  }
473
+ function createWsPongFrame() {
474
+ const maskKey = crypto.randomBytes(4);
475
+ const header = Buffer.alloc(2);
476
+ header[0] = 138;
477
+ header[1] = 128 | 0;
478
+ return Buffer.concat([header, maskKey]);
479
+ }
473
480
  var WsFrameParser = class {
474
481
  constructor(handlers) {
475
482
  this.buffer = Buffer.alloc(0);
@@ -539,7 +546,7 @@ function getTunnelServerUrl(baseUrl) {
539
546
  }
540
547
  return baseUrl.replace(/:\d+/, ":8090");
541
548
  }
542
- async function startTunnel(port, config) {
549
+ async function startTunnel(port, config, tunnelOpts) {
543
550
  if (!config.apiKey) {
544
551
  error("API Key\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. -k \uC635\uC158 \uB610\uB294 CONNECTBASE_API_KEY \uD658\uACBD\uBCC0\uC218\uB97C \uC124\uC815\uD558\uC138\uC694");
545
552
  process.exit(1);
@@ -547,7 +554,13 @@ async function startTunnel(port, config) {
547
554
  const tunnelServerUrl = getTunnelServerUrl(config.baseUrl);
548
555
  const parsedUrl = new URL(tunnelServerUrl);
549
556
  const isHttps = parsedUrl.protocol === "https:";
550
- const wsPath = `/v1/tunnel/connect?api_key=${encodeURIComponent(config.apiKey)}`;
557
+ let wsPath = `/v1/tunnel/connect?api_key=${encodeURIComponent(config.apiKey)}`;
558
+ if (tunnelOpts?.timeout) {
559
+ wsPath += `&timeout=${tunnelOpts.timeout}`;
560
+ }
561
+ if (tunnelOpts?.maxBody) {
562
+ wsPath += `&max_body=${tunnelOpts.maxBody}`;
563
+ }
551
564
  let reconnectAttempts = 0;
552
565
  const maxReconnectAttempts = 10;
553
566
  let shouldReconnect = true;
@@ -608,8 +621,7 @@ ${colors.cyan}ConnectBase Tunnel${colors.reset}`);
608
621
  sock.destroy();
609
622
  },
610
623
  onPing: () => {
611
- const pongMsg = JSON.stringify({ type: "pong" });
612
- sock.write(createWsTextFrame(pongMsg));
624
+ sock.write(createWsPongFrame());
613
625
  }
614
626
  });
615
627
  sock.on("data", (chunk) => parser.feed(chunk));
@@ -673,6 +685,9 @@ ${colors.cyan}ConnectBase Tunnel${colors.reset}`);
673
685
  success(`\uD130\uB110 \uD65C\uC131\uD654!`);
674
686
  log(`${colors.green}\u2192${colors.reset} URL: ${colors.cyan}${msg.url}${colors.reset}`);
675
687
  log(`${colors.green}\u2192${colors.reset} \uB85C\uCEEC: ${colors.cyan}http://localhost:${localPort}${colors.reset}`);
688
+ if (msg.timeout || msg.max_body) {
689
+ log(`${colors.green}\u2192${colors.reset} \uC124\uC815: timeout=${colors.cyan}${msg.timeout}s${colors.reset}, max-body=${colors.cyan}${msg.max_body}MB${colors.reset}`);
690
+ }
676
691
  log(`
677
692
  ${colors.dim}Ctrl+C\uB85C \uC885\uB8CC${colors.reset}
678
693
  `);
@@ -696,14 +711,20 @@ ${colors.dim}Ctrl+C\uB85C \uC885\uB8CC${colors.reset}
696
711
  const headers = msg.headers || {};
697
712
  const bodyBase64 = msg.body;
698
713
  const fullPath = query ? `${reqPath}?${query}` : reqPath;
714
+ const localHeaders = {};
715
+ for (const [key, value] of Object.entries(headers)) {
716
+ if (key.toLowerCase() !== "host") {
717
+ localHeaders[key] = value;
718
+ }
719
+ }
720
+ localHeaders["host"] = `localhost:${localPort}`;
699
721
  const reqOptions = {
700
722
  hostname: "127.0.0.1",
701
723
  port: localPort,
702
724
  path: fullPath,
703
725
  method,
704
- headers: { ...headers, host: `localhost:${localPort}` }
726
+ headers: localHeaders
705
727
  };
706
- delete reqOptions.headers["Host"];
707
728
  const localReq = http.request(reqOptions, (res) => {
708
729
  const chunks = [];
709
730
  res.on("data", (chunk) => chunks.push(chunk));
@@ -768,6 +789,8 @@ ${colors.yellow}\uC635\uC158:${colors.reset}
768
789
  -s, --storage <id> \uC2A4\uD1A0\uB9AC\uC9C0 ID
769
790
  -k, --api-key <key> API Key
770
791
  -u, --base-url <url> \uC11C\uBC84 URL (\uAE30\uBCF8: ${DEFAULT_BASE_URL})
792
+ -t, --timeout <sec> \uD130\uB110 \uC694\uCCAD \uD0C0\uC784\uC544\uC6C3 (\uCD08, tunnel \uC804\uC6A9)
793
+ --max-body <MB> \uD130\uB110 \uCD5C\uB300 \uBC14\uB514 \uD06C\uAE30 (MB, tunnel \uC804\uC6A9)
771
794
  -h, --help \uB3C4\uC6C0\uB9D0 \uD45C\uC2DC
772
795
  -v, --version \uBC84\uC804 \uD45C\uC2DC
773
796
 
@@ -778,6 +801,12 @@ ${colors.yellow}\uBE60\uB978 \uC2DC\uC791:${colors.reset}
778
801
  ${colors.dim}# 2. \uBC30\uD3EC${colors.reset}
779
802
  npm run deploy
780
803
 
804
+ ${colors.dim}# 3. \uD130\uB110 (\uAE30\uBCF8)${colors.reset}
805
+ npx connectbase-client tunnel 3000
806
+
807
+ ${colors.dim}# 4. \uD130\uB110 (GPU \uC11C\uBC84 \uB4F1 \uAE34 \uC751\uB2F5 \uC2DC)${colors.reset}
808
+ npx connectbase-client tunnel 7860 --timeout 300 --max-body 50
809
+
781
810
  ${colors.yellow}\uD658\uACBD\uBCC0\uC218:${colors.reset}
782
811
  CONNECTBASE_API_KEY API Key
783
812
  CONNECTBASE_STORAGE_ID \uC2A4\uD1A0\uB9AC\uC9C0 ID
@@ -805,6 +834,10 @@ function parseArgs(args) {
805
834
  result.options.apiKey = args[++i];
806
835
  } else if (arg === "-u" || arg === "--base-url") {
807
836
  result.options.baseUrl = args[++i];
837
+ } else if (arg === "-t" || arg === "--timeout") {
838
+ result.options.timeout = args[++i];
839
+ } else if (arg === "--max-body") {
840
+ result.options.maxBody = args[++i];
808
841
  } else if (arg === "-h" || arg === "--help") {
809
842
  result.options.help = "true";
810
843
  } else if (arg === "-v" || arg === "--version") {
@@ -860,7 +893,16 @@ async function main() {
860
893
  error("\uC720\uD6A8\uD55C \uD3EC\uD2B8 \uBC88\uD638\uB97C \uC785\uB825\uD558\uC138\uC694 (1-65535)");
861
894
  process.exit(1);
862
895
  }
863
- await startTunnel(port, config);
896
+ const tunnelOpts = {};
897
+ if (parsed.options.timeout) {
898
+ const t = parseInt(parsed.options.timeout, 10);
899
+ if (!isNaN(t) && t > 0) tunnelOpts.timeout = t;
900
+ }
901
+ if (parsed.options.maxBody) {
902
+ const m = parseInt(parsed.options.maxBody, 10);
903
+ if (!isNaN(m) && m > 0) tunnelOpts.maxBody = m;
904
+ }
905
+ await startTunnel(port, config, tunnelOpts);
864
906
  } else {
865
907
  error(`\uC54C \uC218 \uC5C6\uB294 \uBA85\uB839\uC5B4: ${parsed.command}`);
866
908
  showHelp();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "connectbase-client",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Connect Base JavaScript/TypeScript SDK for browser and Node.js",
5
5
  "repository": {
6
6
  "type": "git",