@tagadapay/plugin-sdk 2.7.20 → 2.7.21

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.
@@ -55,6 +55,7 @@ export type { ExtractedAddress, GooglePlaceDetails, GooglePrediction, UseGoogleA
55
55
  export type { ISOCountry, ISORegion, UseISODataResult } from './hooks/useISOData';
56
56
  export type { UsePluginConfigOptions, UsePluginConfigResult } from './hooks/usePluginConfig';
57
57
  export type { TranslateFunction, UseTranslationOptions, UseTranslationResult } from './hooks/useTranslation';
58
+ export { FunnelEventType } from '../core/resources/funnel';
58
59
  export type { UseCheckoutQueryOptions as UseCheckoutOptions, UseCheckoutQueryResult as UseCheckoutResult } from './hooks/useCheckoutQuery';
59
60
  export type { UseDiscountsQueryOptions as UseDiscountsOptions, UseDiscountsQueryResult as UseDiscountsResult } from './hooks/useDiscountsQuery';
60
61
  export type { FunnelEvent, FunnelNavigationAction, FunnelNavigationResult, SimpleFunnelContext, UseFunnelOptions, UseFunnelResult } from './hooks/useFunnel';
@@ -44,5 +44,7 @@ export { useTranslation } from './hooks/useTranslation';
44
44
  export { useVipOffersQuery as useVipOffers } from './hooks/useVipOffersQuery';
45
45
  // Funnel hooks
46
46
  export { useFunnel, useSimpleFunnel } from './hooks/useFunnel';
47
+ // TanStack Query types
48
+ export { FunnelEventType } from '../core/resources/funnel';
47
49
  // Re-export utilities from main react
48
50
  export { formatMoney } from '../../react/utils/money';
@@ -26,6 +26,14 @@ interface TagadaContextValue {
26
26
  lastUpdated: Date | null;
27
27
  };
28
28
  updateCheckoutDebugData: (data: any, error?: Error | null, isLoading?: boolean) => void;
29
+ debugFunnel: {
30
+ isActive: boolean;
31
+ data: any;
32
+ error: Error | null;
33
+ isLoading: boolean;
34
+ lastUpdated: Date | null;
35
+ };
36
+ updateFunnelDebugData: (data: any, error?: Error | null, isLoading?: boolean) => void;
29
37
  refreshCoordinator: {
30
38
  registerCheckoutRefresh: (refreshFn: () => Promise<void>, name?: string) => void;
31
39
  registerOrderBumpRefresh: (refreshFn: () => Promise<void>) => void;
@@ -295,6 +295,13 @@ rawPluginConfig, }) {
295
295
  isLoading: false,
296
296
  lastUpdated: null,
297
297
  });
298
+ const [debugFunnel, setDebugFunnel] = useState({
299
+ isActive: false,
300
+ data: null,
301
+ error: null,
302
+ isLoading: false,
303
+ lastUpdated: null,
304
+ });
298
305
  // Initialize auth state
299
306
  const [auth, setAuth] = useState({
300
307
  isAuthenticated: false,
@@ -480,6 +487,65 @@ rawPluginConfig, }) {
480
487
  setIsLoading(false);
481
488
  }
482
489
  }, [apiService, hasAttemptedAnonymousToken, initializeSession, finalDebugMode, isActiveInstance, instanceId]);
490
+ // Initialize token from storage or create anonymous token (extracted to stable callback)
491
+ const initializeToken = useCallback(async () => {
492
+ if (!isActiveInstance) {
493
+ console.log(`🚫 [TagadaProvider] Instance ${instanceId} is not active, skipping token initialization`);
494
+ return;
495
+ }
496
+ try {
497
+ console.debug('[SDK] Initializing token...');
498
+ setIsLoading(true);
499
+ // Check for existing token
500
+ const existingToken = getClientToken();
501
+ let tokenToUse = null;
502
+ // Check URL params for token
503
+ const urlParams = new URLSearchParams(window.location.search);
504
+ const queryToken = urlParams.get('token');
505
+ if (queryToken) {
506
+ console.debug('[SDK] Found token in URL params');
507
+ tokenToUse = queryToken;
508
+ setClientToken(queryToken);
509
+ }
510
+ else if (existingToken && !isTokenExpired(existingToken)) {
511
+ console.debug('[SDK] Using existing token from storage');
512
+ tokenToUse = existingToken;
513
+ }
514
+ else {
515
+ console.debug('[SDK] No valid token found');
516
+ // Determine storeId for anonymous token
517
+ const targetStoreId = storeId || 'default-store';
518
+ await createAnonymousToken(targetStoreId);
519
+ return;
520
+ }
521
+ if (tokenToUse) {
522
+ setToken(tokenToUse);
523
+ // Update the API service with the token
524
+ apiService.updateToken(tokenToUse);
525
+ // IMPORTANT: Immediately sync token to API client
526
+ apiClient.updateToken(tokenToUse);
527
+ console.log('[SDK] Token immediately synced to ApiClient:', tokenToUse.substring(0, 8) + '...');
528
+ // Decode token to get session data
529
+ const decodedSession = decodeJWTClient(tokenToUse);
530
+ if (decodedSession) {
531
+ setSession(decodedSession);
532
+ // Initialize session with API call
533
+ await initializeSession(decodedSession);
534
+ }
535
+ else {
536
+ console.error('[SDK] Failed to decode token');
537
+ setIsInitialized(true);
538
+ setIsSessionInitialized(false); // Session failed to initialize
539
+ setIsLoading(false);
540
+ }
541
+ }
542
+ }
543
+ catch (error) {
544
+ console.error('[SDK] Error initializing token:', error);
545
+ setIsInitialized(true);
546
+ setIsLoading(false);
547
+ }
548
+ }, [apiService, apiClient, storeId, createAnonymousToken, initializeSession, isActiveInstance, instanceId]);
483
549
  // Initialize token from storage or create anonymous token
484
550
  // This runs in the background after phases 1 & 2 complete, but doesn't block rendering
485
551
  useEffect(() => {
@@ -500,62 +566,23 @@ rawPluginConfig, }) {
500
566
  return;
501
567
  }
502
568
  isInitializing.current = true;
503
- const initializeToken = async () => {
504
- try {
505
- console.debug('[SDK] Initializing token...');
506
- setIsLoading(true);
507
- // Check for existing token
508
- const existingToken = getClientToken();
509
- let tokenToUse = null;
510
- // Check URL params for token
511
- const urlParams = new URLSearchParams(window.location.search);
512
- const queryToken = urlParams.get('token');
513
- if (queryToken) {
514
- console.debug('[SDK] Found token in URL params');
515
- tokenToUse = queryToken;
516
- setClientToken(queryToken);
517
- }
518
- else if (existingToken && !isTokenExpired(existingToken)) {
519
- console.debug('[SDK] Using existing token from storage');
520
- tokenToUse = existingToken;
521
- }
522
- else {
523
- console.debug('[SDK] No valid token found');
524
- // Determine storeId for anonymous token
525
- const targetStoreId = storeId || 'default-store';
526
- await createAnonymousToken(targetStoreId);
527
- return;
528
- }
529
- if (tokenToUse) {
530
- setToken(tokenToUse);
531
- // Update the API service with the token
532
- apiService.updateToken(tokenToUse);
533
- // IMPORTANT: Immediately sync token to API client
534
- apiClient.updateToken(tokenToUse);
535
- console.log('[SDK] Token immediately synced to ApiClient:', tokenToUse.substring(0, 8) + '...');
536
- // Decode token to get session data
537
- const decodedSession = decodeJWTClient(tokenToUse);
538
- if (decodedSession) {
539
- setSession(decodedSession);
540
- // Initialize session with API call
541
- await initializeSession(decodedSession);
542
- }
543
- else {
544
- console.error('[SDK] Failed to decode token');
545
- setIsInitialized(true);
546
- setIsSessionInitialized(false); // Session failed to initialize
547
- setIsLoading(false);
548
- }
549
- }
550
- }
551
- catch (error) {
552
- console.error('[SDK] Error initializing token:', error);
553
- setIsInitialized(true);
554
- setIsLoading(false);
555
- }
556
- };
557
569
  void initializeToken();
558
- }, [storeId, createAnonymousToken, initializeSession, configLoading, isActiveInstance, instanceId]);
570
+ }, [storeId, initializeToken, configLoading, isActiveInstance, instanceId]);
571
+ // Listen for storage changes (e.g., token updated in another tab)
572
+ useEffect(() => {
573
+ if (!isActiveInstance) {
574
+ return;
575
+ }
576
+ function onStorage() {
577
+ // Re-run initialization when token may have changed in another tab
578
+ isInitializing.current = false;
579
+ void initializeToken();
580
+ }
581
+ window.addEventListener('storage', onStorage);
582
+ return () => {
583
+ window.removeEventListener('storage', onStorage);
584
+ };
585
+ }, [initializeToken, isActiveInstance]);
559
586
  // Update auth state when customer/session changes
560
587
  useEffect(() => {
561
588
  setAuth({
@@ -671,6 +698,16 @@ rawPluginConfig, }) {
671
698
  pluginConfigLoading: configLoading,
672
699
  debugCheckout,
673
700
  updateCheckoutDebugData: memoizedUpdateDebugData,
701
+ debugFunnel,
702
+ updateFunnelDebugData: (data, error, isLoading) => {
703
+ setDebugFunnel({
704
+ isActive: true,
705
+ data,
706
+ error: error ?? null,
707
+ isLoading: isLoading ?? false,
708
+ lastUpdated: new Date(),
709
+ });
710
+ },
674
711
  refreshCoordinator,
675
712
  money: memoizedMoneyUtils,
676
713
  }), [
@@ -685,6 +722,8 @@ rawPluginConfig, }) {
685
722
  isLoading,
686
723
  isInitialized,
687
724
  isSessionInitialized,
725
+ debugCheckout,
726
+ debugFunnel,
688
727
  finalDebugMode,
689
728
  pluginConfig,
690
729
  configLoading,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tagadapay/plugin-sdk",
3
- "version": "2.7.20",
3
+ "version": "2.7.21",
4
4
  "description": "Modern React SDK for building Tagada Pay plugins",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",