connectbase-client 3.27.1 → 3.29.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/CHANGELOG.md +60 -0
- package/dist/cli.js +14 -1
- package/dist/connect-base.umd.js +4 -4
- package/dist/index.d.mts +77 -24
- package/dist/index.d.ts +77 -24
- package/dist/index.js +119 -70
- package/dist/index.mjs +119 -70
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,66 @@
|
|
|
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.29.0] - 2026-06-02
|
|
7
|
+
|
|
8
|
+
### Added — `connectbase tunnel --token <고정값>` proxy_token 핀 (platform-issue 019e8623)
|
|
9
|
+
|
|
10
|
+
비-public 터널의 `proxy_token` 이 **재연결마다 회전**해, 그 토큰을 스냅샷 저장하는 통합
|
|
11
|
+
(외부 MCP `custom_header X-Proxy-Token`, 터널을 가리키는 웹훅 등)이 다음 재연결부터
|
|
12
|
+
`401 invalid or missing proxy token` 으로 깨지던 문제를 해결한다.
|
|
13
|
+
|
|
14
|
+
- **`cli.ts` — `tunnel --token <value>`** — proxy_token 을 고정값으로 핀. 재연결 핸드셰이크마다
|
|
15
|
+
같은 값(`?proxy_token=`)을 보내 회전을 방지한다. 16~128자 `[A-Za-z0-9_-]` 검증(클라 선검사 +
|
|
16
|
+
서버 `ValidateProxyToken` 동일 규칙). 미지정 시 기존 동작(매 연결 새 발급) 유지 — 하위호환.
|
|
17
|
+
- **CLI 라벨 재등록 idempotent** — 같은 라벨 + 같은 `tunnel_id` 재등록은 더 이상 409 경고를
|
|
18
|
+
내지 않고 기존 바인딩을 그대로 유지한다(콘솔 수동 PATCH 안내 제거). 라벨이 *다른* tunnel_id 에
|
|
19
|
+
묶여 있을 때만 충돌로 처리. 회전이 이미 일어나 깨진 경우의 즉시 복구용으로 백엔드에
|
|
20
|
+
현재 토큰 조회 경로(MCP `get_tunnel_label_proxy_token` / REST `GET .../endpoint-proxy-token/:label`)도
|
|
21
|
+
추가됐다.
|
|
22
|
+
|
|
23
|
+
## [3.28.1] - 2026-06-02
|
|
24
|
+
|
|
25
|
+
### Added — `RelationType` 에 `many-to-one` 추가 (platform-issue 019e83a0-c7d0)
|
|
26
|
+
|
|
27
|
+
`cb.database.createRelation` 의 `relation_type` 으로 `many-to-one`(외래키→부모 단일 객체
|
|
28
|
+
populate 의 정석)을 지정할 수 있게 됐다. 기존엔 문서/MCP 는 `many-to-one` 을 안내하면서도
|
|
29
|
+
SDK/REST 관계 API 는 `one-to-one | one-to-many | many-to-many` 3종만 허용해, 문서대로
|
|
30
|
+
`many-to-one` 을 쓰면 `400 유효하지 않은 관계 타입` + TS 타입 에러가 났다.
|
|
31
|
+
|
|
32
|
+
- **`types/database.ts` — `RelationType`** 에 `'many-to-one'` 추가(4종 동등). additive 변경이라
|
|
33
|
+
하위호환. 백엔드(data-server)도 ent enum·populate(단일 객체) 동등 처리하도록 함께 수정됨.
|
|
34
|
+
|
|
35
|
+
### Fixed — `oauth.signIn` JSDoc 예시 정정
|
|
36
|
+
|
|
37
|
+
`createIfNotExists` 예시가 `callbackUrl` 자리에 클라이언트 인스턴스(`cb`)를 넘기는 오기였다.
|
|
38
|
+
실제 URL 문자열로 교정(런타임/타입 영향 없음, 문서만).
|
|
39
|
+
|
|
40
|
+
## [3.28.0] - 2026-06-02
|
|
41
|
+
|
|
42
|
+
### Added — `cb.ai.chatStream` 취소(AbortSignal) 지원 (platform-issue 019e82e1)
|
|
43
|
+
|
|
44
|
+
`chatStream(request, callbacks)` 에 진행 중인 스트림/서버측 agent tool loop 를 끊을 수단이
|
|
45
|
+
없어, "중단" 시 클라이언트 콜백만 무음 처리되고 SSE 연결과 서버 도구 루프는 계속 진행됐다
|
|
46
|
+
(토큰·도구 호출 비용 지속).
|
|
47
|
+
|
|
48
|
+
- **`api/ai.ts` — `chatStream(request, callbacks, options?)`** — 선택적 3번째 인자
|
|
49
|
+
`options?: { signal?: AbortSignal }` 추가. `signal` 을 fetch 에 그대로 전달해 abort 시
|
|
50
|
+
SSE 연결을 닫는다. 연결이 닫히면 서버의 요청 컨텍스트가 취소되어 agent tool loop 도 중단된다.
|
|
51
|
+
- **`types/ai.ts`** — `AIChatStreamCallbacks` 에 `onAbort?: () => void` 추가, `AIChatStreamOptions`
|
|
52
|
+
신규 export. abort 시 `onError` 가 아니라 `onAbort` 가 호출되고 reader 가 해제된다.
|
|
53
|
+
- 하위호환: 기존 2-인자 호출은 그대로 동작.
|
|
54
|
+
|
|
55
|
+
### Added — `cb.oauth.signIn` 의 `createIfNotExists` 옵션 (platform-issue 019e83b5)
|
|
56
|
+
|
|
57
|
+
`signIn` 은 기존 회원만 로그인하고 미가입 사용자는 콜백에서 `error=account_not_found` 로
|
|
58
|
+
반려된다(의도된 설계 — silent auto-signup 회귀 차단). 로그인=가입 통합 버튼을 한 호출로
|
|
59
|
+
처리하려는 경우를 위해 옵션을 추가했다.
|
|
60
|
+
|
|
61
|
+
- **`api/oauth.ts` — `signIn(provider, callbackUrl, state?, options?)`** — 선택적 4번째 인자
|
|
62
|
+
`options?: { createIfNotExists?: boolean }` 추가. `true` 면 `intent=signup` 으로 동작해
|
|
63
|
+
미가입 사용자를 자동 생성한다([signUp] 과 동일, idempotent). 백엔드 변경 없는 순수 passthrough.
|
|
64
|
+
- 하위호환: 기존 호출은 그대로 `signin` 의도.
|
|
65
|
+
|
|
6
66
|
## [3.27.0] - 2026-05-28
|
|
7
67
|
|
|
8
68
|
### Fixed — `signInAsGuestMember` 의 silent session overwrite 차단 + 게스트 식별 필드 노출 (platform-issue 019e6c5d)
|
package/dist/cli.js
CHANGED
|
@@ -1779,7 +1779,7 @@ async function registerEndpointBinding(baseUrl, appId, secretKey, tunnelId, labe
|
|
|
1779
1779
|
success(`Endpoint "${label}" \uC790\uB3D9 \uB4F1\uB85D \uC644\uB8CC`);
|
|
1780
1780
|
log(`${colors.green}\u2192${colors.reset} SDK: ${colors.cyan}cb.endpoint.call("${label}", { path: "/...", method: "POST", body: ... })${colors.reset}`);
|
|
1781
1781
|
} else if (res.status === 409) {
|
|
1782
|
-
warn(`"${label}" \uB77C\uBCA8\uC774 \
|
|
1782
|
+
warn(`"${label}" \uB77C\uBCA8\uC774 \uB2E4\uB978 \uD130\uB110\uC5D0 \uC774\uBBF8 \uBB36\uC5EC \uC788\uC2B5\uB2C8\uB2E4. \uC774 \uD130\uB110\uB85C \uC62E\uAE30\uB824\uBA74 \uCF58\uC194\uC5D0\uC11C endpoint \uC758 tunnel_id \uB97C \uC218\uC815(PATCH)\uD558\uC138\uC694.`);
|
|
1783
1783
|
} else {
|
|
1784
1784
|
const text = await res.text().catch(() => "");
|
|
1785
1785
|
error(`Endpoint "${label}" \uC790\uB3D9 \uB4F1\uB85D \uC2E4\uD328 (status ${res.status}): ${text || "(\uBE48 \uC751\uB2F5)"}`);
|
|
@@ -1867,6 +1867,9 @@ async function startTunnel(port, config, tunnelOpts) {
|
|
|
1867
1867
|
if (tunnelOpts?.public) {
|
|
1868
1868
|
wsPath += `&public=1`;
|
|
1869
1869
|
}
|
|
1870
|
+
if (tunnelOpts?.token) {
|
|
1871
|
+
wsPath += `&proxy_token=${encodeURIComponent(tunnelOpts.token)}`;
|
|
1872
|
+
}
|
|
1870
1873
|
let reconnectAttempts = 0;
|
|
1871
1874
|
const maxReconnectAttempts = 10;
|
|
1872
1875
|
let shouldReconnect = true;
|
|
@@ -2350,6 +2353,7 @@ ${colors.yellow}\uC635\uC158:${colors.reset}
|
|
|
2350
2353
|
--force \uD130\uB110 lockfile \uBB34\uC2DC (\uC911\uBCF5 \uC2E4\uD589 \uAC15\uC81C, tunnel \uC804\uC6A9)
|
|
2351
2354
|
--public proxy_token \uAC80\uC99D \uBE44\uD65C\uC131\uD654 \u2014 \uC6F9\uD6C5/\uC678\uBD80 \uC9C1\uC811 \uD638\uCD9C\uC6A9 (tunnel \uC804\uC6A9)
|
|
2352
2355
|
--show-token proxy_token \uACFC curl \uC608\uC2DC\uB97C \uCD9C\uB825 (--public \uC544\uB2CC \uACBD\uC6B0)
|
|
2356
|
+
--token <value> proxy_token \uACE0\uC815\uAC12 (16-128\uC790 [A-Za-z0-9_-]) \u2014 \uC7AC\uC5F0\uACB0\uC5D0\uB3C4 \uD1A0\uD070 \uD68C\uC804 \uBC29\uC9C0. \uC678\uBD80 MCP custom_header \uB4F1 \uC548\uC815 \uD1B5\uD569\uC6A9 (tunnel \uC804\uC6A9)
|
|
2353
2357
|
--label <name> Endpoint binding \uC790\uB3D9 \uB4F1\uB85D (tunnel \uC804\uC6A9) \u2014 SDK \uC758 cb.endpoint.call(label) \uD638\uCD9C \uAC00\uB2A5
|
|
2354
2358
|
--description <text> Endpoint binding \uC124\uBA85 (--label \uB3D9\uBC18 \uC2DC\uB9CC)
|
|
2355
2359
|
-d, --dev Dev \uD658\uACBD\uC5D0 \uBC30\uD3EC (deploy \uC804\uC6A9)
|
|
@@ -2429,6 +2433,8 @@ function parseArgs(args) {
|
|
|
2429
2433
|
result.options.label = args[++i];
|
|
2430
2434
|
} else if (arg === "--description") {
|
|
2431
2435
|
result.options.description = args[++i];
|
|
2436
|
+
} else if (arg === "--token") {
|
|
2437
|
+
result.options.token = args[++i];
|
|
2432
2438
|
} else if (arg === "-a" || arg === "--app") {
|
|
2433
2439
|
result.options.appId = args[++i];
|
|
2434
2440
|
} else if (arg === "--force") {
|
|
@@ -2548,6 +2554,13 @@ async function main() {
|
|
|
2548
2554
|
if (parsed.options.description) {
|
|
2549
2555
|
tunnelOpts.description = parsed.options.description;
|
|
2550
2556
|
}
|
|
2557
|
+
if (parsed.options.token) {
|
|
2558
|
+
if (!/^[A-Za-z0-9_-]{16,128}$/.test(parsed.options.token)) {
|
|
2559
|
+
error("--token \uC740 16-128\uC790\uC758 [A-Za-z0-9_-] \uC5EC\uC57C \uD569\uB2C8\uB2E4");
|
|
2560
|
+
process.exit(1);
|
|
2561
|
+
}
|
|
2562
|
+
tunnelOpts.token = parsed.options.token;
|
|
2563
|
+
}
|
|
2551
2564
|
await startTunnel(port, config, tunnelOpts);
|
|
2552
2565
|
} else {
|
|
2553
2566
|
error(`\uC54C \uC218 \uC5C6\uB294 \uBA85\uB839\uC5B4: ${parsed.command}`);
|