connectbase-client 3.5.0 → 3.5.2

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 CHANGED
@@ -3,6 +3,44 @@
3
3
  본 SDK 의 모든 주요 변경사항을 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/) 형식으로 기록합니다.
4
4
  버전은 [Semantic Versioning](https://semver.org/lang/ko/) 을 따릅니다.
5
5
 
6
+ ## [3.5.2] - 2026-05-01
7
+
8
+ ### Fixed — `connectbase tunnel --label` / `--description` 옵션이 파싱되지 않던 문제
9
+
10
+ 3.5.1 의 인증 헤더 / `await` 수정에도 불구하고 `--label` / `--description` 으로
11
+ endpoint binding 자동 등록이 한 번도 트리거되지 않던 문제를 수정했습니다.
12
+ 원인은 `parseArgs()` 의 옵션 파싱 분기 자체가 두 옵션을 매칭하지 않아
13
+ `parsed.options.label === undefined` 로 떨어지고, 결과적으로
14
+ `if (tunnelOpts?.label && tunnelUrl)` 가드가 항상 false 가 되어
15
+ `registerEndpointBinding()` 이 호출되지 않았던 것입니다.
16
+
17
+ - `parseArgs()` 의 while 루프에 `--label` / `--description` 분기 추가
18
+ (기존 `--storage` / `--max-body` 와 동일 패턴).
19
+ - `parseArgs()` 를 `export` 로 노출 + `test/cli-parse-args.test.ts` 회귀 테스트
20
+ 추가 — `--label` 단독 / `--label` + `--description` 조합 / 미지정 / `--description`
21
+ 단독 4 가지 케이스를 검증해 동일 회귀 차단.
22
+
23
+ 회귀 영향 범위: 3.5.1 에서 `--label` / `--description` 을 사용했던 모든 호출
24
+ (즉 endpoint binding 자동 등록 기능 전체). 다른 옵션·기본 `tunnel` 동작에는 영향 없음.
25
+
26
+ ## [3.5.1] - 2026-05-01
27
+
28
+ ### Fixed — `connectbase tunnel --label` endpoint 자동 등록 401
29
+
30
+ `--label` 옵션 사용 시 호출되는 `POST /v1/apps/:appID/endpoints/cli` 가 모든 요청에서
31
+ 401 ("유효하지 않은 토큰입니다") 으로 떨어져 endpoint binding 이 한 번도 등록되지
32
+ 않던 문제를 수정했습니다. 결과적으로 `cb.endpoint.call("label", ...)` 가 항상
33
+ `endpoint not found` (404) 로 실패했습니다.
34
+
35
+ - CLI 가 `Authorization: Bearer cb_sk_*` 로 호출하던 것을 서버 dual-auth 미들웨어가
36
+ 요구하는 **`X-Public-Key: cb_sk_*`** 헤더로 변경.
37
+ - `void registerEndpointBinding(...)` 의 fire-and-forget 호출을 `await` 로 변경 —
38
+ 성공/실패 메시지가 "Ctrl+C 로 종료" 안내 앞에 출력됨.
39
+ - 등록 실패 / 네트워크 오류는 stdout 이 아닌 **stderr** (빨간색 ✗) 로 출력 —
40
+ 파이프/리다이렉트 환경에서도 사용자가 실패를 인지할 수 있도록.
41
+
42
+ 회귀 영향 범위: `--label` 사용자만 해당 (기본 `connectbase tunnel <port>` 는 영향 없음).
43
+
6
44
  ## [3.5.0] - 2026-04-30
7
45
 
8
46
  ### Added — Knowledge Base 사용자별 격리
package/dist/cli.js CHANGED
@@ -33,6 +33,7 @@ var cli_exports = {};
33
33
  __export(cli_exports, {
34
34
  computeDeployDiff: () => computeDeployDiff,
35
35
  normalizeRelativePath: () => normalizeRelativePath,
36
+ parseArgs: () => parseArgs,
36
37
  sha256Hex: () => sha256Hex
37
38
  });
38
39
  module.exports = __toCommonJS(cli_exports);
@@ -1571,7 +1572,7 @@ async function registerEndpointBinding(baseUrl, appId, secretKey, tunnelUrl, lab
1571
1572
  const host = u.hostname;
1572
1573
  const tunnelId = host.replace(/\.tunnel\.connectbase\.world$/, "");
1573
1574
  if (!tunnelId || tunnelId === host) {
1574
- log(`${colors.yellow}\u26A0 tunnel_id \uCD94\uCD9C \uC2E4\uD328 (${tunnelUrl}) \u2014 endpoint \uC790\uB3D9 \uB4F1\uB85D skip${colors.reset}`);
1575
+ error(`tunnel_id \uCD94\uCD9C \uC2E4\uD328 (${tunnelUrl}) \u2014 endpoint "${label}" \uC790\uB3D9 \uB4F1\uB85D skip`);
1575
1576
  return;
1576
1577
  }
1577
1578
  const apiBase = baseUrl.replace(/\/+$/, "");
@@ -1579,7 +1580,7 @@ async function registerEndpointBinding(baseUrl, appId, secretKey, tunnelUrl, lab
1579
1580
  method: "POST",
1580
1581
  headers: {
1581
1582
  "Content-Type": "application/json",
1582
- "Authorization": `Bearer ${secretKey}`
1583
+ "X-Public-Key": secretKey
1583
1584
  },
1584
1585
  body: JSON.stringify({
1585
1586
  label,
@@ -1591,13 +1592,16 @@ async function registerEndpointBinding(baseUrl, appId, secretKey, tunnelUrl, lab
1591
1592
  success(`Endpoint "${label}" \uC790\uB3D9 \uB4F1\uB85D \uC644\uB8CC`);
1592
1593
  log(`${colors.green}\u2192${colors.reset} SDK: ${colors.cyan}cb.endpoint.call("${label}", { path: "/...", method: "POST", body: ... })${colors.reset}`);
1593
1594
  } else if (res.status === 409) {
1594
- log(`${colors.yellow}\u26A0 "${label}" \uB77C\uBCA8\uC774 \uC774\uBBF8 \uB4F1\uB85D\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4.${colors.reset} \uC0C8 tunnel_id \uB85C \uAC31\uC2E0\uD558\uB824\uBA74 \uCF58\uC194\uC5D0\uC11C \uC218\uB3D9 PATCH.`);
1595
+ warn(`"${label}" \uB77C\uBCA8\uC774 \uC774\uBBF8 \uB4F1\uB85D\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4. \uC0C8 tunnel_id \uB85C \uAC31\uC2E0\uD558\uB824\uBA74 \uCF58\uC194\uC5D0\uC11C \uC218\uB3D9 PATCH.`);
1595
1596
  } else {
1596
1597
  const text = await res.text().catch(() => "");
1597
- log(`${colors.yellow}\u26A0 endpoint \uB4F1\uB85D \uC2E4\uD328 (status ${res.status}): ${text}${colors.reset}`);
1598
+ error(`Endpoint "${label}" \uC790\uB3D9 \uB4F1\uB85D \uC2E4\uD328 (status ${res.status}): ${text || "(\uBE48 \uC751\uB2F5)"}`);
1599
+ if (res.status === 401) {
1600
+ info("cb_sk_ Secret Key \uC778\uC9C0, \uCF58\uC194\uC5D0\uC11C \uD68C\uC218\uB418\uC9C0 \uC54A\uC558\uB294\uC9C0 \uD655\uC778\uD558\uC138\uC694.");
1601
+ }
1598
1602
  }
1599
1603
  } catch (err) {
1600
- log(`${colors.yellow}\u26A0 endpoint \uB4F1\uB85D \uC911 \uC5D0\uB7EC: ${err instanceof Error ? err.message : err}${colors.reset}`);
1604
+ error(`Endpoint "${label}" \uC790\uB3D9 \uB4F1\uB85D \uC911 \uB124\uD2B8\uC6CC\uD06C \uC624\uB958: ${err instanceof Error ? err.message : err}`);
1601
1605
  }
1602
1606
  }
1603
1607
  function acquireTunnelLock2(appID, port, force) {
@@ -1736,7 +1740,9 @@ ${colors.cyan}ConnectBase Tunnel${colors.reset}`);
1736
1740
  onMessage: (data) => {
1737
1741
  try {
1738
1742
  const msg = JSON.parse(data);
1739
- handleMessage(msg, sock, port);
1743
+ handleMessage(msg, sock, port).catch((e) => {
1744
+ error(`\uBA54\uC2DC\uC9C0 \uCC98\uB9AC \uC911 \uC608\uC678: ${e instanceof Error ? e.message : e}`);
1745
+ });
1740
1746
  } catch (e) {
1741
1747
  warn(`\uBA54\uC2DC\uC9C0 \uD30C\uC2F1 \uC2E4\uD328: ${e}`);
1742
1748
  }
@@ -1804,7 +1810,7 @@ ${colors.cyan}ConnectBase Tunnel${colors.reset}`);
1804
1810
  info(`${(delay / 1e3).toFixed(0)}\uCD08 \uD6C4 \uC7AC\uC5F0\uACB0 \uC2DC\uB3C4... (${reconnectAttempts}/${maxReconnectAttempts})`);
1805
1811
  setTimeout(connect, delay);
1806
1812
  }
1807
- function handleMessage(msg, sock, localPort) {
1813
+ async function handleMessage(msg, sock, localPort) {
1808
1814
  switch (msg.type) {
1809
1815
  case "tunnel_ready": {
1810
1816
  const proxyToken = typeof msg.proxy_token === "string" ? msg.proxy_token : "";
@@ -1832,7 +1838,7 @@ ${colors.dim}\uC678\uBD80 \uC9C1\uC811 \uD638\uCD9C \uC2DC \uB2E4\uC74C \uD5E4\u
1832
1838
  log(`${colors.dim} $ curl "${tunnelUrl}/?proxy_token=${proxyToken}"${colors.reset}`);
1833
1839
  }
1834
1840
  if (tunnelOpts?.label && tunnelUrl) {
1835
- void registerEndpointBinding(
1841
+ await registerEndpointBinding(
1836
1842
  config.baseUrl,
1837
1843
  appId,
1838
1844
  tunnelKey,
@@ -2088,6 +2094,10 @@ function parseArgs(args) {
2088
2094
  result.options.timeout = args[++i];
2089
2095
  } else if (arg === "--max-body") {
2090
2096
  result.options.maxBody = args[++i];
2097
+ } else if (arg === "--label") {
2098
+ result.options.label = args[++i];
2099
+ } else if (arg === "--description") {
2100
+ result.options.description = args[++i];
2091
2101
  } else if (arg === "-a" || arg === "--app") {
2092
2102
  result.options.appId = args[++i];
2093
2103
  } else if (arg === "--force") {
@@ -2216,5 +2226,6 @@ main().catch((err) => {
2216
2226
  0 && (module.exports = {
2217
2227
  computeDeployDiff,
2218
2228
  normalizeRelativePath,
2229
+ parseArgs,
2219
2230
  sha256Hex
2220
2231
  });
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "connectbase-client",
3
- "version": "3.5.0",
3
+ "version": "3.5.2",
4
4
  "description": "Connect Base JavaScript/TypeScript SDK for browser and Node.js",
5
5
  "repository": {
6
6
  "type": "git",
7
- "url": "https://github.com/connectbase-world/connectbase.git",
7
+ "url": "git+https://github.com/connectbase-world/connectbase.git",
8
8
  "directory": "frontend/package/public/connect-base-client"
9
9
  },
10
10
  "homepage": "https://github.com/connectbase-world/connectbase/tree/release/frontend/package/public/connect-base-client#readme",
@@ -21,8 +21,8 @@
21
21
  "browser": "dist/connect-base.umd.js",
22
22
  "unpkg": "dist/connect-base.umd.js",
23
23
  "bin": {
24
- "connectbase": "./dist/cli.js",
25
- "connectbase-client": "./dist/cli.js"
24
+ "connectbase": "dist/cli.js",
25
+ "connectbase-client": "dist/cli.js"
26
26
  },
27
27
  "exports": {
28
28
  ".": {