connectbase-client 3.1.0 → 3.2.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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,60 @@
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.2.1] - 2026-04-29
7
+
8
+ ### Fixed — Docs
9
+
10
+ `cb.endpoint.url(label, path)` 의 README/JSDoc 예제와 CHANGELOG `[3.2.0]` 설명을
11
+ ConnectBase 프록시 인증 모델에 맞춰 정정. 코드 동작 변화 없음 (JSDoc / README /
12
+ CHANGELOG 만 수정).
13
+
14
+ - 3.2.0 의 `<img src={cb.endpoint.url(...)}>` / `new WebSocket(cb.endpoint.url(...))`
15
+ 예제는 실제로는 401 — `/v1/proxy/:label/*` 가 `X-Public-Key` 헤더를 강제하고
16
+ 쿼리 파라미터 폴백이 없어, 커스텀 헤더를 못 보내는 브라우저 네이티브 API
17
+ (`<img>`, native `WebSocket`, `<script src>`, `EventSource`) 는 인증 자체가
18
+ 불가능. 잘못된 시연 코드를 제거.
19
+ - 정정된 사용 사례:
20
+ - **이미지 렌더링**: `cb.endpoint.call(...)` 로 받아
21
+ `URL.createObjectURL(await res.blob())` 패턴 사용. 영구 URL 이 필요하면
22
+ `cb.storage.uploadByPath` 로 업로드.
23
+ - **URL 전달**: Service Worker / 백엔드 워커 / 커스텀 fetch wrapper 처럼 호출자가
24
+ `X-Public-Key` 헤더를 직접 부착할 수 있는 환경.
25
+ - **로깅·디버깅**: 라벨 → 최종 URL 매핑 확인.
26
+ - `EndpointAPI` 클래스 / `cb.endpoint.{call,url,pollUntil}` 동작은 3.2.0 과 동일.
27
+
28
+ ## [3.2.0] - 2026-04-29
29
+
30
+ ### Added — Endpoint API 헬퍼 (`pollUntil` / `url`)
31
+
32
+ ComfyUI × 웹스토리지 같은 e2e 통합 패턴 (작업 제출 → 폴링 → 결과 저장) 을
33
+ 단일 진입점으로 묶기 위한 헬퍼 2개. `cb.endpoint.call()` 만으로도 가능했지만
34
+ 사용자가 매번 직접 작성하던 보일러플레이트를 SDK 가 흡수.
35
+
36
+ - **`cb.endpoint.pollUntil<T>(label, init, predicate, opts)`** — long-poll 한 줄
37
+ 처리. ComfyUI `/history/{id}`, A1111 `/sdapi/v1/progress`, 자체 큐 API 처럼
38
+ "작업 제출 → 폴링" 패턴 전용. `predicate` 가 값을 반환할 때까지 반복 호출,
39
+ HTTP 5xx/네트워크 오류는 재시도, 4xx 는 즉시 reject, `AbortSignal`/`timeoutMs`
40
+ 지원. `parse: "json" | "text" | "none"` 으로 본문 파싱 방식 선택.
41
+ - **`cb.endpoint.url(label, path)`** — 라벨 + path 의 최종 호출 URL
42
+ (`${baseUrl}/v1/proxy/${label}${path}`) 만 조립해서 반환. URL 을 Service
43
+ Worker / 백엔드 워커로 넘기거나 로깅·디버깅 용도. ⚠️ `<img src>` / 네이티브
44
+ `WebSocket` / `<script src>` / `EventSource` 처럼 커스텀 헤더를 못 보내는
45
+ 브라우저 API 에 직접 넘기면 401 — ConnectBase 프록시는 항상 `X-Public-Key`
46
+ 헤더를 요구하고 쿼리 파라미터 폴백이 없음. 그 경우엔 `call()` 로 받아
47
+ `URL.createObjectURL(await res.blob())` 패턴 사용.
48
+ - 신규 export: `PollUntilOptions` 타입.
49
+
50
+ ### Docs
51
+
52
+ - `examples/ai-image-generator/` — UMD CDN 한 줄 + 빌드 도구 0 으로 동작하는
53
+ ComfyUI × 웹스토리지 스타터. SDK 로딩 실패 감지, pre-flight 키 검증, 모든
54
+ KSampler seed 랜덤화, cache-bust 워크플로우 fetch, AbortController 일괄 취소,
55
+ step indicator, localStorage 갤러리, ⌘/Ctrl+Enter 단축키 등 11가지
56
+ 베스트프랙티스 채택.
57
+ - `docs/integration/comfyui-web-storage.md` — e2e 통합 가이드 + "왜 이 구조가
58
+ 정답인가" / "안티패턴 7가지".
59
+
6
60
  ## [3.1.0] - 2026-04-29
7
61
 
8
62
  ### Added — Endpoint API (로컬 모델 터널 dumb pipe)
package/README.md CHANGED
@@ -883,6 +883,89 @@ The SDK assembles the URL as `${baseUrl}/v1/proxy/${label}${path}` and forwards
883
883
  the request. Because the response is the raw `fetch` `Response`, streaming
884
884
  formats (SSE, chunked, NDJSON) work out of the box.
885
885
 
886
+ #### `cb.endpoint.pollUntil<T>(label, init, predicate, opts?): Promise<T>`
887
+
888
+ One-line "submit job → poll for result" pattern. Repeatedly calls the same
889
+ endpoint until `predicate` returns a value. Designed for ComfyUI `/history/{id}`,
890
+ A1111 `/sdapi/v1/progress`, or any custom queue API.
891
+
892
+ Behavior:
893
+ - Calls `cb.endpoint.call(label, init)` and passes the parsed body to `predicate`
894
+ - Returns `undefined` from `predicate` → wait `intervalMs` and retry
895
+ - Returns a value from `predicate` → resolve immediately with that value
896
+ - HTTP `5xx` / network error → retry. HTTP `4xx` → reject (job-level error)
897
+ - `timeoutMs` exceeded or `signal` aborted → reject
898
+
899
+ ```typescript
900
+ type Hist = Record<
901
+ string,
902
+ { outputs: Record<string, { images?: { filename: string }[] }> }
903
+ >
904
+
905
+ const filename = await cb.endpoint.pollUntil<string>(
906
+ 'comfyui-main',
907
+ { path: `/history/${promptId}` },
908
+ (data: Hist) => {
909
+ const entry = data[promptId]
910
+ if (!entry) return undefined // still queued
911
+ for (const out of Object.values(entry.outputs)) {
912
+ const img = out.images?.[0]
913
+ if (img) return img.filename
914
+ }
915
+ return undefined
916
+ },
917
+ { intervalMs: 1000, timeoutMs: 5 * 60_000 },
918
+ )
919
+ ```
920
+
921
+ **`PollUntilOptions`**
922
+
923
+ | Field | Type | Default | Description |
924
+ |-------|------|---------|-------------|
925
+ | `intervalMs` | `number` | `1500` | Poll interval in ms |
926
+ | `timeoutMs` | `number` | `300000` (5 min) | Total timeout in ms — reject if exceeded |
927
+ | `parse` | `'json' \| 'text' \| 'none'` | `'json'` | Body parser. `'json'` falls back to `undefined` on parse error |
928
+ | `signal` | `AbortSignal` | — | External cancel signal — reject immediately on abort |
929
+
930
+ #### `cb.endpoint.url(label, path): string`
931
+
932
+ Returns the assembled call URL (`${baseUrl}/v1/proxy/${label}${path}`) for
933
+ URL-passing scenarios where you control the request and can attach the
934
+ `X-Public-Key` header yourself.
935
+
936
+ ⚠️ **Browser-native APIs that cannot set custom headers will fail with `401`.**
937
+ ConnectBase's proxy requires `X-Public-Key` on every call (header-only — no
938
+ `?api_key=` fallback), so `<img src>`, `new Image()`, native `WebSocket`,
939
+ `<script src>`, EventSource, etc. **cannot authenticate** through this URL.
940
+ Use `cb.endpoint.call()` instead for those cases:
941
+
942
+ ```typescript
943
+ // ✅ Render an image: download via call(), then convert to a blob URL
944
+ const res = await cb.endpoint.call('comfyui-main', {
945
+ path: `/view?filename=${encodeURIComponent(name)}`,
946
+ })
947
+ img.src = URL.createObjectURL(await res.blob())
948
+ // ...later: URL.revokeObjectURL(img.src)
949
+ ```
950
+
951
+ For permanent images (works across CDN, survives tunnel restarts), upload the
952
+ blob to `cb.storage` and use `saved.url` — see
953
+ [`examples/ai-image-generator/`](https://github.com/connectbase-world/connectbase/tree/release/examples/ai-image-generator).
954
+
955
+ When `cb.endpoint.url()` IS the right tool:
956
+
957
+ - Logging / debugging the resolved tunnel URL
958
+ - Passing the URL to a backend service or worker that will make the call with proper headers
959
+ - Building a `RequestInfo` for a custom `fetch()` wrapper (you control headers)
960
+
961
+ ```typescript
962
+ console.log(cb.endpoint.url('comfyui-main', '/prompt'))
963
+ // → https://api.connectbase.world/v1/proxy/comfyui-main/prompt
964
+
965
+ // Hand the URL to a Service Worker that injects X-Public-Key
966
+ sw.postMessage({ url: cb.endpoint.url('comfyui-main', '/prompt'), key: PK })
967
+ ```
968
+
886
969
  ### Push Notifications
887
970
 
888
971
  ```typescript