connectbase-client 1.8.0 → 1.9.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 CHANGED
@@ -3,6 +3,64 @@
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
+ ## [1.9.0] - 2026-04-24
7
+
8
+ 런타임 내구성·관측성 강화 릴리스. 공개 API 시그니처는 유지되며 모든 변경은 추가·하드닝 성격(비파괴).
9
+
10
+ ### Added — 요청 타임아웃 & AbortSignal
11
+
12
+ - `ConnectBaseConfig.requestTimeoutMs` — 모든 HTTP 호출의 기본 타임아웃(ms). 기본 30000ms, 0/음수 시 비활성.
13
+ - 개별 호출에서 `AbortOptions` (`signal`, `timeout`) 지원 — Storage presigned 업로드 등 장시간 호출을 외부에서 취소 가능.
14
+ - `core/abort.ts`: `createTimeoutController`, `DEFAULT_REQUEST_TIMEOUT_MS` 유틸.
15
+
16
+ ### Added — 전역 에러 관찰 훅
17
+
18
+ - `ConnectBaseConfig.onError` — 모든 `ApiError` / `AuthError` 발생 시 호출되는 옵저버. Sentry/Datadog 등 관측성 파이프라인 연결용.
19
+ - 429 응답 개선: `Retry-After` 헤더(초 또는 HTTP-date)를 파싱해 `ApiError.details.retry_after_seconds` 로 전달.
20
+
21
+ ### Added — 응답 shape 검증 (fail-fast)
22
+
23
+ - `core/validate.ts`: `assertShape` 도입. 서버가 필수 필드를 누락한 응답을 반환해도 즉시 throw 하여 이후 로직이 `undefined` 로 조용히 실패하지 않게 방어.
24
+ - 적용 지점: `auth.signInMember`, `auth.getMe`, `payment.createCheckoutSession`, `push.registerDevice`, `queue.consume`, `subscription.create`.
25
+
26
+ ### Added — Presigned URL 스킴 검증 (SSRF 하드닝)
27
+
28
+ - `core/url-validation.ts`: `validateExternalUrl`, `isLocalhostOrigin`.
29
+ - `StorageAPI` presigned PUT 호출 전에 URL 스킴(https)을 검증해 서버 응답을 맹신하는 경로를 차단. localhost 허용 여부는 런타임 오리진 기반으로 자동 결정.
30
+
31
+ ### Changed — 에러 타입 통일
32
+
33
+ - `FunctionsAPI.invokeAndWait`, `GameAPI.listRooms` / `getRoom` — `throw new Error(...)` → `throw new ApiError(status, message, code)`. `ApiError` 는 `Error` 를 상속하므로 `instanceof Error` / `.message` 로 잡던 기존 코드는 그대로 동작하며, 추가로 `error.code` / `error.statusCode` 로 분기 가능.
34
+ - `VideoAPI` 내부 `request<T>()` — 서버의 구조화 응답 `{ error: { code, message, details } }` 을 완전히 언랩해 `ApiError(status, message, code, details)` 로 변환. timeout 도 함께 적용.
35
+
36
+ ### Changed — Refresh 토큰 회복성
37
+
38
+ - `HttpClient` 에 지수 백오프 도입 — 연속 refresh 실패 시 500ms × 2^n (최대 30s) 동안 재요청을 차단해 서버에 실패 요청이 쏟아지는 회귀를 막는다. 성공 시 카운터 리셋.
39
+ - Refresh 요청 자체도 `requestTimeoutMs` 로 제한.
40
+
41
+ ### Changed — 로깅
42
+
43
+ - `RealtimeAPI`: 내부 `console.error` 를 `private logError()` 로 통일. `options.debug` opt-in 일 때만 출력되어 프로덕션 devtools 에 SDK 로그 노출이 0.
44
+
45
+ ### Docs
46
+
47
+ - `AnalyticsAPI.flush` / `getSession`, `VideoAPI.list` / `getStreamUrl` 에 상세 JSDoc + `@example` 추가.
48
+
49
+ ### Compatibility
50
+
51
+ - **Non-breaking**: 모든 공개 메서드 시그니처 동일. `Error` → `ApiError` 전환은 상속 관계상 기존 `catch (e: Error)` 경로에 영향 없음.
52
+ - **Runtime behavior change**: 서버가 필수 응답 필드를 누락하는 경우, 이전 버전은 `undefined` 로 조용히 진행했지만 1.9.0 은 즉시 throw 한다. 서버 응답이 정상이라면 차이 없음.
53
+
54
+ ## [1.8.1] - 2026-04-23
55
+
56
+ 문서 정합성 패치. SDK 런타임 동작은 1.8.0 과 동일합니다.
57
+
58
+ ### Changed — README
59
+
60
+ - `createData` 예제에 `DataItem` 반환 (id/created_at/updated_at 즉시 사용 가능) 설명 추가.
61
+ - `createMany` 예제 신설 — 반환 shape `{ created: DataItem[], total, success }` 명시.
62
+ - `updateData` 예제를 반환값을 받아 사용하는 형태로 정비.
63
+
6
64
  ## [1.8.0] - 2026-04-19
7
65
 
8
66
  웹 스토리지 CLI 배포(`connectbase deploy ./dist`) 를 manifest 기반 **증분 업로드** 로 재구성. 동일 dist 재배포는 거의 즉시 완료되고, 일부만 바뀐 경우 변경분만 전송한다. 서버 DB 쓰기도 단일 트랜잭션 + bulk insert 로 묶어 전체 배포 시간이 짧아짐.
package/README.md CHANGED
@@ -456,13 +456,20 @@ const { data } = await cb.database.getData('table-id', {
456
456
  limit: 20
457
457
  })
458
458
 
459
- // Insert data
459
+ // Insert data — returns the created DataItem (id + data + created_at + updated_at)
460
460
  const newItem = await cb.database.createData('table-id', {
461
461
  data: { name: 'John', email: 'john@example.com' }
462
462
  })
463
+ console.log(newItem.id) // use immediately for navigation / cache updates
463
464
 
464
- // Update data
465
- await cb.database.updateData('table-id', 'data-id', {
465
+ // Bulk insert — returns { created: DataItem[], total, success, failed? }
466
+ const bulk = await cb.database.createMany('table-id', [
467
+ { data: { name: 'User1' } },
468
+ { data: { name: 'User2' } }
469
+ ])
470
+
471
+ // Update data — returns the updated DataItem with merged fields
472
+ const updated = await cb.database.updateData('table-id', 'data-id', {
466
473
  data: { name: 'Jane' }
467
474
  })
468
475
 
@@ -885,20 +892,53 @@ interface ConnectionState {
885
892
  ## Error Handling
886
893
 
887
894
  ```typescript
895
+ import ConnectBase, { ApiError, AuthError } from 'connectbase-client'
896
+
888
897
  try {
889
- await gameClient.connect()
898
+ await cb.auth.signInMember({ email, password })
890
899
  } catch (error) {
891
- if (error instanceof Error) {
892
- console.error('Connection failed:', error.message)
900
+ if (error instanceof ApiError) {
901
+ // HTTP 응답 기반 에러: status/code/details 로 분기 가능
902
+ if (error.statusCode === 429) {
903
+ const details = error.details as { retry_after_seconds?: number } | undefined
904
+ const retryAfter = details?.retry_after_seconds
905
+ // ...
906
+ }
907
+ } else if (error instanceof AuthError) {
908
+ // refresh 실패/토큰 만료
893
909
  }
894
910
  }
895
911
 
896
- // Or use event handlers
912
+ // Game API 별도 이벤트 핸들러도 지원
897
913
  gameClient.on('onError', (error) => {
898
914
  console.error('Game error:', error.message)
899
915
  })
900
916
  ```
901
917
 
918
+ ### 전역 에러 관찰자 (v1.9.0+)
919
+
920
+ `ConnectBase` 초기화 시 `onError` 옵션을 주면 모든 `ApiError` / `AuthError` 가 한 곳으로 모입니다. Sentry/Datadog 등 관측성 툴과 연결하기 쉽습니다.
921
+
922
+ ```typescript
923
+ const cb = new ConnectBase({
924
+ publicKey: 'cb_pk_...',
925
+ onError: (error) => {
926
+ Sentry.captureException(error)
927
+ },
928
+ })
929
+ ```
930
+
931
+ ### 요청 타임아웃 (v1.9.0+)
932
+
933
+ 기본 30초 타임아웃이 모든 HTTP 호출에 적용됩니다. `requestTimeoutMs` 로 전역 기본값을 바꾸거나, 0 이하 값을 주면 비활성화할 수 있습니다.
934
+
935
+ ```typescript
936
+ const cb = new ConnectBase({
937
+ publicKey: 'cb_pk_...',
938
+ requestTimeoutMs: 60000, // 60s
939
+ })
940
+ ```
941
+
902
942
  ## Best Practices
903
943
 
904
944
  ### State Synchronization