@adstage/web-sdk 2.2.3 → 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -1,5 +1,8 @@
1
1
  'use strict';
2
2
 
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var react = require('react');
5
+
3
6
  // 광고 타입 정의
4
7
  var AdType;
5
8
  (function (AdType) {
@@ -2799,7 +2802,7 @@ class AdsModule {
2799
2802
  throw new Error(`Container not found: ${slot.containerId}`);
2800
2803
  }
2801
2804
  // 이벤트 추적 콜백 함수 (중복 노출 방지 포함)
2802
- const trackEventCallback = (adId, slotId, eventType) => {
2805
+ const trackEventCallback = async (adId, slotId, eventType) => {
2803
2806
  // 노출 이벤트인 경우 중복 확인
2804
2807
  if (eventType === AdEventType.VIEWABLE) {
2805
2808
  if (ViewableEventTracker.isDuplicateViewable(adId, slotId, this._config?.debug)) {
@@ -2812,8 +2815,20 @@ class AdsModule {
2812
2815
  console.log(`✅ New viewable recorded for ad ${adId} in slot ${slotId}`);
2813
2816
  }
2814
2817
  }
2815
- if (this.advertisementEventTracker && this._config?.debug) {
2816
- console.log(`📊 Advertisement event tracked: ${eventType} for ad ${adId} in slot ${slotId}`);
2818
+ // 실제 API 호출로 이벤트 전송
2819
+ if (this.advertisementEventTracker) {
2820
+ try {
2821
+ await this.advertisementEventTracker.trackAdvertisementEvent(adId, slotId, eventType, {} // 기본 메타데이터
2822
+ );
2823
+ if (this._config?.debug) {
2824
+ console.log(`📊 Advertisement event tracked: ${eventType} for ad ${adId} in slot ${slotId}`);
2825
+ }
2826
+ }
2827
+ catch (error) {
2828
+ if (this._config?.debug) {
2829
+ console.error(`❌ Failed to track ${eventType} event for ad ${adId}:`, error);
2830
+ }
2831
+ }
2817
2832
  }
2818
2833
  };
2819
2834
  let sliderElement;
@@ -3236,6 +3251,13 @@ class AdStage {
3236
3251
  productionMode: false,
3237
3252
  ...config
3238
3253
  };
3254
+ // baseUrl이 설정되었으면 endpoints에 적용
3255
+ if (config.baseUrl) {
3256
+ endpoints.setBaseUrl(config.baseUrl);
3257
+ if (config.debug) {
3258
+ console.log('🔄 API base URL set to:', config.baseUrl);
3259
+ }
3260
+ }
3239
3261
  // 모듈 동기 초기화
3240
3262
  const enabledModules = instance._config.modules || ['ads', 'events', 'config'];
3241
3263
  for (const moduleName of enabledModules) {
@@ -3279,53 +3301,14 @@ class AdStage {
3279
3301
  * 편의성을 위한 정적 모듈 접근자들
3280
3302
  */
3281
3303
  static get ads() {
3282
- // 🚀 자동 초기화: 아직 초기화되지 않았으면 환경변수로 자동 초기화
3283
- if (!AdStage.instance?._isInitialized) {
3284
- AdStage.autoInit();
3285
- }
3286
3304
  return AdStage.getInstance().ads;
3287
3305
  }
3288
3306
  static get events() {
3289
- if (!AdStage.instance?._isInitialized) {
3290
- AdStage.autoInit();
3291
- }
3292
3307
  return AdStage.getInstance().events;
3293
3308
  }
3294
3309
  static get config() {
3295
- if (!AdStage.instance?._isInitialized) {
3296
- AdStage.autoInit();
3297
- }
3298
3310
  return AdStage.getInstance().config;
3299
3311
  }
3300
- /**
3301
- * 🆕 자동 초기화 - 환경변수 기반
3302
- */
3303
- static autoInit() {
3304
- if (typeof window === 'undefined')
3305
- return; // 서버 사이드에서는 실행 안함
3306
- try {
3307
- // 환경변수에서 API 키 자동 로드
3308
- const apiKey = window.__ADSTAGE_API_KEY__ || // 런타임 설정
3309
- process.env.NEXT_PUBLIC_ADSTAGE_API_KEY || // Next.js
3310
- process.env.REACT_APP_ADSTAGE_API_KEY || // Create React App
3311
- process.env.VITE_ADSTAGE_API_KEY || // Vite
3312
- 'demo-api-key'; // 개발용 fallback
3313
- const isDevelopment = "production" === 'development' ||
3314
- window.__ADSTAGE_DEBUG__ === true;
3315
- AdStage.init({
3316
- apiKey: apiKey,
3317
- debug: isDevelopment,
3318
- modules: ['ads', 'config']
3319
- });
3320
- if (isDevelopment) {
3321
- console.log('🔄 AdStage SDK auto-initialized with API key:', apiKey.substring(0, 8) + '...');
3322
- }
3323
- }
3324
- catch (error) {
3325
- console.warn('AdStage auto-initialization failed:', error);
3326
- console.warn('Please call AdStage.init() manually or set NEXT_PUBLIC_ADSTAGE_API_KEY environment variable');
3327
- }
3328
- }
3329
3312
  /**
3330
3313
  * SDK 리셋 (테스트용)
3331
3314
  */
@@ -3337,6 +3320,82 @@ class AdStage {
3337
3320
  }
3338
3321
  }
3339
3322
 
3323
+ const AdStageContext = react.createContext(null);
3324
+ function AdStageProvider({ children, config }) {
3325
+ const [isInitialized, setIsInitialized] = react.useState(false);
3326
+ const [currentConfig, setCurrentConfig] = react.useState(null);
3327
+ const [error, setError] = react.useState(null);
3328
+ const initialize = (newConfig) => {
3329
+ try {
3330
+ setError(null);
3331
+ // 기존 인스턴스가 있으면 리셋
3332
+ if (isInitialized) {
3333
+ AdStage.reset();
3334
+ }
3335
+ AdStage.init(newConfig);
3336
+ setCurrentConfig(newConfig);
3337
+ setIsInitialized(true);
3338
+ if (newConfig.debug) {
3339
+ console.log('✅ AdStage SDK initialized successfully via React Provider');
3340
+ }
3341
+ }
3342
+ catch (err) {
3343
+ const errorMessage = err instanceof Error ? err.message : 'Unknown error';
3344
+ setError(errorMessage);
3345
+ console.error('❌ AdStage SDK initialization failed:', err);
3346
+ setIsInitialized(false);
3347
+ setCurrentConfig(null);
3348
+ }
3349
+ };
3350
+ const reset = () => {
3351
+ try {
3352
+ AdStage.reset();
3353
+ setIsInitialized(false);
3354
+ setCurrentConfig(null);
3355
+ setError(null);
3356
+ }
3357
+ catch (err) {
3358
+ console.error('❌ AdStage SDK reset failed:', err);
3359
+ }
3360
+ };
3361
+ // 자동 초기화
3362
+ react.useEffect(() => {
3363
+ if (config && !isInitialized) {
3364
+ initialize(config);
3365
+ }
3366
+ }, [config, isInitialized]);
3367
+ const contextValue = {
3368
+ isInitialized,
3369
+ config: currentConfig,
3370
+ initialize,
3371
+ reset,
3372
+ error
3373
+ };
3374
+ return (jsxRuntime.jsx(AdStageContext.Provider, { value: contextValue, children: children }));
3375
+ }
3376
+ /**
3377
+ * AdStage Context Hook
3378
+ * AdStageProvider 내에서 SDK 상태에 접근할 수 있습니다.
3379
+ */
3380
+ function useAdStage() {
3381
+ const context = react.useContext(AdStageContext);
3382
+ if (!context) {
3383
+ throw new Error('useAdStage must be used within an AdStageProvider');
3384
+ }
3385
+ return context;
3386
+ }
3387
+ /**
3388
+ * AdStage SDK Hook
3389
+ * 초기화된 AdStage 인스턴스에 직접 접근할 수 있습니다.
3390
+ */
3391
+ function useAdStageSDK() {
3392
+ const { isInitialized } = useAdStage();
3393
+ if (!isInitialized) {
3394
+ throw new Error('AdStage SDK is not initialized. Please call initialize() first or provide config to AdStageProvider.');
3395
+ }
3396
+ return AdStage;
3397
+ }
3398
+
3340
3399
  /**
3341
3400
  * AdStage Web SDK
3342
3401
  * 네임스페이스 아키텍처 기반 SDK
@@ -3347,5 +3406,8 @@ const SDK_VERSION = '2.0.0';
3347
3406
  const SUPPORTED_MODULES = ['ads', 'events', 'config'];
3348
3407
 
3349
3408
  exports.AdStage = AdStage;
3409
+ exports.AdStageProvider = AdStageProvider;
3350
3410
  exports.SDK_VERSION = SDK_VERSION;
3351
3411
  exports.SUPPORTED_MODULES = SUPPORTED_MODULES;
3412
+ exports.useAdStage = useAdStage;
3413
+ exports.useAdStageSDK = useAdStageSDK;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+
1
4
  /**
2
5
  * AdStage SDK 모듈 타입
3
6
  */
@@ -513,16 +516,39 @@ declare class AdStage {
513
516
  static get ads(): AdsModule;
514
517
  static get events(): EventsModule;
515
518
  static get config(): ConfigModule;
516
- /**
517
- * 🆕 자동 초기화 - 환경변수 기반
518
- */
519
- private static autoInit;
520
519
  /**
521
520
  * SDK 리셋 (테스트용)
522
521
  */
523
522
  static reset(): void;
524
523
  }
525
524
 
525
+ interface AdStageContextType {
526
+ isInitialized: boolean;
527
+ config: AdStageConfig | null;
528
+ initialize: (config: AdStageConfig) => void;
529
+ reset: () => void;
530
+ error: string | null;
531
+ }
532
+ interface AdStageProviderProps {
533
+ children: ReactNode;
534
+ /**
535
+ * 자동 초기화를 위한 설정 (선택사항)
536
+ * 제공되면 Provider 마운트 시 자동으로 초기화됩니다.
537
+ */
538
+ config?: AdStageConfig;
539
+ }
540
+ declare function AdStageProvider({ children, config }: AdStageProviderProps): react_jsx_runtime.JSX.Element;
541
+ /**
542
+ * AdStage Context Hook
543
+ * AdStageProvider 내에서 SDK 상태에 접근할 수 있습니다.
544
+ */
545
+ declare function useAdStage(): AdStageContextType;
546
+ /**
547
+ * AdStage SDK Hook
548
+ * 초기화된 AdStage 인스턴스에 직접 접근할 수 있습니다.
549
+ */
550
+ declare function useAdStageSDK(): typeof AdStage;
551
+
526
552
  /**
527
553
  * AdStage Web SDK
528
554
  * 네임스페이스 아키텍처 기반 SDK
@@ -531,4 +557,4 @@ declare class AdStage {
531
557
  declare const SDK_VERSION = "2.0.0";
532
558
  declare const SUPPORTED_MODULES: readonly ["ads", "events", "config"];
533
559
 
534
- export { AdEventType, AdOptions, AdSlot, AdStage, AdStageConfig, AdType, Advertisement, ApiResponse, BaseModule, EventProperties, ModuleName, OrganizationInfo, PageData, SDK_VERSION, SUPPORTED_MODULES };
560
+ export { AdEventType, AdOptions, AdSlot, AdStage, AdStageConfig, AdStageProvider, AdType, Advertisement, ApiResponse, BaseModule, EventProperties, ModuleName, OrganizationInfo, PageData, SDK_VERSION, SUPPORTED_MODULES, useAdStage, useAdStageSDK };
package/dist/index.esm.js CHANGED
@@ -1,3 +1,6 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { createContext, useState, useEffect, useContext } from 'react';
3
+
1
4
  // 광고 타입 정의
2
5
  var AdType;
3
6
  (function (AdType) {
@@ -2797,7 +2800,7 @@ class AdsModule {
2797
2800
  throw new Error(`Container not found: ${slot.containerId}`);
2798
2801
  }
2799
2802
  // 이벤트 추적 콜백 함수 (중복 노출 방지 포함)
2800
- const trackEventCallback = (adId, slotId, eventType) => {
2803
+ const trackEventCallback = async (adId, slotId, eventType) => {
2801
2804
  // 노출 이벤트인 경우 중복 확인
2802
2805
  if (eventType === AdEventType.VIEWABLE) {
2803
2806
  if (ViewableEventTracker.isDuplicateViewable(adId, slotId, this._config?.debug)) {
@@ -2810,8 +2813,20 @@ class AdsModule {
2810
2813
  console.log(`✅ New viewable recorded for ad ${adId} in slot ${slotId}`);
2811
2814
  }
2812
2815
  }
2813
- if (this.advertisementEventTracker && this._config?.debug) {
2814
- console.log(`📊 Advertisement event tracked: ${eventType} for ad ${adId} in slot ${slotId}`);
2816
+ // 실제 API 호출로 이벤트 전송
2817
+ if (this.advertisementEventTracker) {
2818
+ try {
2819
+ await this.advertisementEventTracker.trackAdvertisementEvent(adId, slotId, eventType, {} // 기본 메타데이터
2820
+ );
2821
+ if (this._config?.debug) {
2822
+ console.log(`📊 Advertisement event tracked: ${eventType} for ad ${adId} in slot ${slotId}`);
2823
+ }
2824
+ }
2825
+ catch (error) {
2826
+ if (this._config?.debug) {
2827
+ console.error(`❌ Failed to track ${eventType} event for ad ${adId}:`, error);
2828
+ }
2829
+ }
2815
2830
  }
2816
2831
  };
2817
2832
  let sliderElement;
@@ -3234,6 +3249,13 @@ class AdStage {
3234
3249
  productionMode: false,
3235
3250
  ...config
3236
3251
  };
3252
+ // baseUrl이 설정되었으면 endpoints에 적용
3253
+ if (config.baseUrl) {
3254
+ endpoints.setBaseUrl(config.baseUrl);
3255
+ if (config.debug) {
3256
+ console.log('🔄 API base URL set to:', config.baseUrl);
3257
+ }
3258
+ }
3237
3259
  // 모듈 동기 초기화
3238
3260
  const enabledModules = instance._config.modules || ['ads', 'events', 'config'];
3239
3261
  for (const moduleName of enabledModules) {
@@ -3277,53 +3299,14 @@ class AdStage {
3277
3299
  * 편의성을 위한 정적 모듈 접근자들
3278
3300
  */
3279
3301
  static get ads() {
3280
- // 🚀 자동 초기화: 아직 초기화되지 않았으면 환경변수로 자동 초기화
3281
- if (!AdStage.instance?._isInitialized) {
3282
- AdStage.autoInit();
3283
- }
3284
3302
  return AdStage.getInstance().ads;
3285
3303
  }
3286
3304
  static get events() {
3287
- if (!AdStage.instance?._isInitialized) {
3288
- AdStage.autoInit();
3289
- }
3290
3305
  return AdStage.getInstance().events;
3291
3306
  }
3292
3307
  static get config() {
3293
- if (!AdStage.instance?._isInitialized) {
3294
- AdStage.autoInit();
3295
- }
3296
3308
  return AdStage.getInstance().config;
3297
3309
  }
3298
- /**
3299
- * 🆕 자동 초기화 - 환경변수 기반
3300
- */
3301
- static autoInit() {
3302
- if (typeof window === 'undefined')
3303
- return; // 서버 사이드에서는 실행 안함
3304
- try {
3305
- // 환경변수에서 API 키 자동 로드
3306
- const apiKey = window.__ADSTAGE_API_KEY__ || // 런타임 설정
3307
- process.env.NEXT_PUBLIC_ADSTAGE_API_KEY || // Next.js
3308
- process.env.REACT_APP_ADSTAGE_API_KEY || // Create React App
3309
- process.env.VITE_ADSTAGE_API_KEY || // Vite
3310
- 'demo-api-key'; // 개발용 fallback
3311
- const isDevelopment = "production" === 'development' ||
3312
- window.__ADSTAGE_DEBUG__ === true;
3313
- AdStage.init({
3314
- apiKey: apiKey,
3315
- debug: isDevelopment,
3316
- modules: ['ads', 'config']
3317
- });
3318
- if (isDevelopment) {
3319
- console.log('🔄 AdStage SDK auto-initialized with API key:', apiKey.substring(0, 8) + '...');
3320
- }
3321
- }
3322
- catch (error) {
3323
- console.warn('AdStage auto-initialization failed:', error);
3324
- console.warn('Please call AdStage.init() manually or set NEXT_PUBLIC_ADSTAGE_API_KEY environment variable');
3325
- }
3326
- }
3327
3310
  /**
3328
3311
  * SDK 리셋 (테스트용)
3329
3312
  */
@@ -3335,6 +3318,82 @@ class AdStage {
3335
3318
  }
3336
3319
  }
3337
3320
 
3321
+ const AdStageContext = createContext(null);
3322
+ function AdStageProvider({ children, config }) {
3323
+ const [isInitialized, setIsInitialized] = useState(false);
3324
+ const [currentConfig, setCurrentConfig] = useState(null);
3325
+ const [error, setError] = useState(null);
3326
+ const initialize = (newConfig) => {
3327
+ try {
3328
+ setError(null);
3329
+ // 기존 인스턴스가 있으면 리셋
3330
+ if (isInitialized) {
3331
+ AdStage.reset();
3332
+ }
3333
+ AdStage.init(newConfig);
3334
+ setCurrentConfig(newConfig);
3335
+ setIsInitialized(true);
3336
+ if (newConfig.debug) {
3337
+ console.log('✅ AdStage SDK initialized successfully via React Provider');
3338
+ }
3339
+ }
3340
+ catch (err) {
3341
+ const errorMessage = err instanceof Error ? err.message : 'Unknown error';
3342
+ setError(errorMessage);
3343
+ console.error('❌ AdStage SDK initialization failed:', err);
3344
+ setIsInitialized(false);
3345
+ setCurrentConfig(null);
3346
+ }
3347
+ };
3348
+ const reset = () => {
3349
+ try {
3350
+ AdStage.reset();
3351
+ setIsInitialized(false);
3352
+ setCurrentConfig(null);
3353
+ setError(null);
3354
+ }
3355
+ catch (err) {
3356
+ console.error('❌ AdStage SDK reset failed:', err);
3357
+ }
3358
+ };
3359
+ // 자동 초기화
3360
+ useEffect(() => {
3361
+ if (config && !isInitialized) {
3362
+ initialize(config);
3363
+ }
3364
+ }, [config, isInitialized]);
3365
+ const contextValue = {
3366
+ isInitialized,
3367
+ config: currentConfig,
3368
+ initialize,
3369
+ reset,
3370
+ error
3371
+ };
3372
+ return (jsx(AdStageContext.Provider, { value: contextValue, children: children }));
3373
+ }
3374
+ /**
3375
+ * AdStage Context Hook
3376
+ * AdStageProvider 내에서 SDK 상태에 접근할 수 있습니다.
3377
+ */
3378
+ function useAdStage() {
3379
+ const context = useContext(AdStageContext);
3380
+ if (!context) {
3381
+ throw new Error('useAdStage must be used within an AdStageProvider');
3382
+ }
3383
+ return context;
3384
+ }
3385
+ /**
3386
+ * AdStage SDK Hook
3387
+ * 초기화된 AdStage 인스턴스에 직접 접근할 수 있습니다.
3388
+ */
3389
+ function useAdStageSDK() {
3390
+ const { isInitialized } = useAdStage();
3391
+ if (!isInitialized) {
3392
+ throw new Error('AdStage SDK is not initialized. Please call initialize() first or provide config to AdStageProvider.');
3393
+ }
3394
+ return AdStage;
3395
+ }
3396
+
3338
3397
  /**
3339
3398
  * AdStage Web SDK
3340
3399
  * 네임스페이스 아키텍처 기반 SDK
@@ -3344,4 +3403,4 @@ class AdStage {
3344
3403
  const SDK_VERSION = '2.0.0';
3345
3404
  const SUPPORTED_MODULES = ['ads', 'events', 'config'];
3346
3405
 
3347
- export { AdStage, SDK_VERSION, SUPPORTED_MODULES };
3406
+ export { AdStage, AdStageProvider, SDK_VERSION, SUPPORTED_MODULES, useAdStage, useAdStageSDK };
@@ -2797,7 +2797,7 @@ class AdsModule {
2797
2797
  throw new Error(`Container not found: ${slot.containerId}`);
2798
2798
  }
2799
2799
  // 이벤트 추적 콜백 함수 (중복 노출 방지 포함)
2800
- const trackEventCallback = (adId, slotId, eventType) => {
2800
+ const trackEventCallback = async (adId, slotId, eventType) => {
2801
2801
  // 노출 이벤트인 경우 중복 확인
2802
2802
  if (eventType === AdEventType.VIEWABLE) {
2803
2803
  if (ViewableEventTracker.isDuplicateViewable(adId, slotId, this._config?.debug)) {
@@ -2810,8 +2810,20 @@ class AdsModule {
2810
2810
  console.log(`✅ New viewable recorded for ad ${adId} in slot ${slotId}`);
2811
2811
  }
2812
2812
  }
2813
- if (this.advertisementEventTracker && this._config?.debug) {
2814
- console.log(`📊 Advertisement event tracked: ${eventType} for ad ${adId} in slot ${slotId}`);
2813
+ // 실제 API 호출로 이벤트 전송
2814
+ if (this.advertisementEventTracker) {
2815
+ try {
2816
+ await this.advertisementEventTracker.trackAdvertisementEvent(adId, slotId, eventType, {} // 기본 메타데이터
2817
+ );
2818
+ if (this._config?.debug) {
2819
+ console.log(`📊 Advertisement event tracked: ${eventType} for ad ${adId} in slot ${slotId}`);
2820
+ }
2821
+ }
2822
+ catch (error) {
2823
+ if (this._config?.debug) {
2824
+ console.error(`❌ Failed to track ${eventType} event for ad ${adId}:`, error);
2825
+ }
2826
+ }
2815
2827
  }
2816
2828
  };
2817
2829
  let sliderElement;
@@ -3234,6 +3246,13 @@ class AdStage {
3234
3246
  productionMode: false,
3235
3247
  ...config
3236
3248
  };
3249
+ // baseUrl이 설정되었으면 endpoints에 적용
3250
+ if (config.baseUrl) {
3251
+ endpoints.setBaseUrl(config.baseUrl);
3252
+ if (config.debug) {
3253
+ console.log('🔄 API base URL set to:', config.baseUrl);
3254
+ }
3255
+ }
3237
3256
  // 모듈 동기 초기화
3238
3257
  const enabledModules = instance._config.modules || ['ads', 'events', 'config'];
3239
3258
  for (const moduleName of enabledModules) {
@@ -3277,53 +3296,14 @@ class AdStage {
3277
3296
  * 편의성을 위한 정적 모듈 접근자들
3278
3297
  */
3279
3298
  static get ads() {
3280
- // 🚀 자동 초기화: 아직 초기화되지 않았으면 환경변수로 자동 초기화
3281
- if (!AdStage.instance?._isInitialized) {
3282
- AdStage.autoInit();
3283
- }
3284
3299
  return AdStage.getInstance().ads;
3285
3300
  }
3286
3301
  static get events() {
3287
- if (!AdStage.instance?._isInitialized) {
3288
- AdStage.autoInit();
3289
- }
3290
3302
  return AdStage.getInstance().events;
3291
3303
  }
3292
3304
  static get config() {
3293
- if (!AdStage.instance?._isInitialized) {
3294
- AdStage.autoInit();
3295
- }
3296
3305
  return AdStage.getInstance().config;
3297
3306
  }
3298
- /**
3299
- * 🆕 자동 초기화 - 환경변수 기반
3300
- */
3301
- static autoInit() {
3302
- if (typeof window === 'undefined')
3303
- return; // 서버 사이드에서는 실행 안함
3304
- try {
3305
- // 환경변수에서 API 키 자동 로드
3306
- const apiKey = window.__ADSTAGE_API_KEY__ || // 런타임 설정
3307
- process.env.NEXT_PUBLIC_ADSTAGE_API_KEY || // Next.js
3308
- process.env.REACT_APP_ADSTAGE_API_KEY || // Create React App
3309
- process.env.VITE_ADSTAGE_API_KEY || // Vite
3310
- 'demo-api-key'; // 개발용 fallback
3311
- const isDevelopment = "production" === 'development' ||
3312
- window.__ADSTAGE_DEBUG__ === true;
3313
- AdStage.init({
3314
- apiKey: apiKey,
3315
- debug: isDevelopment,
3316
- modules: ['ads', 'config']
3317
- });
3318
- if (isDevelopment) {
3319
- console.log('🔄 AdStage SDK auto-initialized with API key:', apiKey.substring(0, 8) + '...');
3320
- }
3321
- }
3322
- catch (error) {
3323
- console.warn('AdStage auto-initialization failed:', error);
3324
- console.warn('Please call AdStage.init() manually or set NEXT_PUBLIC_ADSTAGE_API_KEY environment variable');
3325
- }
3326
- }
3327
3307
  /**
3328
3308
  * SDK 리셋 (테스트용)
3329
3309
  */
@@ -3335,6 +3315,157 @@ class AdStage {
3335
3315
  }
3336
3316
  }
3337
3317
 
3318
+ var jsxRuntime = {exports: {}};
3319
+
3320
+ var reactJsxRuntime_production_min = {};
3321
+
3322
+ var react = {exports: {}};
3323
+
3324
+ var react_production_min = {};
3325
+
3326
+ /**
3327
+ * @license React
3328
+ * react.production.min.js
3329
+ *
3330
+ * Copyright (c) Facebook, Inc. and its affiliates.
3331
+ *
3332
+ * This source code is licensed under the MIT license found in the
3333
+ * LICENSE file in the root directory of this source tree.
3334
+ */
3335
+
3336
+ var hasRequiredReact_production_min;
3337
+
3338
+ function requireReact_production_min () {
3339
+ if (hasRequiredReact_production_min) return react_production_min;
3340
+ hasRequiredReact_production_min = 1;
3341
+ var l=Symbol.for("react.element"),n=Symbol.for("react.portal"),p=Symbol.for("react.fragment"),q=Symbol.for("react.strict_mode"),r=Symbol.for("react.profiler"),t=Symbol.for("react.provider"),u=Symbol.for("react.context"),v=Symbol.for("react.forward_ref"),w=Symbol.for("react.suspense"),x=Symbol.for("react.memo"),y=Symbol.for("react.lazy"),z=Symbol.iterator;function A(a){if(null===a||"object"!==typeof a)return null;a=z&&a[z]||a["@@iterator"];return "function"===typeof a?a:null}
3342
+ var B={isMounted:function(){return !1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},C=Object.assign,D={};function E(a,b,e){this.props=a;this.context=b;this.refs=D;this.updater=e||B;}E.prototype.isReactComponent={};
3343
+ E.prototype.setState=function(a,b){if("object"!==typeof a&&"function"!==typeof a&&null!=a)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,a,b,"setState");};E.prototype.forceUpdate=function(a){this.updater.enqueueForceUpdate(this,a,"forceUpdate");};function F(){}F.prototype=E.prototype;function G(a,b,e){this.props=a;this.context=b;this.refs=D;this.updater=e||B;}var H=G.prototype=new F;
3344
+ H.constructor=G;C(H,E.prototype);H.isPureReactComponent=!0;var I=Array.isArray,J=Object.prototype.hasOwnProperty,K={current:null},L={key:!0,ref:!0,__self:!0,__source:!0};
3345
+ function M(a,b,e){var d,c={},k=null,h=null;if(null!=b)for(d in void 0!==b.ref&&(h=b.ref),void 0!==b.key&&(k=""+b.key),b)J.call(b,d)&&!L.hasOwnProperty(d)&&(c[d]=b[d]);var g=arguments.length-2;if(1===g)c.children=e;else if(1<g){for(var f=Array(g),m=0;m<g;m++)f[m]=arguments[m+2];c.children=f;}if(a&&a.defaultProps)for(d in g=a.defaultProps,g)void 0===c[d]&&(c[d]=g[d]);return {$$typeof:l,type:a,key:k,ref:h,props:c,_owner:K.current}}
3346
+ function N(a,b){return {$$typeof:l,type:a.type,key:b,ref:a.ref,props:a.props,_owner:a._owner}}function O(a){return "object"===typeof a&&null!==a&&a.$$typeof===l}function escape(a){var b={"=":"=0",":":"=2"};return "$"+a.replace(/[=:]/g,function(a){return b[a]})}var P=/\/+/g;function Q(a,b){return "object"===typeof a&&null!==a&&null!=a.key?escape(""+a.key):b.toString(36)}
3347
+ function R(a,b,e,d,c){var k=typeof a;if("undefined"===k||"boolean"===k)a=null;var h=!1;if(null===a)h=!0;else switch(k){case "string":case "number":h=!0;break;case "object":switch(a.$$typeof){case l:case n:h=!0;}}if(h)return h=a,c=c(h),a=""===d?"."+Q(h,0):d,I(c)?(e="",null!=a&&(e=a.replace(P,"$&/")+"/"),R(c,b,e,"",function(a){return a})):null!=c&&(O(c)&&(c=N(c,e+(!c.key||h&&h.key===c.key?"":(""+c.key).replace(P,"$&/")+"/")+a)),b.push(c)),1;h=0;d=""===d?".":d+":";if(I(a))for(var g=0;g<a.length;g++){k=
3348
+ a[g];var f=d+Q(k,g);h+=R(k,b,e,f,c);}else if(f=A(a),"function"===typeof f)for(a=f.call(a),g=0;!(k=a.next()).done;)k=k.value,f=d+Q(k,g++),h+=R(k,b,e,f,c);else if("object"===k)throw b=String(a),Error("Objects are not valid as a React child (found: "+("[object Object]"===b?"object with keys {"+Object.keys(a).join(", ")+"}":b)+"). If you meant to render a collection of children, use an array instead.");return h}
3349
+ function S(a,b,e){if(null==a)return a;var d=[],c=0;R(a,d,"","",function(a){return b.call(e,a,c++)});return d}function T(a){if(-1===a._status){var b=a._result;b=b();b.then(function(b){if(0===a._status||-1===a._status)a._status=1,a._result=b;},function(b){if(0===a._status||-1===a._status)a._status=2,a._result=b;});-1===a._status&&(a._status=0,a._result=b);}if(1===a._status)return a._result.default;throw a._result;}
3350
+ var U={current:null},V={transition:null},W={ReactCurrentDispatcher:U,ReactCurrentBatchConfig:V,ReactCurrentOwner:K};function X(){throw Error("act(...) is not supported in production builds of React.");}
3351
+ react_production_min.Children={map:S,forEach:function(a,b,e){S(a,function(){b.apply(this,arguments);},e);},count:function(a){var b=0;S(a,function(){b++;});return b},toArray:function(a){return S(a,function(a){return a})||[]},only:function(a){if(!O(a))throw Error("React.Children.only expected to receive a single React element child.");return a}};react_production_min.Component=E;react_production_min.Fragment=p;react_production_min.Profiler=r;react_production_min.PureComponent=G;react_production_min.StrictMode=q;react_production_min.Suspense=w;
3352
+ react_production_min.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=W;react_production_min.act=X;
3353
+ react_production_min.cloneElement=function(a,b,e){if(null===a||void 0===a)throw Error("React.cloneElement(...): The argument must be a React element, but you passed "+a+".");var d=C({},a.props),c=a.key,k=a.ref,h=a._owner;if(null!=b){void 0!==b.ref&&(k=b.ref,h=K.current);void 0!==b.key&&(c=""+b.key);if(a.type&&a.type.defaultProps)var g=a.type.defaultProps;for(f in b)J.call(b,f)&&!L.hasOwnProperty(f)&&(d[f]=void 0===b[f]&&void 0!==g?g[f]:b[f]);}var f=arguments.length-2;if(1===f)d.children=e;else if(1<f){g=Array(f);
3354
+ for(var m=0;m<f;m++)g[m]=arguments[m+2];d.children=g;}return {$$typeof:l,type:a.type,key:c,ref:k,props:d,_owner:h}};react_production_min.createContext=function(a){a={$$typeof:u,_currentValue:a,_currentValue2:a,_threadCount:0,Provider:null,Consumer:null,_defaultValue:null,_globalName:null};a.Provider={$$typeof:t,_context:a};return a.Consumer=a};react_production_min.createElement=M;react_production_min.createFactory=function(a){var b=M.bind(null,a);b.type=a;return b};react_production_min.createRef=function(){return {current:null}};
3355
+ react_production_min.forwardRef=function(a){return {$$typeof:v,render:a}};react_production_min.isValidElement=O;react_production_min.lazy=function(a){return {$$typeof:y,_payload:{_status:-1,_result:a},_init:T}};react_production_min.memo=function(a,b){return {$$typeof:x,type:a,compare:void 0===b?null:b}};react_production_min.startTransition=function(a){var b=V.transition;V.transition={};try{a();}finally{V.transition=b;}};react_production_min.unstable_act=X;react_production_min.useCallback=function(a,b){return U.current.useCallback(a,b)};react_production_min.useContext=function(a){return U.current.useContext(a)};
3356
+ react_production_min.useDebugValue=function(){};react_production_min.useDeferredValue=function(a){return U.current.useDeferredValue(a)};react_production_min.useEffect=function(a,b){return U.current.useEffect(a,b)};react_production_min.useId=function(){return U.current.useId()};react_production_min.useImperativeHandle=function(a,b,e){return U.current.useImperativeHandle(a,b,e)};react_production_min.useInsertionEffect=function(a,b){return U.current.useInsertionEffect(a,b)};react_production_min.useLayoutEffect=function(a,b){return U.current.useLayoutEffect(a,b)};
3357
+ react_production_min.useMemo=function(a,b){return U.current.useMemo(a,b)};react_production_min.useReducer=function(a,b,e){return U.current.useReducer(a,b,e)};react_production_min.useRef=function(a){return U.current.useRef(a)};react_production_min.useState=function(a){return U.current.useState(a)};react_production_min.useSyncExternalStore=function(a,b,e){return U.current.useSyncExternalStore(a,b,e)};react_production_min.useTransition=function(){return U.current.useTransition()};react_production_min.version="18.3.1";
3358
+ return react_production_min;
3359
+ }
3360
+
3361
+ {
3362
+ react.exports = requireReact_production_min();
3363
+ }
3364
+
3365
+ var reactExports = react.exports;
3366
+
3367
+ /**
3368
+ * @license React
3369
+ * react-jsx-runtime.production.min.js
3370
+ *
3371
+ * Copyright (c) Facebook, Inc. and its affiliates.
3372
+ *
3373
+ * This source code is licensed under the MIT license found in the
3374
+ * LICENSE file in the root directory of this source tree.
3375
+ */
3376
+
3377
+ var hasRequiredReactJsxRuntime_production_min;
3378
+
3379
+ function requireReactJsxRuntime_production_min () {
3380
+ if (hasRequiredReactJsxRuntime_production_min) return reactJsxRuntime_production_min;
3381
+ hasRequiredReactJsxRuntime_production_min = 1;
3382
+ var f=reactExports,k=Symbol.for("react.element"),l=Symbol.for("react.fragment"),m=Object.prototype.hasOwnProperty,n=f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,p={key:!0,ref:!0,__self:!0,__source:!0};
3383
+ function q(c,a,g){var b,d={},e=null,h=null;void 0!==g&&(e=""+g);void 0!==a.key&&(e=""+a.key);void 0!==a.ref&&(h=a.ref);for(b in a)m.call(a,b)&&!p.hasOwnProperty(b)&&(d[b]=a[b]);if(c&&c.defaultProps)for(b in a=c.defaultProps,a)void 0===d[b]&&(d[b]=a[b]);return {$$typeof:k,type:c,key:e,ref:h,props:d,_owner:n.current}}reactJsxRuntime_production_min.Fragment=l;reactJsxRuntime_production_min.jsx=q;reactJsxRuntime_production_min.jsxs=q;
3384
+ return reactJsxRuntime_production_min;
3385
+ }
3386
+
3387
+ {
3388
+ jsxRuntime.exports = requireReactJsxRuntime_production_min();
3389
+ }
3390
+
3391
+ var jsxRuntimeExports = jsxRuntime.exports;
3392
+
3393
+ const AdStageContext = reactExports.createContext(null);
3394
+ function AdStageProvider({ children, config }) {
3395
+ const [isInitialized, setIsInitialized] = reactExports.useState(false);
3396
+ const [currentConfig, setCurrentConfig] = reactExports.useState(null);
3397
+ const [error, setError] = reactExports.useState(null);
3398
+ const initialize = (newConfig) => {
3399
+ try {
3400
+ setError(null);
3401
+ // 기존 인스턴스가 있으면 리셋
3402
+ if (isInitialized) {
3403
+ AdStage.reset();
3404
+ }
3405
+ AdStage.init(newConfig);
3406
+ setCurrentConfig(newConfig);
3407
+ setIsInitialized(true);
3408
+ if (newConfig.debug) {
3409
+ console.log('✅ AdStage SDK initialized successfully via React Provider');
3410
+ }
3411
+ }
3412
+ catch (err) {
3413
+ const errorMessage = err instanceof Error ? err.message : 'Unknown error';
3414
+ setError(errorMessage);
3415
+ console.error('❌ AdStage SDK initialization failed:', err);
3416
+ setIsInitialized(false);
3417
+ setCurrentConfig(null);
3418
+ }
3419
+ };
3420
+ const reset = () => {
3421
+ try {
3422
+ AdStage.reset();
3423
+ setIsInitialized(false);
3424
+ setCurrentConfig(null);
3425
+ setError(null);
3426
+ }
3427
+ catch (err) {
3428
+ console.error('❌ AdStage SDK reset failed:', err);
3429
+ }
3430
+ };
3431
+ // 자동 초기화
3432
+ reactExports.useEffect(() => {
3433
+ if (config && !isInitialized) {
3434
+ initialize(config);
3435
+ }
3436
+ }, [config, isInitialized]);
3437
+ const contextValue = {
3438
+ isInitialized,
3439
+ config: currentConfig,
3440
+ initialize,
3441
+ reset,
3442
+ error
3443
+ };
3444
+ return (jsxRuntimeExports.jsx(AdStageContext.Provider, { value: contextValue, children: children }));
3445
+ }
3446
+ /**
3447
+ * AdStage Context Hook
3448
+ * AdStageProvider 내에서 SDK 상태에 접근할 수 있습니다.
3449
+ */
3450
+ function useAdStage() {
3451
+ const context = reactExports.useContext(AdStageContext);
3452
+ if (!context) {
3453
+ throw new Error('useAdStage must be used within an AdStageProvider');
3454
+ }
3455
+ return context;
3456
+ }
3457
+ /**
3458
+ * AdStage SDK Hook
3459
+ * 초기화된 AdStage 인스턴스에 직접 접근할 수 있습니다.
3460
+ */
3461
+ function useAdStageSDK() {
3462
+ const { isInitialized } = useAdStage();
3463
+ if (!isInitialized) {
3464
+ throw new Error('AdStage SDK is not initialized. Please call initialize() first or provide config to AdStageProvider.');
3465
+ }
3466
+ return AdStage;
3467
+ }
3468
+
3338
3469
  /**
3339
3470
  * AdStage Web SDK
3340
3471
  * 네임스페이스 아키텍처 기반 SDK
@@ -3344,4 +3475,4 @@ class AdStage {
3344
3475
  const SDK_VERSION = '2.0.0';
3345
3476
  const SUPPORTED_MODULES = ['ads', 'events', 'config'];
3346
3477
 
3347
- export { AdStage, SDK_VERSION, SUPPORTED_MODULES };
3478
+ export { AdStage, AdStageProvider, SDK_VERSION, SUPPORTED_MODULES, useAdStage, useAdStageSDK };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@adstage/web-sdk",
3
- "version": "2.2.3",
4
- "description": "AdStage Web SDK - Production-ready marketing platform SDK with auto-initialization, dynamic sizing, centered image positioning, user-defined size support, and adaptive height adjustment",
3
+ "version": "2.3.2",
4
+ "description": "AdStage Web SDK - Production-ready marketing platform SDK with React Provider support for seamless integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs.js",
7
7
  "module": "dist/index.esm.js",
@@ -39,7 +39,7 @@
39
39
  "ads",
40
40
  "banner",
41
41
  "text",
42
- "video",
42
+ "video",
43
43
  "native",
44
44
  "interstitial",
45
45
  "sdk",
@@ -7,6 +7,7 @@ import { AdStageConfig, ModuleName } from '../types/config';
7
7
  import { AdsModule } from '../modules/ads/AdsModule';
8
8
  import { ConfigModule } from '../modules/config/ConfigModule';
9
9
  import { EventsModule } from '../modules/events/EventsModule';
10
+ import { endpoints } from '../constants/endpoints';
10
11
 
11
12
  export class AdStage {
12
13
  private static instance: AdStage;
@@ -52,6 +53,14 @@ export class AdStage {
52
53
  ...config
53
54
  };
54
55
 
56
+ // baseUrl이 설정되었으면 endpoints에 적용
57
+ if (config.baseUrl) {
58
+ endpoints.setBaseUrl(config.baseUrl);
59
+ if (config.debug) {
60
+ console.log('🔄 API base URL set to:', config.baseUrl);
61
+ }
62
+ }
63
+
55
64
  // 모듈 동기 초기화
56
65
  const enabledModules = instance._config.modules || ['ads', 'events', 'config'];
57
66
 
@@ -102,61 +111,17 @@ export class AdStage {
102
111
  * 편의성을 위한 정적 모듈 접근자들
103
112
  */
104
113
  public static get ads() {
105
- // 🚀 자동 초기화: 아직 초기화되지 않았으면 환경변수로 자동 초기화
106
- if (!AdStage.instance?._isInitialized) {
107
- AdStage.autoInit();
108
- }
109
114
  return AdStage.getInstance().ads;
110
115
  }
111
116
 
112
117
  public static get events() {
113
- if (!AdStage.instance?._isInitialized) {
114
- AdStage.autoInit();
115
- }
116
118
  return AdStage.getInstance().events;
117
119
  }
118
120
 
119
121
  public static get config() {
120
- if (!AdStage.instance?._isInitialized) {
121
- AdStage.autoInit();
122
- }
123
122
  return AdStage.getInstance().config;
124
123
  }
125
124
 
126
- /**
127
- * 🆕 자동 초기화 - 환경변수 기반
128
- */
129
- private static autoInit(): void {
130
- if (typeof window === 'undefined') return; // 서버 사이드에서는 실행 안함
131
-
132
- try {
133
- // 환경변수에서 API 키 자동 로드
134
- const apiKey =
135
- (window as any).__ADSTAGE_API_KEY__ || // 런타임 설정
136
- process.env.NEXT_PUBLIC_ADSTAGE_API_KEY || // Next.js
137
- process.env.REACT_APP_ADSTAGE_API_KEY || // Create React App
138
- process.env.VITE_ADSTAGE_API_KEY || // Vite
139
- 'demo-api-key'; // 개발용 fallback
140
-
141
- const isDevelopment =
142
- process.env.NODE_ENV === 'development' ||
143
- (window as any).__ADSTAGE_DEBUG__ === true;
144
-
145
- AdStage.init({
146
- apiKey: apiKey,
147
- debug: isDevelopment,
148
- modules: ['ads', 'config']
149
- });
150
-
151
- if (isDevelopment) {
152
- console.log('🔄 AdStage SDK auto-initialized with API key:', apiKey.substring(0, 8) + '...');
153
- }
154
- } catch (error) {
155
- console.warn('AdStage auto-initialization failed:', error);
156
- console.warn('Please call AdStage.init() manually or set NEXT_PUBLIC_ADSTAGE_API_KEY environment variable');
157
- }
158
- }
159
-
160
125
  /**
161
126
  * SDK 리셋 (테스트용)
162
127
  */
package/src/index.ts CHANGED
@@ -6,6 +6,9 @@
6
6
  // 메인 네임스페이스 클래스
7
7
  export { default as AdStage } from './core/AdStage';
8
8
 
9
+ // React 통합 (선택적)
10
+ export { AdStageProvider, useAdStage, useAdStageSDK } from './react';
11
+
9
12
  // 설정 및 타입
10
13
  export type { AdStageConfig, ModuleName, BaseModule, ApiResponse, OrganizationInfo } from './types/config';
11
14
 
@@ -106,6 +106,7 @@ export class AdvertisementEventTracker {
106
106
  }),
107
107
  };
108
108
 
109
+
109
110
  await fetch(
110
111
  `${this.baseUrl}/advertisements/events/${adId}/${eventType}`,
111
112
  {
@@ -929,7 +929,7 @@ export class AdsModule implements BaseModule {
929
929
  }
930
930
 
931
931
  // 이벤트 추적 콜백 함수 (중복 노출 방지 포함)
932
- const trackEventCallback = (adId: string, slotId: string, eventType: AdEventType) => {
932
+ const trackEventCallback = async (adId: string, slotId: string, eventType: AdEventType) => {
933
933
  // 노출 이벤트인 경우 중복 확인
934
934
  if (eventType === AdEventType.VIEWABLE) {
935
935
  if (ViewableEventTracker.isDuplicateViewable(adId, slotId, this._config?.debug)) {
@@ -944,8 +944,24 @@ export class AdsModule implements BaseModule {
944
944
  }
945
945
  }
946
946
 
947
- if (this.advertisementEventTracker && this._config?.debug) {
948
- console.log(`📊 Advertisement event tracked: ${eventType} for ad ${adId} in slot ${slotId}`);
947
+ // 실제 API 호출로 이벤트 전송
948
+ if (this.advertisementEventTracker) {
949
+ try {
950
+ await this.advertisementEventTracker.trackAdvertisementEvent(
951
+ adId,
952
+ slotId,
953
+ eventType,
954
+ {} // 기본 메타데이터
955
+ );
956
+
957
+ if (this._config?.debug) {
958
+ console.log(`📊 Advertisement event tracked: ${eventType} for ad ${adId} in slot ${slotId}`);
959
+ }
960
+ } catch (error) {
961
+ if (this._config?.debug) {
962
+ console.error(`❌ Failed to track ${eventType} event for ad ${adId}:`, error);
963
+ }
964
+ }
949
965
  }
950
966
  };
951
967
 
@@ -0,0 +1,117 @@
1
+ /**
2
+ * AdStage SDK - React Provider
3
+ * React 애플리케이션에서 AdStage SDK를 쉽게 사용할 수 있도록 하는 Provider 컴포넌트
4
+ */
5
+
6
+ import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react';
7
+ import AdStage from '../core/AdStage';
8
+ import { AdStageConfig } from '../types/config';
9
+
10
+ interface AdStageContextType {
11
+ isInitialized: boolean;
12
+ config: AdStageConfig | null;
13
+ initialize: (config: AdStageConfig) => void;
14
+ reset: () => void;
15
+ error: string | null;
16
+ }
17
+
18
+ const AdStageContext = createContext<AdStageContextType | null>(null);
19
+
20
+ interface AdStageProviderProps {
21
+ children: ReactNode;
22
+ /**
23
+ * 자동 초기화를 위한 설정 (선택사항)
24
+ * 제공되면 Provider 마운트 시 자동으로 초기화됩니다.
25
+ */
26
+ config?: AdStageConfig;
27
+ }
28
+
29
+ export function AdStageProvider({ children, config }: AdStageProviderProps) {
30
+ const [isInitialized, setIsInitialized] = useState(false);
31
+ const [currentConfig, setCurrentConfig] = useState<AdStageConfig | null>(null);
32
+ const [error, setError] = useState<string | null>(null);
33
+
34
+ const initialize = (newConfig: AdStageConfig) => {
35
+ try {
36
+ setError(null);
37
+
38
+ // 기존 인스턴스가 있으면 리셋
39
+ if (isInitialized) {
40
+ AdStage.reset();
41
+ }
42
+
43
+ AdStage.init(newConfig);
44
+
45
+ setCurrentConfig(newConfig);
46
+ setIsInitialized(true);
47
+
48
+ if (newConfig.debug) {
49
+ console.log('✅ AdStage SDK initialized successfully via React Provider');
50
+ }
51
+ } catch (err) {
52
+ const errorMessage = err instanceof Error ? err.message : 'Unknown error';
53
+ setError(errorMessage);
54
+ console.error('❌ AdStage SDK initialization failed:', err);
55
+ setIsInitialized(false);
56
+ setCurrentConfig(null);
57
+ }
58
+ };
59
+
60
+ const reset = () => {
61
+ try {
62
+ AdStage.reset();
63
+ setIsInitialized(false);
64
+ setCurrentConfig(null);
65
+ setError(null);
66
+ } catch (err) {
67
+ console.error('❌ AdStage SDK reset failed:', err);
68
+ }
69
+ };
70
+
71
+ // 자동 초기화
72
+ useEffect(() => {
73
+ if (config && !isInitialized) {
74
+ initialize(config);
75
+ }
76
+ }, [config, isInitialized]);
77
+
78
+ const contextValue: AdStageContextType = {
79
+ isInitialized,
80
+ config: currentConfig,
81
+ initialize,
82
+ reset,
83
+ error
84
+ };
85
+
86
+ return (
87
+ <AdStageContext.Provider value={contextValue}>
88
+ {children}
89
+ </AdStageContext.Provider>
90
+ );
91
+ }
92
+
93
+ /**
94
+ * AdStage Context Hook
95
+ * AdStageProvider 내에서 SDK 상태에 접근할 수 있습니다.
96
+ */
97
+ export function useAdStage(): AdStageContextType {
98
+ const context = useContext(AdStageContext);
99
+ if (!context) {
100
+ throw new Error('useAdStage must be used within an AdStageProvider');
101
+ }
102
+ return context;
103
+ }
104
+
105
+ /**
106
+ * AdStage SDK Hook
107
+ * 초기화된 AdStage 인스턴스에 직접 접근할 수 있습니다.
108
+ */
109
+ export function useAdStageSDK() {
110
+ const { isInitialized } = useAdStage();
111
+
112
+ if (!isInitialized) {
113
+ throw new Error('AdStage SDK is not initialized. Please call initialize() first or provide config to AdStageProvider.');
114
+ }
115
+
116
+ return AdStage;
117
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * AdStage Web SDK - React Integration
3
+ * React 애플리케이션을 위한 컴포넌트와 훅들
4
+ */
5
+
6
+ export { AdStageProvider, useAdStage, useAdStageSDK } from './AdStageProvider';
7
+
8
+ // 타입들도 재export
9
+ export type { AdStageConfig, ModuleName, BaseModule } from '../types/config';
10
+ export type { AdOptions } from '../modules/ads/AdsModule';
11
+ export type { AdType, AdEventType, Advertisement, AdSlot } from '../types/advertisement';