connectbase-client 1.8.1 → 1.9.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/dist/index.d.mts CHANGED
@@ -13,6 +13,11 @@ declare class AuthError extends Error {
13
13
  constructor(message: string);
14
14
  }
15
15
 
16
+ interface AbortOptions {
17
+ timeout?: number;
18
+ signal?: AbortSignal;
19
+ }
20
+
16
21
  type TokenPersistence = 'localStorage' | 'sessionStorage' | 'none';
17
22
  interface HttpClientConfig {
18
23
  baseUrl: string;
@@ -39,6 +44,16 @@ interface HttpClientConfig {
39
44
  * - 'localStorage': 브라우저 종료 후에도 유지. JS 접근 가능 → XSS 로 영구 탈취 가능
40
45
  */
41
46
  persistence?: TokenPersistence;
47
+ /**
48
+ * 요청별 기본 타임아웃(ms). 개별 호출의 `timeout` 이 우선.
49
+ * 기본값 30000ms. 0 또는 음수 지정 시 타임아웃 비활성화.
50
+ */
51
+ requestTimeoutMs?: number;
52
+ /**
53
+ * 전역 에러 관찰자. 모든 ApiError/AuthError 발생 시 호출된다.
54
+ * 운영 관측성(Sentry/Datadog/자체 엔드포인트)과 연결하기 위한 훅.
55
+ */
56
+ onError?: (error: ApiError | AuthError) => void;
42
57
  onTokenRefresh?: (tokens: {
43
58
  accessToken: string;
44
59
  refreshToken: string;
@@ -46,7 +61,7 @@ interface HttpClientConfig {
46
61
  onAuthError?: (error: AuthError) => void;
47
62
  onTokenExpired?: () => void;
48
63
  }
49
- interface RequestConfig {
64
+ interface RequestConfig extends AbortOptions {
50
65
  skipAuth?: boolean;
51
66
  headers?: Record<string, string>;
52
67
  }
@@ -55,6 +70,8 @@ declare class HttpClient {
55
70
  private isRefreshing;
56
71
  private refreshPromise;
57
72
  private storageKey;
73
+ private refreshFailureCount;
74
+ private refreshLockedUntil;
58
75
  constructor(config: HttpClientConfig);
59
76
  private warnIfUnsafePersistence;
60
77
  updateConfig(config: Partial<HttpClientConfig>): void;
@@ -104,9 +121,14 @@ declare class HttpClient {
104
121
  */
105
122
  getBaseUrl(): string;
106
123
  private refreshAccessToken;
124
+ private emitError;
107
125
  private isTokenExpired;
108
126
  private prepareHeaders;
109
127
  private handleResponse;
128
+ /**
129
+ * AbortController 를 관리하며 fetch 호출을 실행. 타임아웃/외부 signal 병합.
130
+ */
131
+ private doFetch;
110
132
  get<T>(url: string, config?: RequestConfig): Promise<T>;
111
133
  post<T>(url: string, data?: unknown, config?: RequestConfig): Promise<T>;
112
134
  put<T>(url: string, data: unknown, config?: RequestConfig): Promise<T>;
@@ -114,7 +136,8 @@ declare class HttpClient {
114
136
  delete<T>(url: string, config?: RequestConfig): Promise<T>;
115
137
  /**
116
138
  * Raw fetch 요청 (SSE 스트리밍 등에 사용)
117
- * 인증 헤더가 자동으로 추가됩니다.
139
+ * 인증 헤더가 자동으로 추가됩니다. timeout 은 호출자가 직접 signal 로 관리해야 합니다
140
+ * (스트리밍 특성상 전역 timeout 을 강제하지 않음).
118
141
  */
119
142
  fetchRaw(url: string, init?: RequestInit): Promise<Response>;
120
143
  }
@@ -230,9 +253,31 @@ declare class AnalyticsAPI {
230
253
  * 세션 heartbeat 자동 전송 시작 (30초 간격)
231
254
  */
232
255
  enableHeartbeat(): void;
233
- /** 큐에 있는 이벤트 즉시 전송 */
256
+ /**
257
+ * 큐에 있는 이벤트 즉시 전송.
258
+ *
259
+ * 기본적으로 이벤트는 배치(10개) 또는 주기(5초)로 flush 되지만, 페이지 이탈 직전이나
260
+ * 결정적 이벤트(결제 완료 등)는 수동으로 `flush()` 를 호출해 전송 지연을 줄일 수 있다.
261
+ *
262
+ * @returns 서버 응답 완료 시까지 대기하는 Promise
263
+ *
264
+ * @example
265
+ * ```ts
266
+ * // 결제 완료 직후 이탈에 대비해 즉시 flush
267
+ * await cb.analytics.track('purchase_completed', { order_id: '123' })
268
+ * await cb.analytics.flush()
269
+ * window.location.href = '/thank-you'
270
+ * ```
271
+ */
234
272
  flush(): Promise<void>;
235
- /** 세션 매니저 접근 (고급) */
273
+ /**
274
+ * 세션 매니저 접근 (고급 사용자용).
275
+ *
276
+ * 외부에서 세션 ID 를 읽어 자체 로깅에 합치거나 강제 세션 종료/재시작이 필요한 경우
277
+ * 사용. 일반적으로는 AnalyticsAPI 가 내부적으로 세션을 관리하므로 호출할 필요가 없다.
278
+ *
279
+ * @returns 내부 SessionManager 인스턴스
280
+ */
236
281
  getSession(): SessionManager;
237
282
  private canTrack;
238
283
  private isDNT;
@@ -1864,6 +1909,12 @@ declare class StorageAPI {
1864
1909
  * API Key 인증 시 /v1/public 접두사 반환
1865
1910
  */
1866
1911
  private getPublicPrefix;
1912
+ /**
1913
+ * Presigned URL 로 직접 업로드. 호출 전에 URL 스킴(https)을 검증해
1914
+ * 서버 응답을 그대로 신뢰하는 SSRF/오용 경로를 차단.
1915
+ * 타임아웃과 외부 signal 을 모두 지원한다.
1916
+ */
1917
+ private uploadToPresigned;
1867
1918
  /**
1868
1919
  * 파일 목록 조회
1869
1920
  *
@@ -2735,6 +2786,12 @@ declare class RealtimeAPI {
2735
2786
  onReadReceipt(category: string, handler: ReadReceiptHandler): () => void;
2736
2787
  private doConnect;
2737
2788
  private log;
2789
+ /**
2790
+ * 에러 로그. `options.debug` 가 true 일 때만 console 에 출력.
2791
+ * 운영 환경에서는 소비자 애플리케이션의 `ConnectBase({ onError })` 또는
2792
+ * `cb.errorTracker` 로 전달하는 것을 권장하므로 SDK 자체 console 출력은 opt-in.
2793
+ */
2794
+ private logError;
2738
2795
  private handleServerMessage;
2739
2796
  private handleDisconnect;
2740
2797
  /**
@@ -4509,7 +4566,29 @@ declare class VideoAPI {
4509
4566
  */
4510
4567
  waitForReady(videoId: string, options?: WaitOptions): Promise<Video>;
4511
4568
  /**
4512
- * List videos
4569
+ * 영상 목록 조회.
4570
+ *
4571
+ * 필터링/페이지네이션 옵션을 조합해 조건에 맞는 영상들을 반환한다.
4572
+ * API Key(publicKey) 또는 JWT 인증이 모두 지원되며, publicKey 로는 공개 영상만 노출된다.
4573
+ *
4574
+ * @param options - 필터/페이지네이션 옵션
4575
+ * @param options.status - `uploading` | `processing` | `ready` | `failed`
4576
+ * @param options.visibility - `public` | `unlisted` | `private` | `members`
4577
+ * @param options.search - 제목 부분 일치 검색
4578
+ * @param options.channel_id - 특정 채널로 한정
4579
+ * @param options.page - 1 부터 시작
4580
+ * @param options.limit - 기본 20, 최대 100
4581
+ * @returns `videos` 배열과 `total` 카운트를 포함하는 응답
4582
+ *
4583
+ * @example
4584
+ * ```ts
4585
+ * // 내 채널의 최근 공개 영상 10개
4586
+ * const { videos, total } = await cb.video.list({
4587
+ * channel_id: 'ch_abc',
4588
+ * visibility: 'public',
4589
+ * limit: 10,
4590
+ * })
4591
+ * ```
4513
4592
  */
4514
4593
  list(options?: VideoListOptions): Promise<VideoListResponse>;
4515
4594
  /**
@@ -4525,7 +4604,20 @@ declare class VideoAPI {
4525
4604
  */
4526
4605
  delete(videoId: string): Promise<void>;
4527
4606
  /**
4528
- * Get streaming URL for a video
4607
+ * 영상 스트리밍 URL 획득 (HLS manifest 권장).
4608
+ *
4609
+ * 반환된 URL 은 `hls.js` 또는 Safari 네이티브 HLS 플레이어에 그대로 전달 가능하다.
4610
+ * 서명된 URL 이므로 만료 시간이 존재하며, 갱신이 필요한 경우 다시 호출한다.
4611
+ *
4612
+ * @param videoId - 대상 영상 ID
4613
+ * @param quality - `auto` (기본) | `1080p` | `720p` | `480p` | `360p` 등 트랜스코딩된 품질 레벨
4614
+ * @returns HLS manifest URL 과 만료 정보
4615
+ *
4616
+ * @example
4617
+ * ```ts
4618
+ * const { url, expires_at } = await cb.video.getStreamUrl(videoId, '720p')
4619
+ * videoElement.src = url
4620
+ * ```
4529
4621
  */
4530
4622
  getStreamUrl(videoId: string, quality?: string): Promise<StreamURLResponse>;
4531
4623
  /**
@@ -6622,16 +6714,34 @@ interface ConnectBaseConfig {
6622
6714
  onTokenExpired?: () => void;
6623
6715
  /**
6624
6716
  * 토큰 저장 방식.
6625
- * - 'localStorage': 브라우저 종료 후에도 유지 (기본값)
6626
- * - 'sessionStorage': 탭 종료 시 삭제
6627
- * - 'none': 메모리에만 저장 (페이지 새로고침 삭제)
6628
- * @default 'localStorage'
6717
+ * - 'none' (기본·권장): 메모리에만 저장. 새로고침 재로그인 필요. XSS 노출 최소화
6718
+ * - 'sessionStorage': 탭 종료 시 삭제 (XSS 시 현재 탭 세션 탈취 가능)
6719
+ * - 'localStorage': 브라우저 종료 후에도 유지 (XSS토큰 영구 탈취 가능 — 콘솔 경고 출력)
6720
+ * @default 'none'
6629
6721
  */
6630
6722
  persistence?: TokenPersistence;
6631
6723
  /**
6632
6724
  * 에러 트래커 설정
6633
6725
  */
6634
6726
  errorTracker?: ErrorTrackerConfig;
6727
+ /**
6728
+ * 기본 요청 타임아웃(ms). 개별 호출의 `timeout` 이 지정되면 해당 값이 우선.
6729
+ * 기본값 30000ms. 0 또는 음수 지정 시 타임아웃 비활성화.
6730
+ */
6731
+ requestTimeoutMs?: number;
6732
+ /**
6733
+ * 전역 에러 관찰자. 모든 `ApiError` / `AuthError` 발생 시 호출됩니다.
6734
+ * Sentry/Datadog 등 관측성 파이프라인과 연결하기 위한 훅.
6735
+ *
6736
+ * @example
6737
+ * ```ts
6738
+ * const cb = new ConnectBase({
6739
+ * publicKey: '...',
6740
+ * onError: (err) => Sentry.captureException(err),
6741
+ * })
6742
+ * ```
6743
+ */
6744
+ onError?: (error: ApiError | AuthError) => void;
6635
6745
  }
6636
6746
  /**
6637
6747
  * Connect Base SDK
package/dist/index.d.ts CHANGED
@@ -13,6 +13,11 @@ declare class AuthError extends Error {
13
13
  constructor(message: string);
14
14
  }
15
15
 
16
+ interface AbortOptions {
17
+ timeout?: number;
18
+ signal?: AbortSignal;
19
+ }
20
+
16
21
  type TokenPersistence = 'localStorage' | 'sessionStorage' | 'none';
17
22
  interface HttpClientConfig {
18
23
  baseUrl: string;
@@ -39,6 +44,16 @@ interface HttpClientConfig {
39
44
  * - 'localStorage': 브라우저 종료 후에도 유지. JS 접근 가능 → XSS 로 영구 탈취 가능
40
45
  */
41
46
  persistence?: TokenPersistence;
47
+ /**
48
+ * 요청별 기본 타임아웃(ms). 개별 호출의 `timeout` 이 우선.
49
+ * 기본값 30000ms. 0 또는 음수 지정 시 타임아웃 비활성화.
50
+ */
51
+ requestTimeoutMs?: number;
52
+ /**
53
+ * 전역 에러 관찰자. 모든 ApiError/AuthError 발생 시 호출된다.
54
+ * 운영 관측성(Sentry/Datadog/자체 엔드포인트)과 연결하기 위한 훅.
55
+ */
56
+ onError?: (error: ApiError | AuthError) => void;
42
57
  onTokenRefresh?: (tokens: {
43
58
  accessToken: string;
44
59
  refreshToken: string;
@@ -46,7 +61,7 @@ interface HttpClientConfig {
46
61
  onAuthError?: (error: AuthError) => void;
47
62
  onTokenExpired?: () => void;
48
63
  }
49
- interface RequestConfig {
64
+ interface RequestConfig extends AbortOptions {
50
65
  skipAuth?: boolean;
51
66
  headers?: Record<string, string>;
52
67
  }
@@ -55,6 +70,8 @@ declare class HttpClient {
55
70
  private isRefreshing;
56
71
  private refreshPromise;
57
72
  private storageKey;
73
+ private refreshFailureCount;
74
+ private refreshLockedUntil;
58
75
  constructor(config: HttpClientConfig);
59
76
  private warnIfUnsafePersistence;
60
77
  updateConfig(config: Partial<HttpClientConfig>): void;
@@ -104,9 +121,14 @@ declare class HttpClient {
104
121
  */
105
122
  getBaseUrl(): string;
106
123
  private refreshAccessToken;
124
+ private emitError;
107
125
  private isTokenExpired;
108
126
  private prepareHeaders;
109
127
  private handleResponse;
128
+ /**
129
+ * AbortController 를 관리하며 fetch 호출을 실행. 타임아웃/외부 signal 병합.
130
+ */
131
+ private doFetch;
110
132
  get<T>(url: string, config?: RequestConfig): Promise<T>;
111
133
  post<T>(url: string, data?: unknown, config?: RequestConfig): Promise<T>;
112
134
  put<T>(url: string, data: unknown, config?: RequestConfig): Promise<T>;
@@ -114,7 +136,8 @@ declare class HttpClient {
114
136
  delete<T>(url: string, config?: RequestConfig): Promise<T>;
115
137
  /**
116
138
  * Raw fetch 요청 (SSE 스트리밍 등에 사용)
117
- * 인증 헤더가 자동으로 추가됩니다.
139
+ * 인증 헤더가 자동으로 추가됩니다. timeout 은 호출자가 직접 signal 로 관리해야 합니다
140
+ * (스트리밍 특성상 전역 timeout 을 강제하지 않음).
118
141
  */
119
142
  fetchRaw(url: string, init?: RequestInit): Promise<Response>;
120
143
  }
@@ -230,9 +253,31 @@ declare class AnalyticsAPI {
230
253
  * 세션 heartbeat 자동 전송 시작 (30초 간격)
231
254
  */
232
255
  enableHeartbeat(): void;
233
- /** 큐에 있는 이벤트 즉시 전송 */
256
+ /**
257
+ * 큐에 있는 이벤트 즉시 전송.
258
+ *
259
+ * 기본적으로 이벤트는 배치(10개) 또는 주기(5초)로 flush 되지만, 페이지 이탈 직전이나
260
+ * 결정적 이벤트(결제 완료 등)는 수동으로 `flush()` 를 호출해 전송 지연을 줄일 수 있다.
261
+ *
262
+ * @returns 서버 응답 완료 시까지 대기하는 Promise
263
+ *
264
+ * @example
265
+ * ```ts
266
+ * // 결제 완료 직후 이탈에 대비해 즉시 flush
267
+ * await cb.analytics.track('purchase_completed', { order_id: '123' })
268
+ * await cb.analytics.flush()
269
+ * window.location.href = '/thank-you'
270
+ * ```
271
+ */
234
272
  flush(): Promise<void>;
235
- /** 세션 매니저 접근 (고급) */
273
+ /**
274
+ * 세션 매니저 접근 (고급 사용자용).
275
+ *
276
+ * 외부에서 세션 ID 를 읽어 자체 로깅에 합치거나 강제 세션 종료/재시작이 필요한 경우
277
+ * 사용. 일반적으로는 AnalyticsAPI 가 내부적으로 세션을 관리하므로 호출할 필요가 없다.
278
+ *
279
+ * @returns 내부 SessionManager 인스턴스
280
+ */
236
281
  getSession(): SessionManager;
237
282
  private canTrack;
238
283
  private isDNT;
@@ -1864,6 +1909,12 @@ declare class StorageAPI {
1864
1909
  * API Key 인증 시 /v1/public 접두사 반환
1865
1910
  */
1866
1911
  private getPublicPrefix;
1912
+ /**
1913
+ * Presigned URL 로 직접 업로드. 호출 전에 URL 스킴(https)을 검증해
1914
+ * 서버 응답을 그대로 신뢰하는 SSRF/오용 경로를 차단.
1915
+ * 타임아웃과 외부 signal 을 모두 지원한다.
1916
+ */
1917
+ private uploadToPresigned;
1867
1918
  /**
1868
1919
  * 파일 목록 조회
1869
1920
  *
@@ -2735,6 +2786,12 @@ declare class RealtimeAPI {
2735
2786
  onReadReceipt(category: string, handler: ReadReceiptHandler): () => void;
2736
2787
  private doConnect;
2737
2788
  private log;
2789
+ /**
2790
+ * 에러 로그. `options.debug` 가 true 일 때만 console 에 출력.
2791
+ * 운영 환경에서는 소비자 애플리케이션의 `ConnectBase({ onError })` 또는
2792
+ * `cb.errorTracker` 로 전달하는 것을 권장하므로 SDK 자체 console 출력은 opt-in.
2793
+ */
2794
+ private logError;
2738
2795
  private handleServerMessage;
2739
2796
  private handleDisconnect;
2740
2797
  /**
@@ -4509,7 +4566,29 @@ declare class VideoAPI {
4509
4566
  */
4510
4567
  waitForReady(videoId: string, options?: WaitOptions): Promise<Video>;
4511
4568
  /**
4512
- * List videos
4569
+ * 영상 목록 조회.
4570
+ *
4571
+ * 필터링/페이지네이션 옵션을 조합해 조건에 맞는 영상들을 반환한다.
4572
+ * API Key(publicKey) 또는 JWT 인증이 모두 지원되며, publicKey 로는 공개 영상만 노출된다.
4573
+ *
4574
+ * @param options - 필터/페이지네이션 옵션
4575
+ * @param options.status - `uploading` | `processing` | `ready` | `failed`
4576
+ * @param options.visibility - `public` | `unlisted` | `private` | `members`
4577
+ * @param options.search - 제목 부분 일치 검색
4578
+ * @param options.channel_id - 특정 채널로 한정
4579
+ * @param options.page - 1 부터 시작
4580
+ * @param options.limit - 기본 20, 최대 100
4581
+ * @returns `videos` 배열과 `total` 카운트를 포함하는 응답
4582
+ *
4583
+ * @example
4584
+ * ```ts
4585
+ * // 내 채널의 최근 공개 영상 10개
4586
+ * const { videos, total } = await cb.video.list({
4587
+ * channel_id: 'ch_abc',
4588
+ * visibility: 'public',
4589
+ * limit: 10,
4590
+ * })
4591
+ * ```
4513
4592
  */
4514
4593
  list(options?: VideoListOptions): Promise<VideoListResponse>;
4515
4594
  /**
@@ -4525,7 +4604,20 @@ declare class VideoAPI {
4525
4604
  */
4526
4605
  delete(videoId: string): Promise<void>;
4527
4606
  /**
4528
- * Get streaming URL for a video
4607
+ * 영상 스트리밍 URL 획득 (HLS manifest 권장).
4608
+ *
4609
+ * 반환된 URL 은 `hls.js` 또는 Safari 네이티브 HLS 플레이어에 그대로 전달 가능하다.
4610
+ * 서명된 URL 이므로 만료 시간이 존재하며, 갱신이 필요한 경우 다시 호출한다.
4611
+ *
4612
+ * @param videoId - 대상 영상 ID
4613
+ * @param quality - `auto` (기본) | `1080p` | `720p` | `480p` | `360p` 등 트랜스코딩된 품질 레벨
4614
+ * @returns HLS manifest URL 과 만료 정보
4615
+ *
4616
+ * @example
4617
+ * ```ts
4618
+ * const { url, expires_at } = await cb.video.getStreamUrl(videoId, '720p')
4619
+ * videoElement.src = url
4620
+ * ```
4529
4621
  */
4530
4622
  getStreamUrl(videoId: string, quality?: string): Promise<StreamURLResponse>;
4531
4623
  /**
@@ -6622,16 +6714,34 @@ interface ConnectBaseConfig {
6622
6714
  onTokenExpired?: () => void;
6623
6715
  /**
6624
6716
  * 토큰 저장 방식.
6625
- * - 'localStorage': 브라우저 종료 후에도 유지 (기본값)
6626
- * - 'sessionStorage': 탭 종료 시 삭제
6627
- * - 'none': 메모리에만 저장 (페이지 새로고침 삭제)
6628
- * @default 'localStorage'
6717
+ * - 'none' (기본·권장): 메모리에만 저장. 새로고침 재로그인 필요. XSS 노출 최소화
6718
+ * - 'sessionStorage': 탭 종료 시 삭제 (XSS 시 현재 탭 세션 탈취 가능)
6719
+ * - 'localStorage': 브라우저 종료 후에도 유지 (XSS토큰 영구 탈취 가능 — 콘솔 경고 출력)
6720
+ * @default 'none'
6629
6721
  */
6630
6722
  persistence?: TokenPersistence;
6631
6723
  /**
6632
6724
  * 에러 트래커 설정
6633
6725
  */
6634
6726
  errorTracker?: ErrorTrackerConfig;
6727
+ /**
6728
+ * 기본 요청 타임아웃(ms). 개별 호출의 `timeout` 이 지정되면 해당 값이 우선.
6729
+ * 기본값 30000ms. 0 또는 음수 지정 시 타임아웃 비활성화.
6730
+ */
6731
+ requestTimeoutMs?: number;
6732
+ /**
6733
+ * 전역 에러 관찰자. 모든 `ApiError` / `AuthError` 발생 시 호출됩니다.
6734
+ * Sentry/Datadog 등 관측성 파이프라인과 연결하기 위한 훅.
6735
+ *
6736
+ * @example
6737
+ * ```ts
6738
+ * const cb = new ConnectBase({
6739
+ * publicKey: '...',
6740
+ * onError: (err) => Sentry.captureException(err),
6741
+ * })
6742
+ * ```
6743
+ */
6744
+ onError?: (error: ApiError | AuthError) => void;
6635
6745
  }
6636
6746
  /**
6637
6747
  * Connect Base SDK