connectbase-client 5.12.0 → 5.12.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/dist/index.d.mts CHANGED
@@ -7154,39 +7154,6 @@ interface ReadReceiptInfo {
7154
7154
  /** 읽음 확인 핸들러 */
7155
7155
  type ReadReceiptHandler = (receipt: ReadReceiptInfo) => void;
7156
7156
 
7157
- /**
7158
- * Realtime API
7159
- * WebSocket 기반 실시간 통신 API
7160
- *
7161
- * @example
7162
- * ```typescript
7163
- * // 연결
7164
- * await client.realtime.connect()
7165
- *
7166
- * // 카테고리 구독
7167
- * const chat = await client.realtime.subscribe('chat-room-1')
7168
- *
7169
- * // 메시지 수신
7170
- * chat.onMessage((msg) => {
7171
- * console.log('Received:', msg.data)
7172
- * })
7173
- *
7174
- * // 메시지 전송
7175
- * await chat.send({ text: 'Hello!' })
7176
- *
7177
- * // 히스토리 조회 (persist=true인 카테고리만)
7178
- * if (chat.info.persist) {
7179
- * const history = await chat.getHistory(50)
7180
- * console.log('History:', history.messages)
7181
- * }
7182
- *
7183
- * // 구독 해제
7184
- * await chat.unsubscribe()
7185
- *
7186
- * // 연결 해제
7187
- * client.realtime.disconnect()
7188
- * ```
7189
- */
7190
7157
  declare class RealtimeAPI {
7191
7158
  private http;
7192
7159
  private socketUrl;
package/dist/index.d.ts CHANGED
@@ -7154,39 +7154,6 @@ interface ReadReceiptInfo {
7154
7154
  /** 읽음 확인 핸들러 */
7155
7155
  type ReadReceiptHandler = (receipt: ReadReceiptInfo) => void;
7156
7156
 
7157
- /**
7158
- * Realtime API
7159
- * WebSocket 기반 실시간 통신 API
7160
- *
7161
- * @example
7162
- * ```typescript
7163
- * // 연결
7164
- * await client.realtime.connect()
7165
- *
7166
- * // 카테고리 구독
7167
- * const chat = await client.realtime.subscribe('chat-room-1')
7168
- *
7169
- * // 메시지 수신
7170
- * chat.onMessage((msg) => {
7171
- * console.log('Received:', msg.data)
7172
- * })
7173
- *
7174
- * // 메시지 전송
7175
- * await chat.send({ text: 'Hello!' })
7176
- *
7177
- * // 히스토리 조회 (persist=true인 카테고리만)
7178
- * if (chat.info.persist) {
7179
- * const history = await chat.getHistory(50)
7180
- * console.log('History:', history.messages)
7181
- * }
7182
- *
7183
- * // 구독 해제
7184
- * await chat.unsubscribe()
7185
- *
7186
- * // 연결 해제
7187
- * client.realtime.disconnect()
7188
- * ```
7189
- */
7190
7157
  declare class RealtimeAPI {
7191
7158
  private http;
7192
7159
  private socketUrl;
package/dist/index.js CHANGED
@@ -7209,6 +7209,7 @@ var QueueAPI = class {
7209
7209
  };
7210
7210
 
7211
7211
  // src/api/realtime.ts
7212
+ var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
7212
7213
  var RealtimeAPI = class {
7213
7214
  constructor(http, socketUrl) {
7214
7215
  this.ws = null;
@@ -7286,6 +7287,11 @@ var RealtimeAPI = class {
7286
7287
  if (options.userId) {
7287
7288
  this.userId = options.userId;
7288
7289
  }
7290
+ if (this.userId && !this.options.accessToken && UUID_RE.test(this.userId)) {
7291
+ throw new Error(
7292
+ `Invalid userId: "${this.userId}" looks like a UUID, which is reserved for authenticated members. Pass that member's accessToken (JWT) instead of userId+publicKey, or use a non-UUID identifier for anonymous/guest connections.`
7293
+ );
7294
+ }
7289
7295
  this.connectPromise = this.doConnect();
7290
7296
  try {
7291
7297
  await this.connectPromise;
@@ -7305,6 +7311,7 @@ var RealtimeAPI = class {
7305
7311
  * (degraded) AI stream() 이 SSE 로 동작하게 한다. 백그라운드 WS 재연결 머신은 정지한다.
7306
7312
  */
7307
7313
  activateSseFallback(cause) {
7314
+ if (this.sseFallbackActive) return;
7308
7315
  if (this.ws) {
7309
7316
  try {
7310
7317
  this.ws.close();
@@ -7312,14 +7319,20 @@ var RealtimeAPI = class {
7312
7319
  }
7313
7320
  this.ws = null;
7314
7321
  }
7322
+ const causeMsg = cause instanceof Error ? cause.message : String(cause);
7315
7323
  this.sseFallbackActive = true;
7316
7324
  this.activeTransport = "sse";
7317
7325
  this.state = "connected";
7318
7326
  this.retryCount = 0;
7319
7327
  this.log(
7320
- `WS unavailable (${cause instanceof Error ? cause.message : String(cause)}); using SSE fallback transport for AI streaming`
7328
+ `WS unavailable (${causeMsg}); using SSE fallback transport for AI streaming`
7321
7329
  );
7322
7330
  this.notifyStateChange();
7331
+ this.notifyError(
7332
+ new Error(
7333
+ `Realtime WebSocket unavailable, downgraded to SSE fallback transport (cb.realtime.transport === 'sse'). Only realtime.stream() works in this mode \u2014 subscribe/send/setPresence/typing calls will throw. Cause: ${causeMsg}`
7334
+ )
7335
+ );
7323
7336
  }
7324
7337
  /**
7325
7338
  * 연결 해제
@@ -11658,7 +11671,7 @@ var HttpClient = class {
11658
11671
  if (this.persistence !== "none") return;
11659
11672
  if (!this.config.refreshToken) return;
11660
11673
  try {
11661
- await this.refreshAccessToken();
11674
+ await this.refreshAccessToken({ silent: true });
11662
11675
  } catch {
11663
11676
  }
11664
11677
  }
@@ -11791,7 +11804,8 @@ var HttpClient = class {
11791
11804
  getAppId() {
11792
11805
  return this.config.appId;
11793
11806
  }
11794
- async refreshAccessToken() {
11807
+ async refreshAccessToken(options) {
11808
+ const silent = options?.silent ?? false;
11795
11809
  if (this.isRefreshing) {
11796
11810
  return this.refreshPromise;
11797
11811
  }
@@ -11905,27 +11919,35 @@ var HttpClient = class {
11905
11919
  );
11906
11920
  this.refreshLockedUntil = Date.now() + backoffMs;
11907
11921
  if (failureKind === "permanent") {
11908
- this.clearTokens();
11909
- this.config.onTokenExpired?.();
11922
+ if (!silent) {
11923
+ this.clearTokens();
11924
+ this.config.onTokenExpired?.();
11925
+ }
11910
11926
  const error2 = new AuthError(`${baseMsg}. Please login again.`);
11911
- this.emitError(error2);
11912
- this.config.onAuthError?.(error2);
11927
+ if (!silent) {
11928
+ this.emitError(error2);
11929
+ this.config.onAuthError?.(error2);
11930
+ }
11913
11931
  throw error2;
11914
11932
  }
11915
11933
  if (failureKind === "client_bug") {
11916
11934
  const error2 = new AuthError(
11917
11935
  `${baseMsg}. Client request invalid; tokens preserved.`
11918
11936
  );
11919
- this.emitError(error2);
11920
- this.config.onAuthError?.(error2);
11937
+ if (!silent) {
11938
+ this.emitError(error2);
11939
+ this.config.onAuthError?.(error2);
11940
+ }
11921
11941
  throw error2;
11922
11942
  }
11923
11943
  const error = new AuthError(
11924
11944
  `${baseMsg}. Transient failure; tokens preserved, will retry after backoff.`
11925
11945
  );
11926
- this.emitError(error);
11927
- this.config.onTransientRefreshFailure?.(error);
11928
- this.config.onAuthError?.(error);
11946
+ if (!silent) {
11947
+ this.emitError(error);
11948
+ this.config.onTransientRefreshFailure?.(error);
11949
+ this.config.onAuthError?.(error);
11950
+ }
11929
11951
  throw error;
11930
11952
  } finally {
11931
11953
  cleanup();
package/dist/index.mjs CHANGED
@@ -7160,6 +7160,7 @@ var QueueAPI = class {
7160
7160
  };
7161
7161
 
7162
7162
  // src/api/realtime.ts
7163
+ var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
7163
7164
  var RealtimeAPI = class {
7164
7165
  constructor(http, socketUrl) {
7165
7166
  this.ws = null;
@@ -7237,6 +7238,11 @@ var RealtimeAPI = class {
7237
7238
  if (options.userId) {
7238
7239
  this.userId = options.userId;
7239
7240
  }
7241
+ if (this.userId && !this.options.accessToken && UUID_RE.test(this.userId)) {
7242
+ throw new Error(
7243
+ `Invalid userId: "${this.userId}" looks like a UUID, which is reserved for authenticated members. Pass that member's accessToken (JWT) instead of userId+publicKey, or use a non-UUID identifier for anonymous/guest connections.`
7244
+ );
7245
+ }
7240
7246
  this.connectPromise = this.doConnect();
7241
7247
  try {
7242
7248
  await this.connectPromise;
@@ -7256,6 +7262,7 @@ var RealtimeAPI = class {
7256
7262
  * (degraded) AI stream() 이 SSE 로 동작하게 한다. 백그라운드 WS 재연결 머신은 정지한다.
7257
7263
  */
7258
7264
  activateSseFallback(cause) {
7265
+ if (this.sseFallbackActive) return;
7259
7266
  if (this.ws) {
7260
7267
  try {
7261
7268
  this.ws.close();
@@ -7263,14 +7270,20 @@ var RealtimeAPI = class {
7263
7270
  }
7264
7271
  this.ws = null;
7265
7272
  }
7273
+ const causeMsg = cause instanceof Error ? cause.message : String(cause);
7266
7274
  this.sseFallbackActive = true;
7267
7275
  this.activeTransport = "sse";
7268
7276
  this.state = "connected";
7269
7277
  this.retryCount = 0;
7270
7278
  this.log(
7271
- `WS unavailable (${cause instanceof Error ? cause.message : String(cause)}); using SSE fallback transport for AI streaming`
7279
+ `WS unavailable (${causeMsg}); using SSE fallback transport for AI streaming`
7272
7280
  );
7273
7281
  this.notifyStateChange();
7282
+ this.notifyError(
7283
+ new Error(
7284
+ `Realtime WebSocket unavailable, downgraded to SSE fallback transport (cb.realtime.transport === 'sse'). Only realtime.stream() works in this mode \u2014 subscribe/send/setPresence/typing calls will throw. Cause: ${causeMsg}`
7285
+ )
7286
+ );
7274
7287
  }
7275
7288
  /**
7276
7289
  * 연결 해제
@@ -11609,7 +11622,7 @@ var HttpClient = class {
11609
11622
  if (this.persistence !== "none") return;
11610
11623
  if (!this.config.refreshToken) return;
11611
11624
  try {
11612
- await this.refreshAccessToken();
11625
+ await this.refreshAccessToken({ silent: true });
11613
11626
  } catch {
11614
11627
  }
11615
11628
  }
@@ -11742,7 +11755,8 @@ var HttpClient = class {
11742
11755
  getAppId() {
11743
11756
  return this.config.appId;
11744
11757
  }
11745
- async refreshAccessToken() {
11758
+ async refreshAccessToken(options) {
11759
+ const silent = options?.silent ?? false;
11746
11760
  if (this.isRefreshing) {
11747
11761
  return this.refreshPromise;
11748
11762
  }
@@ -11856,27 +11870,35 @@ var HttpClient = class {
11856
11870
  );
11857
11871
  this.refreshLockedUntil = Date.now() + backoffMs;
11858
11872
  if (failureKind === "permanent") {
11859
- this.clearTokens();
11860
- this.config.onTokenExpired?.();
11873
+ if (!silent) {
11874
+ this.clearTokens();
11875
+ this.config.onTokenExpired?.();
11876
+ }
11861
11877
  const error2 = new AuthError(`${baseMsg}. Please login again.`);
11862
- this.emitError(error2);
11863
- this.config.onAuthError?.(error2);
11878
+ if (!silent) {
11879
+ this.emitError(error2);
11880
+ this.config.onAuthError?.(error2);
11881
+ }
11864
11882
  throw error2;
11865
11883
  }
11866
11884
  if (failureKind === "client_bug") {
11867
11885
  const error2 = new AuthError(
11868
11886
  `${baseMsg}. Client request invalid; tokens preserved.`
11869
11887
  );
11870
- this.emitError(error2);
11871
- this.config.onAuthError?.(error2);
11888
+ if (!silent) {
11889
+ this.emitError(error2);
11890
+ this.config.onAuthError?.(error2);
11891
+ }
11872
11892
  throw error2;
11873
11893
  }
11874
11894
  const error = new AuthError(
11875
11895
  `${baseMsg}. Transient failure; tokens preserved, will retry after backoff.`
11876
11896
  );
11877
- this.emitError(error);
11878
- this.config.onTransientRefreshFailure?.(error);
11879
- this.config.onAuthError?.(error);
11897
+ if (!silent) {
11898
+ this.emitError(error);
11899
+ this.config.onTransientRefreshFailure?.(error);
11900
+ this.config.onAuthError?.(error);
11901
+ }
11880
11902
  throw error;
11881
11903
  } finally {
11882
11904
  cleanup();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "connectbase-client",
3
- "version": "5.12.0",
3
+ "version": "5.12.2",
4
4
  "description": "Connect Base JavaScript/TypeScript SDK for browser and Node.js",
5
5
  "repository": {
6
6
  "type": "git",