connectbase-client 4.1.0 → 4.2.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/dist/index.d.mts CHANGED
@@ -4440,6 +4440,27 @@ declare global {
4440
4440
  }
4441
4441
  interface NativeBridgeInterface {
4442
4442
  platform?: "electron" | "react-native" | "ios" | "android";
4443
+ /** 실행 OS (react-native: 'ios' | 'android', electron: process.platform) */
4444
+ os?: string;
4445
+ /** 네이티브 셸에서 실행 중인지 (패키징 앱이면 항상 true) */
4446
+ isNative?: boolean;
4447
+ /** 브릿지 원시 호출 (문서화되지 않은 타입 호출용) */
4448
+ call?: (type: string, payload?: unknown, options?: {
4449
+ timeoutMs?: number;
4450
+ }) => Promise<unknown>;
4451
+ app?: {
4452
+ getVersion?: () => Promise<string>;
4453
+ getName?: () => Promise<string>;
4454
+ getInfo?: () => Promise<NativeAppInfo>;
4455
+ getPath?: (name: string) => Promise<string | null>;
4456
+ reload?: () => Promise<void>;
4457
+ quit?: () => Promise<void>;
4458
+ };
4459
+ browser?: {
4460
+ openExternal: (url: string) => Promise<{
4461
+ success: boolean;
4462
+ }>;
4463
+ };
4443
4464
  camera?: {
4444
4465
  takePicture: (options?: CameraOptions) => Promise<ImageResult>;
4445
4466
  pickImage: (options?: PickImageOptions) => Promise<ImageResult[]>;
@@ -4455,6 +4476,9 @@ interface NativeBridgeInterface {
4455
4476
  scheduleLocal: (options: LocalNotificationOptions) => Promise<{
4456
4477
  notificationId: string;
4457
4478
  }>;
4479
+ setBadgeCount?: (count: number) => Promise<{
4480
+ success: boolean;
4481
+ }>;
4458
4482
  };
4459
4483
  speech?: {
4460
4484
  recognize: (options?: SpeechRecognizeOptions) => Promise<SpeechResult>;
@@ -4497,12 +4521,6 @@ interface NativeBridgeInterface {
4497
4521
  rewarded: boolean;
4498
4522
  }>;
4499
4523
  };
4500
- app?: {
4501
- getVersion: () => Promise<string>;
4502
- getName: () => Promise<string>;
4503
- getPath: (name: string) => Promise<string | null>;
4504
- quit: () => Promise<void>;
4505
- };
4506
4524
  system?: {
4507
4525
  getInfo: () => Promise<SystemInfo>;
4508
4526
  getMemory: () => Promise<MemoryInfo>;
@@ -4592,10 +4610,34 @@ interface NativeBridgeInterface {
4592
4610
  saveToGallery?: (uri: string) => Promise<{
4593
4611
  uri: string;
4594
4612
  }>;
4613
+ /** 모바일: 앱 문서/캐시 디렉터리 URI */
4614
+ getDirectories?: () => Promise<{
4615
+ document: string | null;
4616
+ cache: string | null;
4617
+ }>;
4618
+ /** 데스크톱: 접근이 허용된 앱 전용 데이터 폴더 */
4619
+ getAppDir?: () => Promise<string>;
4595
4620
  };
4596
4621
  onDeepLink?: (callback: (url: string) => void) => () => void;
4597
4622
  }
4598
4623
  type Platform = "web" | "mobile" | "desktop";
4624
+ /** 패키징 앱 정보 (`cb.native.getAppInfo()`) */
4625
+ interface NativeAppInfo {
4626
+ platform: string;
4627
+ os?: string;
4628
+ osVersion?: string;
4629
+ arch?: string;
4630
+ appVersion?: string;
4631
+ electronVersion?: string;
4632
+ webUrl?: string;
4633
+ }
4634
+ /** 위치 추적 핸들 (`cb.native.location.watchPosition()`) */
4635
+ interface LocationWatch {
4636
+ /** 네이티브 watch 식별자 (웹 폴백에서는 geolocation watch id) */
4637
+ watchId: string;
4638
+ /** 추적 중지 */
4639
+ clear: () => Promise<void>;
4640
+ }
4599
4641
  interface CameraOptions {
4600
4642
  quality?: number;
4601
4643
  base64?: boolean;
@@ -4748,6 +4790,20 @@ declare class NativeAPI {
4748
4790
  * 현재 플랫폼 감지
4749
4791
  */
4750
4792
  getPlatform(): Platform;
4793
+ /**
4794
+ * 패키징 앱(네이티브 셸) 안에서 실행 중인지
4795
+ */
4796
+ isNativeApp(): boolean;
4797
+ /**
4798
+ * 패키징 앱 정보 조회 (웹에서는 null)
4799
+ *
4800
+ * @example
4801
+ * ```typescript
4802
+ * const info = await cb.native.getAppInfo()
4803
+ * // { platform: 'react-native', os: 'ios', appVersion: '1.0.0', webUrl: '...' }
4804
+ * ```
4805
+ */
4806
+ getAppInfo(): Promise<NativeAppInfo | null>;
4751
4807
  /**
4752
4808
  * 특정 네이티브 기능 지원 여부 확인
4753
4809
  */
@@ -4835,6 +4891,42 @@ declare class NativeAPI {
4835
4891
  * 현재 위치 가져오기
4836
4892
  */
4837
4893
  getCurrentPosition: (options?: LocationOptions) => Promise<Position>;
4894
+ /**
4895
+ * 위치 추적 시작.
4896
+ *
4897
+ * 패키징 앱(모바일)에서는 네이티브가 `nativeLocationUpdate` 이벤트로 갱신을 보내고,
4898
+ * 웹/데스크톱에서는 Geolocation `watchPosition` 을 사용한다.
4899
+ *
4900
+ * @example
4901
+ * ```typescript
4902
+ * const watch = await cb.native.location.watchPosition((pos) => console.log(pos))
4903
+ * // 나중에
4904
+ * await watch.clear()
4905
+ * ```
4906
+ */
4907
+ watchPosition: (onUpdate: (position: Position) => void, options?: LocationOptions) => Promise<LocationWatch>;
4908
+ };
4909
+ /**
4910
+ * 모바일 전용 푸시 API
4911
+ *
4912
+ * 패키징 앱은 raw 디바이스 토큰(iOS=APNS, Android=FCM)을 발급받아
4913
+ * `cb.push.registerDevice()` 로 등록해야 서버 발송이 가능하다.
4914
+ */
4915
+ push: {
4916
+ /**
4917
+ * 네이티브 디바이스 푸시 토큰 조회.
4918
+ * 웹(패키징 앱이 아닌 경우)에서는 null 을 반환한다.
4919
+ */
4920
+ getToken: () => Promise<{
4921
+ token: string;
4922
+ platform?: string;
4923
+ } | null>;
4924
+ /** 알림 권한 요청 (웹은 Web Notification 권한) */
4925
+ requestPermission: () => Promise<boolean>;
4926
+ /** 로컬 알림 예약 (패키징 앱 전용) */
4927
+ scheduleLocal: (options: LocalNotificationOptions) => Promise<string | null>;
4928
+ /** 앱 아이콘 배지 숫자 설정 (미지원 플랫폼에서는 무시) */
4929
+ setBadgeCount: (count: number) => Promise<boolean>;
4838
4930
  };
4839
4931
  /**
4840
4932
  * 크로스 플랫폼 알림 API
package/dist/index.d.ts CHANGED
@@ -4440,6 +4440,27 @@ declare global {
4440
4440
  }
4441
4441
  interface NativeBridgeInterface {
4442
4442
  platform?: "electron" | "react-native" | "ios" | "android";
4443
+ /** 실행 OS (react-native: 'ios' | 'android', electron: process.platform) */
4444
+ os?: string;
4445
+ /** 네이티브 셸에서 실행 중인지 (패키징 앱이면 항상 true) */
4446
+ isNative?: boolean;
4447
+ /** 브릿지 원시 호출 (문서화되지 않은 타입 호출용) */
4448
+ call?: (type: string, payload?: unknown, options?: {
4449
+ timeoutMs?: number;
4450
+ }) => Promise<unknown>;
4451
+ app?: {
4452
+ getVersion?: () => Promise<string>;
4453
+ getName?: () => Promise<string>;
4454
+ getInfo?: () => Promise<NativeAppInfo>;
4455
+ getPath?: (name: string) => Promise<string | null>;
4456
+ reload?: () => Promise<void>;
4457
+ quit?: () => Promise<void>;
4458
+ };
4459
+ browser?: {
4460
+ openExternal: (url: string) => Promise<{
4461
+ success: boolean;
4462
+ }>;
4463
+ };
4443
4464
  camera?: {
4444
4465
  takePicture: (options?: CameraOptions) => Promise<ImageResult>;
4445
4466
  pickImage: (options?: PickImageOptions) => Promise<ImageResult[]>;
@@ -4455,6 +4476,9 @@ interface NativeBridgeInterface {
4455
4476
  scheduleLocal: (options: LocalNotificationOptions) => Promise<{
4456
4477
  notificationId: string;
4457
4478
  }>;
4479
+ setBadgeCount?: (count: number) => Promise<{
4480
+ success: boolean;
4481
+ }>;
4458
4482
  };
4459
4483
  speech?: {
4460
4484
  recognize: (options?: SpeechRecognizeOptions) => Promise<SpeechResult>;
@@ -4497,12 +4521,6 @@ interface NativeBridgeInterface {
4497
4521
  rewarded: boolean;
4498
4522
  }>;
4499
4523
  };
4500
- app?: {
4501
- getVersion: () => Promise<string>;
4502
- getName: () => Promise<string>;
4503
- getPath: (name: string) => Promise<string | null>;
4504
- quit: () => Promise<void>;
4505
- };
4506
4524
  system?: {
4507
4525
  getInfo: () => Promise<SystemInfo>;
4508
4526
  getMemory: () => Promise<MemoryInfo>;
@@ -4592,10 +4610,34 @@ interface NativeBridgeInterface {
4592
4610
  saveToGallery?: (uri: string) => Promise<{
4593
4611
  uri: string;
4594
4612
  }>;
4613
+ /** 모바일: 앱 문서/캐시 디렉터리 URI */
4614
+ getDirectories?: () => Promise<{
4615
+ document: string | null;
4616
+ cache: string | null;
4617
+ }>;
4618
+ /** 데스크톱: 접근이 허용된 앱 전용 데이터 폴더 */
4619
+ getAppDir?: () => Promise<string>;
4595
4620
  };
4596
4621
  onDeepLink?: (callback: (url: string) => void) => () => void;
4597
4622
  }
4598
4623
  type Platform = "web" | "mobile" | "desktop";
4624
+ /** 패키징 앱 정보 (`cb.native.getAppInfo()`) */
4625
+ interface NativeAppInfo {
4626
+ platform: string;
4627
+ os?: string;
4628
+ osVersion?: string;
4629
+ arch?: string;
4630
+ appVersion?: string;
4631
+ electronVersion?: string;
4632
+ webUrl?: string;
4633
+ }
4634
+ /** 위치 추적 핸들 (`cb.native.location.watchPosition()`) */
4635
+ interface LocationWatch {
4636
+ /** 네이티브 watch 식별자 (웹 폴백에서는 geolocation watch id) */
4637
+ watchId: string;
4638
+ /** 추적 중지 */
4639
+ clear: () => Promise<void>;
4640
+ }
4599
4641
  interface CameraOptions {
4600
4642
  quality?: number;
4601
4643
  base64?: boolean;
@@ -4748,6 +4790,20 @@ declare class NativeAPI {
4748
4790
  * 현재 플랫폼 감지
4749
4791
  */
4750
4792
  getPlatform(): Platform;
4793
+ /**
4794
+ * 패키징 앱(네이티브 셸) 안에서 실행 중인지
4795
+ */
4796
+ isNativeApp(): boolean;
4797
+ /**
4798
+ * 패키징 앱 정보 조회 (웹에서는 null)
4799
+ *
4800
+ * @example
4801
+ * ```typescript
4802
+ * const info = await cb.native.getAppInfo()
4803
+ * // { platform: 'react-native', os: 'ios', appVersion: '1.0.0', webUrl: '...' }
4804
+ * ```
4805
+ */
4806
+ getAppInfo(): Promise<NativeAppInfo | null>;
4751
4807
  /**
4752
4808
  * 특정 네이티브 기능 지원 여부 확인
4753
4809
  */
@@ -4835,6 +4891,42 @@ declare class NativeAPI {
4835
4891
  * 현재 위치 가져오기
4836
4892
  */
4837
4893
  getCurrentPosition: (options?: LocationOptions) => Promise<Position>;
4894
+ /**
4895
+ * 위치 추적 시작.
4896
+ *
4897
+ * 패키징 앱(모바일)에서는 네이티브가 `nativeLocationUpdate` 이벤트로 갱신을 보내고,
4898
+ * 웹/데스크톱에서는 Geolocation `watchPosition` 을 사용한다.
4899
+ *
4900
+ * @example
4901
+ * ```typescript
4902
+ * const watch = await cb.native.location.watchPosition((pos) => console.log(pos))
4903
+ * // 나중에
4904
+ * await watch.clear()
4905
+ * ```
4906
+ */
4907
+ watchPosition: (onUpdate: (position: Position) => void, options?: LocationOptions) => Promise<LocationWatch>;
4908
+ };
4909
+ /**
4910
+ * 모바일 전용 푸시 API
4911
+ *
4912
+ * 패키징 앱은 raw 디바이스 토큰(iOS=APNS, Android=FCM)을 발급받아
4913
+ * `cb.push.registerDevice()` 로 등록해야 서버 발송이 가능하다.
4914
+ */
4915
+ push: {
4916
+ /**
4917
+ * 네이티브 디바이스 푸시 토큰 조회.
4918
+ * 웹(패키징 앱이 아닌 경우)에서는 null 을 반환한다.
4919
+ */
4920
+ getToken: () => Promise<{
4921
+ token: string;
4922
+ platform?: string;
4923
+ } | null>;
4924
+ /** 알림 권한 요청 (웹은 Web Notification 권한) */
4925
+ requestPermission: () => Promise<boolean>;
4926
+ /** 로컬 알림 예약 (패키징 앱 전용) */
4927
+ scheduleLocal: (options: LocalNotificationOptions) => Promise<string | null>;
4928
+ /** 앱 아이콘 배지 숫자 설정 (미지원 플랫폼에서는 무시) */
4929
+ setBadgeCount: (count: number) => Promise<boolean>;
4838
4930
  };
4839
4931
  /**
4840
4932
  * 크로스 플랫폼 알림 API
package/dist/index.js CHANGED
@@ -5042,6 +5042,101 @@ var NativeAPI = class {
5042
5042
  }
5043
5043
  );
5044
5044
  });
5045
+ },
5046
+ /**
5047
+ * 위치 추적 시작.
5048
+ *
5049
+ * 패키징 앱(모바일)에서는 네이티브가 `nativeLocationUpdate` 이벤트로 갱신을 보내고,
5050
+ * 웹/데스크톱에서는 Geolocation `watchPosition` 을 사용한다.
5051
+ *
5052
+ * @example
5053
+ * ```typescript
5054
+ * const watch = await cb.native.location.watchPosition((pos) => console.log(pos))
5055
+ * // 나중에
5056
+ * await watch.clear()
5057
+ * ```
5058
+ */
5059
+ watchPosition: async (onUpdate, options) => {
5060
+ const platform = this.getPlatform();
5061
+ const bridge = window.NativeBridge;
5062
+ if (platform === "mobile" && bridge?.location?.watchPosition) {
5063
+ const { watchId } = await bridge.location.watchPosition(options);
5064
+ const handler = (event) => {
5065
+ const detail = event.detail;
5066
+ if (!detail || detail.watchId && detail.watchId !== watchId) return;
5067
+ onUpdate({
5068
+ latitude: detail.latitude,
5069
+ longitude: detail.longitude,
5070
+ altitude: detail.altitude,
5071
+ accuracy: detail.accuracy,
5072
+ timestamp: detail.timestamp
5073
+ });
5074
+ };
5075
+ window.addEventListener("nativeLocationUpdate", handler);
5076
+ return {
5077
+ watchId,
5078
+ clear: async () => {
5079
+ window.removeEventListener("nativeLocationUpdate", handler);
5080
+ await bridge.location?.stopWatch(watchId);
5081
+ }
5082
+ };
5083
+ }
5084
+ const id = navigator.geolocation.watchPosition(
5085
+ (pos) => onUpdate({
5086
+ latitude: pos.coords.latitude,
5087
+ longitude: pos.coords.longitude,
5088
+ altitude: pos.coords.altitude,
5089
+ accuracy: pos.coords.accuracy,
5090
+ timestamp: pos.timestamp
5091
+ }),
5092
+ void 0,
5093
+ {
5094
+ enableHighAccuracy: options?.accuracy === "high",
5095
+ timeout: 1e4,
5096
+ maximumAge: 0
5097
+ }
5098
+ );
5099
+ return {
5100
+ watchId: String(id),
5101
+ clear: async () => navigator.geolocation.clearWatch(id)
5102
+ };
5103
+ }
5104
+ };
5105
+ /**
5106
+ * 모바일 전용 푸시 API
5107
+ *
5108
+ * 패키징 앱은 raw 디바이스 토큰(iOS=APNS, Android=FCM)을 발급받아
5109
+ * `cb.push.registerDevice()` 로 등록해야 서버 발송이 가능하다.
5110
+ */
5111
+ this.push = {
5112
+ /**
5113
+ * 네이티브 디바이스 푸시 토큰 조회.
5114
+ * 웹(패키징 앱이 아닌 경우)에서는 null 을 반환한다.
5115
+ */
5116
+ getToken: async () => {
5117
+ if (this.getPlatform() === "mobile" && window.NativeBridge?.push) {
5118
+ return window.NativeBridge.push.getToken();
5119
+ }
5120
+ return null;
5121
+ },
5122
+ /** 알림 권한 요청 (웹은 Web Notification 권한) */
5123
+ requestPermission: async () => {
5124
+ return this.notification.requestPermission();
5125
+ },
5126
+ /** 로컬 알림 예약 (패키징 앱 전용) */
5127
+ scheduleLocal: async (options) => {
5128
+ if (this.getPlatform() === "mobile" && window.NativeBridge?.push) {
5129
+ const result = await window.NativeBridge.push.scheduleLocal(options);
5130
+ return result.notificationId;
5131
+ }
5132
+ return null;
5133
+ },
5134
+ /** 앱 아이콘 배지 숫자 설정 (미지원 플랫폼에서는 무시) */
5135
+ setBadgeCount: async (count) => {
5136
+ const setter = window.NativeBridge?.push?.setBadgeCount;
5137
+ if (!setter) return false;
5138
+ const result = await setter(count);
5139
+ return result.success;
5045
5140
  }
5046
5141
  };
5047
5142
  /**
@@ -5057,6 +5152,16 @@ var NativeAPI = class {
5057
5152
  const result = await window.NativeBridge.notification.show(options);
5058
5153
  return result.success;
5059
5154
  }
5155
+ if (platform === "mobile" && window.NativeBridge?.push?.scheduleLocal) {
5156
+ const granted = await this.notification.requestPermission();
5157
+ if (!granted) return false;
5158
+ await window.NativeBridge.push.scheduleLocal({
5159
+ title: options.title,
5160
+ body: options.body,
5161
+ trigger: null
5162
+ });
5163
+ return true;
5164
+ }
5060
5165
  if (!("Notification" in window)) return false;
5061
5166
  if (Notification.permission !== "granted") {
5062
5167
  const permission = await Notification.requestPermission();
@@ -5096,6 +5201,10 @@ var NativeAPI = class {
5096
5201
  const result = await window.NativeBridge.shell.openExternal(url);
5097
5202
  return result.success;
5098
5203
  }
5204
+ if (platform === "mobile" && window.NativeBridge?.browser) {
5205
+ const result = await window.NativeBridge.browser.openExternal(url);
5206
+ return result.success;
5207
+ }
5099
5208
  window.open(url, "_blank");
5100
5209
  return true;
5101
5210
  }
@@ -5341,6 +5450,26 @@ var NativeAPI = class {
5341
5450
  if (bridge?.camera || window.ReactNativeWebView) return "mobile";
5342
5451
  return "web";
5343
5452
  }
5453
+ /**
5454
+ * 패키징 앱(네이티브 셸) 안에서 실행 중인지
5455
+ */
5456
+ isNativeApp() {
5457
+ return this.getPlatform() !== "web";
5458
+ }
5459
+ /**
5460
+ * 패키징 앱 정보 조회 (웹에서는 null)
5461
+ *
5462
+ * @example
5463
+ * ```typescript
5464
+ * const info = await cb.native.getAppInfo()
5465
+ * // { platform: 'react-native', os: 'ios', appVersion: '1.0.0', webUrl: '...' }
5466
+ * ```
5467
+ */
5468
+ async getAppInfo() {
5469
+ const getInfo = this.bridge?.app?.getInfo;
5470
+ if (!getInfo) return null;
5471
+ return getInfo();
5472
+ }
5344
5473
  /**
5345
5474
  * 특정 네이티브 기능 지원 여부 확인
5346
5475
  */
package/dist/index.mjs CHANGED
@@ -4996,6 +4996,101 @@ var NativeAPI = class {
4996
4996
  }
4997
4997
  );
4998
4998
  });
4999
+ },
5000
+ /**
5001
+ * 위치 추적 시작.
5002
+ *
5003
+ * 패키징 앱(모바일)에서는 네이티브가 `nativeLocationUpdate` 이벤트로 갱신을 보내고,
5004
+ * 웹/데스크톱에서는 Geolocation `watchPosition` 을 사용한다.
5005
+ *
5006
+ * @example
5007
+ * ```typescript
5008
+ * const watch = await cb.native.location.watchPosition((pos) => console.log(pos))
5009
+ * // 나중에
5010
+ * await watch.clear()
5011
+ * ```
5012
+ */
5013
+ watchPosition: async (onUpdate, options) => {
5014
+ const platform = this.getPlatform();
5015
+ const bridge = window.NativeBridge;
5016
+ if (platform === "mobile" && bridge?.location?.watchPosition) {
5017
+ const { watchId } = await bridge.location.watchPosition(options);
5018
+ const handler = (event) => {
5019
+ const detail = event.detail;
5020
+ if (!detail || detail.watchId && detail.watchId !== watchId) return;
5021
+ onUpdate({
5022
+ latitude: detail.latitude,
5023
+ longitude: detail.longitude,
5024
+ altitude: detail.altitude,
5025
+ accuracy: detail.accuracy,
5026
+ timestamp: detail.timestamp
5027
+ });
5028
+ };
5029
+ window.addEventListener("nativeLocationUpdate", handler);
5030
+ return {
5031
+ watchId,
5032
+ clear: async () => {
5033
+ window.removeEventListener("nativeLocationUpdate", handler);
5034
+ await bridge.location?.stopWatch(watchId);
5035
+ }
5036
+ };
5037
+ }
5038
+ const id = navigator.geolocation.watchPosition(
5039
+ (pos) => onUpdate({
5040
+ latitude: pos.coords.latitude,
5041
+ longitude: pos.coords.longitude,
5042
+ altitude: pos.coords.altitude,
5043
+ accuracy: pos.coords.accuracy,
5044
+ timestamp: pos.timestamp
5045
+ }),
5046
+ void 0,
5047
+ {
5048
+ enableHighAccuracy: options?.accuracy === "high",
5049
+ timeout: 1e4,
5050
+ maximumAge: 0
5051
+ }
5052
+ );
5053
+ return {
5054
+ watchId: String(id),
5055
+ clear: async () => navigator.geolocation.clearWatch(id)
5056
+ };
5057
+ }
5058
+ };
5059
+ /**
5060
+ * 모바일 전용 푸시 API
5061
+ *
5062
+ * 패키징 앱은 raw 디바이스 토큰(iOS=APNS, Android=FCM)을 발급받아
5063
+ * `cb.push.registerDevice()` 로 등록해야 서버 발송이 가능하다.
5064
+ */
5065
+ this.push = {
5066
+ /**
5067
+ * 네이티브 디바이스 푸시 토큰 조회.
5068
+ * 웹(패키징 앱이 아닌 경우)에서는 null 을 반환한다.
5069
+ */
5070
+ getToken: async () => {
5071
+ if (this.getPlatform() === "mobile" && window.NativeBridge?.push) {
5072
+ return window.NativeBridge.push.getToken();
5073
+ }
5074
+ return null;
5075
+ },
5076
+ /** 알림 권한 요청 (웹은 Web Notification 권한) */
5077
+ requestPermission: async () => {
5078
+ return this.notification.requestPermission();
5079
+ },
5080
+ /** 로컬 알림 예약 (패키징 앱 전용) */
5081
+ scheduleLocal: async (options) => {
5082
+ if (this.getPlatform() === "mobile" && window.NativeBridge?.push) {
5083
+ const result = await window.NativeBridge.push.scheduleLocal(options);
5084
+ return result.notificationId;
5085
+ }
5086
+ return null;
5087
+ },
5088
+ /** 앱 아이콘 배지 숫자 설정 (미지원 플랫폼에서는 무시) */
5089
+ setBadgeCount: async (count) => {
5090
+ const setter = window.NativeBridge?.push?.setBadgeCount;
5091
+ if (!setter) return false;
5092
+ const result = await setter(count);
5093
+ return result.success;
4999
5094
  }
5000
5095
  };
5001
5096
  /**
@@ -5011,6 +5106,16 @@ var NativeAPI = class {
5011
5106
  const result = await window.NativeBridge.notification.show(options);
5012
5107
  return result.success;
5013
5108
  }
5109
+ if (platform === "mobile" && window.NativeBridge?.push?.scheduleLocal) {
5110
+ const granted = await this.notification.requestPermission();
5111
+ if (!granted) return false;
5112
+ await window.NativeBridge.push.scheduleLocal({
5113
+ title: options.title,
5114
+ body: options.body,
5115
+ trigger: null
5116
+ });
5117
+ return true;
5118
+ }
5014
5119
  if (!("Notification" in window)) return false;
5015
5120
  if (Notification.permission !== "granted") {
5016
5121
  const permission = await Notification.requestPermission();
@@ -5050,6 +5155,10 @@ var NativeAPI = class {
5050
5155
  const result = await window.NativeBridge.shell.openExternal(url);
5051
5156
  return result.success;
5052
5157
  }
5158
+ if (platform === "mobile" && window.NativeBridge?.browser) {
5159
+ const result = await window.NativeBridge.browser.openExternal(url);
5160
+ return result.success;
5161
+ }
5053
5162
  window.open(url, "_blank");
5054
5163
  return true;
5055
5164
  }
@@ -5295,6 +5404,26 @@ var NativeAPI = class {
5295
5404
  if (bridge?.camera || window.ReactNativeWebView) return "mobile";
5296
5405
  return "web";
5297
5406
  }
5407
+ /**
5408
+ * 패키징 앱(네이티브 셸) 안에서 실행 중인지
5409
+ */
5410
+ isNativeApp() {
5411
+ return this.getPlatform() !== "web";
5412
+ }
5413
+ /**
5414
+ * 패키징 앱 정보 조회 (웹에서는 null)
5415
+ *
5416
+ * @example
5417
+ * ```typescript
5418
+ * const info = await cb.native.getAppInfo()
5419
+ * // { platform: 'react-native', os: 'ios', appVersion: '1.0.0', webUrl: '...' }
5420
+ * ```
5421
+ */
5422
+ async getAppInfo() {
5423
+ const getInfo = this.bridge?.app?.getInfo;
5424
+ if (!getInfo) return null;
5425
+ return getInfo();
5426
+ }
5298
5427
  /**
5299
5428
  * 특정 네이티브 기능 지원 여부 확인
5300
5429
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "connectbase-client",
3
- "version": "4.1.0",
3
+ "version": "4.2.0",
4
4
  "description": "Connect Base JavaScript/TypeScript SDK for browser and Node.js",
5
5
  "repository": {
6
6
  "type": "git",