connectbase-client 1.9.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +61 -0
- package/dist/connect-base.umd.js +3 -3
- package/dist/index.d.mts +161 -4
- package/dist/index.d.ts +161 -4
- package/dist/index.js +116 -1
- package/dist/index.mjs +116 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -172,6 +172,77 @@ interface AnalyticsEvent {
|
|
|
172
172
|
properties?: Record<string, unknown>;
|
|
173
173
|
timestamp?: number;
|
|
174
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* 인기 페이지 목록 응답.
|
|
177
|
+
*
|
|
178
|
+
* 백엔드 `dto.PopularPagesResponse` 와 1:1 매핑.
|
|
179
|
+
*/
|
|
180
|
+
interface PopularPagesResponse {
|
|
181
|
+
pages: Array<{
|
|
182
|
+
page_path: string;
|
|
183
|
+
page_views: number;
|
|
184
|
+
}>;
|
|
185
|
+
start_date: number;
|
|
186
|
+
end_date: number;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* 방문자 목록 응답.
|
|
190
|
+
*
|
|
191
|
+
* 백엔드 `dto.VisitorListResponse` 와 1:1 매핑. `app_member_id` 는 게스트 방문자에는
|
|
192
|
+
* 없을 수 있다.
|
|
193
|
+
*/
|
|
194
|
+
interface VisitorListResponse {
|
|
195
|
+
visitors: Array<{
|
|
196
|
+
id: string;
|
|
197
|
+
visitor_uid: string;
|
|
198
|
+
app_member_id?: string;
|
|
199
|
+
total_visits: number;
|
|
200
|
+
total_page_views: number;
|
|
201
|
+
referrer?: string;
|
|
202
|
+
last_ip?: string;
|
|
203
|
+
country?: string;
|
|
204
|
+
is_bot: boolean;
|
|
205
|
+
first_visit_at: string;
|
|
206
|
+
last_visit_at: string;
|
|
207
|
+
}>;
|
|
208
|
+
total: number;
|
|
209
|
+
limit: number;
|
|
210
|
+
offset: number;
|
|
211
|
+
has_more: boolean;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* 페이지 전환 플로우(Sankey) 응답.
|
|
215
|
+
*
|
|
216
|
+
* 백엔드 `dto.NavigationFlowResponse` 와 1:1 매핑. `nodes` 는 페이지, `links` 는 전환.
|
|
217
|
+
*/
|
|
218
|
+
interface NavigationFlowResponse {
|
|
219
|
+
nodes: Array<{
|
|
220
|
+
id: string;
|
|
221
|
+
label: string;
|
|
222
|
+
value: number;
|
|
223
|
+
}>;
|
|
224
|
+
links: Array<{
|
|
225
|
+
source: string;
|
|
226
|
+
target: string;
|
|
227
|
+
value: number;
|
|
228
|
+
}>;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* 조회 메서드 공통 옵션.
|
|
232
|
+
*
|
|
233
|
+
* `start_date` / `end_date` 는 백엔드가 정수형 epoch-day 또는 yyyymmdd 로 다루는 값
|
|
234
|
+
* (서비스 메서드 시그니처 기준 int). 0 또는 미지정 시 기본 기간을 사용.
|
|
235
|
+
*/
|
|
236
|
+
interface AnalyticsRangeOptions {
|
|
237
|
+
start_date?: number;
|
|
238
|
+
end_date?: number;
|
|
239
|
+
limit?: number;
|
|
240
|
+
}
|
|
241
|
+
interface VisitorListOptions {
|
|
242
|
+
limit?: number;
|
|
243
|
+
offset?: number;
|
|
244
|
+
sort_by?: 'last_visit' | 'total_visits' | 'total_page_views';
|
|
245
|
+
}
|
|
175
246
|
declare class SessionManager {
|
|
176
247
|
private _sessionId;
|
|
177
248
|
private _visitorUid;
|
|
@@ -270,6 +341,33 @@ declare class AnalyticsAPI {
|
|
|
270
341
|
* ```
|
|
271
342
|
*/
|
|
272
343
|
flush(): Promise<void>;
|
|
344
|
+
/**
|
|
345
|
+
* 인기 페이지 조회 (콘솔 JWT 또는 User Secret Key `cb_sk_` 인증 필요).
|
|
346
|
+
*
|
|
347
|
+
* 브라우저 환경에서 Public Key(`cb_pk_`) 만 가진 SDK 인스턴스로는 호출이 차단된다.
|
|
348
|
+
* Functions / 어드민 앱 등 cb_sk_ 환경에서 사용하라.
|
|
349
|
+
*
|
|
350
|
+
* @param storageWebId 조회할 웹스토리지 ID. 미지정 시 `init()` 에 전달된 ID 사용.
|
|
351
|
+
* @param options 기간/limit 옵션
|
|
352
|
+
* @example
|
|
353
|
+
* ```ts
|
|
354
|
+
* const { pages } = await cb.analytics.getPopularPages('019d8...', { limit: 20 })
|
|
355
|
+
* ```
|
|
356
|
+
*/
|
|
357
|
+
getPopularPages(storageWebId?: string, options?: AnalyticsRangeOptions): Promise<PopularPagesResponse>;
|
|
358
|
+
/**
|
|
359
|
+
* 페이지 전환 플로우(Sankey) 조회 — JWT/cb_sk_ 인증 필요.
|
|
360
|
+
*/
|
|
361
|
+
getNavigationFlow(storageWebId?: string, options?: AnalyticsRangeOptions): Promise<NavigationFlowResponse>;
|
|
362
|
+
/**
|
|
363
|
+
* 방문자 목록 조회 — JWT/cb_sk_ 인증 필요.
|
|
364
|
+
*/
|
|
365
|
+
getVisitors(storageWebId?: string, options?: VisitorListOptions): Promise<VisitorListResponse>;
|
|
366
|
+
/**
|
|
367
|
+
* 조회 메서드 공통 가드 — Public Key 인증 SDK 인스턴스에서는 명확한 에러를 던진다.
|
|
368
|
+
* 백엔드 라우트는 cb_pk_ 를 거부하므로 호출 자체를 막는 것이 디버깅에 유리.
|
|
369
|
+
*/
|
|
370
|
+
private requireServerSideStorageId;
|
|
273
371
|
/**
|
|
274
372
|
* 세션 매니저 접근 (고급 사용자용).
|
|
275
373
|
*
|
|
@@ -3174,12 +3272,17 @@ interface GetAuthorizationURLResponse {
|
|
|
3174
3272
|
}
|
|
3175
3273
|
/**
|
|
3176
3274
|
* OAuth 콜백 응답
|
|
3275
|
+
*
|
|
3276
|
+
* `email` 은 1.10 부터 추가된 선택적 필드. Apple private relay 또는 이메일 권한 미동의
|
|
3277
|
+
* 시 빈 문자열 / undefined 일 수 있다. 값이 있으면 첫 로그인 시점에 이메일을 확보할 수 있어
|
|
3278
|
+
* 별도 `getMember()` 호출이 불필요하다.
|
|
3177
3279
|
*/
|
|
3178
3280
|
interface OAuthCallbackResponse {
|
|
3179
3281
|
member_id: string;
|
|
3180
3282
|
access_token: string;
|
|
3181
3283
|
refresh_token: string;
|
|
3182
3284
|
is_new_member: boolean;
|
|
3285
|
+
email?: string;
|
|
3183
3286
|
}
|
|
3184
3287
|
|
|
3185
3288
|
/**
|
|
@@ -3284,6 +3387,7 @@ declare class OAuthAPI {
|
|
|
3284
3387
|
refresh_token?: string;
|
|
3285
3388
|
member_id?: string;
|
|
3286
3389
|
is_new_member?: boolean;
|
|
3390
|
+
email?: string;
|
|
3287
3391
|
state?: string;
|
|
3288
3392
|
error?: string;
|
|
3289
3393
|
} | null;
|
|
@@ -3308,6 +3412,7 @@ declare class OAuthAPI {
|
|
|
3308
3412
|
refresh_token: string;
|
|
3309
3413
|
member_id: string;
|
|
3310
3414
|
is_new_member: boolean;
|
|
3415
|
+
email?: string;
|
|
3311
3416
|
state?: string;
|
|
3312
3417
|
} | null>;
|
|
3313
3418
|
}
|
|
@@ -4095,6 +4200,35 @@ interface WebPushSubscription {
|
|
|
4095
4200
|
};
|
|
4096
4201
|
}
|
|
4097
4202
|
|
|
4203
|
+
/**
|
|
4204
|
+
* `cb.push.sendToMembers` 페이로드. 백엔드 `dto.SendPushRequest` 의 멤버 발송 케이스
|
|
4205
|
+
* 에 매핑되며, target_type / target_member_ids 는 SDK 가 자동 채운다.
|
|
4206
|
+
*/
|
|
4207
|
+
interface SendToMembersPayload {
|
|
4208
|
+
title: string;
|
|
4209
|
+
body: string;
|
|
4210
|
+
imageUrl?: string;
|
|
4211
|
+
data?: Record<string, unknown>;
|
|
4212
|
+
/** 'ios' | 'android' | 'web' 중 선택. 빈 배열/미지정 시 전체 플랫폼 발송. */
|
|
4213
|
+
platforms?: Array<'ios' | 'android' | 'web'>;
|
|
4214
|
+
/** TTL(초). 기본 86400 (24h). */
|
|
4215
|
+
ttlSeconds?: number;
|
|
4216
|
+
priority?: 'normal' | 'high';
|
|
4217
|
+
clickAction?: string;
|
|
4218
|
+
/** ISO8601 형식 예약 발송 시각. 미지정 시 즉시 발송. */
|
|
4219
|
+
scheduledAt?: string;
|
|
4220
|
+
}
|
|
4221
|
+
/**
|
|
4222
|
+
* 발송 결과. 백엔드 `dto.SendResultResponse` 와 1:1 매핑.
|
|
4223
|
+
*/
|
|
4224
|
+
interface SendPushResult {
|
|
4225
|
+
message_id: string;
|
|
4226
|
+
total_target: number;
|
|
4227
|
+
sent_count: number;
|
|
4228
|
+
failed_count: number;
|
|
4229
|
+
status: string;
|
|
4230
|
+
error_message?: string;
|
|
4231
|
+
}
|
|
4098
4232
|
/**
|
|
4099
4233
|
* 푸시 알림 API
|
|
4100
4234
|
*
|
|
@@ -4233,6 +4367,29 @@ declare class PushAPI {
|
|
|
4233
4367
|
* @param deviceToken Web Push endpoint URL (등록 시 사용한 endpoint)
|
|
4234
4368
|
*/
|
|
4235
4369
|
unregisterWebPush(deviceToken: string): Promise<void>;
|
|
4370
|
+
/**
|
|
4371
|
+
* 회원 ID 목록으로 푸시 발송 — Functions / cb_sk_ 인증 환경 전용.
|
|
4372
|
+
*
|
|
4373
|
+
* 백엔드 라우트 `POST /v1/apps/:appID/push/send` 는 콘솔 JWT 또는 User Secret Key
|
|
4374
|
+
* (`cb_sk_`) 만 받는다. 브라우저 SDK 의 Public Key(`cb_pk_`) 인스턴스에서는 호출
|
|
4375
|
+
* 자체가 차단되며, 권한 누설을 막기 위해 명확한 에러를 던진다.
|
|
4376
|
+
*
|
|
4377
|
+
* @param appId 발송 대상 앱 ID (cb_sk_ 환경은 user 단위 권한이므로 명시 전달).
|
|
4378
|
+
* @param memberIds 받는 회원 ID 배열 (UUID).
|
|
4379
|
+
* @param payload 푸시 내용/옵션.
|
|
4380
|
+
*
|
|
4381
|
+
* @example
|
|
4382
|
+
* ```ts
|
|
4383
|
+
* // ConnectBase Function (Node.js, secrets.CB_SECRET_KEY 주입)
|
|
4384
|
+
* const result = await cb.push.sendToMembers(APP_ID, [memberId], {
|
|
4385
|
+
* title: '새 알림',
|
|
4386
|
+
* body: '확인해보세요',
|
|
4387
|
+
* data: { route: '/notifications' },
|
|
4388
|
+
* })
|
|
4389
|
+
* console.log(result.message_id, result.sent_count)
|
|
4390
|
+
* ```
|
|
4391
|
+
*/
|
|
4392
|
+
sendToMembers(appId: string, memberIds: string[], payload: SendToMembersPayload): Promise<SendPushResult>;
|
|
4236
4393
|
/**
|
|
4237
4394
|
* 브라우저 고유 ID 생성 (localStorage에 저장)
|
|
4238
4395
|
*/
|
|
@@ -6714,10 +6871,10 @@ interface ConnectBaseConfig {
|
|
|
6714
6871
|
onTokenExpired?: () => void;
|
|
6715
6872
|
/**
|
|
6716
6873
|
* 토큰 저장 방식.
|
|
6717
|
-
* - '
|
|
6718
|
-
* - 'sessionStorage': 탭 종료 시 삭제
|
|
6719
|
-
* - '
|
|
6720
|
-
* @default '
|
|
6874
|
+
* - 'none' (기본·권장): 메모리에만 저장. 새로고침 시 재로그인 필요. XSS 노출 최소화
|
|
6875
|
+
* - 'sessionStorage': 탭 종료 시 삭제 (XSS 시 현재 탭 세션 탈취 가능)
|
|
6876
|
+
* - 'localStorage': 브라우저 종료 후에도 유지 (XSS 시 토큰 영구 탈취 가능 — 콘솔 경고 출력)
|
|
6877
|
+
* @default 'none'
|
|
6721
6878
|
*/
|
|
6722
6879
|
persistence?: TokenPersistence;
|
|
6723
6880
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -172,6 +172,77 @@ interface AnalyticsEvent {
|
|
|
172
172
|
properties?: Record<string, unknown>;
|
|
173
173
|
timestamp?: number;
|
|
174
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* 인기 페이지 목록 응답.
|
|
177
|
+
*
|
|
178
|
+
* 백엔드 `dto.PopularPagesResponse` 와 1:1 매핑.
|
|
179
|
+
*/
|
|
180
|
+
interface PopularPagesResponse {
|
|
181
|
+
pages: Array<{
|
|
182
|
+
page_path: string;
|
|
183
|
+
page_views: number;
|
|
184
|
+
}>;
|
|
185
|
+
start_date: number;
|
|
186
|
+
end_date: number;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* 방문자 목록 응답.
|
|
190
|
+
*
|
|
191
|
+
* 백엔드 `dto.VisitorListResponse` 와 1:1 매핑. `app_member_id` 는 게스트 방문자에는
|
|
192
|
+
* 없을 수 있다.
|
|
193
|
+
*/
|
|
194
|
+
interface VisitorListResponse {
|
|
195
|
+
visitors: Array<{
|
|
196
|
+
id: string;
|
|
197
|
+
visitor_uid: string;
|
|
198
|
+
app_member_id?: string;
|
|
199
|
+
total_visits: number;
|
|
200
|
+
total_page_views: number;
|
|
201
|
+
referrer?: string;
|
|
202
|
+
last_ip?: string;
|
|
203
|
+
country?: string;
|
|
204
|
+
is_bot: boolean;
|
|
205
|
+
first_visit_at: string;
|
|
206
|
+
last_visit_at: string;
|
|
207
|
+
}>;
|
|
208
|
+
total: number;
|
|
209
|
+
limit: number;
|
|
210
|
+
offset: number;
|
|
211
|
+
has_more: boolean;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* 페이지 전환 플로우(Sankey) 응답.
|
|
215
|
+
*
|
|
216
|
+
* 백엔드 `dto.NavigationFlowResponse` 와 1:1 매핑. `nodes` 는 페이지, `links` 는 전환.
|
|
217
|
+
*/
|
|
218
|
+
interface NavigationFlowResponse {
|
|
219
|
+
nodes: Array<{
|
|
220
|
+
id: string;
|
|
221
|
+
label: string;
|
|
222
|
+
value: number;
|
|
223
|
+
}>;
|
|
224
|
+
links: Array<{
|
|
225
|
+
source: string;
|
|
226
|
+
target: string;
|
|
227
|
+
value: number;
|
|
228
|
+
}>;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* 조회 메서드 공통 옵션.
|
|
232
|
+
*
|
|
233
|
+
* `start_date` / `end_date` 는 백엔드가 정수형 epoch-day 또는 yyyymmdd 로 다루는 값
|
|
234
|
+
* (서비스 메서드 시그니처 기준 int). 0 또는 미지정 시 기본 기간을 사용.
|
|
235
|
+
*/
|
|
236
|
+
interface AnalyticsRangeOptions {
|
|
237
|
+
start_date?: number;
|
|
238
|
+
end_date?: number;
|
|
239
|
+
limit?: number;
|
|
240
|
+
}
|
|
241
|
+
interface VisitorListOptions {
|
|
242
|
+
limit?: number;
|
|
243
|
+
offset?: number;
|
|
244
|
+
sort_by?: 'last_visit' | 'total_visits' | 'total_page_views';
|
|
245
|
+
}
|
|
175
246
|
declare class SessionManager {
|
|
176
247
|
private _sessionId;
|
|
177
248
|
private _visitorUid;
|
|
@@ -270,6 +341,33 @@ declare class AnalyticsAPI {
|
|
|
270
341
|
* ```
|
|
271
342
|
*/
|
|
272
343
|
flush(): Promise<void>;
|
|
344
|
+
/**
|
|
345
|
+
* 인기 페이지 조회 (콘솔 JWT 또는 User Secret Key `cb_sk_` 인증 필요).
|
|
346
|
+
*
|
|
347
|
+
* 브라우저 환경에서 Public Key(`cb_pk_`) 만 가진 SDK 인스턴스로는 호출이 차단된다.
|
|
348
|
+
* Functions / 어드민 앱 등 cb_sk_ 환경에서 사용하라.
|
|
349
|
+
*
|
|
350
|
+
* @param storageWebId 조회할 웹스토리지 ID. 미지정 시 `init()` 에 전달된 ID 사용.
|
|
351
|
+
* @param options 기간/limit 옵션
|
|
352
|
+
* @example
|
|
353
|
+
* ```ts
|
|
354
|
+
* const { pages } = await cb.analytics.getPopularPages('019d8...', { limit: 20 })
|
|
355
|
+
* ```
|
|
356
|
+
*/
|
|
357
|
+
getPopularPages(storageWebId?: string, options?: AnalyticsRangeOptions): Promise<PopularPagesResponse>;
|
|
358
|
+
/**
|
|
359
|
+
* 페이지 전환 플로우(Sankey) 조회 — JWT/cb_sk_ 인증 필요.
|
|
360
|
+
*/
|
|
361
|
+
getNavigationFlow(storageWebId?: string, options?: AnalyticsRangeOptions): Promise<NavigationFlowResponse>;
|
|
362
|
+
/**
|
|
363
|
+
* 방문자 목록 조회 — JWT/cb_sk_ 인증 필요.
|
|
364
|
+
*/
|
|
365
|
+
getVisitors(storageWebId?: string, options?: VisitorListOptions): Promise<VisitorListResponse>;
|
|
366
|
+
/**
|
|
367
|
+
* 조회 메서드 공통 가드 — Public Key 인증 SDK 인스턴스에서는 명확한 에러를 던진다.
|
|
368
|
+
* 백엔드 라우트는 cb_pk_ 를 거부하므로 호출 자체를 막는 것이 디버깅에 유리.
|
|
369
|
+
*/
|
|
370
|
+
private requireServerSideStorageId;
|
|
273
371
|
/**
|
|
274
372
|
* 세션 매니저 접근 (고급 사용자용).
|
|
275
373
|
*
|
|
@@ -3174,12 +3272,17 @@ interface GetAuthorizationURLResponse {
|
|
|
3174
3272
|
}
|
|
3175
3273
|
/**
|
|
3176
3274
|
* OAuth 콜백 응답
|
|
3275
|
+
*
|
|
3276
|
+
* `email` 은 1.10 부터 추가된 선택적 필드. Apple private relay 또는 이메일 권한 미동의
|
|
3277
|
+
* 시 빈 문자열 / undefined 일 수 있다. 값이 있으면 첫 로그인 시점에 이메일을 확보할 수 있어
|
|
3278
|
+
* 별도 `getMember()` 호출이 불필요하다.
|
|
3177
3279
|
*/
|
|
3178
3280
|
interface OAuthCallbackResponse {
|
|
3179
3281
|
member_id: string;
|
|
3180
3282
|
access_token: string;
|
|
3181
3283
|
refresh_token: string;
|
|
3182
3284
|
is_new_member: boolean;
|
|
3285
|
+
email?: string;
|
|
3183
3286
|
}
|
|
3184
3287
|
|
|
3185
3288
|
/**
|
|
@@ -3284,6 +3387,7 @@ declare class OAuthAPI {
|
|
|
3284
3387
|
refresh_token?: string;
|
|
3285
3388
|
member_id?: string;
|
|
3286
3389
|
is_new_member?: boolean;
|
|
3390
|
+
email?: string;
|
|
3287
3391
|
state?: string;
|
|
3288
3392
|
error?: string;
|
|
3289
3393
|
} | null;
|
|
@@ -3308,6 +3412,7 @@ declare class OAuthAPI {
|
|
|
3308
3412
|
refresh_token: string;
|
|
3309
3413
|
member_id: string;
|
|
3310
3414
|
is_new_member: boolean;
|
|
3415
|
+
email?: string;
|
|
3311
3416
|
state?: string;
|
|
3312
3417
|
} | null>;
|
|
3313
3418
|
}
|
|
@@ -4095,6 +4200,35 @@ interface WebPushSubscription {
|
|
|
4095
4200
|
};
|
|
4096
4201
|
}
|
|
4097
4202
|
|
|
4203
|
+
/**
|
|
4204
|
+
* `cb.push.sendToMembers` 페이로드. 백엔드 `dto.SendPushRequest` 의 멤버 발송 케이스
|
|
4205
|
+
* 에 매핑되며, target_type / target_member_ids 는 SDK 가 자동 채운다.
|
|
4206
|
+
*/
|
|
4207
|
+
interface SendToMembersPayload {
|
|
4208
|
+
title: string;
|
|
4209
|
+
body: string;
|
|
4210
|
+
imageUrl?: string;
|
|
4211
|
+
data?: Record<string, unknown>;
|
|
4212
|
+
/** 'ios' | 'android' | 'web' 중 선택. 빈 배열/미지정 시 전체 플랫폼 발송. */
|
|
4213
|
+
platforms?: Array<'ios' | 'android' | 'web'>;
|
|
4214
|
+
/** TTL(초). 기본 86400 (24h). */
|
|
4215
|
+
ttlSeconds?: number;
|
|
4216
|
+
priority?: 'normal' | 'high';
|
|
4217
|
+
clickAction?: string;
|
|
4218
|
+
/** ISO8601 형식 예약 발송 시각. 미지정 시 즉시 발송. */
|
|
4219
|
+
scheduledAt?: string;
|
|
4220
|
+
}
|
|
4221
|
+
/**
|
|
4222
|
+
* 발송 결과. 백엔드 `dto.SendResultResponse` 와 1:1 매핑.
|
|
4223
|
+
*/
|
|
4224
|
+
interface SendPushResult {
|
|
4225
|
+
message_id: string;
|
|
4226
|
+
total_target: number;
|
|
4227
|
+
sent_count: number;
|
|
4228
|
+
failed_count: number;
|
|
4229
|
+
status: string;
|
|
4230
|
+
error_message?: string;
|
|
4231
|
+
}
|
|
4098
4232
|
/**
|
|
4099
4233
|
* 푸시 알림 API
|
|
4100
4234
|
*
|
|
@@ -4233,6 +4367,29 @@ declare class PushAPI {
|
|
|
4233
4367
|
* @param deviceToken Web Push endpoint URL (등록 시 사용한 endpoint)
|
|
4234
4368
|
*/
|
|
4235
4369
|
unregisterWebPush(deviceToken: string): Promise<void>;
|
|
4370
|
+
/**
|
|
4371
|
+
* 회원 ID 목록으로 푸시 발송 — Functions / cb_sk_ 인증 환경 전용.
|
|
4372
|
+
*
|
|
4373
|
+
* 백엔드 라우트 `POST /v1/apps/:appID/push/send` 는 콘솔 JWT 또는 User Secret Key
|
|
4374
|
+
* (`cb_sk_`) 만 받는다. 브라우저 SDK 의 Public Key(`cb_pk_`) 인스턴스에서는 호출
|
|
4375
|
+
* 자체가 차단되며, 권한 누설을 막기 위해 명확한 에러를 던진다.
|
|
4376
|
+
*
|
|
4377
|
+
* @param appId 발송 대상 앱 ID (cb_sk_ 환경은 user 단위 권한이므로 명시 전달).
|
|
4378
|
+
* @param memberIds 받는 회원 ID 배열 (UUID).
|
|
4379
|
+
* @param payload 푸시 내용/옵션.
|
|
4380
|
+
*
|
|
4381
|
+
* @example
|
|
4382
|
+
* ```ts
|
|
4383
|
+
* // ConnectBase Function (Node.js, secrets.CB_SECRET_KEY 주입)
|
|
4384
|
+
* const result = await cb.push.sendToMembers(APP_ID, [memberId], {
|
|
4385
|
+
* title: '새 알림',
|
|
4386
|
+
* body: '확인해보세요',
|
|
4387
|
+
* data: { route: '/notifications' },
|
|
4388
|
+
* })
|
|
4389
|
+
* console.log(result.message_id, result.sent_count)
|
|
4390
|
+
* ```
|
|
4391
|
+
*/
|
|
4392
|
+
sendToMembers(appId: string, memberIds: string[], payload: SendToMembersPayload): Promise<SendPushResult>;
|
|
4236
4393
|
/**
|
|
4237
4394
|
* 브라우저 고유 ID 생성 (localStorage에 저장)
|
|
4238
4395
|
*/
|
|
@@ -6714,10 +6871,10 @@ interface ConnectBaseConfig {
|
|
|
6714
6871
|
onTokenExpired?: () => void;
|
|
6715
6872
|
/**
|
|
6716
6873
|
* 토큰 저장 방식.
|
|
6717
|
-
* - '
|
|
6718
|
-
* - 'sessionStorage': 탭 종료 시 삭제
|
|
6719
|
-
* - '
|
|
6720
|
-
* @default '
|
|
6874
|
+
* - 'none' (기본·권장): 메모리에만 저장. 새로고침 시 재로그인 필요. XSS 노출 최소화
|
|
6875
|
+
* - 'sessionStorage': 탭 종료 시 삭제 (XSS 시 현재 탭 세션 탈취 가능)
|
|
6876
|
+
* - 'localStorage': 브라우저 종료 후에도 유지 (XSS 시 토큰 영구 탈취 가능 — 콘솔 경고 출력)
|
|
6877
|
+
* @default 'none'
|
|
6721
6878
|
*/
|
|
6722
6879
|
persistence?: TokenPersistence;
|
|
6723
6880
|
/**
|
package/dist/index.js
CHANGED
|
@@ -4474,11 +4474,13 @@ var OAuthAPI = class {
|
|
|
4474
4474
|
reject(new Error(event.data.error));
|
|
4475
4475
|
return;
|
|
4476
4476
|
}
|
|
4477
|
+
const rawEmail = event.data.email;
|
|
4477
4478
|
const result = {
|
|
4478
4479
|
member_id: event.data.member_id,
|
|
4479
4480
|
access_token: event.data.access_token,
|
|
4480
4481
|
refresh_token: event.data.refresh_token,
|
|
4481
|
-
is_new_member: event.data.is_new_member === "true" || event.data.is_new_member === true
|
|
4482
|
+
is_new_member: event.data.is_new_member === "true" || event.data.is_new_member === true,
|
|
4483
|
+
...typeof rawEmail === "string" && rawEmail.length > 0 ? { email: rawEmail } : {}
|
|
4482
4484
|
};
|
|
4483
4485
|
this.http.setTokens(result.access_token, result.refresh_token);
|
|
4484
4486
|
resolve(result);
|
|
@@ -4546,11 +4548,13 @@ var OAuthAPI = class {
|
|
|
4546
4548
|
if (!accessToken || !refreshToken || !memberId) {
|
|
4547
4549
|
return null;
|
|
4548
4550
|
}
|
|
4551
|
+
const emailParam = params.get("email");
|
|
4549
4552
|
const result = {
|
|
4550
4553
|
access_token: accessToken,
|
|
4551
4554
|
refresh_token: refreshToken,
|
|
4552
4555
|
member_id: memberId,
|
|
4553
4556
|
is_new_member: params.get("is_new_member") === "true",
|
|
4557
|
+
...emailParam ? { email: emailParam } : {},
|
|
4554
4558
|
state: params.get("state") || void 0
|
|
4555
4559
|
};
|
|
4556
4560
|
if (window.opener) {
|
|
@@ -4588,6 +4592,7 @@ var OAuthAPI = class {
|
|
|
4588
4592
|
refresh_token: resp.refresh_token,
|
|
4589
4593
|
member_id: resp.member_id,
|
|
4590
4594
|
is_new_member: resp.is_new_member,
|
|
4595
|
+
...resp.email ? { email: resp.email } : {},
|
|
4591
4596
|
state: params.get("state") || void 0
|
|
4592
4597
|
};
|
|
4593
4598
|
if (window.opener) {
|
|
@@ -5264,6 +5269,53 @@ var PushAPI = class {
|
|
|
5264
5269
|
const prefix = this.getPublicPrefix();
|
|
5265
5270
|
await this.http.delete(`${prefix}/push/devices/${encodeURIComponent(deviceToken)}`);
|
|
5266
5271
|
}
|
|
5272
|
+
// ============ Server-side Send (Functions / cb_sk_ 전용) ============
|
|
5273
|
+
/**
|
|
5274
|
+
* 회원 ID 목록으로 푸시 발송 — Functions / cb_sk_ 인증 환경 전용.
|
|
5275
|
+
*
|
|
5276
|
+
* 백엔드 라우트 `POST /v1/apps/:appID/push/send` 는 콘솔 JWT 또는 User Secret Key
|
|
5277
|
+
* (`cb_sk_`) 만 받는다. 브라우저 SDK 의 Public Key(`cb_pk_`) 인스턴스에서는 호출
|
|
5278
|
+
* 자체가 차단되며, 권한 누설을 막기 위해 명확한 에러를 던진다.
|
|
5279
|
+
*
|
|
5280
|
+
* @param appId 발송 대상 앱 ID (cb_sk_ 환경은 user 단위 권한이므로 명시 전달).
|
|
5281
|
+
* @param memberIds 받는 회원 ID 배열 (UUID).
|
|
5282
|
+
* @param payload 푸시 내용/옵션.
|
|
5283
|
+
*
|
|
5284
|
+
* @example
|
|
5285
|
+
* ```ts
|
|
5286
|
+
* // ConnectBase Function (Node.js, secrets.CB_SECRET_KEY 주입)
|
|
5287
|
+
* const result = await cb.push.sendToMembers(APP_ID, [memberId], {
|
|
5288
|
+
* title: '새 알림',
|
|
5289
|
+
* body: '확인해보세요',
|
|
5290
|
+
* data: { route: '/notifications' },
|
|
5291
|
+
* })
|
|
5292
|
+
* console.log(result.message_id, result.sent_count)
|
|
5293
|
+
* ```
|
|
5294
|
+
*/
|
|
5295
|
+
async sendToMembers(appId, memberIds, payload) {
|
|
5296
|
+
if (this.http.hasPublicKey()) {
|
|
5297
|
+
throw new Error(
|
|
5298
|
+
"cb.push.sendToMembers() \uB294 User Secret Key(cb_sk_) \uB610\uB294 \uCF58\uC194 JWT \uC778\uC99D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4. Public Key(cb_pk_) SDK \uC778\uC2A4\uD134\uC2A4\uB85C\uB294 \uD638\uCD9C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 Functions \uD658\uACBD\uC5D0\uC11C \uC0AC\uC6A9\uD558\uC138\uC694."
|
|
5299
|
+
);
|
|
5300
|
+
}
|
|
5301
|
+
if (memberIds.length === 0) {
|
|
5302
|
+
throw new Error("cb.push.sendToMembers(): memberIds \uAC00 \uBE44\uC5B4\uC788\uC2B5\uB2C8\uB2E4.");
|
|
5303
|
+
}
|
|
5304
|
+
const body = {
|
|
5305
|
+
target_type: "members",
|
|
5306
|
+
target_member_ids: memberIds,
|
|
5307
|
+
title: payload.title,
|
|
5308
|
+
body: payload.body,
|
|
5309
|
+
...payload.imageUrl !== void 0 ? { image_url: payload.imageUrl } : {},
|
|
5310
|
+
...payload.data !== void 0 ? { data: payload.data } : {},
|
|
5311
|
+
...payload.platforms !== void 0 ? { platforms: payload.platforms } : {},
|
|
5312
|
+
...payload.ttlSeconds !== void 0 ? { ttl: payload.ttlSeconds } : {},
|
|
5313
|
+
...payload.priority !== void 0 ? { priority: payload.priority } : {},
|
|
5314
|
+
...payload.clickAction !== void 0 ? { click_action: payload.clickAction } : {},
|
|
5315
|
+
...payload.scheduledAt !== void 0 ? { scheduled_at: payload.scheduledAt } : {}
|
|
5316
|
+
};
|
|
5317
|
+
return this.http.post(`/v1/apps/${appId}/push/send`, body);
|
|
5318
|
+
}
|
|
5267
5319
|
// ============ Helper Methods ============
|
|
5268
5320
|
/**
|
|
5269
5321
|
* 브라우저 고유 ID 생성 (localStorage에 저장)
|
|
@@ -8173,6 +8225,15 @@ var SessionManager = class {
|
|
|
8173
8225
|
return generateId();
|
|
8174
8226
|
}
|
|
8175
8227
|
};
|
|
8228
|
+
function buildAnalyticsQuery(options) {
|
|
8229
|
+
if (!options) return "";
|
|
8230
|
+
const params = new URLSearchParams();
|
|
8231
|
+
if (options.start_date !== void 0) params.set("start_date", String(options.start_date));
|
|
8232
|
+
if (options.end_date !== void 0) params.set("end_date", String(options.end_date));
|
|
8233
|
+
if (options.limit !== void 0) params.set("limit", String(options.limit));
|
|
8234
|
+
const qs = params.toString();
|
|
8235
|
+
return qs ? `?${qs}` : "";
|
|
8236
|
+
}
|
|
8176
8237
|
function parseUTM() {
|
|
8177
8238
|
if (typeof window === "undefined") return {};
|
|
8178
8239
|
try {
|
|
@@ -8441,6 +8502,60 @@ var AnalyticsAPI = class {
|
|
|
8441
8502
|
async flush() {
|
|
8442
8503
|
await this.flushQueue();
|
|
8443
8504
|
}
|
|
8505
|
+
/**
|
|
8506
|
+
* 인기 페이지 조회 (콘솔 JWT 또는 User Secret Key `cb_sk_` 인증 필요).
|
|
8507
|
+
*
|
|
8508
|
+
* 브라우저 환경에서 Public Key(`cb_pk_`) 만 가진 SDK 인스턴스로는 호출이 차단된다.
|
|
8509
|
+
* Functions / 어드민 앱 등 cb_sk_ 환경에서 사용하라.
|
|
8510
|
+
*
|
|
8511
|
+
* @param storageWebId 조회할 웹스토리지 ID. 미지정 시 `init()` 에 전달된 ID 사용.
|
|
8512
|
+
* @param options 기간/limit 옵션
|
|
8513
|
+
* @example
|
|
8514
|
+
* ```ts
|
|
8515
|
+
* const { pages } = await cb.analytics.getPopularPages('019d8...', { limit: 20 })
|
|
8516
|
+
* ```
|
|
8517
|
+
*/
|
|
8518
|
+
async getPopularPages(storageWebId, options) {
|
|
8519
|
+
const id = this.requireServerSideStorageId(storageWebId, "getPopularPages");
|
|
8520
|
+
const qs = buildAnalyticsQuery(options);
|
|
8521
|
+
return this.http.get(`/v1/storages/web/${id}/popular-pages${qs}`);
|
|
8522
|
+
}
|
|
8523
|
+
/**
|
|
8524
|
+
* 페이지 전환 플로우(Sankey) 조회 — JWT/cb_sk_ 인증 필요.
|
|
8525
|
+
*/
|
|
8526
|
+
async getNavigationFlow(storageWebId, options) {
|
|
8527
|
+
const id = this.requireServerSideStorageId(storageWebId, "getNavigationFlow");
|
|
8528
|
+
const qs = buildAnalyticsQuery(options);
|
|
8529
|
+
return this.http.get(`/v1/storages/web/${id}/navigation/flow${qs}`);
|
|
8530
|
+
}
|
|
8531
|
+
/**
|
|
8532
|
+
* 방문자 목록 조회 — JWT/cb_sk_ 인증 필요.
|
|
8533
|
+
*/
|
|
8534
|
+
async getVisitors(storageWebId, options) {
|
|
8535
|
+
const id = this.requireServerSideStorageId(storageWebId, "getVisitors");
|
|
8536
|
+
const params = new URLSearchParams();
|
|
8537
|
+
if (options?.limit !== void 0) params.set("limit", String(options.limit));
|
|
8538
|
+
if (options?.offset !== void 0) params.set("offset", String(options.offset));
|
|
8539
|
+
if (options?.sort_by) params.set("sort_by", options.sort_by);
|
|
8540
|
+
const qs = params.toString() ? `?${params.toString()}` : "";
|
|
8541
|
+
return this.http.get(`/v1/storages/web/${id}/visitors${qs}`);
|
|
8542
|
+
}
|
|
8543
|
+
/**
|
|
8544
|
+
* 조회 메서드 공통 가드 — Public Key 인증 SDK 인스턴스에서는 명확한 에러를 던진다.
|
|
8545
|
+
* 백엔드 라우트는 cb_pk_ 를 거부하므로 호출 자체를 막는 것이 디버깅에 유리.
|
|
8546
|
+
*/
|
|
8547
|
+
requireServerSideStorageId(storageWebId, methodName) {
|
|
8548
|
+
if (this.http.hasPublicKey()) {
|
|
8549
|
+
throw new Error(
|
|
8550
|
+
`cb.analytics.${methodName}() \uB294 \uCF58\uC194 JWT \uB610\uB294 User Secret Key(cb_sk_) \uC778\uC99D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \uBE0C\uB77C\uC6B0\uC800 SDK \uC758 Public Key(cb_pk_) \uB85C\uB294 \uD638\uCD9C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 Functions \uD658\uACBD\uC5D0\uC11C \uC0AC\uC6A9\uD558\uC138\uC694.`
|
|
8551
|
+
);
|
|
8552
|
+
}
|
|
8553
|
+
const id = storageWebId ?? this.storageWebId;
|
|
8554
|
+
if (!id) {
|
|
8555
|
+
throw new Error(`cb.analytics.${methodName}() \uD638\uCD9C \uC2DC storageWebId \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4 (init \uB610\uB294 \uC778\uC790\uB85C \uC804\uB2EC).`);
|
|
8556
|
+
}
|
|
8557
|
+
return id;
|
|
8558
|
+
}
|
|
8444
8559
|
/**
|
|
8445
8560
|
* 세션 매니저 접근 (고급 사용자용).
|
|
8446
8561
|
*
|