connectbase-client 0.1.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/README.md +565 -0
- package/dist/connect-base.umd.js +3 -0
- package/dist/index.d.mts +3346 -0
- package/dist/index.d.ts +3346 -0
- package/dist/index.js +4577 -0
- package/dist/index.mjs +4543 -0
- package/package.json +50 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,3346 @@
|
|
|
1
|
+
declare class ApiError extends Error {
|
|
2
|
+
statusCode: number;
|
|
3
|
+
constructor(statusCode: number, message: string);
|
|
4
|
+
}
|
|
5
|
+
declare class AuthError extends Error {
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface HttpClientConfig {
|
|
10
|
+
baseUrl: string;
|
|
11
|
+
apiKey?: string;
|
|
12
|
+
accessToken?: string;
|
|
13
|
+
refreshToken?: string;
|
|
14
|
+
onTokenRefresh?: (tokens: {
|
|
15
|
+
accessToken: string;
|
|
16
|
+
refreshToken: string;
|
|
17
|
+
}) => void;
|
|
18
|
+
onAuthError?: (error: AuthError) => void;
|
|
19
|
+
}
|
|
20
|
+
interface RequestConfig {
|
|
21
|
+
skipAuth?: boolean;
|
|
22
|
+
headers?: Record<string, string>;
|
|
23
|
+
}
|
|
24
|
+
declare class HttpClient {
|
|
25
|
+
private config;
|
|
26
|
+
private isRefreshing;
|
|
27
|
+
private refreshPromise;
|
|
28
|
+
constructor(config: HttpClientConfig);
|
|
29
|
+
updateConfig(config: Partial<HttpClientConfig>): void;
|
|
30
|
+
setTokens(accessToken: string, refreshToken: string): void;
|
|
31
|
+
clearTokens(): void;
|
|
32
|
+
/**
|
|
33
|
+
* API Key가 설정되어 있는지 확인
|
|
34
|
+
*/
|
|
35
|
+
hasApiKey(): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* API Key 반환
|
|
38
|
+
*/
|
|
39
|
+
getApiKey(): string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Access Token 반환
|
|
42
|
+
*/
|
|
43
|
+
getAccessToken(): string | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Base URL 반환
|
|
46
|
+
*/
|
|
47
|
+
getBaseUrl(): string;
|
|
48
|
+
private refreshAccessToken;
|
|
49
|
+
private isTokenExpired;
|
|
50
|
+
private prepareHeaders;
|
|
51
|
+
private handleResponse;
|
|
52
|
+
get<T>(url: string, config?: RequestConfig): Promise<T>;
|
|
53
|
+
post<T>(url: string, data?: unknown, config?: RequestConfig): Promise<T>;
|
|
54
|
+
put<T>(url: string, data: unknown, config?: RequestConfig): Promise<T>;
|
|
55
|
+
patch<T>(url: string, data: unknown, config?: RequestConfig): Promise<T>;
|
|
56
|
+
delete<T>(url: string, config?: RequestConfig): Promise<T>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
interface SignUpRequest {
|
|
60
|
+
email: string;
|
|
61
|
+
password: string;
|
|
62
|
+
name?: string;
|
|
63
|
+
}
|
|
64
|
+
interface SignUpResponse {
|
|
65
|
+
access_token: string;
|
|
66
|
+
refresh_token: string;
|
|
67
|
+
user: UserInfo;
|
|
68
|
+
}
|
|
69
|
+
interface SignInRequest {
|
|
70
|
+
email: string;
|
|
71
|
+
password: string;
|
|
72
|
+
}
|
|
73
|
+
interface SignInResponse {
|
|
74
|
+
access_token: string;
|
|
75
|
+
refresh_token: string;
|
|
76
|
+
user: UserInfo;
|
|
77
|
+
}
|
|
78
|
+
interface AnonymousSignUpResponse {
|
|
79
|
+
access_token: string;
|
|
80
|
+
refresh_token: string;
|
|
81
|
+
anonymous_uid: string;
|
|
82
|
+
}
|
|
83
|
+
interface AnonymousSignInRequest {
|
|
84
|
+
anonymous_uid?: string;
|
|
85
|
+
}
|
|
86
|
+
interface AnonymousSignInResponse {
|
|
87
|
+
access_token: string;
|
|
88
|
+
refresh_token: string;
|
|
89
|
+
anonymous_uid?: string;
|
|
90
|
+
}
|
|
91
|
+
interface UserInfo {
|
|
92
|
+
id: string;
|
|
93
|
+
email: string;
|
|
94
|
+
name?: string;
|
|
95
|
+
email_verified: boolean;
|
|
96
|
+
created_at: string;
|
|
97
|
+
is_anonymous?: boolean;
|
|
98
|
+
}
|
|
99
|
+
/** 앱 멤버 게스트 가입 응답 */
|
|
100
|
+
interface GuestMemberSignInResponse {
|
|
101
|
+
member_id: string;
|
|
102
|
+
access_token: string;
|
|
103
|
+
refresh_token: string;
|
|
104
|
+
}
|
|
105
|
+
/** 앱 멤버 회원가입 요청 */
|
|
106
|
+
interface MemberSignUpRequest {
|
|
107
|
+
login_id: string;
|
|
108
|
+
password: string;
|
|
109
|
+
nickname?: string;
|
|
110
|
+
}
|
|
111
|
+
/** 앱 멤버 회원가입 응답 */
|
|
112
|
+
interface MemberSignUpResponse {
|
|
113
|
+
member_id: string;
|
|
114
|
+
nickname: string;
|
|
115
|
+
access_token: string;
|
|
116
|
+
refresh_token: string;
|
|
117
|
+
}
|
|
118
|
+
/** 앱 멤버 로그인 요청 */
|
|
119
|
+
interface MemberSignInRequest {
|
|
120
|
+
login_id: string;
|
|
121
|
+
password: string;
|
|
122
|
+
}
|
|
123
|
+
/** 앱 멤버 로그인 응답 */
|
|
124
|
+
interface MemberSignInResponse {
|
|
125
|
+
member_id: string;
|
|
126
|
+
nickname: string;
|
|
127
|
+
access_token: string;
|
|
128
|
+
refresh_token: string;
|
|
129
|
+
}
|
|
130
|
+
/** 앱 인증 설정 응답 */
|
|
131
|
+
interface AuthSettingsResponse {
|
|
132
|
+
/** 아이디/비밀번호 로그인 허용 여부 */
|
|
133
|
+
allow_id_password_login: boolean;
|
|
134
|
+
/** 게스트 로그인 허용 여부 */
|
|
135
|
+
allow_guest_login: boolean;
|
|
136
|
+
/** 활성화된 OAuth 프로바이더 목록 (GOOGLE, KAKAO, NAVER, APPLE, GITHUB, DISCORD) */
|
|
137
|
+
enabled_oauth_providers: string[];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
declare class AuthAPI {
|
|
141
|
+
private http;
|
|
142
|
+
private anonymousLoginPromise;
|
|
143
|
+
private guestMemberLoginPromise;
|
|
144
|
+
private cachedAnonymousUIDKey;
|
|
145
|
+
private cachedGuestMemberTokenKey;
|
|
146
|
+
constructor(http: HttpClient);
|
|
147
|
+
/**
|
|
148
|
+
* 앱의 인증 설정 조회
|
|
149
|
+
* 어떤 로그인 방식이 허용되는지 확인합니다.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* const settings = await client.auth.getAuthSettings()
|
|
154
|
+
* if (settings.allow_guest_login) {
|
|
155
|
+
* await client.auth.signInAsGuestMember()
|
|
156
|
+
* } else if (settings.allow_id_password_login) {
|
|
157
|
+
* // 로그인 폼 표시
|
|
158
|
+
* } else if (settings.enabled_oauth_providers.includes('GOOGLE')) {
|
|
159
|
+
* // 구글 소셜 로그인 버튼 표시
|
|
160
|
+
* }
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
getAuthSettings(): Promise<AuthSettingsResponse>;
|
|
164
|
+
/**
|
|
165
|
+
* 현재 앱의 anonymous_uid 스토리지 키 생성
|
|
166
|
+
* apiKey를 해시하여 앱별 고유 키 생성 (원본 apiKey 노출 방지)
|
|
167
|
+
* 성능 최적화: 키를 캐싱하여 반복 해시 계산 방지
|
|
168
|
+
*/
|
|
169
|
+
private getAnonymousUIDKey;
|
|
170
|
+
/**
|
|
171
|
+
* 회원가입
|
|
172
|
+
*/
|
|
173
|
+
signUp(data: SignUpRequest): Promise<SignUpResponse>;
|
|
174
|
+
/**
|
|
175
|
+
* 로그인
|
|
176
|
+
*/
|
|
177
|
+
signIn(data: SignInRequest): Promise<SignInResponse>;
|
|
178
|
+
/**
|
|
179
|
+
* 익명 로그인
|
|
180
|
+
* 계정 없이 게스트로 앱을 사용할 수 있습니다.
|
|
181
|
+
* 로컬 스토리지에 저장된 anonymous_uid가 있으면 기존 계정으로 재로그인을 시도합니다.
|
|
182
|
+
* 동시 호출 시 중복 요청 방지 (race condition 방지)
|
|
183
|
+
*/
|
|
184
|
+
signInAnonymously(): Promise<AnonymousSignInResponse>;
|
|
185
|
+
/**
|
|
186
|
+
* 실제 익명 로그인 실행 (내부 메서드)
|
|
187
|
+
*/
|
|
188
|
+
private executeAnonymousLogin;
|
|
189
|
+
/**
|
|
190
|
+
* 저장된 anonymous_uid 조회
|
|
191
|
+
*/
|
|
192
|
+
getStoredAnonymousUID(): string | null;
|
|
193
|
+
/**
|
|
194
|
+
* anonymous_uid 저장
|
|
195
|
+
*/
|
|
196
|
+
private storeAnonymousUID;
|
|
197
|
+
/**
|
|
198
|
+
* 저장된 anonymous_uid 삭제
|
|
199
|
+
*/
|
|
200
|
+
clearAnonymousUID(): void;
|
|
201
|
+
/**
|
|
202
|
+
* 로그아웃
|
|
203
|
+
*/
|
|
204
|
+
signOut(): Promise<void>;
|
|
205
|
+
/**
|
|
206
|
+
* 현재 사용자 정보 조회
|
|
207
|
+
* 토큰이 없거나 유효하지 않으면 자동으로 익명 계정을 생성합니다.
|
|
208
|
+
* @param autoAnonymous - 자동 익명 로그인 활성화 (기본값: false, 명시적으로 활성화 필요)
|
|
209
|
+
*/
|
|
210
|
+
getCurrentUser(autoAnonymous?: boolean): Promise<UserInfo>;
|
|
211
|
+
/**
|
|
212
|
+
* 이메일 인증 메일 재발송
|
|
213
|
+
*/
|
|
214
|
+
resendVerificationEmail(): Promise<void>;
|
|
215
|
+
/**
|
|
216
|
+
* 앱 멤버 게스트 가입
|
|
217
|
+
* API Key로 인증된 앱에 게스트 멤버로 가입합니다.
|
|
218
|
+
* 실시간 채팅 등에서 JWT 토큰 기반 인증이 필요할 때 사용합니다.
|
|
219
|
+
* 로컬 스토리지에 저장된 토큰이 있으면 기존 계정으로 재로그인을 시도합니다.
|
|
220
|
+
* 동시 호출 시 중복 요청 방지 (race condition 방지)
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```typescript
|
|
224
|
+
* // 게스트로 가입하고 실시간 연결
|
|
225
|
+
* const guest = await client.auth.signInAsGuestMember()
|
|
226
|
+
* await client.realtime.connect({ accessToken: guest.access_token })
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
signInAsGuestMember(): Promise<GuestMemberSignInResponse>;
|
|
230
|
+
/**
|
|
231
|
+
* 실제 게스트 멤버 로그인 실행 (내부 메서드)
|
|
232
|
+
*/
|
|
233
|
+
private executeGuestMemberLogin;
|
|
234
|
+
/**
|
|
235
|
+
* JWT 토큰 만료 여부 확인 (로컬 검증)
|
|
236
|
+
*/
|
|
237
|
+
private isTokenExpired;
|
|
238
|
+
/**
|
|
239
|
+
* 현재 앱의 guest_member 토큰 스토리지 키 생성
|
|
240
|
+
*/
|
|
241
|
+
private getGuestMemberTokenKey;
|
|
242
|
+
/**
|
|
243
|
+
* 저장된 게스트 멤버 토큰 조회
|
|
244
|
+
*/
|
|
245
|
+
private getStoredGuestMemberTokens;
|
|
246
|
+
/**
|
|
247
|
+
* 게스트 멤버 토큰 저장
|
|
248
|
+
*/
|
|
249
|
+
private storeGuestMemberTokens;
|
|
250
|
+
/**
|
|
251
|
+
* 저장된 게스트 멤버 토큰 삭제
|
|
252
|
+
*/
|
|
253
|
+
clearGuestMemberTokens(): void;
|
|
254
|
+
/**
|
|
255
|
+
* 앱 멤버 회원가입 (이메일/ID 기반)
|
|
256
|
+
* 앱에 새로운 멤버를 등록합니다.
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```typescript
|
|
260
|
+
* const result = await client.auth.signUpMember({
|
|
261
|
+
* login_id: 'user@example.com',
|
|
262
|
+
* password: 'password123',
|
|
263
|
+
* nickname: 'John'
|
|
264
|
+
* })
|
|
265
|
+
* console.log('가입 완료:', result.member_id)
|
|
266
|
+
* ```
|
|
267
|
+
*/
|
|
268
|
+
signUpMember(data: MemberSignUpRequest): Promise<MemberSignUpResponse>;
|
|
269
|
+
/**
|
|
270
|
+
* 앱 멤버 로그인 (이메일/ID 기반)
|
|
271
|
+
* 기존 멤버로 로그인합니다.
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* ```typescript
|
|
275
|
+
* const result = await client.auth.signInMember({
|
|
276
|
+
* login_id: 'user@example.com',
|
|
277
|
+
* password: 'password123'
|
|
278
|
+
* })
|
|
279
|
+
* console.log('로그인 성공:', result.member_id)
|
|
280
|
+
* ```
|
|
281
|
+
*/
|
|
282
|
+
signInMember(data: MemberSignInRequest): Promise<MemberSignInResponse>;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
type DataType = 'string' | 'number' | 'boolean' | 'date' | 'object' | 'array';
|
|
286
|
+
interface ColumnSchema {
|
|
287
|
+
id: string;
|
|
288
|
+
name: string;
|
|
289
|
+
data_type: DataType;
|
|
290
|
+
is_required: boolean;
|
|
291
|
+
default_value?: string;
|
|
292
|
+
validation_rule?: string;
|
|
293
|
+
order: number;
|
|
294
|
+
created_at: string;
|
|
295
|
+
updated_at?: string;
|
|
296
|
+
}
|
|
297
|
+
interface CreateColumnRequest {
|
|
298
|
+
name: string;
|
|
299
|
+
data_type: DataType;
|
|
300
|
+
is_required: boolean;
|
|
301
|
+
default_value?: string;
|
|
302
|
+
validation_rule?: string;
|
|
303
|
+
order: number;
|
|
304
|
+
}
|
|
305
|
+
interface UpdateColumnRequest {
|
|
306
|
+
name?: string;
|
|
307
|
+
data_type?: DataType;
|
|
308
|
+
is_required?: boolean;
|
|
309
|
+
default_value?: string;
|
|
310
|
+
validation_rule?: string;
|
|
311
|
+
order?: number;
|
|
312
|
+
}
|
|
313
|
+
interface TableSchema {
|
|
314
|
+
id: string;
|
|
315
|
+
name: string;
|
|
316
|
+
description?: string;
|
|
317
|
+
columns: ColumnSchema[];
|
|
318
|
+
created_at: string;
|
|
319
|
+
updated_at?: string;
|
|
320
|
+
}
|
|
321
|
+
interface CreateTableRequest {
|
|
322
|
+
name: string;
|
|
323
|
+
description?: string;
|
|
324
|
+
}
|
|
325
|
+
interface DataItem {
|
|
326
|
+
id: string;
|
|
327
|
+
data: Record<string, unknown>;
|
|
328
|
+
created_at: string;
|
|
329
|
+
updated_at: string;
|
|
330
|
+
}
|
|
331
|
+
interface CreateDataRequest {
|
|
332
|
+
data: Record<string, unknown>;
|
|
333
|
+
}
|
|
334
|
+
interface UpdateDataRequest {
|
|
335
|
+
data: Record<string, unknown>;
|
|
336
|
+
}
|
|
337
|
+
interface FetchDataResponse {
|
|
338
|
+
data: DataItem[];
|
|
339
|
+
total_count: number;
|
|
340
|
+
limit: number;
|
|
341
|
+
offset: number;
|
|
342
|
+
}
|
|
343
|
+
interface QueryOptions {
|
|
344
|
+
limit?: number;
|
|
345
|
+
offset?: number;
|
|
346
|
+
orderBy?: string;
|
|
347
|
+
orderDirection?: 'asc' | 'desc';
|
|
348
|
+
where?: WhereCondition;
|
|
349
|
+
}
|
|
350
|
+
type WhereCondition = Record<string, unknown | WhereOperator>;
|
|
351
|
+
interface WhereOperator {
|
|
352
|
+
$eq?: unknown;
|
|
353
|
+
$ne?: unknown;
|
|
354
|
+
$gt?: number;
|
|
355
|
+
$gte?: number;
|
|
356
|
+
$lt?: number;
|
|
357
|
+
$lte?: number;
|
|
358
|
+
$in?: unknown[];
|
|
359
|
+
$nin?: unknown[];
|
|
360
|
+
$contains?: string;
|
|
361
|
+
$startsWith?: string;
|
|
362
|
+
$endsWith?: string;
|
|
363
|
+
}
|
|
364
|
+
interface BulkCreateResponse {
|
|
365
|
+
created: DataItem[];
|
|
366
|
+
failed?: BulkError[];
|
|
367
|
+
total: number;
|
|
368
|
+
success: number;
|
|
369
|
+
}
|
|
370
|
+
interface BulkError {
|
|
371
|
+
index: number;
|
|
372
|
+
error: string;
|
|
373
|
+
}
|
|
374
|
+
interface DeleteWhereResponse {
|
|
375
|
+
deleted: number;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
declare class DatabaseAPI {
|
|
379
|
+
private http;
|
|
380
|
+
constructor(http: HttpClient);
|
|
381
|
+
/**
|
|
382
|
+
* API Key 인증 시 /v1/public 접두사 반환
|
|
383
|
+
*/
|
|
384
|
+
private getPublicPrefix;
|
|
385
|
+
/**
|
|
386
|
+
* 테이블 목록 조회
|
|
387
|
+
*/
|
|
388
|
+
getTables(databaseId: string): Promise<TableSchema[]>;
|
|
389
|
+
/**
|
|
390
|
+
* 테이블 생성
|
|
391
|
+
*/
|
|
392
|
+
createTable(databaseId: string, data: CreateTableRequest): Promise<TableSchema>;
|
|
393
|
+
/**
|
|
394
|
+
* 테이블 삭제
|
|
395
|
+
*/
|
|
396
|
+
deleteTable(databaseId: string, tableId: string): Promise<void>;
|
|
397
|
+
/**
|
|
398
|
+
* 컬럼 목록 조회
|
|
399
|
+
*/
|
|
400
|
+
getColumns(tableId: string): Promise<ColumnSchema[]>;
|
|
401
|
+
/**
|
|
402
|
+
* 컬럼 생성
|
|
403
|
+
*/
|
|
404
|
+
createColumn(tableId: string, data: CreateColumnRequest): Promise<ColumnSchema>;
|
|
405
|
+
/**
|
|
406
|
+
* 컬럼 수정
|
|
407
|
+
*/
|
|
408
|
+
updateColumn(tableId: string, columnId: string, data: UpdateColumnRequest): Promise<ColumnSchema>;
|
|
409
|
+
/**
|
|
410
|
+
* 컬럼 삭제
|
|
411
|
+
*/
|
|
412
|
+
deleteColumn(tableId: string, columnId: string): Promise<void>;
|
|
413
|
+
/**
|
|
414
|
+
* 데이터 조회 (페이지네이션)
|
|
415
|
+
*/
|
|
416
|
+
getData(tableId: string, options?: QueryOptions): Promise<FetchDataResponse>;
|
|
417
|
+
/**
|
|
418
|
+
* 조건부 데이터 조회 (Where, OrderBy)
|
|
419
|
+
*/
|
|
420
|
+
queryData(tableId: string, options: QueryOptions): Promise<FetchDataResponse>;
|
|
421
|
+
/**
|
|
422
|
+
* 단일 데이터 조회
|
|
423
|
+
*/
|
|
424
|
+
getDataById(tableId: string, dataId: string): Promise<DataItem>;
|
|
425
|
+
/**
|
|
426
|
+
* 데이터 생성
|
|
427
|
+
*/
|
|
428
|
+
createData(tableId: string, data: CreateDataRequest): Promise<DataItem>;
|
|
429
|
+
/**
|
|
430
|
+
* 데이터 수정
|
|
431
|
+
*/
|
|
432
|
+
updateData(tableId: string, dataId: string, data: UpdateDataRequest): Promise<DataItem>;
|
|
433
|
+
/**
|
|
434
|
+
* 데이터 삭제
|
|
435
|
+
*/
|
|
436
|
+
deleteData(tableId: string, dataId: string): Promise<void>;
|
|
437
|
+
/**
|
|
438
|
+
* 여러 데이터 한번에 생성 (Bulk Create)
|
|
439
|
+
*/
|
|
440
|
+
createMany(tableId: string, items: CreateDataRequest[]): Promise<BulkCreateResponse>;
|
|
441
|
+
/**
|
|
442
|
+
* 조건에 맞는 데이터 삭제
|
|
443
|
+
*/
|
|
444
|
+
deleteWhere(tableId: string, where: WhereCondition): Promise<DeleteWhereResponse>;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
interface FileItem {
|
|
448
|
+
id: string;
|
|
449
|
+
name: string;
|
|
450
|
+
path: string;
|
|
451
|
+
type: 'file' | 'folder';
|
|
452
|
+
mime_type?: string;
|
|
453
|
+
size: number;
|
|
454
|
+
url?: string;
|
|
455
|
+
parent_id?: string;
|
|
456
|
+
children?: FileItem[];
|
|
457
|
+
created_at: string;
|
|
458
|
+
updated_at: string;
|
|
459
|
+
}
|
|
460
|
+
interface UploadFileResponse {
|
|
461
|
+
id: string;
|
|
462
|
+
name: string;
|
|
463
|
+
path: string;
|
|
464
|
+
type: string;
|
|
465
|
+
mime_type: string;
|
|
466
|
+
size: number;
|
|
467
|
+
url: string;
|
|
468
|
+
parent_id?: string;
|
|
469
|
+
created_at: string;
|
|
470
|
+
}
|
|
471
|
+
interface CreateFolderRequest {
|
|
472
|
+
name: string;
|
|
473
|
+
parent_id?: string;
|
|
474
|
+
}
|
|
475
|
+
interface CreateFolderResponse {
|
|
476
|
+
id: string;
|
|
477
|
+
name: string;
|
|
478
|
+
path: string;
|
|
479
|
+
type: string;
|
|
480
|
+
parent_id?: string;
|
|
481
|
+
created_at: string;
|
|
482
|
+
}
|
|
483
|
+
interface MoveFileRequest {
|
|
484
|
+
new_parent_id?: string;
|
|
485
|
+
}
|
|
486
|
+
interface RenameFileRequest {
|
|
487
|
+
name: string;
|
|
488
|
+
}
|
|
489
|
+
interface RenameFileResponse {
|
|
490
|
+
id: string;
|
|
491
|
+
name: string;
|
|
492
|
+
path: string;
|
|
493
|
+
}
|
|
494
|
+
interface FetchFilesResponse {
|
|
495
|
+
files: FileItem[];
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
declare class StorageAPI {
|
|
499
|
+
private http;
|
|
500
|
+
constructor(http: HttpClient);
|
|
501
|
+
/**
|
|
502
|
+
* API Key 인증 시 /v1/public 접두사 반환
|
|
503
|
+
*/
|
|
504
|
+
private getPublicPrefix;
|
|
505
|
+
/**
|
|
506
|
+
* 파일 목록 조회
|
|
507
|
+
*/
|
|
508
|
+
getFiles(storageId: string): Promise<FileItem[]>;
|
|
509
|
+
/**
|
|
510
|
+
* 파일 업로드
|
|
511
|
+
*/
|
|
512
|
+
uploadFile(storageId: string, file: File, parentId?: string): Promise<UploadFileResponse>;
|
|
513
|
+
/**
|
|
514
|
+
* 여러 파일 업로드
|
|
515
|
+
*/
|
|
516
|
+
uploadFiles(storageId: string, files: File[], parentId?: string): Promise<UploadFileResponse[]>;
|
|
517
|
+
/**
|
|
518
|
+
* 폴더 생성
|
|
519
|
+
*/
|
|
520
|
+
createFolder(storageId: string, data: CreateFolderRequest): Promise<CreateFolderResponse>;
|
|
521
|
+
/**
|
|
522
|
+
* 파일/폴더 삭제
|
|
523
|
+
*/
|
|
524
|
+
deleteFile(storageId: string, fileId: string): Promise<void>;
|
|
525
|
+
/**
|
|
526
|
+
* 파일/폴더 이동
|
|
527
|
+
*/
|
|
528
|
+
moveFile(storageId: string, fileId: string, data: MoveFileRequest): Promise<void>;
|
|
529
|
+
/**
|
|
530
|
+
* 파일/폴더 이름 변경
|
|
531
|
+
*/
|
|
532
|
+
renameFile(storageId: string, fileId: string, data: RenameFileRequest): Promise<RenameFileResponse>;
|
|
533
|
+
/**
|
|
534
|
+
* 파일 URL 가져오기
|
|
535
|
+
*/
|
|
536
|
+
getFileUrl(file: FileItem): string | null;
|
|
537
|
+
/**
|
|
538
|
+
* 이미지 파일 여부 확인
|
|
539
|
+
*/
|
|
540
|
+
isImageFile(file: FileItem): boolean;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* API Key 관련 타입 정의
|
|
545
|
+
*/
|
|
546
|
+
/**
|
|
547
|
+
* API Key 아이템
|
|
548
|
+
*/
|
|
549
|
+
interface ApiKeyItem {
|
|
550
|
+
/** API Key ID */
|
|
551
|
+
id: string;
|
|
552
|
+
/** API Key 이름 */
|
|
553
|
+
name: string;
|
|
554
|
+
/** 키 앞 12자리 (표시용) */
|
|
555
|
+
key_prefix: string;
|
|
556
|
+
/** 활성화 상태 */
|
|
557
|
+
is_active: boolean;
|
|
558
|
+
/** 마지막 사용 시간 */
|
|
559
|
+
last_used_at?: string;
|
|
560
|
+
/** 만료일 (null이면 무제한) */
|
|
561
|
+
expires_at?: string;
|
|
562
|
+
/** 생성일 */
|
|
563
|
+
created_at: string;
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* API Key 생성 요청
|
|
567
|
+
*/
|
|
568
|
+
interface CreateApiKeyRequest {
|
|
569
|
+
/** API Key 이름 (예: Production, Development) */
|
|
570
|
+
name: string;
|
|
571
|
+
/** 만료일 (옵션) */
|
|
572
|
+
expires_at?: string;
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* API Key 생성 응답 (전체 키는 이때만 반환됨)
|
|
576
|
+
*/
|
|
577
|
+
interface CreateApiKeyResponse {
|
|
578
|
+
/** API Key ID */
|
|
579
|
+
id: string;
|
|
580
|
+
/** API Key 이름 */
|
|
581
|
+
name: string;
|
|
582
|
+
/** 전체 키 값 (생성 시에만 반환, 안전하게 보관 필요) */
|
|
583
|
+
key: string;
|
|
584
|
+
/** 키 앞 12자리 (표시용) */
|
|
585
|
+
key_prefix: string;
|
|
586
|
+
/** 활성화 상태 */
|
|
587
|
+
is_active: boolean;
|
|
588
|
+
/** 만료일 */
|
|
589
|
+
expires_at?: string;
|
|
590
|
+
/** 생성일 */
|
|
591
|
+
created_at: string;
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* API Key 목록 조회 응답
|
|
595
|
+
*/
|
|
596
|
+
interface FetchApiKeysResponse {
|
|
597
|
+
api_keys: ApiKeyItem[];
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* API Key 수정 요청
|
|
601
|
+
*/
|
|
602
|
+
interface UpdateApiKeyRequest {
|
|
603
|
+
/** API Key 이름 변경 */
|
|
604
|
+
name?: string;
|
|
605
|
+
/** 활성화/비활성화 */
|
|
606
|
+
is_active?: boolean;
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* API Key 수정 응답
|
|
610
|
+
*/
|
|
611
|
+
interface UpdateApiKeyResponse {
|
|
612
|
+
id: string;
|
|
613
|
+
name: string;
|
|
614
|
+
key_prefix: string;
|
|
615
|
+
is_active: boolean;
|
|
616
|
+
expires_at?: string;
|
|
617
|
+
created_at: string;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* API Key 관리 API
|
|
622
|
+
*
|
|
623
|
+
* @example
|
|
624
|
+
* ```typescript
|
|
625
|
+
* // API Key 목록 조회
|
|
626
|
+
* const keys = await cb.apiKey.getApiKeys('app-id')
|
|
627
|
+
*
|
|
628
|
+
* // 새 API Key 생성
|
|
629
|
+
* const newKey = await cb.apiKey.createApiKey('app-id', { name: 'Production' })
|
|
630
|
+
* console.log(newKey.key) // 전체 키 (이때만 볼 수 있음!)
|
|
631
|
+
*
|
|
632
|
+
* // API Key 비활성화
|
|
633
|
+
* await cb.apiKey.updateApiKey('app-id', 'key-id', { is_active: false })
|
|
634
|
+
*
|
|
635
|
+
* // API Key 삭제
|
|
636
|
+
* await cb.apiKey.deleteApiKey('app-id', 'key-id')
|
|
637
|
+
* ```
|
|
638
|
+
*/
|
|
639
|
+
declare class ApiKeyAPI {
|
|
640
|
+
private http;
|
|
641
|
+
constructor(http: HttpClient);
|
|
642
|
+
/**
|
|
643
|
+
* 앱의 API Key 목록을 조회합니다
|
|
644
|
+
* @param appId 앱 ID
|
|
645
|
+
*/
|
|
646
|
+
getApiKeys(appId: string): Promise<FetchApiKeysResponse>;
|
|
647
|
+
/**
|
|
648
|
+
* 새 API Key를 생성합니다
|
|
649
|
+
*
|
|
650
|
+
* **중요**: 반환되는 `key` 값은 이 응답에서만 볼 수 있습니다.
|
|
651
|
+
* 안전한 곳에 저장하세요.
|
|
652
|
+
*
|
|
653
|
+
* @param appId 앱 ID
|
|
654
|
+
* @param data 생성할 API Key 정보
|
|
655
|
+
*/
|
|
656
|
+
createApiKey(appId: string, data: CreateApiKeyRequest): Promise<CreateApiKeyResponse>;
|
|
657
|
+
/**
|
|
658
|
+
* API Key를 수정합니다 (이름 변경, 활성화/비활성화)
|
|
659
|
+
* @param appId 앱 ID
|
|
660
|
+
* @param keyId API Key ID
|
|
661
|
+
* @param data 수정할 정보
|
|
662
|
+
*/
|
|
663
|
+
updateApiKey(appId: string, keyId: string, data: UpdateApiKeyRequest): Promise<UpdateApiKeyResponse>;
|
|
664
|
+
/**
|
|
665
|
+
* API Key를 삭제합니다
|
|
666
|
+
* @param appId 앱 ID
|
|
667
|
+
* @param keyId API Key ID
|
|
668
|
+
*/
|
|
669
|
+
deleteApiKey(appId: string, keyId: string): Promise<void>;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* 함수 실행 요청
|
|
674
|
+
*/
|
|
675
|
+
interface InvokeFunctionRequest {
|
|
676
|
+
/** 함수에 전달할 데이터 */
|
|
677
|
+
payload?: Record<string, unknown>;
|
|
678
|
+
/** 실행 타임아웃 (초) */
|
|
679
|
+
timeout?: number;
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* 함수 실행 응답
|
|
683
|
+
*/
|
|
684
|
+
interface InvokeFunctionResponse {
|
|
685
|
+
/** 실행 성공 여부 */
|
|
686
|
+
success: boolean;
|
|
687
|
+
/** 실행 ID */
|
|
688
|
+
execution_id: string;
|
|
689
|
+
/** 함수 실행 결과 */
|
|
690
|
+
result?: Record<string, unknown>;
|
|
691
|
+
/** 실행 시간 (밀리초) */
|
|
692
|
+
duration: number;
|
|
693
|
+
/** 실행 상태 ('success' | 'error' | 'timeout') */
|
|
694
|
+
status: 'success' | 'error' | 'timeout';
|
|
695
|
+
/** 에러 메시지 (실패 시) */
|
|
696
|
+
error?: string;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
declare class FunctionsAPI {
|
|
700
|
+
private http;
|
|
701
|
+
constructor(http: HttpClient);
|
|
702
|
+
/**
|
|
703
|
+
* API Key 인증 시 /v1/public 접두사 반환
|
|
704
|
+
*/
|
|
705
|
+
private getPublicPrefix;
|
|
706
|
+
/**
|
|
707
|
+
* 서버리스 함수 실행
|
|
708
|
+
*
|
|
709
|
+
* @param functionId - 함수 ID
|
|
710
|
+
* @param payload - 함수에 전달할 데이터 (선택)
|
|
711
|
+
* @param timeout - 실행 타임아웃 (초, 선택)
|
|
712
|
+
* @returns 함수 실행 결과
|
|
713
|
+
*
|
|
714
|
+
* @example
|
|
715
|
+
* ```typescript
|
|
716
|
+
* // 기본 실행
|
|
717
|
+
* const result = await cb.functions.invoke('function-id')
|
|
718
|
+
*
|
|
719
|
+
* // 데이터와 함께 실행
|
|
720
|
+
* const result = await cb.functions.invoke('function-id', {
|
|
721
|
+
* name: 'John',
|
|
722
|
+
* age: 30
|
|
723
|
+
* })
|
|
724
|
+
*
|
|
725
|
+
* // 타임아웃 설정
|
|
726
|
+
* const result = await cb.functions.invoke('function-id', { data: 'test' }, 60)
|
|
727
|
+
* ```
|
|
728
|
+
*/
|
|
729
|
+
invoke(functionId: string, payload?: Record<string, unknown>, timeout?: number): Promise<InvokeFunctionResponse>;
|
|
730
|
+
/**
|
|
731
|
+
* 서버리스 함수 실행 (비동기 래퍼)
|
|
732
|
+
* 결과만 반환하고 메타데이터는 제외
|
|
733
|
+
*
|
|
734
|
+
* @param functionId - 함수 ID
|
|
735
|
+
* @param payload - 함수에 전달할 데이터 (선택)
|
|
736
|
+
* @returns 함수 실행 결과 데이터
|
|
737
|
+
*
|
|
738
|
+
* @example
|
|
739
|
+
* ```typescript
|
|
740
|
+
* const data = await cb.functions.call('function-id', { name: 'John' })
|
|
741
|
+
* console.log(data) // 함수가 반환한 데이터
|
|
742
|
+
* ```
|
|
743
|
+
*/
|
|
744
|
+
call<T = unknown>(functionId: string, payload?: Record<string, unknown>): Promise<T>;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Realtime API 타입 정의
|
|
749
|
+
*/
|
|
750
|
+
/** 구독 옵션 */
|
|
751
|
+
interface SubscribeOptions {
|
|
752
|
+
/** 히스토리 로드 개수 (persist=true인 카테고리만) */
|
|
753
|
+
historyLimit?: number;
|
|
754
|
+
}
|
|
755
|
+
/** 카테고리 정보 */
|
|
756
|
+
interface CategoryInfo {
|
|
757
|
+
category: string;
|
|
758
|
+
persist: boolean;
|
|
759
|
+
historyCount: number;
|
|
760
|
+
readReceipt: boolean;
|
|
761
|
+
}
|
|
762
|
+
/** 메시지 데이터 */
|
|
763
|
+
interface RealtimeMessage<T = unknown> {
|
|
764
|
+
id?: string;
|
|
765
|
+
category: string;
|
|
766
|
+
from?: string;
|
|
767
|
+
data: T;
|
|
768
|
+
sentAt: number;
|
|
769
|
+
}
|
|
770
|
+
/** 히스토리 응답 */
|
|
771
|
+
interface HistoryResponse<T = unknown> {
|
|
772
|
+
category: string;
|
|
773
|
+
messages: RealtimeMessage<T>[];
|
|
774
|
+
total: number;
|
|
775
|
+
}
|
|
776
|
+
/** WebSocket 연결 상태 */
|
|
777
|
+
type ConnectionState = 'connecting' | 'connected' | 'disconnected' | 'reconnecting';
|
|
778
|
+
/** 연결 옵션 */
|
|
779
|
+
interface RealtimeConnectOptions {
|
|
780
|
+
/** 재연결 시도 횟수 (기본: 5) */
|
|
781
|
+
maxRetries?: number;
|
|
782
|
+
/** 재연결 간격 (밀리초, 기본: 1000) */
|
|
783
|
+
retryInterval?: number;
|
|
784
|
+
/** 사용자 ID (인증된 사용자) */
|
|
785
|
+
userId?: string;
|
|
786
|
+
/** JWT 액세스 토큰 (앱 멤버 인증용, API Key보다 우선) */
|
|
787
|
+
accessToken?: string;
|
|
788
|
+
}
|
|
789
|
+
/** 이벤트 핸들러 타입 */
|
|
790
|
+
type MessageHandler<T = unknown> = (message: RealtimeMessage<T>) => void;
|
|
791
|
+
type ErrorHandler = (error: Error) => void;
|
|
792
|
+
type StateChangeHandler = (state: ConnectionState) => void;
|
|
793
|
+
/** 메시지 전송 옵션 */
|
|
794
|
+
interface SendOptions {
|
|
795
|
+
/** true면 발신자도 메시지를 받음 (기본값: true) */
|
|
796
|
+
includeSelf?: boolean;
|
|
797
|
+
}
|
|
798
|
+
/** 구독 객체 */
|
|
799
|
+
interface Subscription {
|
|
800
|
+
/** 카테고리 정보 */
|
|
801
|
+
info: CategoryInfo;
|
|
802
|
+
/** 메시지 전송 */
|
|
803
|
+
send<T = unknown>(data: T, options?: SendOptions): Promise<void>;
|
|
804
|
+
/** 히스토리 조회 (persist=true인 경우만) */
|
|
805
|
+
getHistory<T = unknown>(limit?: number): Promise<HistoryResponse<T>>;
|
|
806
|
+
/** 구독 해제 */
|
|
807
|
+
unsubscribe(): Promise<void>;
|
|
808
|
+
/** 메시지 수신 핸들러 등록 */
|
|
809
|
+
onMessage<T = unknown>(handler: MessageHandler<T>): void;
|
|
810
|
+
}
|
|
811
|
+
/** 클라이언트 -> 서버 메시지 */
|
|
812
|
+
interface ClientMessage {
|
|
813
|
+
category: string;
|
|
814
|
+
action: 'subscribe' | 'unsubscribe' | 'send' | 'invoke' | 'ping' | 'history';
|
|
815
|
+
data?: unknown;
|
|
816
|
+
request_id: string;
|
|
817
|
+
}
|
|
818
|
+
/** 서버 -> 클라이언트 메시지 */
|
|
819
|
+
interface ServerMessage<T = unknown> {
|
|
820
|
+
category?: string;
|
|
821
|
+
event: 'connected' | 'subscribed' | 'unsubscribed' | 'message' | 'sent' | 'result' | 'error' | 'pong' | 'history';
|
|
822
|
+
data?: T;
|
|
823
|
+
request_id?: string;
|
|
824
|
+
error?: string;
|
|
825
|
+
timestamp: number;
|
|
826
|
+
}
|
|
827
|
+
/** 연결 성공 데이터 */
|
|
828
|
+
interface ConnectedData {
|
|
829
|
+
connection_id: string;
|
|
830
|
+
app_id: string;
|
|
831
|
+
client_id: string;
|
|
832
|
+
user_id?: string;
|
|
833
|
+
}
|
|
834
|
+
/** 구독 성공 데이터 */
|
|
835
|
+
interface SubscribedData {
|
|
836
|
+
category: string;
|
|
837
|
+
persist: boolean;
|
|
838
|
+
history_count: number;
|
|
839
|
+
read_receipt: boolean;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
/**
|
|
843
|
+
* Realtime API
|
|
844
|
+
* WebSocket 기반 실시간 통신 API
|
|
845
|
+
*
|
|
846
|
+
* @example
|
|
847
|
+
* ```typescript
|
|
848
|
+
* // 연결
|
|
849
|
+
* await client.realtime.connect()
|
|
850
|
+
*
|
|
851
|
+
* // 카테고리 구독
|
|
852
|
+
* const chat = await client.realtime.subscribe('chat-room-1')
|
|
853
|
+
*
|
|
854
|
+
* // 메시지 수신
|
|
855
|
+
* chat.onMessage((msg) => {
|
|
856
|
+
* console.log('Received:', msg.data)
|
|
857
|
+
* })
|
|
858
|
+
*
|
|
859
|
+
* // 메시지 전송
|
|
860
|
+
* await chat.send({ text: 'Hello!' })
|
|
861
|
+
*
|
|
862
|
+
* // 히스토리 조회 (persist=true인 카테고리만)
|
|
863
|
+
* if (chat.info.persist) {
|
|
864
|
+
* const history = await chat.getHistory(50)
|
|
865
|
+
* console.log('History:', history.messages)
|
|
866
|
+
* }
|
|
867
|
+
*
|
|
868
|
+
* // 구독 해제
|
|
869
|
+
* await chat.unsubscribe()
|
|
870
|
+
*
|
|
871
|
+
* // 연결 해제
|
|
872
|
+
* client.realtime.disconnect()
|
|
873
|
+
* ```
|
|
874
|
+
*/
|
|
875
|
+
declare class RealtimeAPI {
|
|
876
|
+
private http;
|
|
877
|
+
private socketUrl;
|
|
878
|
+
private ws;
|
|
879
|
+
private state;
|
|
880
|
+
private _connectionId;
|
|
881
|
+
private clientId;
|
|
882
|
+
private userId?;
|
|
883
|
+
private _appId;
|
|
884
|
+
/** 현재 연결 ID */
|
|
885
|
+
get connectionId(): string | null;
|
|
886
|
+
/** 현재 연결된 앱 ID */
|
|
887
|
+
get appId(): string | null;
|
|
888
|
+
private options;
|
|
889
|
+
private retryCount;
|
|
890
|
+
private pendingRequests;
|
|
891
|
+
private subscriptions;
|
|
892
|
+
private stateHandlers;
|
|
893
|
+
private errorHandlers;
|
|
894
|
+
constructor(http: HttpClient, socketUrl: string);
|
|
895
|
+
/**
|
|
896
|
+
* WebSocket 연결
|
|
897
|
+
* @param options 연결 옵션
|
|
898
|
+
* - accessToken: JWT 토큰으로 인증 (앱 멤버용, API Key보다 우선)
|
|
899
|
+
* - userId: 사용자 식별자 (표시용)
|
|
900
|
+
*/
|
|
901
|
+
connect(options?: RealtimeConnectOptions): Promise<void>;
|
|
902
|
+
/**
|
|
903
|
+
* 연결 해제
|
|
904
|
+
*/
|
|
905
|
+
disconnect(): void;
|
|
906
|
+
/**
|
|
907
|
+
* 카테고리 구독
|
|
908
|
+
*/
|
|
909
|
+
subscribe(category: string, options?: SubscribeOptions): Promise<Subscription>;
|
|
910
|
+
/**
|
|
911
|
+
* 구독 해제
|
|
912
|
+
*/
|
|
913
|
+
unsubscribe(category: string): Promise<void>;
|
|
914
|
+
/**
|
|
915
|
+
* 메시지 전송
|
|
916
|
+
* @param category 카테고리 이름
|
|
917
|
+
* @param data 전송할 데이터
|
|
918
|
+
* @param options 전송 옵션 (includeSelf: 발신자도 메시지 수신 여부, 기본값 true)
|
|
919
|
+
*/
|
|
920
|
+
sendMessage<T = unknown>(category: string, data: T, options?: SendOptions): Promise<void>;
|
|
921
|
+
/**
|
|
922
|
+
* 히스토리 조회
|
|
923
|
+
*/
|
|
924
|
+
getHistory<T = unknown>(category: string, limit?: number): Promise<HistoryResponse<T>>;
|
|
925
|
+
/**
|
|
926
|
+
* 연결 상태
|
|
927
|
+
*/
|
|
928
|
+
getState(): ConnectionState;
|
|
929
|
+
/**
|
|
930
|
+
* 상태 변경 핸들러 등록
|
|
931
|
+
*/
|
|
932
|
+
onStateChange(handler: StateChangeHandler): () => void;
|
|
933
|
+
/**
|
|
934
|
+
* 에러 핸들러 등록
|
|
935
|
+
*/
|
|
936
|
+
onError(handler: ErrorHandler): () => void;
|
|
937
|
+
private doConnect;
|
|
938
|
+
private handleServerMessage;
|
|
939
|
+
private handleDisconnect;
|
|
940
|
+
private sendRequest;
|
|
941
|
+
private notifyStateChange;
|
|
942
|
+
private notifyError;
|
|
943
|
+
private generateClientId;
|
|
944
|
+
private generateRequestId;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
/**
|
|
948
|
+
* WebRTC 타입 정의
|
|
949
|
+
*/
|
|
950
|
+
/** WebRTC 채널 모드 */
|
|
951
|
+
type WebRTCMode = 'broadcast' | 'interactive';
|
|
952
|
+
/** WebRTC 연결 상태 */
|
|
953
|
+
type WebRTCConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'failed';
|
|
954
|
+
/** WebRTC 연결 옵션 */
|
|
955
|
+
interface WebRTCConnectOptions {
|
|
956
|
+
/** 룸 ID (channel:room 형식 권장) */
|
|
957
|
+
roomId: string;
|
|
958
|
+
/** 사용자 ID (선택) */
|
|
959
|
+
userId?: string;
|
|
960
|
+
/** 방송자 여부 (broadcast 모드에서 사용) */
|
|
961
|
+
isBroadcaster?: boolean;
|
|
962
|
+
/** 로컬 미디어 스트림 */
|
|
963
|
+
localStream?: MediaStream;
|
|
964
|
+
}
|
|
965
|
+
/** 피어 정보 */
|
|
966
|
+
interface PeerInfo {
|
|
967
|
+
/** 피어 ID */
|
|
968
|
+
peer_id: string;
|
|
969
|
+
/** 사용자 ID */
|
|
970
|
+
user_id?: string;
|
|
971
|
+
/** 방송자 여부 */
|
|
972
|
+
is_broadcaster?: boolean;
|
|
973
|
+
/** 참가 시간 */
|
|
974
|
+
joined_at?: string;
|
|
975
|
+
}
|
|
976
|
+
/** 룸 정보 */
|
|
977
|
+
interface RoomInfo {
|
|
978
|
+
/** 룸 ID */
|
|
979
|
+
room_id: string;
|
|
980
|
+
/** 채널 이름 */
|
|
981
|
+
channel_name: string;
|
|
982
|
+
/** 채널 타입 (broadcast/interactive) */
|
|
983
|
+
channel_type: WebRTCMode;
|
|
984
|
+
/** 참가자 목록 */
|
|
985
|
+
peers: PeerInfo[];
|
|
986
|
+
}
|
|
987
|
+
/** 시그널링 메시지 타입 */
|
|
988
|
+
type SignalingMessageType = 'join' | 'joined' | 'leave' | 'offer' | 'answer' | 'ice_candidate' | 'peer_joined' | 'peer_left' | 'error';
|
|
989
|
+
/** 시그널링 메시지 */
|
|
990
|
+
interface SignalingMessage {
|
|
991
|
+
type: SignalingMessageType;
|
|
992
|
+
room_id?: string;
|
|
993
|
+
peer_id?: string;
|
|
994
|
+
target_id?: string;
|
|
995
|
+
sdp?: string;
|
|
996
|
+
candidate?: RTCIceCandidateInit;
|
|
997
|
+
data?: unknown;
|
|
998
|
+
}
|
|
999
|
+
/** ICE 서버 설정 */
|
|
1000
|
+
interface ICEServer {
|
|
1001
|
+
urls: string | string[];
|
|
1002
|
+
username?: string;
|
|
1003
|
+
credential?: string;
|
|
1004
|
+
}
|
|
1005
|
+
/** ICE 서버 목록 응답 */
|
|
1006
|
+
interface ICEServersResponse {
|
|
1007
|
+
ice_servers: ICEServer[];
|
|
1008
|
+
}
|
|
1009
|
+
/** 룸 통계 */
|
|
1010
|
+
interface RoomStats {
|
|
1011
|
+
room_id: string;
|
|
1012
|
+
peer_count: number;
|
|
1013
|
+
broadcaster_count: number;
|
|
1014
|
+
created_at: string;
|
|
1015
|
+
}
|
|
1016
|
+
/** 앱 통계 응답 */
|
|
1017
|
+
interface AppStatsResponse {
|
|
1018
|
+
total_rooms: number;
|
|
1019
|
+
total_peers: number;
|
|
1020
|
+
rooms: RoomStats[];
|
|
1021
|
+
}
|
|
1022
|
+
/** 룸 목록 응답 */
|
|
1023
|
+
interface RoomsResponse {
|
|
1024
|
+
rooms: RoomStats[];
|
|
1025
|
+
}
|
|
1026
|
+
/** 참가 요청 */
|
|
1027
|
+
interface JoinRoomRequest {
|
|
1028
|
+
room_id: string;
|
|
1029
|
+
user_id?: string;
|
|
1030
|
+
is_broadcaster?: boolean;
|
|
1031
|
+
}
|
|
1032
|
+
/** 참가 응답 */
|
|
1033
|
+
interface JoinRoomResponse {
|
|
1034
|
+
peer_id: string;
|
|
1035
|
+
room_id: string;
|
|
1036
|
+
channel_name: string;
|
|
1037
|
+
channel_type: WebRTCMode;
|
|
1038
|
+
peers: PeerInfo[];
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
/**
|
|
1042
|
+
* WebRTC API
|
|
1043
|
+
* 실시간 영상/음성 통화 (Pion WebRTC 기반)
|
|
1044
|
+
*/
|
|
1045
|
+
declare class WebRTCAPI {
|
|
1046
|
+
private http;
|
|
1047
|
+
private webrtcUrl;
|
|
1048
|
+
private ws;
|
|
1049
|
+
private state;
|
|
1050
|
+
private stateListeners;
|
|
1051
|
+
private errorListeners;
|
|
1052
|
+
private peerJoinedListeners;
|
|
1053
|
+
private peerLeftListeners;
|
|
1054
|
+
private remoteStreamListeners;
|
|
1055
|
+
private reconnectAttempts;
|
|
1056
|
+
private maxReconnectAttempts;
|
|
1057
|
+
private reconnectTimeout;
|
|
1058
|
+
private currentRoomId;
|
|
1059
|
+
private currentPeerId;
|
|
1060
|
+
private currentUserId;
|
|
1061
|
+
private isBroadcaster;
|
|
1062
|
+
private localStream;
|
|
1063
|
+
private channelType;
|
|
1064
|
+
private peerConnections;
|
|
1065
|
+
private remoteStreams;
|
|
1066
|
+
private iceServers;
|
|
1067
|
+
constructor(http: HttpClient, webrtcUrl: string);
|
|
1068
|
+
/**
|
|
1069
|
+
* ICE 서버 목록 조회
|
|
1070
|
+
*/
|
|
1071
|
+
getICEServers(): Promise<ICEServer[]>;
|
|
1072
|
+
/**
|
|
1073
|
+
* WebRTC 시그널링 서버에 연결
|
|
1074
|
+
*
|
|
1075
|
+
* @example
|
|
1076
|
+
* ```typescript
|
|
1077
|
+
* // 로컬 스트림 가져오기
|
|
1078
|
+
* const localStream = await navigator.mediaDevices.getUserMedia({
|
|
1079
|
+
* video: true,
|
|
1080
|
+
* audio: true
|
|
1081
|
+
* })
|
|
1082
|
+
*
|
|
1083
|
+
* // WebRTC 연결
|
|
1084
|
+
* await cb.webrtc.connect({
|
|
1085
|
+
* roomId: 'live:room-123',
|
|
1086
|
+
* userId: 'user-456',
|
|
1087
|
+
* isBroadcaster: true,
|
|
1088
|
+
* localStream
|
|
1089
|
+
* })
|
|
1090
|
+
* ```
|
|
1091
|
+
*/
|
|
1092
|
+
connect(options: WebRTCConnectOptions): Promise<void>;
|
|
1093
|
+
private connectWebSocket;
|
|
1094
|
+
private buildWebSocketUrl;
|
|
1095
|
+
private handleSignalingMessage;
|
|
1096
|
+
private createPeerConnection;
|
|
1097
|
+
private handleOffer;
|
|
1098
|
+
private handleAnswer;
|
|
1099
|
+
private handleICECandidate;
|
|
1100
|
+
private closePeerConnection;
|
|
1101
|
+
private sendSignaling;
|
|
1102
|
+
private handleDisconnect;
|
|
1103
|
+
private attemptReconnect;
|
|
1104
|
+
/**
|
|
1105
|
+
* WebRTC 연결 해제
|
|
1106
|
+
*/
|
|
1107
|
+
disconnect(): void;
|
|
1108
|
+
/**
|
|
1109
|
+
* 현재 연결 상태 조회
|
|
1110
|
+
*/
|
|
1111
|
+
getState(): WebRTCConnectionState;
|
|
1112
|
+
/**
|
|
1113
|
+
* 현재 룸 ID 조회
|
|
1114
|
+
*/
|
|
1115
|
+
getRoomId(): string | null;
|
|
1116
|
+
/**
|
|
1117
|
+
* 현재 피어 ID 조회
|
|
1118
|
+
*/
|
|
1119
|
+
getPeerId(): string | null;
|
|
1120
|
+
/**
|
|
1121
|
+
* 현재 채널 타입 조회
|
|
1122
|
+
*/
|
|
1123
|
+
getChannelType(): WebRTCMode;
|
|
1124
|
+
/**
|
|
1125
|
+
* 원격 스트림 조회
|
|
1126
|
+
*/
|
|
1127
|
+
getRemoteStream(peerId: string): MediaStream | undefined;
|
|
1128
|
+
/**
|
|
1129
|
+
* 모든 원격 스트림 조회
|
|
1130
|
+
*/
|
|
1131
|
+
getAllRemoteStreams(): Map<string, MediaStream>;
|
|
1132
|
+
/**
|
|
1133
|
+
* 로컬 스트림 교체
|
|
1134
|
+
*/
|
|
1135
|
+
replaceLocalStream(newStream: MediaStream): void;
|
|
1136
|
+
/**
|
|
1137
|
+
* 오디오 음소거/해제
|
|
1138
|
+
*/
|
|
1139
|
+
setAudioEnabled(enabled: boolean): void;
|
|
1140
|
+
/**
|
|
1141
|
+
* 비디오 켜기/끄기
|
|
1142
|
+
*/
|
|
1143
|
+
setVideoEnabled(enabled: boolean): void;
|
|
1144
|
+
/**
|
|
1145
|
+
* 연결 상태 변경 이벤트
|
|
1146
|
+
*/
|
|
1147
|
+
onStateChange(callback: (state: WebRTCConnectionState) => void): () => void;
|
|
1148
|
+
/**
|
|
1149
|
+
* 에러 이벤트
|
|
1150
|
+
*/
|
|
1151
|
+
onError(callback: (error: Error) => void): () => void;
|
|
1152
|
+
/**
|
|
1153
|
+
* 피어 참가 이벤트
|
|
1154
|
+
*/
|
|
1155
|
+
onPeerJoined(callback: (peerId: string, info: PeerInfo) => void): () => void;
|
|
1156
|
+
/**
|
|
1157
|
+
* 피어 퇴장 이벤트
|
|
1158
|
+
*/
|
|
1159
|
+
onPeerLeft(callback: (peerId: string) => void): () => void;
|
|
1160
|
+
/**
|
|
1161
|
+
* 원격 스트림 수신 이벤트
|
|
1162
|
+
*/
|
|
1163
|
+
onRemoteStream(callback: (peerId: string, stream: MediaStream) => void): () => void;
|
|
1164
|
+
private setState;
|
|
1165
|
+
private emitError;
|
|
1166
|
+
private emitPeerJoined;
|
|
1167
|
+
private emitPeerLeft;
|
|
1168
|
+
private emitRemoteStream;
|
|
1169
|
+
/**
|
|
1170
|
+
* 앱의 WebRTC 통계 조회
|
|
1171
|
+
*/
|
|
1172
|
+
getStats(appID: string): Promise<AppStatsResponse>;
|
|
1173
|
+
/**
|
|
1174
|
+
* 앱의 활성 룸 목록 조회
|
|
1175
|
+
*/
|
|
1176
|
+
getRooms(appID: string): Promise<RoomsResponse>;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
type ErrorType = 'error' | 'unhandledrejection' | 'resource' | 'network' | 'custom';
|
|
1180
|
+
interface ErrorReport {
|
|
1181
|
+
message: string;
|
|
1182
|
+
source?: string;
|
|
1183
|
+
lineno?: number;
|
|
1184
|
+
colno?: number;
|
|
1185
|
+
stack?: string;
|
|
1186
|
+
error_type?: ErrorType;
|
|
1187
|
+
url?: string;
|
|
1188
|
+
referrer?: string;
|
|
1189
|
+
}
|
|
1190
|
+
interface ErrorTrackerConfig {
|
|
1191
|
+
/**
|
|
1192
|
+
* 에러 자동 캡처 활성화 여부
|
|
1193
|
+
* @default true
|
|
1194
|
+
*/
|
|
1195
|
+
autoCapture?: boolean;
|
|
1196
|
+
/**
|
|
1197
|
+
* 캡처할 에러 타입
|
|
1198
|
+
* @default ['error', 'unhandledrejection']
|
|
1199
|
+
*/
|
|
1200
|
+
captureTypes?: ErrorType[];
|
|
1201
|
+
/**
|
|
1202
|
+
* 에러 배치 전송 간격 (ms)
|
|
1203
|
+
* @default 5000
|
|
1204
|
+
*/
|
|
1205
|
+
batchInterval?: number;
|
|
1206
|
+
/**
|
|
1207
|
+
* 최대 배치 크기
|
|
1208
|
+
* @default 10
|
|
1209
|
+
*/
|
|
1210
|
+
maxBatchSize?: number;
|
|
1211
|
+
/**
|
|
1212
|
+
* 에러 필터 함수 (false 반환 시 무시)
|
|
1213
|
+
*/
|
|
1214
|
+
beforeSend?: (error: ErrorReport) => ErrorReport | false | null;
|
|
1215
|
+
/**
|
|
1216
|
+
* 디버그 모드 (콘솔 로깅)
|
|
1217
|
+
* @default false
|
|
1218
|
+
*/
|
|
1219
|
+
debug?: boolean;
|
|
1220
|
+
}
|
|
1221
|
+
/**
|
|
1222
|
+
* 에러 트래커 API
|
|
1223
|
+
* 클라이언트 JavaScript 에러를 서버로 리포트합니다.
|
|
1224
|
+
*/
|
|
1225
|
+
declare class ErrorTrackerAPI {
|
|
1226
|
+
private http;
|
|
1227
|
+
private storageWebId;
|
|
1228
|
+
private config;
|
|
1229
|
+
private errorQueue;
|
|
1230
|
+
private batchTimer;
|
|
1231
|
+
private isInitialized;
|
|
1232
|
+
private originalOnError;
|
|
1233
|
+
private originalOnUnhandledRejection;
|
|
1234
|
+
constructor(http: HttpClient, config?: ErrorTrackerConfig);
|
|
1235
|
+
/**
|
|
1236
|
+
* 에러 트래커 초기화
|
|
1237
|
+
* @param storageWebId 웹 스토리지 ID
|
|
1238
|
+
*/
|
|
1239
|
+
init(storageWebId: string): void;
|
|
1240
|
+
/**
|
|
1241
|
+
* 에러 트래커 정리 (언마운트 시 호출)
|
|
1242
|
+
*/
|
|
1243
|
+
destroy(): void;
|
|
1244
|
+
/**
|
|
1245
|
+
* 수동으로 에러 리포트
|
|
1246
|
+
*/
|
|
1247
|
+
captureError(error: Error | string, extra?: Partial<ErrorReport>): Promise<void>;
|
|
1248
|
+
/**
|
|
1249
|
+
* 커스텀 에러 리포트
|
|
1250
|
+
*/
|
|
1251
|
+
captureMessage(message: string, extra?: Partial<ErrorReport>): Promise<void>;
|
|
1252
|
+
/**
|
|
1253
|
+
* 큐에 있는 에러들 즉시 전송
|
|
1254
|
+
*/
|
|
1255
|
+
flush(): Promise<void>;
|
|
1256
|
+
private log;
|
|
1257
|
+
private setupAutoCapture;
|
|
1258
|
+
private removeAutoCapture;
|
|
1259
|
+
private handleGlobalError;
|
|
1260
|
+
private handleUnhandledRejection;
|
|
1261
|
+
private createErrorReport;
|
|
1262
|
+
private queueError;
|
|
1263
|
+
private startBatchTimer;
|
|
1264
|
+
private stopBatchTimer;
|
|
1265
|
+
private flushQueue;
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
/**
|
|
1269
|
+
* OAuth 프로바이더 타입
|
|
1270
|
+
*/
|
|
1271
|
+
type OAuthProvider = 'google' | 'naver' | 'github' | 'discord';
|
|
1272
|
+
/**
|
|
1273
|
+
* 활성화된 OAuth 프로바이더 정보
|
|
1274
|
+
*/
|
|
1275
|
+
interface EnabledProviderInfo {
|
|
1276
|
+
provider: OAuthProvider;
|
|
1277
|
+
client_id: string;
|
|
1278
|
+
}
|
|
1279
|
+
/**
|
|
1280
|
+
* 활성화된 프로바이더 목록 응답
|
|
1281
|
+
*/
|
|
1282
|
+
interface EnabledProvidersResponse {
|
|
1283
|
+
providers: EnabledProviderInfo[];
|
|
1284
|
+
}
|
|
1285
|
+
/**
|
|
1286
|
+
* OAuth 인증 URL 요청
|
|
1287
|
+
*/
|
|
1288
|
+
interface GetAuthorizationURLRequest {
|
|
1289
|
+
redirect_uri: string;
|
|
1290
|
+
state?: string;
|
|
1291
|
+
}
|
|
1292
|
+
/**
|
|
1293
|
+
* OAuth 인증 URL 응답
|
|
1294
|
+
*/
|
|
1295
|
+
interface GetAuthorizationURLResponse {
|
|
1296
|
+
authorization_url: string;
|
|
1297
|
+
}
|
|
1298
|
+
/**
|
|
1299
|
+
* OAuth 콜백 요청
|
|
1300
|
+
*/
|
|
1301
|
+
interface OAuthCallbackRequest {
|
|
1302
|
+
code: string;
|
|
1303
|
+
redirect_uri: string;
|
|
1304
|
+
}
|
|
1305
|
+
/**
|
|
1306
|
+
* OAuth 콜백 응답
|
|
1307
|
+
*/
|
|
1308
|
+
interface OAuthCallbackResponse {
|
|
1309
|
+
member_id: string;
|
|
1310
|
+
access_token: string;
|
|
1311
|
+
refresh_token: string;
|
|
1312
|
+
is_new_member: boolean;
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
/**
|
|
1316
|
+
* OAuth API
|
|
1317
|
+
* 소셜 로그인 (Google, Naver, GitHub, Discord)
|
|
1318
|
+
*/
|
|
1319
|
+
declare class OAuthAPI {
|
|
1320
|
+
private http;
|
|
1321
|
+
constructor(http: HttpClient);
|
|
1322
|
+
/**
|
|
1323
|
+
* 활성화된 OAuth 프로바이더 목록 조회
|
|
1324
|
+
* 콘솔에서 설정된 소셜 로그인 프로바이더 목록을 반환합니다.
|
|
1325
|
+
*
|
|
1326
|
+
* @example
|
|
1327
|
+
* ```typescript
|
|
1328
|
+
* const { providers } = await cb.oauth.getEnabledProviders()
|
|
1329
|
+
* // [{ provider: 'google', client_id: '...' }, { provider: 'kakao', client_id: '...' }]
|
|
1330
|
+
* ```
|
|
1331
|
+
*/
|
|
1332
|
+
getEnabledProviders(): Promise<EnabledProvidersResponse>;
|
|
1333
|
+
/**
|
|
1334
|
+
* OAuth 인증 URL 조회
|
|
1335
|
+
* 사용자를 소셜 로그인 페이지로 리다이렉트할 URL을 반환합니다.
|
|
1336
|
+
*
|
|
1337
|
+
* @param provider - OAuth 프로바이더 (google, naver, github, discord)
|
|
1338
|
+
* @param options - redirect_uri와 선택적 state 파라미터
|
|
1339
|
+
* @returns 인증 URL
|
|
1340
|
+
*
|
|
1341
|
+
* @example
|
|
1342
|
+
* ```typescript
|
|
1343
|
+
* const { authorization_url } = await cb.oauth.getAuthorizationURL('google', {
|
|
1344
|
+
* redirect_uri: 'https://myapp.com/auth/callback'
|
|
1345
|
+
* })
|
|
1346
|
+
*
|
|
1347
|
+
* // 사용자를 OAuth 페이지로 리다이렉트
|
|
1348
|
+
* window.location.href = authorization_url
|
|
1349
|
+
* ```
|
|
1350
|
+
*/
|
|
1351
|
+
getAuthorizationURL(provider: OAuthProvider, options: GetAuthorizationURLRequest): Promise<GetAuthorizationURLResponse>;
|
|
1352
|
+
/**
|
|
1353
|
+
* OAuth 콜백 처리
|
|
1354
|
+
* 소셜 로그인 후 콜백으로 받은 code를 사용하여 로그인을 완료합니다.
|
|
1355
|
+
* 성공 시 자동으로 토큰이 저장됩니다.
|
|
1356
|
+
*
|
|
1357
|
+
* @param provider - OAuth 프로바이더
|
|
1358
|
+
* @param data - code와 redirect_uri
|
|
1359
|
+
* @returns 로그인 결과 (member_id, 토큰, 신규 회원 여부)
|
|
1360
|
+
*
|
|
1361
|
+
* @example
|
|
1362
|
+
* ```typescript
|
|
1363
|
+
* // 콜백 페이지에서 URL 파라미터로 code 추출
|
|
1364
|
+
* const urlParams = new URLSearchParams(window.location.search)
|
|
1365
|
+
* const code = urlParams.get('code')
|
|
1366
|
+
*
|
|
1367
|
+
* const result = await cb.oauth.handleCallback('google', {
|
|
1368
|
+
* code: code,
|
|
1369
|
+
* redirect_uri: 'https://myapp.com/auth/callback'
|
|
1370
|
+
* })
|
|
1371
|
+
*
|
|
1372
|
+
* if (result.is_new_member) {
|
|
1373
|
+
* console.log('신규 회원입니다!')
|
|
1374
|
+
* }
|
|
1375
|
+
* ```
|
|
1376
|
+
*/
|
|
1377
|
+
handleCallback(provider: OAuthProvider, data: OAuthCallbackRequest): Promise<OAuthCallbackResponse>;
|
|
1378
|
+
/**
|
|
1379
|
+
* 소셜 로그인 전체 플로우 (팝업 방식)
|
|
1380
|
+
* 새 창에서 소셜 로그인을 처리하고 결과를 Promise로 반환합니다.
|
|
1381
|
+
*
|
|
1382
|
+
* @param provider - OAuth 프로바이더
|
|
1383
|
+
* @param redirectUri - 콜백 URL (이 페이지에서 postMessage로 결과 전달 필요)
|
|
1384
|
+
* @returns 로그인 결과
|
|
1385
|
+
*
|
|
1386
|
+
* @example
|
|
1387
|
+
* ```typescript
|
|
1388
|
+
* // 로그인 버튼 클릭 시
|
|
1389
|
+
* const result = await cb.oauth.signInWithPopup('google', 'https://myapp.com/auth/popup-callback')
|
|
1390
|
+
* console.log('로그인 성공:', result.member_id)
|
|
1391
|
+
* ```
|
|
1392
|
+
*
|
|
1393
|
+
* @example
|
|
1394
|
+
* ```html
|
|
1395
|
+
* <!-- popup-callback.html -->
|
|
1396
|
+
* <script>
|
|
1397
|
+
* const urlParams = new URLSearchParams(window.location.search)
|
|
1398
|
+
* const code = urlParams.get('code')
|
|
1399
|
+
* const error = urlParams.get('error')
|
|
1400
|
+
*
|
|
1401
|
+
* window.opener.postMessage({
|
|
1402
|
+
* type: 'oauth-callback',
|
|
1403
|
+
* code,
|
|
1404
|
+
* error
|
|
1405
|
+
* }, '*')
|
|
1406
|
+
* window.close()
|
|
1407
|
+
* </script>
|
|
1408
|
+
* ```
|
|
1409
|
+
*/
|
|
1410
|
+
signInWithPopup(provider: OAuthProvider, redirectUri: string): Promise<OAuthCallbackResponse>;
|
|
1411
|
+
/**
|
|
1412
|
+
* 소셜 로그인 (리다이렉트 방식)
|
|
1413
|
+
* 현재 페이지를 소셜 로그인 페이지로 리다이렉트합니다.
|
|
1414
|
+
* 콜백 URL에서 handleCallback()을 호출하여 로그인을 완료해야 합니다.
|
|
1415
|
+
*
|
|
1416
|
+
* @param provider - OAuth 프로바이더
|
|
1417
|
+
* @param redirectUri - 콜백 URL
|
|
1418
|
+
*
|
|
1419
|
+
* @example
|
|
1420
|
+
* ```typescript
|
|
1421
|
+
* // 로그인 버튼 클릭 시
|
|
1422
|
+
* await cb.oauth.signInWithRedirect('google', 'https://myapp.com/auth/callback')
|
|
1423
|
+
* // 페이지가 Google 로그인으로 리다이렉트됨
|
|
1424
|
+
* ```
|
|
1425
|
+
*
|
|
1426
|
+
* @example
|
|
1427
|
+
* ```typescript
|
|
1428
|
+
* // callback 페이지에서
|
|
1429
|
+
* const urlParams = new URLSearchParams(window.location.search)
|
|
1430
|
+
* const code = urlParams.get('code')
|
|
1431
|
+
*
|
|
1432
|
+
* if (code) {
|
|
1433
|
+
* const result = await cb.oauth.handleCallback('google', {
|
|
1434
|
+
* code,
|
|
1435
|
+
* redirect_uri: 'https://myapp.com/auth/callback'
|
|
1436
|
+
* })
|
|
1437
|
+
* // 로그인 완료, 메인 페이지로 이동
|
|
1438
|
+
* window.location.href = '/'
|
|
1439
|
+
* }
|
|
1440
|
+
* ```
|
|
1441
|
+
*/
|
|
1442
|
+
signInWithRedirect(provider: OAuthProvider, redirectUri: string): Promise<void>;
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
type PaymentStatus = 'pending' | 'ready' | 'in_progress' | 'done' | 'canceled' | 'partial_canceled' | 'aborted' | 'expired' | 'failed';
|
|
1446
|
+
interface PreparePaymentRequest {
|
|
1447
|
+
amount: number;
|
|
1448
|
+
order_name: string;
|
|
1449
|
+
order_id?: string;
|
|
1450
|
+
customer_email?: string;
|
|
1451
|
+
customer_name?: string;
|
|
1452
|
+
customer_phone?: string;
|
|
1453
|
+
metadata?: Record<string, unknown>;
|
|
1454
|
+
}
|
|
1455
|
+
interface PreparePaymentResponse {
|
|
1456
|
+
payment_id: string;
|
|
1457
|
+
order_id: string;
|
|
1458
|
+
amount: number;
|
|
1459
|
+
order_name: string;
|
|
1460
|
+
customer_key: string;
|
|
1461
|
+
toss_client_key: string;
|
|
1462
|
+
success_url: string;
|
|
1463
|
+
fail_url: string;
|
|
1464
|
+
}
|
|
1465
|
+
interface ConfirmPaymentRequest {
|
|
1466
|
+
payment_key: string;
|
|
1467
|
+
order_id: string;
|
|
1468
|
+
amount: number;
|
|
1469
|
+
}
|
|
1470
|
+
interface ConfirmPaymentResponse {
|
|
1471
|
+
payment_id: string;
|
|
1472
|
+
order_id: string;
|
|
1473
|
+
amount: number;
|
|
1474
|
+
status: PaymentStatus;
|
|
1475
|
+
method: string;
|
|
1476
|
+
receipt_url?: string;
|
|
1477
|
+
approved_at?: string;
|
|
1478
|
+
}
|
|
1479
|
+
interface CancelPaymentRequest {
|
|
1480
|
+
cancel_reason: string;
|
|
1481
|
+
cancel_amount?: number;
|
|
1482
|
+
}
|
|
1483
|
+
interface CancelPaymentResponse {
|
|
1484
|
+
payment_id: string;
|
|
1485
|
+
order_id: string;
|
|
1486
|
+
original_amount: number;
|
|
1487
|
+
canceled_amount: number;
|
|
1488
|
+
status: PaymentStatus;
|
|
1489
|
+
canceled_at?: string;
|
|
1490
|
+
}
|
|
1491
|
+
interface PaymentDetail {
|
|
1492
|
+
payment_id: string;
|
|
1493
|
+
order_id: string;
|
|
1494
|
+
order_name: string;
|
|
1495
|
+
amount: number;
|
|
1496
|
+
currency: string;
|
|
1497
|
+
status: PaymentStatus;
|
|
1498
|
+
method?: string;
|
|
1499
|
+
customer_id?: string;
|
|
1500
|
+
customer_email?: string;
|
|
1501
|
+
customer_name?: string;
|
|
1502
|
+
receipt_url?: string;
|
|
1503
|
+
approved_at?: string;
|
|
1504
|
+
canceled_at?: string;
|
|
1505
|
+
canceled_amount?: number;
|
|
1506
|
+
cancel_reason?: string;
|
|
1507
|
+
failure_code?: string;
|
|
1508
|
+
failure_message?: string;
|
|
1509
|
+
metadata?: Record<string, unknown>;
|
|
1510
|
+
created_at: string;
|
|
1511
|
+
updated_at: string;
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
declare class PaymentAPI {
|
|
1515
|
+
private http;
|
|
1516
|
+
constructor(http: HttpClient);
|
|
1517
|
+
/**
|
|
1518
|
+
* API Key 인증 시 /v1/public 접두사 반환
|
|
1519
|
+
*/
|
|
1520
|
+
private getPublicPrefix;
|
|
1521
|
+
/**
|
|
1522
|
+
* 결제 준비
|
|
1523
|
+
* 토스 결제 위젯에 필요한 정보를 반환합니다.
|
|
1524
|
+
*
|
|
1525
|
+
* @param data - 결제 준비 정보 (금액, 상품명, 고객 정보 등)
|
|
1526
|
+
* @returns 토스 클라이언트 키, 고객 키, 성공/실패 URL 등
|
|
1527
|
+
*
|
|
1528
|
+
* @example
|
|
1529
|
+
* ```typescript
|
|
1530
|
+
* const prepareResult = await client.payment.prepare({
|
|
1531
|
+
* amount: 10000,
|
|
1532
|
+
* order_name: '테스트 상품',
|
|
1533
|
+
* customer_email: 'test@example.com',
|
|
1534
|
+
* customer_name: '홍길동'
|
|
1535
|
+
* })
|
|
1536
|
+
*
|
|
1537
|
+
* // 토스 결제 위젯 초기화
|
|
1538
|
+
* const tossPayments = TossPayments(prepareResult.toss_client_key)
|
|
1539
|
+
* await tossPayments.requestPayment('카드', {
|
|
1540
|
+
* amount: prepareResult.amount,
|
|
1541
|
+
* orderId: prepareResult.order_id,
|
|
1542
|
+
* orderName: prepareResult.order_name,
|
|
1543
|
+
* customerKey: prepareResult.customer_key,
|
|
1544
|
+
* successUrl: prepareResult.success_url,
|
|
1545
|
+
* failUrl: prepareResult.fail_url
|
|
1546
|
+
* })
|
|
1547
|
+
* ```
|
|
1548
|
+
*/
|
|
1549
|
+
prepare(data: PreparePaymentRequest): Promise<PreparePaymentResponse>;
|
|
1550
|
+
/**
|
|
1551
|
+
* 결제 승인
|
|
1552
|
+
* 토스에서 결제 완료 후 콜백으로 받은 정보로 결제를 최종 승인합니다.
|
|
1553
|
+
*
|
|
1554
|
+
* @param data - 결제 승인 정보 (paymentKey, orderId, amount)
|
|
1555
|
+
* @returns 승인된 결제 정보
|
|
1556
|
+
*
|
|
1557
|
+
* @example
|
|
1558
|
+
* ```typescript
|
|
1559
|
+
* // 토스 결제 성공 콜백에서 호출
|
|
1560
|
+
* const result = await client.payment.confirm({
|
|
1561
|
+
* payment_key: 'tgen_20230101000000...',
|
|
1562
|
+
* order_id: 'order_123',
|
|
1563
|
+
* amount: 10000
|
|
1564
|
+
* })
|
|
1565
|
+
*
|
|
1566
|
+
* if (result.status === 'done') {
|
|
1567
|
+
* console.log('결제 완료!')
|
|
1568
|
+
* }
|
|
1569
|
+
* ```
|
|
1570
|
+
*/
|
|
1571
|
+
confirm(data: ConfirmPaymentRequest): Promise<ConfirmPaymentResponse>;
|
|
1572
|
+
/**
|
|
1573
|
+
* 결제 취소
|
|
1574
|
+
* 완료된 결제를 취소합니다. 부분 취소도 가능합니다.
|
|
1575
|
+
*
|
|
1576
|
+
* @param paymentId - 결제 ID (Connect Base에서 발급한 ID)
|
|
1577
|
+
* @param data - 취소 정보 (사유, 부분 취소 금액)
|
|
1578
|
+
* @returns 취소된 결제 정보
|
|
1579
|
+
*
|
|
1580
|
+
* @example
|
|
1581
|
+
* ```typescript
|
|
1582
|
+
* // 전액 취소
|
|
1583
|
+
* const result = await client.payment.cancel(paymentId, {
|
|
1584
|
+
* cancel_reason: '고객 요청'
|
|
1585
|
+
* })
|
|
1586
|
+
*
|
|
1587
|
+
* // 부분 취소
|
|
1588
|
+
* const result = await client.payment.cancel(paymentId, {
|
|
1589
|
+
* cancel_reason: '부분 환불',
|
|
1590
|
+
* cancel_amount: 5000
|
|
1591
|
+
* })
|
|
1592
|
+
* ```
|
|
1593
|
+
*/
|
|
1594
|
+
cancel(paymentId: string, data: CancelPaymentRequest): Promise<CancelPaymentResponse>;
|
|
1595
|
+
/**
|
|
1596
|
+
* 주문 ID로 결제 조회
|
|
1597
|
+
* 특정 주문의 결제 상태를 조회합니다.
|
|
1598
|
+
*
|
|
1599
|
+
* @param orderId - 주문 ID
|
|
1600
|
+
* @returns 결제 상세 정보
|
|
1601
|
+
*
|
|
1602
|
+
* @example
|
|
1603
|
+
* ```typescript
|
|
1604
|
+
* const payment = await client.payment.getByOrderId('order_123')
|
|
1605
|
+
* console.log(`결제 상태: ${payment.status}`)
|
|
1606
|
+
* console.log(`결제 금액: ${payment.amount}원`)
|
|
1607
|
+
* ```
|
|
1608
|
+
*/
|
|
1609
|
+
getByOrderId(orderId: string): Promise<PaymentDetail>;
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
interface IssueBillingKeyRequest {
|
|
1613
|
+
/** 토스 인증 키 (카드 등록 후 받은 키) */
|
|
1614
|
+
auth_key: string;
|
|
1615
|
+
/** 고객 이메일 */
|
|
1616
|
+
customer_email?: string;
|
|
1617
|
+
/** 고객 이름 */
|
|
1618
|
+
customer_name?: string;
|
|
1619
|
+
/** 고객 전화번호 */
|
|
1620
|
+
customer_phone?: string;
|
|
1621
|
+
/** 기본 결제 수단으로 설정 */
|
|
1622
|
+
is_default?: boolean;
|
|
1623
|
+
}
|
|
1624
|
+
interface IssueBillingKeyResponse {
|
|
1625
|
+
/** 빌링키 등록을 위한 URL */
|
|
1626
|
+
auth_url: string;
|
|
1627
|
+
/** 고객 키 (토스에서 사용) */
|
|
1628
|
+
customer_key: string;
|
|
1629
|
+
/** 토스 클라이언트 키 */
|
|
1630
|
+
toss_client_key: string;
|
|
1631
|
+
}
|
|
1632
|
+
interface ConfirmBillingKeyRequest {
|
|
1633
|
+
/** 고객 키 */
|
|
1634
|
+
customer_key: string;
|
|
1635
|
+
/** 토스 인증 키 */
|
|
1636
|
+
auth_key: string;
|
|
1637
|
+
/** 고객 이메일 */
|
|
1638
|
+
customer_email?: string;
|
|
1639
|
+
/** 고객 이름 */
|
|
1640
|
+
customer_name?: string;
|
|
1641
|
+
/** 고객 전화번호 */
|
|
1642
|
+
customer_phone?: string;
|
|
1643
|
+
/** 기본 결제 수단으로 설정 */
|
|
1644
|
+
is_default?: boolean;
|
|
1645
|
+
}
|
|
1646
|
+
interface BillingKeyResponse {
|
|
1647
|
+
/** 빌링키 ID */
|
|
1648
|
+
id: string;
|
|
1649
|
+
/** 고객 키 */
|
|
1650
|
+
customer_key: string;
|
|
1651
|
+
/** 카드사 */
|
|
1652
|
+
card_company: string;
|
|
1653
|
+
/** 마스킹된 카드 번호 */
|
|
1654
|
+
card_number: string;
|
|
1655
|
+
/** 카드 타입 (신용/체크) */
|
|
1656
|
+
card_type: string;
|
|
1657
|
+
/** 카드 별명 */
|
|
1658
|
+
card_nickname: string;
|
|
1659
|
+
/** 기본 결제 수단 여부 */
|
|
1660
|
+
is_default: boolean;
|
|
1661
|
+
/** 활성 여부 */
|
|
1662
|
+
is_active: boolean;
|
|
1663
|
+
/** 고객 이메일 */
|
|
1664
|
+
customer_email: string;
|
|
1665
|
+
/** 고객 이름 */
|
|
1666
|
+
customer_name: string;
|
|
1667
|
+
/** 인증 일시 */
|
|
1668
|
+
authenticated_at: string;
|
|
1669
|
+
/** 생성 일시 */
|
|
1670
|
+
created_at: string;
|
|
1671
|
+
}
|
|
1672
|
+
interface UpdateBillingKeyRequest {
|
|
1673
|
+
/** 카드 별명 */
|
|
1674
|
+
card_nickname?: string;
|
|
1675
|
+
/** 기본 결제 수단 여부 */
|
|
1676
|
+
is_default?: boolean;
|
|
1677
|
+
}
|
|
1678
|
+
interface ListBillingKeysResponse {
|
|
1679
|
+
billing_keys: BillingKeyResponse[];
|
|
1680
|
+
}
|
|
1681
|
+
type BillingCycle = 'daily' | 'weekly' | 'monthly' | 'yearly';
|
|
1682
|
+
type SubscriptionStatus = 'active' | 'paused' | 'canceled' | 'past_due' | 'expired' | 'trial';
|
|
1683
|
+
interface CreateSubscriptionRequest {
|
|
1684
|
+
/** 빌링키 ID */
|
|
1685
|
+
billing_key_id: string;
|
|
1686
|
+
/** 플랜 이름 */
|
|
1687
|
+
plan_name: string;
|
|
1688
|
+
/** 플랜 설명 */
|
|
1689
|
+
plan_description?: string;
|
|
1690
|
+
/** 결제 금액 */
|
|
1691
|
+
amount: number;
|
|
1692
|
+
/** 통화 (기본: KRW) */
|
|
1693
|
+
currency?: string;
|
|
1694
|
+
/** 결제 주기 */
|
|
1695
|
+
billing_cycle: BillingCycle;
|
|
1696
|
+
/** 결제일 (monthly: 1-28일, weekly: 0-6 요일) */
|
|
1697
|
+
billing_day?: number;
|
|
1698
|
+
/** 트라이얼 기간 (일) */
|
|
1699
|
+
trial_days?: number;
|
|
1700
|
+
/** 고객 이메일 */
|
|
1701
|
+
customer_email?: string;
|
|
1702
|
+
/** 고객 이름 */
|
|
1703
|
+
customer_name?: string;
|
|
1704
|
+
/** 메타데이터 */
|
|
1705
|
+
metadata?: Record<string, unknown>;
|
|
1706
|
+
}
|
|
1707
|
+
interface SubscriptionResponse {
|
|
1708
|
+
/** 구독 ID (UUID) */
|
|
1709
|
+
id: string;
|
|
1710
|
+
/** 구독 ID (문자열) */
|
|
1711
|
+
subscription_id: string;
|
|
1712
|
+
/** 플랜 이름 */
|
|
1713
|
+
plan_name: string;
|
|
1714
|
+
/** 플랜 설명 */
|
|
1715
|
+
plan_description: string;
|
|
1716
|
+
/** 결제 금액 */
|
|
1717
|
+
amount: number;
|
|
1718
|
+
/** 통화 */
|
|
1719
|
+
currency: string;
|
|
1720
|
+
/** 결제 주기 */
|
|
1721
|
+
billing_cycle: BillingCycle;
|
|
1722
|
+
/** 결제일 */
|
|
1723
|
+
billing_day: number;
|
|
1724
|
+
/** 구독 상태 */
|
|
1725
|
+
status: SubscriptionStatus;
|
|
1726
|
+
/** 구독 시작일 */
|
|
1727
|
+
started_at: string;
|
|
1728
|
+
/** 현재 기간 시작일 */
|
|
1729
|
+
current_period_start: string;
|
|
1730
|
+
/** 현재 기간 종료일 */
|
|
1731
|
+
current_period_end: string;
|
|
1732
|
+
/** 다음 결제일 */
|
|
1733
|
+
next_billing_at: string | null;
|
|
1734
|
+
/** 취소일 */
|
|
1735
|
+
canceled_at: string | null;
|
|
1736
|
+
/** 종료일 */
|
|
1737
|
+
ended_at: string | null;
|
|
1738
|
+
/** 트라이얼 종료일 */
|
|
1739
|
+
trial_end_at: string | null;
|
|
1740
|
+
/** 총 결제 금액 */
|
|
1741
|
+
total_paid: number;
|
|
1742
|
+
/** 결제 횟수 */
|
|
1743
|
+
payment_count: number;
|
|
1744
|
+
/** 고객 이메일 */
|
|
1745
|
+
customer_email: string;
|
|
1746
|
+
/** 고객 이름 */
|
|
1747
|
+
customer_name: string;
|
|
1748
|
+
/** 메타데이터 */
|
|
1749
|
+
metadata: Record<string, unknown> | null;
|
|
1750
|
+
/** 빌링키 정보 */
|
|
1751
|
+
billing_key?: BillingKeyResponse;
|
|
1752
|
+
/** 생성 일시 */
|
|
1753
|
+
created_at: string;
|
|
1754
|
+
/** 수정 일시 */
|
|
1755
|
+
updated_at: string;
|
|
1756
|
+
}
|
|
1757
|
+
interface UpdateSubscriptionRequest {
|
|
1758
|
+
/** 새 빌링키 ID */
|
|
1759
|
+
billing_key_id?: string;
|
|
1760
|
+
/** 플랜 이름 */
|
|
1761
|
+
plan_name?: string;
|
|
1762
|
+
/** 플랜 설명 */
|
|
1763
|
+
plan_description?: string;
|
|
1764
|
+
/** 결제 금액 */
|
|
1765
|
+
amount?: number;
|
|
1766
|
+
/** 메타데이터 */
|
|
1767
|
+
metadata?: Record<string, unknown>;
|
|
1768
|
+
}
|
|
1769
|
+
interface PauseSubscriptionRequest {
|
|
1770
|
+
/** 일시정지 사유 */
|
|
1771
|
+
reason?: string;
|
|
1772
|
+
}
|
|
1773
|
+
interface CancelSubscriptionRequest {
|
|
1774
|
+
/** 취소 사유 */
|
|
1775
|
+
reason?: string;
|
|
1776
|
+
/** 즉시 취소 여부 (false면 현재 기간 종료 후 취소) */
|
|
1777
|
+
immediate?: boolean;
|
|
1778
|
+
}
|
|
1779
|
+
interface ListSubscriptionsRequest {
|
|
1780
|
+
/** 상태 필터 */
|
|
1781
|
+
status?: SubscriptionStatus;
|
|
1782
|
+
/** 페이지 크기 */
|
|
1783
|
+
limit?: number;
|
|
1784
|
+
/** 오프셋 */
|
|
1785
|
+
offset?: number;
|
|
1786
|
+
}
|
|
1787
|
+
interface ListSubscriptionsResponse {
|
|
1788
|
+
subscriptions: SubscriptionResponse[];
|
|
1789
|
+
total: number;
|
|
1790
|
+
limit: number;
|
|
1791
|
+
offset: number;
|
|
1792
|
+
}
|
|
1793
|
+
type SubscriptionPaymentStatus = 'pending' | 'done' | 'failed' | 'canceled';
|
|
1794
|
+
interface SubscriptionPaymentResponse {
|
|
1795
|
+
/** 결제 ID */
|
|
1796
|
+
id: string;
|
|
1797
|
+
/** 구독 ID */
|
|
1798
|
+
subscription_id: string;
|
|
1799
|
+
/** 토스 결제 키 */
|
|
1800
|
+
payment_key: string;
|
|
1801
|
+
/** 주문 ID */
|
|
1802
|
+
order_id: string;
|
|
1803
|
+
/** 결제 금액 */
|
|
1804
|
+
amount: number;
|
|
1805
|
+
/** 통화 */
|
|
1806
|
+
currency: string;
|
|
1807
|
+
/** 결제 상태 */
|
|
1808
|
+
status: SubscriptionPaymentStatus;
|
|
1809
|
+
/** 기간 시작일 */
|
|
1810
|
+
period_start: string;
|
|
1811
|
+
/** 기간 종료일 */
|
|
1812
|
+
period_end: string;
|
|
1813
|
+
/** 결제 일시 */
|
|
1814
|
+
paid_at: string | null;
|
|
1815
|
+
/** 영수증 URL */
|
|
1816
|
+
receipt_url: string;
|
|
1817
|
+
/** 실패 코드 */
|
|
1818
|
+
failure_code: string;
|
|
1819
|
+
/** 실패 메시지 */
|
|
1820
|
+
failure_message: string;
|
|
1821
|
+
/** 재시도 횟수 */
|
|
1822
|
+
retry_count: number;
|
|
1823
|
+
/** 카드사 */
|
|
1824
|
+
card_company: string;
|
|
1825
|
+
/** 카드 번호 */
|
|
1826
|
+
card_number: string;
|
|
1827
|
+
/** 생성 일시 */
|
|
1828
|
+
created_at: string;
|
|
1829
|
+
}
|
|
1830
|
+
interface ListSubscriptionPaymentsRequest {
|
|
1831
|
+
/** 상태 필터 */
|
|
1832
|
+
status?: SubscriptionPaymentStatus;
|
|
1833
|
+
/** 페이지 크기 */
|
|
1834
|
+
limit?: number;
|
|
1835
|
+
/** 오프셋 */
|
|
1836
|
+
offset?: number;
|
|
1837
|
+
}
|
|
1838
|
+
interface ListSubscriptionPaymentsResponse {
|
|
1839
|
+
payments: SubscriptionPaymentResponse[];
|
|
1840
|
+
total: number;
|
|
1841
|
+
limit: number;
|
|
1842
|
+
offset: number;
|
|
1843
|
+
}
|
|
1844
|
+
interface ChargeWithBillingKeyRequest {
|
|
1845
|
+
/** 빌링키 ID */
|
|
1846
|
+
billing_key_id: string;
|
|
1847
|
+
/** 결제 금액 */
|
|
1848
|
+
amount: number;
|
|
1849
|
+
/** 상품명 */
|
|
1850
|
+
order_name: string;
|
|
1851
|
+
/** 주문 ID (선택) */
|
|
1852
|
+
order_id?: string;
|
|
1853
|
+
/** 고객 이메일 */
|
|
1854
|
+
customer_email?: string;
|
|
1855
|
+
/** 고객 이름 */
|
|
1856
|
+
customer_name?: string;
|
|
1857
|
+
/** 메타데이터 */
|
|
1858
|
+
metadata?: Record<string, unknown>;
|
|
1859
|
+
}
|
|
1860
|
+
interface ChargeWithBillingKeyResponse {
|
|
1861
|
+
/** 토스 결제 키 */
|
|
1862
|
+
payment_key: string;
|
|
1863
|
+
/** 주문 ID */
|
|
1864
|
+
order_id: string;
|
|
1865
|
+
/** 결제 금액 */
|
|
1866
|
+
amount: number;
|
|
1867
|
+
/** 결제 상태 */
|
|
1868
|
+
status: string;
|
|
1869
|
+
/** 영수증 URL */
|
|
1870
|
+
receipt_url: string;
|
|
1871
|
+
/** 승인 일시 */
|
|
1872
|
+
approved_at: string | null;
|
|
1873
|
+
/** 카드사 */
|
|
1874
|
+
card_company: string;
|
|
1875
|
+
/** 카드 번호 */
|
|
1876
|
+
card_number: string;
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
declare class SubscriptionAPI {
|
|
1880
|
+
private http;
|
|
1881
|
+
constructor(http: HttpClient);
|
|
1882
|
+
/**
|
|
1883
|
+
* API Key 인증 시 /v1/public 접두사 반환
|
|
1884
|
+
*/
|
|
1885
|
+
private getPublicPrefix;
|
|
1886
|
+
/**
|
|
1887
|
+
* 빌링키 발급 시작
|
|
1888
|
+
* 토스 카드 등록 위젯에 필요한 정보를 반환합니다.
|
|
1889
|
+
*
|
|
1890
|
+
* @returns 토스 클라이언트 키, 고객 키 등
|
|
1891
|
+
*
|
|
1892
|
+
* @example
|
|
1893
|
+
* ```typescript
|
|
1894
|
+
* const result = await client.subscription.issueBillingKey()
|
|
1895
|
+
*
|
|
1896
|
+
* // 토스 카드 등록 위젯
|
|
1897
|
+
* const tossPayments = TossPayments(result.toss_client_key)
|
|
1898
|
+
* await tossPayments.requestBillingAuth('카드', {
|
|
1899
|
+
* customerKey: result.customer_key,
|
|
1900
|
+
* successUrl: 'https://mysite.com/billing/success',
|
|
1901
|
+
* failUrl: 'https://mysite.com/billing/fail'
|
|
1902
|
+
* })
|
|
1903
|
+
* ```
|
|
1904
|
+
*/
|
|
1905
|
+
issueBillingKey(): Promise<IssueBillingKeyResponse>;
|
|
1906
|
+
/**
|
|
1907
|
+
* 빌링키 등록 확인
|
|
1908
|
+
* 토스에서 카드 등록 완료 후 빌링키를 확정합니다.
|
|
1909
|
+
*
|
|
1910
|
+
* @param data - 등록 확인 정보
|
|
1911
|
+
* @returns 등록된 빌링키 정보
|
|
1912
|
+
*
|
|
1913
|
+
* @example
|
|
1914
|
+
* ```typescript
|
|
1915
|
+
* const billingKey = await client.subscription.confirmBillingKey({
|
|
1916
|
+
* customer_key: 'cust_xxxxx',
|
|
1917
|
+
* auth_key: 'auth_xxxxx',
|
|
1918
|
+
* customer_email: 'test@example.com',
|
|
1919
|
+
* customer_name: '홍길동',
|
|
1920
|
+
* is_default: true
|
|
1921
|
+
* })
|
|
1922
|
+
* ```
|
|
1923
|
+
*/
|
|
1924
|
+
confirmBillingKey(data: ConfirmBillingKeyRequest): Promise<BillingKeyResponse>;
|
|
1925
|
+
/**
|
|
1926
|
+
* 빌링키 목록 조회
|
|
1927
|
+
*
|
|
1928
|
+
* @param customerId - 특정 고객의 빌링키만 조회 (선택)
|
|
1929
|
+
* @returns 빌링키 목록
|
|
1930
|
+
*
|
|
1931
|
+
* @example
|
|
1932
|
+
* ```typescript
|
|
1933
|
+
* const { billing_keys } = await client.subscription.listBillingKeys()
|
|
1934
|
+
* console.log(`등록된 카드: ${billing_keys.length}개`)
|
|
1935
|
+
* ```
|
|
1936
|
+
*/
|
|
1937
|
+
listBillingKeys(customerId?: string): Promise<ListBillingKeysResponse>;
|
|
1938
|
+
/**
|
|
1939
|
+
* 빌링키 상세 조회
|
|
1940
|
+
*
|
|
1941
|
+
* @param billingKeyId - 빌링키 ID
|
|
1942
|
+
* @returns 빌링키 상세 정보
|
|
1943
|
+
*/
|
|
1944
|
+
getBillingKey(billingKeyId: string): Promise<BillingKeyResponse>;
|
|
1945
|
+
/**
|
|
1946
|
+
* 빌링키 수정
|
|
1947
|
+
*
|
|
1948
|
+
* @param billingKeyId - 빌링키 ID
|
|
1949
|
+
* @param data - 수정 정보
|
|
1950
|
+
* @returns 수정된 빌링키 정보
|
|
1951
|
+
*
|
|
1952
|
+
* @example
|
|
1953
|
+
* ```typescript
|
|
1954
|
+
* await client.subscription.updateBillingKey(billingKeyId, {
|
|
1955
|
+
* card_nickname: '주 결제 카드',
|
|
1956
|
+
* is_default: true
|
|
1957
|
+
* })
|
|
1958
|
+
* ```
|
|
1959
|
+
*/
|
|
1960
|
+
updateBillingKey(billingKeyId: string, data: UpdateBillingKeyRequest): Promise<BillingKeyResponse>;
|
|
1961
|
+
/**
|
|
1962
|
+
* 빌링키 삭제
|
|
1963
|
+
*
|
|
1964
|
+
* @param billingKeyId - 빌링키 ID
|
|
1965
|
+
*/
|
|
1966
|
+
deleteBillingKey(billingKeyId: string): Promise<void>;
|
|
1967
|
+
/**
|
|
1968
|
+
* 구독 생성
|
|
1969
|
+
* 정기결제 구독을 생성합니다.
|
|
1970
|
+
*
|
|
1971
|
+
* @param data - 구독 정보
|
|
1972
|
+
* @returns 생성된 구독 정보
|
|
1973
|
+
*
|
|
1974
|
+
* @example
|
|
1975
|
+
* ```typescript
|
|
1976
|
+
* const subscription = await client.subscription.create({
|
|
1977
|
+
* billing_key_id: 'bk_xxxxx',
|
|
1978
|
+
* plan_name: '프리미엄 플랜',
|
|
1979
|
+
* amount: 9900,
|
|
1980
|
+
* billing_cycle: 'monthly',
|
|
1981
|
+
* billing_day: 15, // 매월 15일 결제
|
|
1982
|
+
* trial_days: 7 // 7일 무료 체험
|
|
1983
|
+
* })
|
|
1984
|
+
* ```
|
|
1985
|
+
*/
|
|
1986
|
+
create(data: CreateSubscriptionRequest): Promise<SubscriptionResponse>;
|
|
1987
|
+
/**
|
|
1988
|
+
* 구독 목록 조회
|
|
1989
|
+
*
|
|
1990
|
+
* @param params - 조회 옵션
|
|
1991
|
+
* @returns 구독 목록
|
|
1992
|
+
*
|
|
1993
|
+
* @example
|
|
1994
|
+
* ```typescript
|
|
1995
|
+
* const { subscriptions, total } = await client.subscription.list({
|
|
1996
|
+
* status: 'active',
|
|
1997
|
+
* limit: 10
|
|
1998
|
+
* })
|
|
1999
|
+
* ```
|
|
2000
|
+
*/
|
|
2001
|
+
list(params?: ListSubscriptionsRequest): Promise<ListSubscriptionsResponse>;
|
|
2002
|
+
/**
|
|
2003
|
+
* 구독 상세 조회
|
|
2004
|
+
*
|
|
2005
|
+
* @param subscriptionId - 구독 ID
|
|
2006
|
+
* @returns 구독 상세 정보
|
|
2007
|
+
*/
|
|
2008
|
+
get(subscriptionId: string): Promise<SubscriptionResponse>;
|
|
2009
|
+
/**
|
|
2010
|
+
* 구독 수정
|
|
2011
|
+
*
|
|
2012
|
+
* @param subscriptionId - 구독 ID
|
|
2013
|
+
* @param data - 수정 정보
|
|
2014
|
+
* @returns 수정된 구독 정보
|
|
2015
|
+
*
|
|
2016
|
+
* @example
|
|
2017
|
+
* ```typescript
|
|
2018
|
+
* await client.subscription.update(subscriptionId, {
|
|
2019
|
+
* plan_name: '엔터프라이즈 플랜',
|
|
2020
|
+
* amount: 29900
|
|
2021
|
+
* })
|
|
2022
|
+
* ```
|
|
2023
|
+
*/
|
|
2024
|
+
update(subscriptionId: string, data: UpdateSubscriptionRequest): Promise<SubscriptionResponse>;
|
|
2025
|
+
/**
|
|
2026
|
+
* 구독 일시정지
|
|
2027
|
+
*
|
|
2028
|
+
* @param subscriptionId - 구독 ID
|
|
2029
|
+
* @param data - 일시정지 정보
|
|
2030
|
+
* @returns 일시정지된 구독 정보
|
|
2031
|
+
*
|
|
2032
|
+
* @example
|
|
2033
|
+
* ```typescript
|
|
2034
|
+
* await client.subscription.pause(subscriptionId, {
|
|
2035
|
+
* reason: '고객 요청'
|
|
2036
|
+
* })
|
|
2037
|
+
* ```
|
|
2038
|
+
*/
|
|
2039
|
+
pause(subscriptionId: string, data?: PauseSubscriptionRequest): Promise<SubscriptionResponse>;
|
|
2040
|
+
/**
|
|
2041
|
+
* 구독 재개
|
|
2042
|
+
*
|
|
2043
|
+
* @param subscriptionId - 구독 ID
|
|
2044
|
+
* @returns 재개된 구독 정보
|
|
2045
|
+
*
|
|
2046
|
+
* @example
|
|
2047
|
+
* ```typescript
|
|
2048
|
+
* await client.subscription.resume(subscriptionId)
|
|
2049
|
+
* ```
|
|
2050
|
+
*/
|
|
2051
|
+
resume(subscriptionId: string): Promise<SubscriptionResponse>;
|
|
2052
|
+
/**
|
|
2053
|
+
* 구독 취소
|
|
2054
|
+
*
|
|
2055
|
+
* @param subscriptionId - 구독 ID
|
|
2056
|
+
* @param data - 취소 정보
|
|
2057
|
+
* @returns 취소된 구독 정보
|
|
2058
|
+
*
|
|
2059
|
+
* @example
|
|
2060
|
+
* ```typescript
|
|
2061
|
+
* // 현재 기간 종료 후 취소
|
|
2062
|
+
* await client.subscription.cancel(subscriptionId, {
|
|
2063
|
+
* reason: '서비스 불만족'
|
|
2064
|
+
* })
|
|
2065
|
+
*
|
|
2066
|
+
* // 즉시 취소
|
|
2067
|
+
* await client.subscription.cancel(subscriptionId, {
|
|
2068
|
+
* reason: '즉시 해지 요청',
|
|
2069
|
+
* immediate: true
|
|
2070
|
+
* })
|
|
2071
|
+
* ```
|
|
2072
|
+
*/
|
|
2073
|
+
cancel(subscriptionId: string, data: CancelSubscriptionRequest): Promise<SubscriptionResponse>;
|
|
2074
|
+
/**
|
|
2075
|
+
* 구독 결제 이력 조회
|
|
2076
|
+
*
|
|
2077
|
+
* @param subscriptionId - 구독 ID
|
|
2078
|
+
* @param params - 조회 옵션
|
|
2079
|
+
* @returns 결제 이력 목록
|
|
2080
|
+
*
|
|
2081
|
+
* @example
|
|
2082
|
+
* ```typescript
|
|
2083
|
+
* const { payments } = await client.subscription.listPayments(subscriptionId, {
|
|
2084
|
+
* limit: 10
|
|
2085
|
+
* })
|
|
2086
|
+
* ```
|
|
2087
|
+
*/
|
|
2088
|
+
listPayments(subscriptionId: string, params?: ListSubscriptionPaymentsRequest): Promise<ListSubscriptionPaymentsResponse>;
|
|
2089
|
+
/**
|
|
2090
|
+
* 빌링키로 즉시 결제
|
|
2091
|
+
* 구독 없이 빌링키로 일회성 결제를 진행합니다.
|
|
2092
|
+
*
|
|
2093
|
+
* @param data - 결제 정보
|
|
2094
|
+
* @returns 결제 결과
|
|
2095
|
+
*
|
|
2096
|
+
* @example
|
|
2097
|
+
* ```typescript
|
|
2098
|
+
* const result = await client.subscription.chargeWithBillingKey({
|
|
2099
|
+
* billing_key_id: 'bk_xxxxx',
|
|
2100
|
+
* amount: 15000,
|
|
2101
|
+
* order_name: '추가 결제'
|
|
2102
|
+
* })
|
|
2103
|
+
*
|
|
2104
|
+
* if (result.status === 'DONE') {
|
|
2105
|
+
* console.log('결제 완료!')
|
|
2106
|
+
* }
|
|
2107
|
+
* ```
|
|
2108
|
+
*/
|
|
2109
|
+
chargeWithBillingKey(data: ChargeWithBillingKeyRequest): Promise<ChargeWithBillingKeyResponse>;
|
|
2110
|
+
}
|
|
2111
|
+
|
|
2112
|
+
/**
|
|
2113
|
+
* Push Notification Types
|
|
2114
|
+
*/
|
|
2115
|
+
type PushPlatform = 'ios' | 'android' | 'web';
|
|
2116
|
+
interface RegisterDeviceRequest {
|
|
2117
|
+
/** 디바이스 토큰 (APNS/FCM/Web Push) */
|
|
2118
|
+
device_token: string;
|
|
2119
|
+
/** 플랫폼 */
|
|
2120
|
+
platform: PushPlatform;
|
|
2121
|
+
/** 디바이스 고유 ID (optional) */
|
|
2122
|
+
device_id?: string;
|
|
2123
|
+
/** 디바이스 이름 (예: "iPhone 15 Pro") */
|
|
2124
|
+
device_name?: string;
|
|
2125
|
+
/** 디바이스 모델 (예: "iPhone15,2") */
|
|
2126
|
+
device_model?: string;
|
|
2127
|
+
/** OS 버전 (예: "17.0") */
|
|
2128
|
+
os_version?: string;
|
|
2129
|
+
/** 앱 버전 (예: "1.0.0") */
|
|
2130
|
+
app_version?: string;
|
|
2131
|
+
/** 언어 코드 (예: "ko") */
|
|
2132
|
+
language?: string;
|
|
2133
|
+
/** 타임존 (예: "Asia/Seoul") */
|
|
2134
|
+
timezone?: string;
|
|
2135
|
+
}
|
|
2136
|
+
interface DeviceInfo {
|
|
2137
|
+
id: string;
|
|
2138
|
+
device_token: string;
|
|
2139
|
+
platform: PushPlatform;
|
|
2140
|
+
device_id?: string;
|
|
2141
|
+
device_name?: string;
|
|
2142
|
+
device_model?: string;
|
|
2143
|
+
os_version?: string;
|
|
2144
|
+
app_version?: string;
|
|
2145
|
+
language?: string;
|
|
2146
|
+
timezone?: string;
|
|
2147
|
+
is_active: boolean;
|
|
2148
|
+
last_active_at?: string;
|
|
2149
|
+
created_at: string;
|
|
2150
|
+
updated_at: string;
|
|
2151
|
+
}
|
|
2152
|
+
interface SubscribeTopicRequest {
|
|
2153
|
+
/** 토픽 이름 */
|
|
2154
|
+
topic_name: string;
|
|
2155
|
+
}
|
|
2156
|
+
interface VAPIDPublicKeyResponse {
|
|
2157
|
+
public_key: string;
|
|
2158
|
+
}
|
|
2159
|
+
interface WebPushSubscription {
|
|
2160
|
+
endpoint: string;
|
|
2161
|
+
expirationTime?: number | null;
|
|
2162
|
+
keys: {
|
|
2163
|
+
p256dh: string;
|
|
2164
|
+
auth: string;
|
|
2165
|
+
};
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
/**
|
|
2169
|
+
* 푸시 알림 API
|
|
2170
|
+
*
|
|
2171
|
+
* @example
|
|
2172
|
+
* ```typescript
|
|
2173
|
+
* // 디바이스 등록 (모바일 앱)
|
|
2174
|
+
* const device = await cb.push.registerDevice({
|
|
2175
|
+
* device_token: 'fcm-token-here',
|
|
2176
|
+
* platform: 'android',
|
|
2177
|
+
* device_name: 'Galaxy S24',
|
|
2178
|
+
* })
|
|
2179
|
+
*
|
|
2180
|
+
* // 토픽 구독
|
|
2181
|
+
* await cb.push.subscribeTopic('announcements')
|
|
2182
|
+
*
|
|
2183
|
+
* // Web Push 등록 (브라우저)
|
|
2184
|
+
* const vapidKey = await cb.push.getVAPIDPublicKey()
|
|
2185
|
+
* const subscription = await registration.pushManager.subscribe({
|
|
2186
|
+
* userVisibleOnly: true,
|
|
2187
|
+
* applicationServerKey: vapidKey.public_key
|
|
2188
|
+
* })
|
|
2189
|
+
* await cb.push.registerWebPush(subscription)
|
|
2190
|
+
* ```
|
|
2191
|
+
*/
|
|
2192
|
+
declare class PushAPI {
|
|
2193
|
+
private http;
|
|
2194
|
+
constructor(http: HttpClient);
|
|
2195
|
+
/**
|
|
2196
|
+
* API Key 인증 시 /v1/public 접두사 반환
|
|
2197
|
+
*/
|
|
2198
|
+
private getPublicPrefix;
|
|
2199
|
+
/**
|
|
2200
|
+
* 디바이스 등록 (APNS/FCM 토큰)
|
|
2201
|
+
*
|
|
2202
|
+
* @param request 디바이스 등록 정보
|
|
2203
|
+
* @returns 등록된 디바이스 정보
|
|
2204
|
+
*
|
|
2205
|
+
* @example
|
|
2206
|
+
* ```typescript
|
|
2207
|
+
* // iOS 디바이스 등록
|
|
2208
|
+
* const device = await cb.push.registerDevice({
|
|
2209
|
+
* device_token: 'apns-token-here',
|
|
2210
|
+
* platform: 'ios',
|
|
2211
|
+
* device_name: 'iPhone 15 Pro',
|
|
2212
|
+
* device_model: 'iPhone15,2',
|
|
2213
|
+
* os_version: '17.0',
|
|
2214
|
+
* app_version: '1.0.0',
|
|
2215
|
+
* })
|
|
2216
|
+
*
|
|
2217
|
+
* // Android 디바이스 등록
|
|
2218
|
+
* const device = await cb.push.registerDevice({
|
|
2219
|
+
* device_token: 'fcm-token-here',
|
|
2220
|
+
* platform: 'android',
|
|
2221
|
+
* device_name: 'Galaxy S24',
|
|
2222
|
+
* })
|
|
2223
|
+
* ```
|
|
2224
|
+
*/
|
|
2225
|
+
registerDevice(request: RegisterDeviceRequest): Promise<DeviceInfo>;
|
|
2226
|
+
/**
|
|
2227
|
+
* 디바이스 등록 해제
|
|
2228
|
+
*
|
|
2229
|
+
* @param deviceId 디바이스 ID
|
|
2230
|
+
*
|
|
2231
|
+
* @example
|
|
2232
|
+
* ```typescript
|
|
2233
|
+
* await cb.push.unregisterDevice('device-id-here')
|
|
2234
|
+
* ```
|
|
2235
|
+
*/
|
|
2236
|
+
unregisterDevice(deviceId: string): Promise<void>;
|
|
2237
|
+
/**
|
|
2238
|
+
* 현재 등록된 디바이스 목록 조회
|
|
2239
|
+
*
|
|
2240
|
+
* @returns 디바이스 목록
|
|
2241
|
+
*/
|
|
2242
|
+
getDevices(): Promise<DeviceInfo[]>;
|
|
2243
|
+
/**
|
|
2244
|
+
* 토픽 구독
|
|
2245
|
+
*
|
|
2246
|
+
* @param topicName 토픽 이름
|
|
2247
|
+
*
|
|
2248
|
+
* @example
|
|
2249
|
+
* ```typescript
|
|
2250
|
+
* // 공지사항 토픽 구독
|
|
2251
|
+
* await cb.push.subscribeTopic('announcements')
|
|
2252
|
+
*
|
|
2253
|
+
* // 마케팅 토픽 구독
|
|
2254
|
+
* await cb.push.subscribeTopic('marketing')
|
|
2255
|
+
* ```
|
|
2256
|
+
*/
|
|
2257
|
+
subscribeTopic(topicName: string): Promise<void>;
|
|
2258
|
+
/**
|
|
2259
|
+
* 토픽 구독 해제
|
|
2260
|
+
*
|
|
2261
|
+
* @param topicName 토픽 이름
|
|
2262
|
+
*
|
|
2263
|
+
* @example
|
|
2264
|
+
* ```typescript
|
|
2265
|
+
* await cb.push.unsubscribeTopic('marketing')
|
|
2266
|
+
* ```
|
|
2267
|
+
*/
|
|
2268
|
+
unsubscribeTopic(topicName: string): Promise<void>;
|
|
2269
|
+
/**
|
|
2270
|
+
* 구독 중인 토픽 목록 조회
|
|
2271
|
+
*
|
|
2272
|
+
* @returns 구독 중인 토픽 이름 목록
|
|
2273
|
+
*/
|
|
2274
|
+
getSubscribedTopics(): Promise<string[]>;
|
|
2275
|
+
/**
|
|
2276
|
+
* VAPID Public Key 조회 (Web Push용)
|
|
2277
|
+
*
|
|
2278
|
+
* @returns VAPID Public Key
|
|
2279
|
+
*
|
|
2280
|
+
* @example
|
|
2281
|
+
* ```typescript
|
|
2282
|
+
* const vapidKey = await cb.push.getVAPIDPublicKey()
|
|
2283
|
+
*
|
|
2284
|
+
* // Service Worker에서 Push 구독
|
|
2285
|
+
* const registration = await navigator.serviceWorker.ready
|
|
2286
|
+
* const subscription = await registration.pushManager.subscribe({
|
|
2287
|
+
* userVisibleOnly: true,
|
|
2288
|
+
* applicationServerKey: urlBase64ToUint8Array(vapidKey.public_key)
|
|
2289
|
+
* })
|
|
2290
|
+
*
|
|
2291
|
+
* // 구독 정보 등록
|
|
2292
|
+
* await cb.push.registerWebPush(subscription)
|
|
2293
|
+
* ```
|
|
2294
|
+
*/
|
|
2295
|
+
getVAPIDPublicKey(): Promise<VAPIDPublicKeyResponse>;
|
|
2296
|
+
/**
|
|
2297
|
+
* Web Push 구독 등록
|
|
2298
|
+
*
|
|
2299
|
+
* @param subscription PushSubscription 객체 또는 WebPushSubscription
|
|
2300
|
+
*
|
|
2301
|
+
* @example
|
|
2302
|
+
* ```typescript
|
|
2303
|
+
* // 브라우저에서 Push 구독 후 등록
|
|
2304
|
+
* const registration = await navigator.serviceWorker.ready
|
|
2305
|
+
* const subscription = await registration.pushManager.subscribe({
|
|
2306
|
+
* userVisibleOnly: true,
|
|
2307
|
+
* applicationServerKey: vapidPublicKey
|
|
2308
|
+
* })
|
|
2309
|
+
*
|
|
2310
|
+
* await cb.push.registerWebPush(subscription)
|
|
2311
|
+
* ```
|
|
2312
|
+
*/
|
|
2313
|
+
registerWebPush(subscription: PushSubscription | WebPushSubscription): Promise<DeviceInfo>;
|
|
2314
|
+
/**
|
|
2315
|
+
* Web Push 구독 해제
|
|
2316
|
+
*/
|
|
2317
|
+
unregisterWebPush(): Promise<void>;
|
|
2318
|
+
/**
|
|
2319
|
+
* 브라우저 고유 ID 생성 (localStorage에 저장)
|
|
2320
|
+
*/
|
|
2321
|
+
private generateDeviceId;
|
|
2322
|
+
/**
|
|
2323
|
+
* 브라우저 이름 감지
|
|
2324
|
+
*/
|
|
2325
|
+
private getBrowserName;
|
|
2326
|
+
/**
|
|
2327
|
+
* OS 정보 감지
|
|
2328
|
+
*/
|
|
2329
|
+
private getOSInfo;
|
|
2330
|
+
}
|
|
2331
|
+
|
|
2332
|
+
interface Video {
|
|
2333
|
+
id: string;
|
|
2334
|
+
channel_id: string;
|
|
2335
|
+
title: string;
|
|
2336
|
+
description?: string;
|
|
2337
|
+
status: VideoStatus;
|
|
2338
|
+
visibility: VideoVisibility;
|
|
2339
|
+
duration?: number;
|
|
2340
|
+
original_filename: string;
|
|
2341
|
+
original_size: number;
|
|
2342
|
+
qualities: VideoQuality[];
|
|
2343
|
+
thumbnail_url?: string;
|
|
2344
|
+
stream_url?: string;
|
|
2345
|
+
tags?: string[];
|
|
2346
|
+
view_count: number;
|
|
2347
|
+
like_count: number;
|
|
2348
|
+
comment_count: number;
|
|
2349
|
+
created_at: string;
|
|
2350
|
+
updated_at: string;
|
|
2351
|
+
}
|
|
2352
|
+
type VideoStatus = 'uploading' | 'processing' | 'ready' | 'failed';
|
|
2353
|
+
type VideoVisibility = 'public' | 'private' | 'unlisted' | 'members_only' | 'ppv';
|
|
2354
|
+
interface VideoQuality {
|
|
2355
|
+
quality: string;
|
|
2356
|
+
width: number;
|
|
2357
|
+
height: number;
|
|
2358
|
+
bitrate: number;
|
|
2359
|
+
size: number;
|
|
2360
|
+
status: 'pending' | 'processing' | 'ready' | 'failed';
|
|
2361
|
+
}
|
|
2362
|
+
interface VideoListResponse {
|
|
2363
|
+
videos: Video[];
|
|
2364
|
+
total: number;
|
|
2365
|
+
page: number;
|
|
2366
|
+
limit: number;
|
|
2367
|
+
}
|
|
2368
|
+
interface VideoListOptions {
|
|
2369
|
+
status?: VideoStatus;
|
|
2370
|
+
visibility?: VideoVisibility;
|
|
2371
|
+
search?: string;
|
|
2372
|
+
channel_id?: string;
|
|
2373
|
+
page?: number;
|
|
2374
|
+
limit?: number;
|
|
2375
|
+
}
|
|
2376
|
+
interface UploadOptions {
|
|
2377
|
+
title: string;
|
|
2378
|
+
description?: string;
|
|
2379
|
+
visibility?: VideoVisibility;
|
|
2380
|
+
tags?: string[];
|
|
2381
|
+
channel_id?: string;
|
|
2382
|
+
onProgress?: (progress: UploadProgress) => void;
|
|
2383
|
+
}
|
|
2384
|
+
interface UploadProgress {
|
|
2385
|
+
phase: 'uploading' | 'processing' | 'complete';
|
|
2386
|
+
uploadedChunks: number;
|
|
2387
|
+
totalChunks: number;
|
|
2388
|
+
percentage: number;
|
|
2389
|
+
currentSpeed?: number;
|
|
2390
|
+
}
|
|
2391
|
+
interface UpdateVideoRequest {
|
|
2392
|
+
title?: string;
|
|
2393
|
+
description?: string;
|
|
2394
|
+
visibility?: VideoVisibility;
|
|
2395
|
+
tags?: string[];
|
|
2396
|
+
thumbnail_url?: string;
|
|
2397
|
+
}
|
|
2398
|
+
interface StreamURLResponse {
|
|
2399
|
+
url: string;
|
|
2400
|
+
expires_at: string;
|
|
2401
|
+
quality?: string;
|
|
2402
|
+
}
|
|
2403
|
+
interface InitUploadResponse {
|
|
2404
|
+
session_id: string;
|
|
2405
|
+
video_id: string;
|
|
2406
|
+
chunk_size: number;
|
|
2407
|
+
total_chunks: number;
|
|
2408
|
+
}
|
|
2409
|
+
interface TranscodeStatus {
|
|
2410
|
+
video_id: string;
|
|
2411
|
+
status: 'pending' | 'processing' | 'completed' | 'failed';
|
|
2412
|
+
progress: number;
|
|
2413
|
+
qualities: QualityProgress[];
|
|
2414
|
+
error?: string;
|
|
2415
|
+
}
|
|
2416
|
+
interface QualityProgress {
|
|
2417
|
+
quality: string;
|
|
2418
|
+
status: 'pending' | 'processing' | 'completed' | 'failed';
|
|
2419
|
+
progress: number;
|
|
2420
|
+
}
|
|
2421
|
+
interface WaitOptions {
|
|
2422
|
+
timeout?: number;
|
|
2423
|
+
interval?: number;
|
|
2424
|
+
onProgress?: (progress: UploadProgress) => void;
|
|
2425
|
+
}
|
|
2426
|
+
interface Channel {
|
|
2427
|
+
id: string;
|
|
2428
|
+
owner_id: string;
|
|
2429
|
+
handle: string;
|
|
2430
|
+
name: string;
|
|
2431
|
+
description?: string;
|
|
2432
|
+
avatar_url?: string;
|
|
2433
|
+
banner_url?: string;
|
|
2434
|
+
subscriber_count: number;
|
|
2435
|
+
video_count: number;
|
|
2436
|
+
total_views: number;
|
|
2437
|
+
is_verified: boolean;
|
|
2438
|
+
created_at: string;
|
|
2439
|
+
updated_at: string;
|
|
2440
|
+
}
|
|
2441
|
+
interface CreateChannelRequest {
|
|
2442
|
+
handle: string;
|
|
2443
|
+
name: string;
|
|
2444
|
+
description?: string;
|
|
2445
|
+
}
|
|
2446
|
+
interface UpdateChannelRequest {
|
|
2447
|
+
name?: string;
|
|
2448
|
+
description?: string;
|
|
2449
|
+
avatar_url?: string;
|
|
2450
|
+
banner_url?: string;
|
|
2451
|
+
}
|
|
2452
|
+
interface Playlist {
|
|
2453
|
+
id: string;
|
|
2454
|
+
channel_id: string;
|
|
2455
|
+
title: string;
|
|
2456
|
+
description?: string;
|
|
2457
|
+
visibility: VideoVisibility;
|
|
2458
|
+
thumbnail_url?: string;
|
|
2459
|
+
video_count: number;
|
|
2460
|
+
total_duration: number;
|
|
2461
|
+
created_at: string;
|
|
2462
|
+
updated_at: string;
|
|
2463
|
+
}
|
|
2464
|
+
interface CreatePlaylistRequest {
|
|
2465
|
+
title: string;
|
|
2466
|
+
description?: string;
|
|
2467
|
+
visibility?: VideoVisibility;
|
|
2468
|
+
}
|
|
2469
|
+
interface PlaylistItem {
|
|
2470
|
+
id: string;
|
|
2471
|
+
playlist_id: string;
|
|
2472
|
+
video_id: string;
|
|
2473
|
+
position: number;
|
|
2474
|
+
video?: Video;
|
|
2475
|
+
added_at: string;
|
|
2476
|
+
}
|
|
2477
|
+
interface Shorts {
|
|
2478
|
+
id: string;
|
|
2479
|
+
channel_id: string;
|
|
2480
|
+
video_id: string;
|
|
2481
|
+
title: string;
|
|
2482
|
+
description?: string;
|
|
2483
|
+
visibility: VideoVisibility;
|
|
2484
|
+
view_count: number;
|
|
2485
|
+
like_count: number;
|
|
2486
|
+
comment_count: number;
|
|
2487
|
+
share_count: number;
|
|
2488
|
+
is_remixable: boolean;
|
|
2489
|
+
original_shorts_id?: string;
|
|
2490
|
+
created_at: string;
|
|
2491
|
+
}
|
|
2492
|
+
interface ShortsListResponse {
|
|
2493
|
+
shorts: Shorts[];
|
|
2494
|
+
total: number;
|
|
2495
|
+
next_cursor?: string;
|
|
2496
|
+
}
|
|
2497
|
+
interface VideoComment {
|
|
2498
|
+
id: string;
|
|
2499
|
+
video_id: string;
|
|
2500
|
+
member_id: string;
|
|
2501
|
+
content: string;
|
|
2502
|
+
parent_id?: string;
|
|
2503
|
+
like_count: number;
|
|
2504
|
+
reply_count: number;
|
|
2505
|
+
is_pinned: boolean;
|
|
2506
|
+
is_hearted: boolean;
|
|
2507
|
+
member?: {
|
|
2508
|
+
id: string;
|
|
2509
|
+
name: string;
|
|
2510
|
+
avatar_url?: string;
|
|
2511
|
+
};
|
|
2512
|
+
created_at: string;
|
|
2513
|
+
updated_at: string;
|
|
2514
|
+
}
|
|
2515
|
+
interface CommentListResponse {
|
|
2516
|
+
comments: VideoComment[];
|
|
2517
|
+
total: number;
|
|
2518
|
+
next_cursor?: string;
|
|
2519
|
+
}
|
|
2520
|
+
interface WatchHistoryItem {
|
|
2521
|
+
id: string;
|
|
2522
|
+
video_id: string;
|
|
2523
|
+
video?: Video;
|
|
2524
|
+
watch_duration: number;
|
|
2525
|
+
completed: boolean;
|
|
2526
|
+
last_position: number;
|
|
2527
|
+
watched_at: string;
|
|
2528
|
+
}
|
|
2529
|
+
interface MembershipTier {
|
|
2530
|
+
id: string;
|
|
2531
|
+
channel_id: string;
|
|
2532
|
+
name: string;
|
|
2533
|
+
description?: string;
|
|
2534
|
+
level: number;
|
|
2535
|
+
price: number;
|
|
2536
|
+
currency: string;
|
|
2537
|
+
billing_period: 'monthly' | 'yearly';
|
|
2538
|
+
perks: string[];
|
|
2539
|
+
badge_url?: string;
|
|
2540
|
+
badge_color?: string;
|
|
2541
|
+
member_count: number;
|
|
2542
|
+
is_active: boolean;
|
|
2543
|
+
}
|
|
2544
|
+
interface ChannelMembership {
|
|
2545
|
+
id: string;
|
|
2546
|
+
channel_id: string;
|
|
2547
|
+
member_id: string;
|
|
2548
|
+
tier_id: string;
|
|
2549
|
+
tier?: MembershipTier;
|
|
2550
|
+
status: 'active' | 'cancelled' | 'expired' | 'paused';
|
|
2551
|
+
started_at: string;
|
|
2552
|
+
expires_at?: string;
|
|
2553
|
+
}
|
|
2554
|
+
interface SuperChat {
|
|
2555
|
+
id: string;
|
|
2556
|
+
video_id: string;
|
|
2557
|
+
member_id: string;
|
|
2558
|
+
amount: number;
|
|
2559
|
+
currency: string;
|
|
2560
|
+
message?: string;
|
|
2561
|
+
color: string;
|
|
2562
|
+
display_duration: number;
|
|
2563
|
+
status: 'pending' | 'confirmed' | 'refunded';
|
|
2564
|
+
member?: {
|
|
2565
|
+
id: string;
|
|
2566
|
+
name: string;
|
|
2567
|
+
avatar_url?: string;
|
|
2568
|
+
};
|
|
2569
|
+
created_at: string;
|
|
2570
|
+
}
|
|
2571
|
+
|
|
2572
|
+
declare class VideoProcessingError extends Error {
|
|
2573
|
+
video?: Video;
|
|
2574
|
+
constructor(message: string, video?: Video);
|
|
2575
|
+
}
|
|
2576
|
+
/**
|
|
2577
|
+
* Video API for uploading, streaming, and managing videos
|
|
2578
|
+
*/
|
|
2579
|
+
declare class VideoAPI {
|
|
2580
|
+
private http;
|
|
2581
|
+
private videoBaseUrl;
|
|
2582
|
+
constructor(http: HttpClient, videoBaseUrl?: string);
|
|
2583
|
+
private getDefaultVideoUrl;
|
|
2584
|
+
private getPublicPrefix;
|
|
2585
|
+
private videoFetch;
|
|
2586
|
+
/**
|
|
2587
|
+
* Upload a video file with chunked upload support
|
|
2588
|
+
*/
|
|
2589
|
+
upload(file: File, options: UploadOptions): Promise<Video>;
|
|
2590
|
+
/**
|
|
2591
|
+
* Wait for video processing to complete
|
|
2592
|
+
*/
|
|
2593
|
+
waitForReady(videoId: string, options?: WaitOptions): Promise<Video>;
|
|
2594
|
+
/**
|
|
2595
|
+
* List videos
|
|
2596
|
+
*/
|
|
2597
|
+
list(options?: VideoListOptions): Promise<VideoListResponse>;
|
|
2598
|
+
/**
|
|
2599
|
+
* Get a single video
|
|
2600
|
+
*/
|
|
2601
|
+
get(videoId: string): Promise<Video>;
|
|
2602
|
+
/**
|
|
2603
|
+
* Update video details
|
|
2604
|
+
*/
|
|
2605
|
+
update(videoId: string, data: UpdateVideoRequest): Promise<Video>;
|
|
2606
|
+
/**
|
|
2607
|
+
* Delete a video
|
|
2608
|
+
*/
|
|
2609
|
+
delete(videoId: string): Promise<void>;
|
|
2610
|
+
/**
|
|
2611
|
+
* Get streaming URL for a video
|
|
2612
|
+
*/
|
|
2613
|
+
getStreamUrl(videoId: string, quality?: string): Promise<StreamURLResponse>;
|
|
2614
|
+
/**
|
|
2615
|
+
* Get available thumbnails for a video
|
|
2616
|
+
*/
|
|
2617
|
+
getThumbnails(videoId: string): Promise<string[]>;
|
|
2618
|
+
/**
|
|
2619
|
+
* Get transcode status
|
|
2620
|
+
*/
|
|
2621
|
+
getTranscodeStatus(videoId: string): Promise<TranscodeStatus>;
|
|
2622
|
+
/**
|
|
2623
|
+
* Retry failed transcoding
|
|
2624
|
+
*/
|
|
2625
|
+
retryTranscode(videoId: string): Promise<void>;
|
|
2626
|
+
/**
|
|
2627
|
+
* Create a channel
|
|
2628
|
+
*/
|
|
2629
|
+
createChannel(data: CreateChannelRequest): Promise<Channel>;
|
|
2630
|
+
/**
|
|
2631
|
+
* Get a channel
|
|
2632
|
+
*/
|
|
2633
|
+
getChannel(channelId: string): Promise<Channel>;
|
|
2634
|
+
/**
|
|
2635
|
+
* Get channel by handle
|
|
2636
|
+
*/
|
|
2637
|
+
getChannelByHandle(handle: string): Promise<Channel>;
|
|
2638
|
+
/**
|
|
2639
|
+
* Update channel
|
|
2640
|
+
*/
|
|
2641
|
+
updateChannel(channelId: string, data: UpdateChannelRequest): Promise<Channel>;
|
|
2642
|
+
/**
|
|
2643
|
+
* Subscribe to a channel
|
|
2644
|
+
*/
|
|
2645
|
+
subscribeChannel(channelId: string): Promise<void>;
|
|
2646
|
+
/**
|
|
2647
|
+
* Unsubscribe from a channel
|
|
2648
|
+
*/
|
|
2649
|
+
unsubscribeChannel(channelId: string): Promise<void>;
|
|
2650
|
+
/**
|
|
2651
|
+
* Create a playlist
|
|
2652
|
+
*/
|
|
2653
|
+
createPlaylist(channelId: string, data: CreatePlaylistRequest): Promise<Playlist>;
|
|
2654
|
+
/**
|
|
2655
|
+
* Get playlists for a channel
|
|
2656
|
+
*/
|
|
2657
|
+
getPlaylists(channelId: string): Promise<Playlist[]>;
|
|
2658
|
+
/**
|
|
2659
|
+
* Get playlist items
|
|
2660
|
+
*/
|
|
2661
|
+
getPlaylistItems(playlistId: string): Promise<PlaylistItem[]>;
|
|
2662
|
+
/**
|
|
2663
|
+
* Add video to playlist
|
|
2664
|
+
*/
|
|
2665
|
+
addToPlaylist(playlistId: string, videoId: string, position?: number): Promise<PlaylistItem>;
|
|
2666
|
+
/**
|
|
2667
|
+
* Remove video from playlist
|
|
2668
|
+
*/
|
|
2669
|
+
removeFromPlaylist(playlistId: string, itemId: string): Promise<void>;
|
|
2670
|
+
/**
|
|
2671
|
+
* Get shorts feed
|
|
2672
|
+
*/
|
|
2673
|
+
getShortsFeed(options?: {
|
|
2674
|
+
cursor?: string;
|
|
2675
|
+
limit?: number;
|
|
2676
|
+
}): Promise<ShortsListResponse>;
|
|
2677
|
+
/**
|
|
2678
|
+
* Get trending shorts
|
|
2679
|
+
*/
|
|
2680
|
+
getTrendingShorts(limit?: number): Promise<ShortsListResponse>;
|
|
2681
|
+
/**
|
|
2682
|
+
* Get a single shorts
|
|
2683
|
+
*/
|
|
2684
|
+
getShorts(shortsId: string): Promise<Shorts>;
|
|
2685
|
+
/**
|
|
2686
|
+
* Get comments for a video
|
|
2687
|
+
*/
|
|
2688
|
+
getComments(videoId: string, options?: {
|
|
2689
|
+
cursor?: string;
|
|
2690
|
+
limit?: number;
|
|
2691
|
+
sort?: 'recent' | 'popular';
|
|
2692
|
+
}): Promise<CommentListResponse>;
|
|
2693
|
+
/**
|
|
2694
|
+
* Post a comment
|
|
2695
|
+
*/
|
|
2696
|
+
postComment(videoId: string, content: string, parentId?: string): Promise<VideoComment>;
|
|
2697
|
+
/**
|
|
2698
|
+
* Delete a comment
|
|
2699
|
+
*/
|
|
2700
|
+
deleteComment(commentId: string): Promise<void>;
|
|
2701
|
+
/**
|
|
2702
|
+
* Like a video
|
|
2703
|
+
*/
|
|
2704
|
+
likeVideo(videoId: string): Promise<void>;
|
|
2705
|
+
/**
|
|
2706
|
+
* Unlike a video
|
|
2707
|
+
*/
|
|
2708
|
+
unlikeVideo(videoId: string): Promise<void>;
|
|
2709
|
+
/**
|
|
2710
|
+
* Get watch history
|
|
2711
|
+
*/
|
|
2712
|
+
getWatchHistory(options?: {
|
|
2713
|
+
cursor?: string;
|
|
2714
|
+
limit?: number;
|
|
2715
|
+
}): Promise<{
|
|
2716
|
+
items: WatchHistoryItem[];
|
|
2717
|
+
next_cursor?: string;
|
|
2718
|
+
}>;
|
|
2719
|
+
/**
|
|
2720
|
+
* Clear watch history
|
|
2721
|
+
*/
|
|
2722
|
+
clearWatchHistory(): Promise<void>;
|
|
2723
|
+
/**
|
|
2724
|
+
* Report watch progress
|
|
2725
|
+
*/
|
|
2726
|
+
reportWatchProgress(videoId: string, position: number, duration: number): Promise<void>;
|
|
2727
|
+
/**
|
|
2728
|
+
* Get membership tiers for a channel
|
|
2729
|
+
*/
|
|
2730
|
+
getMembershipTiers(channelId: string): Promise<MembershipTier[]>;
|
|
2731
|
+
/**
|
|
2732
|
+
* Join a membership tier
|
|
2733
|
+
*/
|
|
2734
|
+
joinMembership(channelId: string, tierId: string): Promise<ChannelMembership>;
|
|
2735
|
+
/**
|
|
2736
|
+
* Cancel membership
|
|
2737
|
+
*/
|
|
2738
|
+
cancelMembership(channelId: string, membershipId: string): Promise<void>;
|
|
2739
|
+
/**
|
|
2740
|
+
* Send a super chat
|
|
2741
|
+
*/
|
|
2742
|
+
sendSuperChat(videoId: string, amount: number, message?: string, currency?: string): Promise<SuperChat>;
|
|
2743
|
+
/**
|
|
2744
|
+
* Get super chats for a video
|
|
2745
|
+
*/
|
|
2746
|
+
getSuperChats(videoId: string): Promise<SuperChat[]>;
|
|
2747
|
+
/**
|
|
2748
|
+
* Get recommended videos
|
|
2749
|
+
*/
|
|
2750
|
+
getRecommendations(limit?: number): Promise<Video[]>;
|
|
2751
|
+
/**
|
|
2752
|
+
* Get home feed
|
|
2753
|
+
*/
|
|
2754
|
+
getHomeFeed(limit?: number): Promise<Video[]>;
|
|
2755
|
+
/**
|
|
2756
|
+
* Get related videos
|
|
2757
|
+
*/
|
|
2758
|
+
getRelatedVideos(videoId: string, limit?: number): Promise<Video[]>;
|
|
2759
|
+
/**
|
|
2760
|
+
* Get trending videos
|
|
2761
|
+
*/
|
|
2762
|
+
getTrendingVideos(limit?: number): Promise<Video[]>;
|
|
2763
|
+
/**
|
|
2764
|
+
* Submit recommendation feedback
|
|
2765
|
+
*/
|
|
2766
|
+
submitFeedback(videoId: string, feedback: 'interested' | 'not_interested'): Promise<void>;
|
|
2767
|
+
}
|
|
2768
|
+
|
|
2769
|
+
/**
|
|
2770
|
+
* Game Server Types
|
|
2771
|
+
*/
|
|
2772
|
+
/**
|
|
2773
|
+
* 게임 룸 설정
|
|
2774
|
+
*/
|
|
2775
|
+
interface GameRoomConfig {
|
|
2776
|
+
/** 룸 ID (선택사항, 미지정시 자동 생성) */
|
|
2777
|
+
roomId?: string;
|
|
2778
|
+
/** 카테고리 ID (선택사항) */
|
|
2779
|
+
categoryId?: string;
|
|
2780
|
+
/** 틱 레이트 (TPS, 기본 64) */
|
|
2781
|
+
tickRate?: number;
|
|
2782
|
+
/** 최대 플레이어 수 (기본 100) */
|
|
2783
|
+
maxPlayers?: number;
|
|
2784
|
+
/** 커스텀 메타데이터 */
|
|
2785
|
+
metadata?: Record<string, string>;
|
|
2786
|
+
}
|
|
2787
|
+
/**
|
|
2788
|
+
* 게임 플레이어 정보
|
|
2789
|
+
*/
|
|
2790
|
+
interface GamePlayer {
|
|
2791
|
+
clientId: string;
|
|
2792
|
+
userId?: string;
|
|
2793
|
+
joinedAt: number;
|
|
2794
|
+
metadata?: Record<string, string>;
|
|
2795
|
+
}
|
|
2796
|
+
/**
|
|
2797
|
+
* 게임 상태
|
|
2798
|
+
*/
|
|
2799
|
+
interface GameState {
|
|
2800
|
+
roomId: string;
|
|
2801
|
+
state: Record<string, unknown>;
|
|
2802
|
+
version: number;
|
|
2803
|
+
serverTime: number;
|
|
2804
|
+
tickRate: number;
|
|
2805
|
+
players: GamePlayer[];
|
|
2806
|
+
}
|
|
2807
|
+
/**
|
|
2808
|
+
* 상태 변경 (델타)
|
|
2809
|
+
*/
|
|
2810
|
+
interface StateChange {
|
|
2811
|
+
path: string;
|
|
2812
|
+
operation: 'set' | 'delete';
|
|
2813
|
+
value?: unknown;
|
|
2814
|
+
oldValue?: unknown;
|
|
2815
|
+
}
|
|
2816
|
+
/**
|
|
2817
|
+
* 게임 델타 업데이트
|
|
2818
|
+
*/
|
|
2819
|
+
interface GameDelta {
|
|
2820
|
+
fromVersion: number;
|
|
2821
|
+
toVersion: number;
|
|
2822
|
+
changes: StateChange[];
|
|
2823
|
+
tick: number;
|
|
2824
|
+
}
|
|
2825
|
+
/**
|
|
2826
|
+
* 게임 액션
|
|
2827
|
+
*/
|
|
2828
|
+
interface GameAction {
|
|
2829
|
+
type: string;
|
|
2830
|
+
data?: unknown;
|
|
2831
|
+
clientTimestamp?: number;
|
|
2832
|
+
sequence?: number;
|
|
2833
|
+
}
|
|
2834
|
+
/**
|
|
2835
|
+
* 룸 정보
|
|
2836
|
+
*/
|
|
2837
|
+
interface GameRoomInfo {
|
|
2838
|
+
id: string;
|
|
2839
|
+
appId: string;
|
|
2840
|
+
categoryId?: string;
|
|
2841
|
+
playerCount: number;
|
|
2842
|
+
maxPlayers: number;
|
|
2843
|
+
tickRate: number;
|
|
2844
|
+
isRunning: boolean;
|
|
2845
|
+
createdAt: number;
|
|
2846
|
+
metadata?: Record<string, string>;
|
|
2847
|
+
}
|
|
2848
|
+
/**
|
|
2849
|
+
* 게임 서버 메시지 타입
|
|
2850
|
+
*/
|
|
2851
|
+
type GameServerMessageType = 'room_created' | 'room_joined' | 'room_left' | 'state' | 'delta' | 'player_event' | 'chat' | 'pong' | 'room_list' | 'error';
|
|
2852
|
+
/**
|
|
2853
|
+
* 게임 서버 메시지
|
|
2854
|
+
*/
|
|
2855
|
+
interface GameServerMessage<T = unknown> {
|
|
2856
|
+
type: GameServerMessageType;
|
|
2857
|
+
data: T;
|
|
2858
|
+
serverTime: number;
|
|
2859
|
+
}
|
|
2860
|
+
/**
|
|
2861
|
+
* 플레이어 이벤트
|
|
2862
|
+
*/
|
|
2863
|
+
interface PlayerEvent {
|
|
2864
|
+
event: 'joined' | 'left';
|
|
2865
|
+
roomId: string;
|
|
2866
|
+
player: GamePlayer;
|
|
2867
|
+
serverTime: number;
|
|
2868
|
+
}
|
|
2869
|
+
/**
|
|
2870
|
+
* 채팅 메시지
|
|
2871
|
+
*/
|
|
2872
|
+
interface ChatMessage {
|
|
2873
|
+
roomId: string;
|
|
2874
|
+
clientId: string;
|
|
2875
|
+
userId?: string;
|
|
2876
|
+
message: string;
|
|
2877
|
+
serverTime: number;
|
|
2878
|
+
}
|
|
2879
|
+
/**
|
|
2880
|
+
* 에러 메시지
|
|
2881
|
+
*/
|
|
2882
|
+
interface ErrorMessage {
|
|
2883
|
+
code: string;
|
|
2884
|
+
message: string;
|
|
2885
|
+
}
|
|
2886
|
+
/**
|
|
2887
|
+
* Ping/Pong 응답
|
|
2888
|
+
*/
|
|
2889
|
+
interface PongMessage {
|
|
2890
|
+
clientTimestamp: number;
|
|
2891
|
+
serverTimestamp: number;
|
|
2892
|
+
}
|
|
2893
|
+
/**
|
|
2894
|
+
* 게임 클라이언트 이벤트 핸들러
|
|
2895
|
+
*/
|
|
2896
|
+
interface GameEventHandlers {
|
|
2897
|
+
onConnect?: () => void;
|
|
2898
|
+
onDisconnect?: (event: CloseEvent) => void;
|
|
2899
|
+
onError?: (error: Event | ErrorMessage) => void;
|
|
2900
|
+
onStateUpdate?: (state: GameState) => void;
|
|
2901
|
+
onDelta?: (delta: GameDelta) => void;
|
|
2902
|
+
onPlayerJoined?: (player: GamePlayer) => void;
|
|
2903
|
+
onPlayerLeft?: (player: GamePlayer) => void;
|
|
2904
|
+
onChat?: (message: ChatMessage) => void;
|
|
2905
|
+
onPong?: (pong: PongMessage) => void;
|
|
2906
|
+
}
|
|
2907
|
+
/**
|
|
2908
|
+
* 게임 클라이언트 설정
|
|
2909
|
+
*/
|
|
2910
|
+
interface GameClientConfig {
|
|
2911
|
+
/** 게임 서버 URL */
|
|
2912
|
+
gameServerUrl?: string;
|
|
2913
|
+
/** API Key */
|
|
2914
|
+
apiKey?: string;
|
|
2915
|
+
/** 액세스 토큰 */
|
|
2916
|
+
accessToken?: string;
|
|
2917
|
+
/** 클라이언트 ID */
|
|
2918
|
+
clientId: string;
|
|
2919
|
+
/** 자동 재연결 여부 */
|
|
2920
|
+
autoReconnect?: boolean;
|
|
2921
|
+
/** 재연결 최대 시도 횟수 */
|
|
2922
|
+
maxReconnectAttempts?: number;
|
|
2923
|
+
/** 재연결 간격 (ms) */
|
|
2924
|
+
reconnectInterval?: number;
|
|
2925
|
+
/** 연결 타임아웃 (ms) */
|
|
2926
|
+
connectionTimeout?: number;
|
|
2927
|
+
}
|
|
2928
|
+
/**
|
|
2929
|
+
* 게임 연결 상태
|
|
2930
|
+
*/
|
|
2931
|
+
type GameConnectionStatus = 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'error';
|
|
2932
|
+
/**
|
|
2933
|
+
* 게임 연결 상태 정보
|
|
2934
|
+
*/
|
|
2935
|
+
interface GameConnectionState {
|
|
2936
|
+
status: GameConnectionStatus;
|
|
2937
|
+
transport: 'webtransport' | 'websocket' | null;
|
|
2938
|
+
roomId: string | null;
|
|
2939
|
+
latency: number | null;
|
|
2940
|
+
reconnectAttempt?: number;
|
|
2941
|
+
lastError?: Error;
|
|
2942
|
+
}
|
|
2943
|
+
|
|
2944
|
+
/**
|
|
2945
|
+
* 게임 룸 클라이언트
|
|
2946
|
+
* WebSocket 연결을 관리하고 게임 상태를 동기화합니다.
|
|
2947
|
+
*/
|
|
2948
|
+
declare class GameRoom {
|
|
2949
|
+
private ws;
|
|
2950
|
+
private config;
|
|
2951
|
+
private handlers;
|
|
2952
|
+
private reconnectAttempts;
|
|
2953
|
+
private reconnectTimer;
|
|
2954
|
+
private pingInterval;
|
|
2955
|
+
private actionSequence;
|
|
2956
|
+
private _roomId;
|
|
2957
|
+
private _state;
|
|
2958
|
+
private _isConnected;
|
|
2959
|
+
constructor(config: GameClientConfig);
|
|
2960
|
+
/**
|
|
2961
|
+
* 현재 룸 ID
|
|
2962
|
+
*/
|
|
2963
|
+
get roomId(): string | null;
|
|
2964
|
+
/**
|
|
2965
|
+
* 현재 게임 상태
|
|
2966
|
+
*/
|
|
2967
|
+
get state(): GameState | null;
|
|
2968
|
+
/**
|
|
2969
|
+
* 연결 상태
|
|
2970
|
+
*/
|
|
2971
|
+
get isConnected(): boolean;
|
|
2972
|
+
/**
|
|
2973
|
+
* 이벤트 핸들러 등록
|
|
2974
|
+
*/
|
|
2975
|
+
on<K extends keyof GameEventHandlers>(event: K, handler: GameEventHandlers[K]): this;
|
|
2976
|
+
/**
|
|
2977
|
+
* 게임 서버에 연결
|
|
2978
|
+
*/
|
|
2979
|
+
connect(roomId?: string): Promise<void>;
|
|
2980
|
+
/**
|
|
2981
|
+
* 연결 해제
|
|
2982
|
+
*/
|
|
2983
|
+
disconnect(): void;
|
|
2984
|
+
/**
|
|
2985
|
+
* 룸 생성
|
|
2986
|
+
*/
|
|
2987
|
+
createRoom(config?: GameRoomConfig): Promise<GameState>;
|
|
2988
|
+
/**
|
|
2989
|
+
* 룸 참가
|
|
2990
|
+
*/
|
|
2991
|
+
joinRoom(roomId: string, metadata?: Record<string, string>): Promise<GameState>;
|
|
2992
|
+
/**
|
|
2993
|
+
* 룸 퇴장
|
|
2994
|
+
*/
|
|
2995
|
+
leaveRoom(): Promise<void>;
|
|
2996
|
+
/**
|
|
2997
|
+
* 게임 액션 전송
|
|
2998
|
+
*/
|
|
2999
|
+
sendAction(action: GameAction): void;
|
|
3000
|
+
/**
|
|
3001
|
+
* 채팅 메시지 전송
|
|
3002
|
+
*/
|
|
3003
|
+
sendChat(message: string): void;
|
|
3004
|
+
/**
|
|
3005
|
+
* 현재 상태 요청
|
|
3006
|
+
*/
|
|
3007
|
+
requestState(): Promise<GameState>;
|
|
3008
|
+
/**
|
|
3009
|
+
* 룸 목록 조회
|
|
3010
|
+
*/
|
|
3011
|
+
listRooms(): Promise<GameRoomInfo[]>;
|
|
3012
|
+
/**
|
|
3013
|
+
* Ping 전송 (RTT 측정용)
|
|
3014
|
+
*/
|
|
3015
|
+
ping(): Promise<number>;
|
|
3016
|
+
private buildConnectionUrl;
|
|
3017
|
+
private send;
|
|
3018
|
+
private sendWithHandler;
|
|
3019
|
+
private handleMessage;
|
|
3020
|
+
private handleDelta;
|
|
3021
|
+
private applyChange;
|
|
3022
|
+
private handlePlayerEvent;
|
|
3023
|
+
private scheduleReconnect;
|
|
3024
|
+
private startPingInterval;
|
|
3025
|
+
private stopPingInterval;
|
|
3026
|
+
}
|
|
3027
|
+
/**
|
|
3028
|
+
* 게임 API
|
|
3029
|
+
* HTTP 기반 게임 서버 관리 API
|
|
3030
|
+
*/
|
|
3031
|
+
declare class GameAPI {
|
|
3032
|
+
private http;
|
|
3033
|
+
private gameServerUrl;
|
|
3034
|
+
constructor(http: HttpClient, gameServerUrl?: string);
|
|
3035
|
+
/**
|
|
3036
|
+
* 게임 룸 클라이언트 생성
|
|
3037
|
+
*/
|
|
3038
|
+
createClient(config: Omit<GameClientConfig, 'gameServerUrl'>): GameRoom;
|
|
3039
|
+
/**
|
|
3040
|
+
* 룸 목록 조회 (HTTP)
|
|
3041
|
+
*/
|
|
3042
|
+
listRooms(appId?: string): Promise<GameRoomInfo[]>;
|
|
3043
|
+
/**
|
|
3044
|
+
* 룸 상세 조회 (HTTP)
|
|
3045
|
+
*/
|
|
3046
|
+
getRoom(roomId: string): Promise<GameRoomInfo>;
|
|
3047
|
+
/**
|
|
3048
|
+
* 룸 생성 (HTTP, gRPC 대안)
|
|
3049
|
+
*/
|
|
3050
|
+
createRoom(appId: string, config?: GameRoomConfig): Promise<GameRoomInfo>;
|
|
3051
|
+
/**
|
|
3052
|
+
* 룸 삭제 (HTTP)
|
|
3053
|
+
*/
|
|
3054
|
+
deleteRoom(roomId: string): Promise<void>;
|
|
3055
|
+
private getHeaders;
|
|
3056
|
+
}
|
|
3057
|
+
|
|
3058
|
+
/**
|
|
3059
|
+
* WebTransport-based Game Client
|
|
3060
|
+
*
|
|
3061
|
+
* WebTransport provides lower latency than WebSocket by using:
|
|
3062
|
+
* - UDP-based QUIC protocol
|
|
3063
|
+
* - Unreliable datagrams for real-time game state
|
|
3064
|
+
* - Reliable streams for critical messages
|
|
3065
|
+
*
|
|
3066
|
+
* Falls back to WebSocket if WebTransport is not supported.
|
|
3067
|
+
*/
|
|
3068
|
+
|
|
3069
|
+
/**
|
|
3070
|
+
* Transport type for game connection
|
|
3071
|
+
*/
|
|
3072
|
+
type TransportType = 'webtransport' | 'websocket' | 'auto';
|
|
3073
|
+
/**
|
|
3074
|
+
* Extended game client config with transport options
|
|
3075
|
+
*/
|
|
3076
|
+
interface GameTransportConfig extends GameClientConfig {
|
|
3077
|
+
/** Preferred transport type */
|
|
3078
|
+
transport?: TransportType;
|
|
3079
|
+
/** Use unreliable datagrams for state updates (WebTransport only) */
|
|
3080
|
+
useUnreliableDatagrams?: boolean;
|
|
3081
|
+
/** Maximum datagram size (WebTransport only) */
|
|
3082
|
+
maxDatagramSize?: number;
|
|
3083
|
+
}
|
|
3084
|
+
/**
|
|
3085
|
+
* Check if WebTransport is available
|
|
3086
|
+
*/
|
|
3087
|
+
declare function isWebTransportSupported(): boolean;
|
|
3088
|
+
/**
|
|
3089
|
+
* GameRoomTransport - Game room client with WebTransport support
|
|
3090
|
+
*
|
|
3091
|
+
* Provides the same API as GameRoom but with WebTransport support for
|
|
3092
|
+
* lower latency game state synchronization.
|
|
3093
|
+
*/
|
|
3094
|
+
declare class GameRoomTransport {
|
|
3095
|
+
private transport;
|
|
3096
|
+
private config;
|
|
3097
|
+
private handlers;
|
|
3098
|
+
private reconnectAttempts;
|
|
3099
|
+
private reconnectTimer;
|
|
3100
|
+
private pingInterval;
|
|
3101
|
+
private actionSequence;
|
|
3102
|
+
private _roomId;
|
|
3103
|
+
private _state;
|
|
3104
|
+
private _isConnected;
|
|
3105
|
+
private _connectionStatus;
|
|
3106
|
+
private _lastError;
|
|
3107
|
+
private _latency;
|
|
3108
|
+
private _transportType;
|
|
3109
|
+
private decoder;
|
|
3110
|
+
private pendingHandlers;
|
|
3111
|
+
private messageId;
|
|
3112
|
+
constructor(config: GameTransportConfig);
|
|
3113
|
+
private getDefaultGameServerUrl;
|
|
3114
|
+
/**
|
|
3115
|
+
* Current transport type being used
|
|
3116
|
+
*/
|
|
3117
|
+
get transportType(): TransportType;
|
|
3118
|
+
/**
|
|
3119
|
+
* Current room ID
|
|
3120
|
+
*/
|
|
3121
|
+
get roomId(): string | null;
|
|
3122
|
+
/**
|
|
3123
|
+
* Current game state
|
|
3124
|
+
*/
|
|
3125
|
+
get state(): GameState | null;
|
|
3126
|
+
/**
|
|
3127
|
+
* Connection status
|
|
3128
|
+
*/
|
|
3129
|
+
get isConnected(): boolean;
|
|
3130
|
+
/**
|
|
3131
|
+
* Connection state information
|
|
3132
|
+
*/
|
|
3133
|
+
get connectionState(): GameConnectionState;
|
|
3134
|
+
/**
|
|
3135
|
+
* Current latency (ms)
|
|
3136
|
+
*/
|
|
3137
|
+
get latency(): number;
|
|
3138
|
+
/**
|
|
3139
|
+
* Register event handler
|
|
3140
|
+
*/
|
|
3141
|
+
on<K extends keyof GameEventHandlers>(event: K, handler: GameEventHandlers[K]): this;
|
|
3142
|
+
/**
|
|
3143
|
+
* Connect to game server
|
|
3144
|
+
*/
|
|
3145
|
+
connect(roomId?: string): Promise<void>;
|
|
3146
|
+
/**
|
|
3147
|
+
* Disconnect from server
|
|
3148
|
+
*/
|
|
3149
|
+
disconnect(): void;
|
|
3150
|
+
/**
|
|
3151
|
+
* Create a new room
|
|
3152
|
+
*/
|
|
3153
|
+
createRoom(config?: GameRoomConfig): Promise<GameState>;
|
|
3154
|
+
/**
|
|
3155
|
+
* Join an existing room
|
|
3156
|
+
*/
|
|
3157
|
+
joinRoom(roomId: string, metadata?: Record<string, string>): Promise<GameState>;
|
|
3158
|
+
/**
|
|
3159
|
+
* Leave current room
|
|
3160
|
+
*/
|
|
3161
|
+
leaveRoom(): Promise<void>;
|
|
3162
|
+
/**
|
|
3163
|
+
* Send game action
|
|
3164
|
+
* Uses unreliable transport (datagrams) when WebTransport is available
|
|
3165
|
+
*/
|
|
3166
|
+
sendAction(action: GameAction, reliable?: boolean): void;
|
|
3167
|
+
/**
|
|
3168
|
+
* Send chat message
|
|
3169
|
+
*/
|
|
3170
|
+
sendChat(message: string): void;
|
|
3171
|
+
/**
|
|
3172
|
+
* Request current state
|
|
3173
|
+
*/
|
|
3174
|
+
requestState(): Promise<GameState>;
|
|
3175
|
+
/**
|
|
3176
|
+
* Ping server for latency measurement
|
|
3177
|
+
*/
|
|
3178
|
+
ping(): Promise<number>;
|
|
3179
|
+
private send;
|
|
3180
|
+
private sendWithHandler;
|
|
3181
|
+
private handleMessage;
|
|
3182
|
+
private handleDelta;
|
|
3183
|
+
private applyChange;
|
|
3184
|
+
private handlePlayerEvent;
|
|
3185
|
+
private scheduleReconnect;
|
|
3186
|
+
private startPingInterval;
|
|
3187
|
+
private stopPingInterval;
|
|
3188
|
+
}
|
|
3189
|
+
|
|
3190
|
+
interface ConnectBaseConfig {
|
|
3191
|
+
/**
|
|
3192
|
+
* Connect Base API 서버 URL (선택사항)
|
|
3193
|
+
* @default 'https://api.connectbase.world'
|
|
3194
|
+
* @example 'https://api.connectbase.world'
|
|
3195
|
+
*/
|
|
3196
|
+
baseUrl?: string;
|
|
3197
|
+
/**
|
|
3198
|
+
* Connect Base Socket 서버 URL (선택사항, 실시간 통신용)
|
|
3199
|
+
* @default 'https://socket.connectbase.world'
|
|
3200
|
+
* @example 'https://socket.connectbase.world'
|
|
3201
|
+
*/
|
|
3202
|
+
socketUrl?: string;
|
|
3203
|
+
/**
|
|
3204
|
+
* Connect Base WebRTC 서버 URL (선택사항, 영상/음성 통화용)
|
|
3205
|
+
* @default 'https://webrtc.connectbase.world'
|
|
3206
|
+
* @example 'https://webrtc.connectbase.world'
|
|
3207
|
+
*/
|
|
3208
|
+
webrtcUrl?: string;
|
|
3209
|
+
/**
|
|
3210
|
+
* Connect Base Video 서버 URL (선택사항, 동영상 업로드/스트리밍용)
|
|
3211
|
+
* @default 'https://video.connectbase.world'
|
|
3212
|
+
* @example 'https://video.connectbase.world'
|
|
3213
|
+
*/
|
|
3214
|
+
videoUrl?: string;
|
|
3215
|
+
/**
|
|
3216
|
+
* Connect Base Game 서버 URL (선택사항, 실시간 멀티플레이어 게임용)
|
|
3217
|
+
* @default 'https://game.connectbase.world'
|
|
3218
|
+
* @example 'https://game.connectbase.world'
|
|
3219
|
+
*/
|
|
3220
|
+
gameUrl?: string;
|
|
3221
|
+
/**
|
|
3222
|
+
* API Key (콘솔에서 발급)
|
|
3223
|
+
*/
|
|
3224
|
+
apiKey?: string;
|
|
3225
|
+
/**
|
|
3226
|
+
* 토큰이 갱신될 때 호출되는 콜백
|
|
3227
|
+
*/
|
|
3228
|
+
onTokenRefresh?: (tokens: {
|
|
3229
|
+
accessToken: string;
|
|
3230
|
+
refreshToken: string;
|
|
3231
|
+
}) => void;
|
|
3232
|
+
/**
|
|
3233
|
+
* 인증 에러 발생 시 호출되는 콜백
|
|
3234
|
+
*/
|
|
3235
|
+
onAuthError?: (error: Error) => void;
|
|
3236
|
+
/**
|
|
3237
|
+
* 에러 트래커 설정
|
|
3238
|
+
*/
|
|
3239
|
+
errorTracker?: ErrorTrackerConfig;
|
|
3240
|
+
}
|
|
3241
|
+
/**
|
|
3242
|
+
* Connect Base SDK
|
|
3243
|
+
*
|
|
3244
|
+
* @example
|
|
3245
|
+
* ```typescript
|
|
3246
|
+
* // 간단 초기화 (API Key만 필요)
|
|
3247
|
+
* const cb = new ConnectBase({
|
|
3248
|
+
* apiKey: 'your-api-key'
|
|
3249
|
+
* })
|
|
3250
|
+
*
|
|
3251
|
+
* // 커스텀 서버 URL 사용 시
|
|
3252
|
+
* const cb = new ConnectBase({
|
|
3253
|
+
* baseUrl: 'https://your-server.com',
|
|
3254
|
+
* apiKey: 'your-api-key'
|
|
3255
|
+
* })
|
|
3256
|
+
*
|
|
3257
|
+
* // 데이터 조회
|
|
3258
|
+
* const data = await cb.database.getData('table-id')
|
|
3259
|
+
*
|
|
3260
|
+
* // 파일 업로드
|
|
3261
|
+
* const file = await cb.storage.uploadFile('storage-id', myFile)
|
|
3262
|
+
*
|
|
3263
|
+
* // 서버리스 함수 실행
|
|
3264
|
+
* const result = await cb.functions.invoke('function-id', { name: 'John' })
|
|
3265
|
+
*
|
|
3266
|
+
* // 실시간 통신 (채팅 등)
|
|
3267
|
+
* await cb.realtime.connect()
|
|
3268
|
+
* const chat = await cb.realtime.subscribe('chat-room-1')
|
|
3269
|
+
* chat.onMessage((msg) => console.log(msg))
|
|
3270
|
+
* await chat.send({ text: 'Hello!' })
|
|
3271
|
+
* ```
|
|
3272
|
+
*/
|
|
3273
|
+
declare class ConnectBase {
|
|
3274
|
+
private http;
|
|
3275
|
+
/**
|
|
3276
|
+
* 인증 API
|
|
3277
|
+
*/
|
|
3278
|
+
readonly auth: AuthAPI;
|
|
3279
|
+
/**
|
|
3280
|
+
* 데이터베이스 API
|
|
3281
|
+
*/
|
|
3282
|
+
readonly database: DatabaseAPI;
|
|
3283
|
+
/**
|
|
3284
|
+
* 스토리지 API
|
|
3285
|
+
*/
|
|
3286
|
+
readonly storage: StorageAPI;
|
|
3287
|
+
/**
|
|
3288
|
+
* API Key 관리 API
|
|
3289
|
+
*/
|
|
3290
|
+
readonly apiKey: ApiKeyAPI;
|
|
3291
|
+
/**
|
|
3292
|
+
* 서버리스 함수 API
|
|
3293
|
+
*/
|
|
3294
|
+
readonly functions: FunctionsAPI;
|
|
3295
|
+
/**
|
|
3296
|
+
* 실시간 통신 API (WebSocket)
|
|
3297
|
+
*/
|
|
3298
|
+
readonly realtime: RealtimeAPI;
|
|
3299
|
+
/**
|
|
3300
|
+
* WebRTC API (영상/음성 통화)
|
|
3301
|
+
*/
|
|
3302
|
+
readonly webrtc: WebRTCAPI;
|
|
3303
|
+
/**
|
|
3304
|
+
* 에러 트래커 API (클라이언트 에러 리포팅)
|
|
3305
|
+
*/
|
|
3306
|
+
readonly errorTracker: ErrorTrackerAPI;
|
|
3307
|
+
/**
|
|
3308
|
+
* OAuth API (소셜 로그인)
|
|
3309
|
+
*/
|
|
3310
|
+
readonly oauth: OAuthAPI;
|
|
3311
|
+
/**
|
|
3312
|
+
* 결제 API (토스페이먼츠)
|
|
3313
|
+
*/
|
|
3314
|
+
readonly payment: PaymentAPI;
|
|
3315
|
+
/**
|
|
3316
|
+
* 정기결제/구독 API
|
|
3317
|
+
*/
|
|
3318
|
+
readonly subscription: SubscriptionAPI;
|
|
3319
|
+
/**
|
|
3320
|
+
* 푸시 알림 API
|
|
3321
|
+
*/
|
|
3322
|
+
readonly push: PushAPI;
|
|
3323
|
+
/**
|
|
3324
|
+
* 비디오 API (동영상 업로드/스트리밍)
|
|
3325
|
+
*/
|
|
3326
|
+
readonly video: VideoAPI;
|
|
3327
|
+
/**
|
|
3328
|
+
* 게임 API (실시간 멀티플레이어)
|
|
3329
|
+
*/
|
|
3330
|
+
readonly game: GameAPI;
|
|
3331
|
+
constructor(config?: ConnectBaseConfig);
|
|
3332
|
+
/**
|
|
3333
|
+
* 수동으로 토큰 설정 (기존 토큰으로 세션 복원 시)
|
|
3334
|
+
*/
|
|
3335
|
+
setTokens(accessToken: string, refreshToken: string): void;
|
|
3336
|
+
/**
|
|
3337
|
+
* 토큰 제거
|
|
3338
|
+
*/
|
|
3339
|
+
clearTokens(): void;
|
|
3340
|
+
/**
|
|
3341
|
+
* 설정 업데이트
|
|
3342
|
+
*/
|
|
3343
|
+
updateConfig(config: Partial<ConnectBaseConfig>): void;
|
|
3344
|
+
}
|
|
3345
|
+
|
|
3346
|
+
export { type AnonymousSignInRequest, type AnonymousSignInResponse, type AnonymousSignUpResponse, ApiError, type ApiKeyItem, type AppStatsResponse, AuthError, type AuthSettingsResponse, type BillingCycle, type BillingKeyResponse, type BulkCreateResponse, type BulkError, type CancelPaymentRequest, type CancelPaymentResponse, type CancelSubscriptionRequest, type CategoryInfo, type Channel, type ChannelMembership, type ChargeWithBillingKeyRequest, type ChargeWithBillingKeyResponse, type ChatMessage, type ClientMessage, type ColumnSchema, type CommentListResponse, type ConfirmBillingKeyRequest, type ConfirmPaymentRequest, type ConfirmPaymentResponse, ConnectBase, type ConnectBaseConfig, type ConnectedData, type ConnectionState, type CreateApiKeyRequest, type CreateApiKeyResponse, type CreateChannelRequest, type CreateColumnRequest, type CreateDataRequest, type CreateFolderRequest, type CreateFolderResponse, type CreatePlaylistRequest, type CreateSubscriptionRequest, type CreateTableRequest, type DataItem, type DataType, type DeleteWhereResponse, type DeviceInfo, type EnabledProviderInfo, type EnabledProvidersResponse, type ErrorHandler, type ErrorMessage, type ErrorReport, type ErrorTrackerConfig, type ErrorType, type FetchApiKeysResponse, type FetchDataResponse, type FetchFilesResponse, type FileItem, GameAPI, type GameAction, type GameClientConfig, type GameConnectionState, type GameConnectionStatus, type GameDelta, type GameEventHandlers, type GamePlayer, GameRoom, type GameRoomConfig, type GameRoomInfo, GameRoomTransport, type GameServerMessage, type GameServerMessageType, type GameState, type GameTransportConfig, type GetAuthorizationURLRequest, type GetAuthorizationURLResponse, type GuestMemberSignInResponse, type HistoryResponse, type ICEServer, type ICEServersResponse, type InitUploadResponse, type InvokeFunctionRequest, type InvokeFunctionResponse, type IssueBillingKeyRequest, type IssueBillingKeyResponse, type JoinRoomRequest, type JoinRoomResponse, type ListBillingKeysResponse, type ListSubscriptionPaymentsRequest, type ListSubscriptionPaymentsResponse, type ListSubscriptionsRequest, type ListSubscriptionsResponse, type MemberSignInRequest, type MemberSignInResponse, type MemberSignUpRequest, type MemberSignUpResponse, type MembershipTier, type MessageHandler, type MoveFileRequest, type OAuthCallbackRequest, type OAuthCallbackResponse, type OAuthProvider, type PauseSubscriptionRequest, type PaymentDetail, type PaymentStatus, type PeerInfo, type PlayerEvent, type Playlist, type PlaylistItem, type PongMessage, type PreparePaymentRequest, type PreparePaymentResponse, type PushPlatform, type QualityProgress, type QueryOptions, type RealtimeConnectOptions, type RealtimeMessage, type RegisterDeviceRequest, type RenameFileRequest, type RenameFileResponse, type RoomInfo, type RoomStats, type RoomsResponse, type SendOptions, type ServerMessage, type Shorts, type ShortsListResponse, type SignInRequest, type SignInResponse, type SignUpRequest, type SignUpResponse, type SignalingMessage, type SignalingMessageType, type StateChange, type StateChangeHandler, type StreamURLResponse, type SubscribeOptions, type SubscribeTopicRequest, type SubscribedData, type Subscription, type SubscriptionPaymentResponse, type SubscriptionPaymentStatus, type SubscriptionResponse, type SubscriptionStatus, type SuperChat, type TableSchema, type TranscodeStatus, type TransportType, type UpdateApiKeyRequest, type UpdateApiKeyResponse, type UpdateBillingKeyRequest, type UpdateChannelRequest, type UpdateColumnRequest, type UpdateDataRequest, type UpdateSubscriptionRequest, type UpdateVideoRequest, type UploadFileResponse, type UploadOptions, type UploadProgress, type UserInfo, type VAPIDPublicKeyResponse, type Video, type VideoComment, type VideoListOptions, type VideoListResponse, VideoProcessingError, type VideoQuality, type VideoStatus, type VideoVisibility, type WaitOptions, type WatchHistoryItem, type WebPushSubscription, type WebRTCConnectOptions, type WebRTCConnectionState, type WebRTCMode, type WhereCondition, type WhereOperator, ConnectBase as default, isWebTransportSupported };
|