@tagadapay/plugin-sdk 3.0.9 → 3.0.14

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.
Files changed (31) hide show
  1. package/dist/external-tracker.js +3802 -195
  2. package/dist/external-tracker.min.js +25 -2
  3. package/dist/external-tracker.min.js.map +4 -4
  4. package/dist/react/types.d.ts +2 -0
  5. package/dist/v2/core/client.d.ts +4 -0
  6. package/dist/v2/core/client.js +314 -123
  7. package/dist/v2/core/config/environment.js +6 -0
  8. package/dist/v2/core/funnelClient.d.ts +18 -1
  9. package/dist/v2/core/funnelClient.js +90 -17
  10. package/dist/v2/core/resources/checkout.d.ts +44 -1
  11. package/dist/v2/core/resources/checkout.js +48 -1
  12. package/dist/v2/core/resources/funnel.d.ts +44 -4
  13. package/dist/v2/core/resources/offers.d.ts +26 -0
  14. package/dist/v2/core/resources/offers.js +37 -0
  15. package/dist/v2/core/types.d.ts +3 -1
  16. package/dist/v2/core/utils/authHandoff.d.ts +60 -0
  17. package/dist/v2/core/utils/authHandoff.js +154 -0
  18. package/dist/v2/core/utils/deviceInfo.d.ts +20 -3
  19. package/dist/v2/core/utils/deviceInfo.js +62 -94
  20. package/dist/v2/core/utils/previewMode.d.ts +4 -0
  21. package/dist/v2/core/utils/previewMode.js +4 -0
  22. package/dist/v2/react/components/DebugDrawer.js +68 -46
  23. package/dist/v2/react/hooks/useCheckoutQuery.d.ts +0 -1
  24. package/dist/v2/react/hooks/useCheckoutQuery.js +12 -4
  25. package/dist/v2/react/hooks/useFunnelLegacy.js +39 -11
  26. package/dist/v2/react/hooks/usePreviewOffer.d.ts +3 -3
  27. package/dist/v2/react/hooks/usePreviewOffer.js +20 -15
  28. package/dist/v2/react/hooks/useTranslation.js +12 -4
  29. package/dist/v2/standalone/index.d.ts +2 -1
  30. package/dist/v2/standalone/index.js +2 -1
  31. package/package.json +3 -1
@@ -1,16 +1,27 @@
1
1
  export interface DeviceInfo {
2
2
  userAgent: {
3
+ name: string;
3
4
  browser: {
5
+ major: string;
4
6
  name: string;
5
7
  version: string;
8
+ type?: string;
6
9
  };
7
10
  os: {
8
11
  name: string;
9
12
  version: string;
10
13
  };
11
14
  device?: {
12
- type: string;
13
- model: string;
15
+ model?: string;
16
+ type?: string;
17
+ vendor?: string;
18
+ };
19
+ engine: {
20
+ name: string;
21
+ version: string;
22
+ };
23
+ cpu: {
24
+ architecture: string;
14
25
  };
15
26
  };
16
27
  screenResolution: {
@@ -18,13 +29,19 @@ export interface DeviceInfo {
18
29
  height: number;
19
30
  };
20
31
  timeZone: string;
32
+ flags?: {
33
+ isBot: boolean;
34
+ isChromeFamily: boolean;
35
+ isStandalonePWA: boolean;
36
+ isAppleSilicon: boolean;
37
+ };
21
38
  }
22
39
  /**
23
40
  * Get browser locale
24
41
  */
25
42
  export declare function getBrowserLocale(): string;
26
43
  /**
27
- * Collect all device information
44
+ * Collect all device information using UAParser
28
45
  */
29
46
  export declare function collectDeviceInfo(): DeviceInfo;
30
47
  /**
@@ -1,91 +1,5 @@
1
- /**
2
- * Get basic browser information from user agent
3
- */
4
- function getBrowserInfo() {
5
- const userAgent = navigator.userAgent;
6
- // Chrome
7
- if (userAgent.includes('Chrome')) {
8
- const match = /Chrome\/(\d+)/.exec(userAgent);
9
- return { name: 'Chrome', version: match ? match[1] : 'unknown' };
10
- }
11
- // Firefox
12
- if (userAgent.includes('Firefox')) {
13
- const match = /Firefox\/(\d+)/.exec(userAgent);
14
- return { name: 'Firefox', version: match ? match[1] : 'unknown' };
15
- }
16
- // Safari
17
- if (userAgent.includes('Safari') && !userAgent.includes('Chrome')) {
18
- const match = /Version\/(\d+)/.exec(userAgent);
19
- return { name: 'Safari', version: match ? match[1] : 'unknown' };
20
- }
21
- // Edge
22
- if (userAgent.includes('Edge')) {
23
- const match = /Edge\/(\d+)/.exec(userAgent);
24
- return { name: 'Edge', version: match ? match[1] : 'unknown' };
25
- }
26
- return { name: 'unknown', version: 'unknown' };
27
- }
28
- /**
29
- * Get basic OS information from user agent
30
- */
31
- function getOSInfo() {
32
- const userAgent = navigator.userAgent;
33
- // Windows
34
- if (userAgent.includes('Windows')) {
35
- if (userAgent.includes('Windows NT 10.0'))
36
- return { name: 'Windows', version: '10' };
37
- if (userAgent.includes('Windows NT 6.3'))
38
- return { name: 'Windows', version: '8.1' };
39
- if (userAgent.includes('Windows NT 6.2'))
40
- return { name: 'Windows', version: '8' };
41
- if (userAgent.includes('Windows NT 6.1'))
42
- return { name: 'Windows', version: '7' };
43
- return { name: 'Windows', version: 'unknown' };
44
- }
45
- // macOS
46
- if (userAgent.includes('Mac OS X')) {
47
- const match = /Mac OS X (\d+[._]\d+)/.exec(userAgent);
48
- return { name: 'macOS', version: match ? match[1].replace('_', '.') : 'unknown' };
49
- }
50
- // iOS
51
- if (userAgent.includes('iPhone') || userAgent.includes('iPad')) {
52
- const match = /OS (\d+[._]\d+)/.exec(userAgent);
53
- return { name: 'iOS', version: match ? match[1].replace('_', '.') : 'unknown' };
54
- }
55
- // Android
56
- if (userAgent.includes('Android')) {
57
- const match = /Android (\d+[.\d]*)/.exec(userAgent);
58
- return { name: 'Android', version: match ? match[1] : 'unknown' };
59
- }
60
- // Linux
61
- if (userAgent.includes('Linux')) {
62
- return { name: 'Linux', version: 'unknown' };
63
- }
64
- return { name: 'unknown', version: 'unknown' };
65
- }
66
- /**
67
- * Get device information
68
- */
69
- function getDeviceInfo() {
70
- const userAgent = navigator.userAgent;
71
- // Mobile devices
72
- if (userAgent.includes('iPhone')) {
73
- return { type: 'mobile', model: 'iPhone' };
74
- }
75
- if (userAgent.includes('iPad')) {
76
- return { type: 'tablet', model: 'iPad' };
77
- }
78
- if (userAgent.includes('Android')) {
79
- if (userAgent.includes('Mobile')) {
80
- return { type: 'mobile', model: 'Android' };
81
- }
82
- else {
83
- return { type: 'tablet', model: 'Android' };
84
- }
85
- }
86
- // Desktop (no specific device info)
87
- return undefined;
88
- }
1
+ import { UAParser } from '@ua-parser-js/pro-enterprise';
2
+ import { isBot, isChromeFamily, isStandalonePWA, isAppleSilicon, } from '@ua-parser-js/pro-enterprise/helpers';
89
3
  /**
90
4
  * Get screen resolution
91
5
  */
@@ -120,28 +34,82 @@ export function getBrowserLocale() {
120
34
  }
121
35
  }
122
36
  /**
123
- * Collect all device information
37
+ * Collect all device information using UAParser
124
38
  */
125
39
  export function collectDeviceInfo() {
126
40
  if (typeof window === 'undefined') {
127
41
  // Server-side fallback
128
42
  return {
129
43
  userAgent: {
130
- browser: { name: 'unknown', version: 'unknown' },
131
- os: { name: 'unknown', version: 'unknown' },
44
+ name: '',
45
+ browser: { major: '', name: '', version: '' },
46
+ os: { name: '', version: '' },
47
+ device: undefined,
48
+ engine: { name: '', version: '' },
49
+ cpu: { architecture: '' },
132
50
  },
133
51
  screenResolution: { width: 0, height: 0 },
134
52
  timeZone: 'UTC',
53
+ flags: {
54
+ isBot: false,
55
+ isChromeFamily: false,
56
+ isStandalonePWA: false,
57
+ isAppleSilicon: false,
58
+ },
59
+ };
60
+ }
61
+ const parser = new UAParser();
62
+ const result = parser.getResult();
63
+ // Enhanced detection using UAParser official helpers
64
+ let flags;
65
+ try {
66
+ flags = {
67
+ isBot: isBot(result),
68
+ isChromeFamily: isChromeFamily(result),
69
+ isStandalonePWA: isStandalonePWA(),
70
+ isAppleSilicon: isAppleSilicon(result),
71
+ };
72
+ }
73
+ catch (error) {
74
+ console.error('Failed to compute device flags:', error);
75
+ flags = {
76
+ isBot: false,
77
+ isChromeFamily: false,
78
+ isStandalonePWA: false,
79
+ isAppleSilicon: false,
135
80
  };
136
81
  }
137
82
  return {
138
83
  userAgent: {
139
- browser: getBrowserInfo(),
140
- os: getOSInfo(),
141
- device: getDeviceInfo(),
84
+ name: result.ua,
85
+ browser: {
86
+ major: result.browser.major || '',
87
+ name: result.browser.name || '',
88
+ version: result.browser.version || '',
89
+ type: result.browser.type,
90
+ },
91
+ os: {
92
+ name: result.os.name || '',
93
+ version: result.os.version || '',
94
+ },
95
+ device: result.device.model || result.device.type || result.device.vendor
96
+ ? {
97
+ model: result.device.model,
98
+ type: result.device.type,
99
+ vendor: result.device.vendor,
100
+ }
101
+ : undefined,
102
+ engine: {
103
+ name: result.engine.name || '',
104
+ version: result.engine.version || '',
105
+ },
106
+ cpu: {
107
+ architecture: result.cpu.architecture || '',
108
+ },
142
109
  },
143
110
  screenResolution: getScreenResolution(),
144
111
  timeZone: getTimeZone(),
112
+ flags,
145
113
  };
146
114
  }
147
115
  /**
@@ -13,6 +13,9 @@
13
13
  * - token: Authentication token (URL > localStorage)
14
14
  * - funnelSessionId: Active funnel session (URL > cookie)
15
15
  *
16
+ * ⚠️ Note: authCode is NOT handled here - it has highest priority and is handled
17
+ * separately in client.ts before all other initialization logic.
18
+ *
16
19
  * Usage examples:
17
20
  * - Force production API: ?tagadaClientEnv=production
18
21
  * - Force development API: ?tagadaClientEnv=development
@@ -20,6 +23,7 @@
20
23
  * - Custom API URL: ?tagadaClientBaseUrl=https://tagada.loclx.io
21
24
  * - Combined: ?tagadaClientEnv=local&tagadaClientBaseUrl=https://tagada.loclx.io
22
25
  * - Hard reset + production: ?forceReset=true&tagadaClientEnv=production
26
+ * - Cross-domain auth: ?authCode=ah_... (automatically handled, highest priority)
23
27
  */
24
28
  /**
25
29
  * SDK Override Parameters - centralized across all SDK functions
@@ -13,6 +13,9 @@
13
13
  * - token: Authentication token (URL > localStorage)
14
14
  * - funnelSessionId: Active funnel session (URL > cookie)
15
15
  *
16
+ * ⚠️ Note: authCode is NOT handled here - it has highest priority and is handled
17
+ * separately in client.ts before all other initialization logic.
18
+ *
16
19
  * Usage examples:
17
20
  * - Force production API: ?tagadaClientEnv=production
18
21
  * - Force development API: ?tagadaClientEnv=development
@@ -20,6 +23,7 @@
20
23
  * - Custom API URL: ?tagadaClientBaseUrl=https://tagada.loclx.io
21
24
  * - Combined: ?tagadaClientEnv=local&tagadaClientBaseUrl=https://tagada.loclx.io
22
25
  * - Hard reset + production: ?forceReset=true&tagadaClientEnv=production
26
+ * - Cross-domain auth: ?authCode=ah_... (automatically handled, highest priority)
23
27
  */
24
28
  import { clearClientToken, setClientToken, getClientToken } from './tokenStorage';
25
29
  import { clearFunnelSessionCookie } from './sessionStorage';
@@ -79,6 +79,7 @@ export const DebugDrawer = ({ isOpen, onClose }) => {
79
79
  const [activeTab, setActiveTab] = useState('overview');
80
80
  const [runningScripts, setRunningScripts] = useState(new Set());
81
81
  const [scriptResults, setScriptResults] = useState({});
82
+ const [expandedScriptCategories, setExpandedScriptCategories] = useState({});
82
83
  // Handler to jump to a specific step using direct_navigation
83
84
  const handleJumpToStep = async (stepId, stepName) => {
84
85
  // Try to get sessionId from debug data or context
@@ -187,8 +188,9 @@ export const DebugDrawer = ({ isOpen, onClose }) => {
187
188
  const script = context.debugScripts?.find((s) => s.id === scriptId);
188
189
  if (!script)
189
190
  return;
191
+ // Clear previous script results so only the current script shows a status
192
+ setScriptResults({});
190
193
  setRunningScripts((prev) => new Set(prev).add(scriptId));
191
- setScriptResults((prev) => ({ ...prev, [scriptId]: undefined }));
192
194
  try {
193
195
  await script.run(context);
194
196
  setScriptResults((prev) => ({
@@ -733,51 +735,71 @@ export const DebugDrawer = ({ isOpen, onClose }) => {
733
735
  acc[category].push(script);
734
736
  return acc;
735
737
  }, {});
736
- return Object.entries(grouped).map(([category, scripts]) => (_jsxs("div", { children: [_jsx("div", { style: {
737
- fontSize: '11px',
738
- color: '#9ca3af',
739
- fontWeight: 'bold',
740
- marginBottom: '8px',
741
- textTransform: 'uppercase',
742
- letterSpacing: '0.5px',
743
- }, children: category }), _jsx("div", { style: { display: 'grid', gap: '8px' }, children: scripts.map((script) => {
744
- const isRunning = runningScripts.has(script.id);
745
- const result = scriptResults[script.id];
746
- return (_jsxs("div", { style: {
747
- border: '1px solid #374151',
748
- borderRadius: '6px',
749
- padding: '10px 12px',
750
- backgroundColor: '#111827',
751
- }, children: [_jsxs("div", { style: {
752
- display: 'flex',
753
- justifyContent: 'space-between',
754
- alignItems: 'flex-start',
755
- gap: '12px',
756
- }, children: [_jsxs("div", { style: { flex: 1 }, children: [_jsx("div", { style: {
757
- color: '#f9fafb',
758
- fontWeight: 'bold',
759
- fontSize: '12px',
760
- marginBottom: '4px',
761
- }, children: script.name }), script.description && (_jsx("div", { style: { fontSize: '11px', color: '#9ca3af' }, children: script.description }))] }), _jsx("button", { onClick: () => handleRunScript(script.id), disabled: isRunning, style: {
762
- backgroundColor: isRunning ? '#374151' : '#3b82f6',
763
- color: '#fff',
764
- border: 'none',
765
- borderRadius: '4px',
766
- padding: '6px 12px',
767
- fontSize: '11px',
768
- fontWeight: 'bold',
769
- cursor: isRunning ? 'not-allowed' : 'pointer',
770
- transition: 'background-color 0.2s',
771
- minWidth: '60px',
772
- }, children: isRunning ? '' : '▶ Run' })] }), result && (_jsxs("div", { style: {
773
- marginTop: '8px',
774
- padding: '6px 8px',
775
- borderRadius: '4px',
776
- fontSize: '10px',
777
- backgroundColor: result.success ? '#065f46' : '#7f1d1d',
778
- color: result.success ? '#6ee7b7' : '#fca5a5',
779
- }, children: [result.success ? '' : '❌', " ", result.message] }))] }, script.id));
780
- }) })] }, category)));
738
+ return Object.entries(grouped).map(([category, scripts]) => {
739
+ const isExpanded = expandedScriptCategories[category] ?? false;
740
+ const toggleCategory = () => {
741
+ setExpandedScriptCategories((prev) => ({
742
+ ...prev,
743
+ [category]: !(prev[category] ?? false),
744
+ }));
745
+ };
746
+ return (_jsxs("div", { children: [_jsx("button", { type: "button", onClick: toggleCategory, style: {
747
+ display: 'flex',
748
+ alignItems: 'center',
749
+ justifyContent: 'space-between',
750
+ width: '100%',
751
+ background: 'none',
752
+ border: 'none',
753
+ padding: '6px 0',
754
+ cursor: 'pointer',
755
+ }, children: _jsxs("div", { style: {
756
+ display: 'flex',
757
+ alignItems: 'center',
758
+ gap: '6px',
759
+ fontSize: '11px',
760
+ fontWeight: 'bold',
761
+ textTransform: 'uppercase',
762
+ letterSpacing: '0.5px',
763
+ color: '#9ca3af',
764
+ }, children: [_jsx("span", { style: { fontSize: '10px' }, children: isExpanded ? '' : '▶' }), _jsx("span", { children: category }), _jsxs("span", { style: { fontSize: '10px', color: '#6b7280' }, children: ["(", scripts.length, ")"] })] }) }), isExpanded && (_jsx("div", { style: { display: 'grid', gap: '8px', marginTop: '4px' }, children: scripts.map((script) => {
765
+ const isRunning = runningScripts.has(script.id);
766
+ const result = scriptResults[script.id];
767
+ return (_jsxs("div", { style: {
768
+ border: '1px solid #374151',
769
+ borderRadius: '6px',
770
+ padding: '10px 12px',
771
+ backgroundColor: '#111827',
772
+ }, children: [_jsxs("div", { style: {
773
+ display: 'flex',
774
+ justifyContent: 'space-between',
775
+ alignItems: 'flex-start',
776
+ gap: '12px',
777
+ }, children: [_jsxs("div", { style: { flex: 1 }, children: [_jsx("div", { style: {
778
+ color: '#f9fafb',
779
+ fontWeight: 'bold',
780
+ fontSize: '12px',
781
+ marginBottom: '4px',
782
+ }, children: script.name }), script.description && (_jsx("div", { style: { fontSize: '11px', color: '#9ca3af' }, children: script.description }))] }), _jsx("button", { onClick: () => handleRunScript(script.id), disabled: isRunning, style: {
783
+ backgroundColor: isRunning ? '#374151' : '#3b82f6',
784
+ color: '#fff',
785
+ border: 'none',
786
+ borderRadius: '4px',
787
+ padding: '6px 12px',
788
+ fontSize: '11px',
789
+ fontWeight: 'bold',
790
+ cursor: isRunning ? 'not-allowed' : 'pointer',
791
+ transition: 'background-color 0.2s',
792
+ minWidth: '60px',
793
+ }, children: isRunning ? '⏳' : '▶ Run' })] }), result && (_jsxs("div", { style: {
794
+ marginTop: '8px',
795
+ padding: '6px 8px',
796
+ borderRadius: '4px',
797
+ fontSize: '10px',
798
+ backgroundColor: result.success ? '#065f46' : '#7f1d1d',
799
+ color: result.success ? '#6ee7b7' : '#fca5a5',
800
+ }, children: [result.success ? '✅' : '❌', " ", result.message] }))] }, script.id));
801
+ }) }))] }, category));
802
+ });
781
803
  })() })) : (_jsx("p", { style: { color: '#6b7280' }, children: "No debug scripts available" }))] })), activeTab === 'raw' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Raw Context Data" }), _jsx("div", { style: { fontSize: '12px' }, children: _jsx(TreeView, { data: context, name: "tagadaContext", maxLevel: 4 }) })] }))] })] })] }));
782
804
  };
783
805
  export default DebugDrawer;
@@ -13,7 +13,6 @@ export interface UseCheckoutQueryResult {
13
13
  error: Error | null;
14
14
  isSuccess: boolean;
15
15
  init: (params: CheckoutInitParams) => Promise<{
16
- checkoutUrl: string;
17
16
  checkoutSession: any;
18
17
  checkoutToken: string;
19
18
  }>;
@@ -87,9 +87,9 @@ export function useCheckoutQuery(options = {}) {
87
87
  await refetch();
88
88
  }
89
89
  }, [refetch, checkoutToken]);
90
- // Initialize checkout mutation
90
+ // Initialize checkout mutation (async mode for fast response)
91
91
  const initMutation = useMutation({
92
- mutationFn: (params) => {
92
+ mutationFn: async (params) => {
93
93
  const requestBody = {
94
94
  ...params,
95
95
  storeId: params.storeId || storeId,
@@ -101,7 +101,12 @@ export function useCheckoutQuery(options = {}) {
101
101
  currency: params.customer?.currency ?? currency.code,
102
102
  },
103
103
  };
104
- return checkoutResource.initCheckout(requestBody);
104
+ // Use async mode for fast response (~50ms vs 2-5s)
105
+ const asyncResponse = await checkoutResource.initCheckoutAsync(requestBody);
106
+ return {
107
+ checkoutToken: asyncResponse.checkoutToken,
108
+ checkoutSession: {}, // Will be populated when getCheckout is called
109
+ };
105
110
  },
106
111
  onSuccess: (response) => {
107
112
  // Update URL with checkout token
@@ -257,9 +262,12 @@ export function useCheckoutQuery(options = {}) {
257
262
  await waitForSession();
258
263
  const result = await initMutation.mutateAsync(params);
259
264
  // Update internal token state so the query can fetch the checkout data
265
+ // The query will automatically refetch when token changes, and getCheckout()
266
+ // will automatically wait for async completion (via SDK skipAsyncWait=false)
260
267
  setInternalToken(result.checkoutToken);
268
+ // Return immediately with token
269
+ // checkoutSession will be populated by the query once background processing completes
261
270
  return {
262
- checkoutUrl: result.checkoutUrl,
263
271
  checkoutSession: checkout?.checkoutSession ?? {},
264
272
  checkoutToken: result.checkoutToken,
265
273
  };
@@ -339,12 +339,31 @@ export function useFunnel(options = {}) {
339
339
  onSuccess: (result) => {
340
340
  if (!context)
341
341
  return;
342
+ // 🔥 Fire-and-forget mode: Just acknowledge, no navigation
343
+ if (result.queued) {
344
+ // Update session ID if changed
345
+ if (result.sessionId && result.sessionId !== context.sessionId) {
346
+ const newContext = {
347
+ ...context,
348
+ sessionId: result.sessionId,
349
+ };
350
+ const enrichedContext = enrichContext(newContext);
351
+ setContext(enrichedContext);
352
+ document.cookie = `funnelSessionId=${result.sessionId}; path=/; max-age=86400; SameSite=Lax`;
353
+ }
354
+ return; // Early return for fire-and-forget
355
+ }
342
356
  // 🔄 Handle session recovery (if backend created a new session)
343
357
  let recoveredSessionId;
344
358
  if (result.sessionId && result.sessionId !== context.sessionId) {
345
359
  console.warn(`🔄 Funnel: Session recovered! Old: ${context.sessionId}, New: ${result.sessionId}`);
346
360
  recoveredSessionId = result.sessionId;
347
361
  }
362
+ // Validate required fields for normal navigation
363
+ if (!result.stepId) {
364
+ console.warn('Funnel: Navigation result missing stepId');
365
+ return;
366
+ }
348
367
  // Update local context
349
368
  const newContext = {
350
369
  ...context,
@@ -366,13 +385,13 @@ export function useFunnel(options = {}) {
366
385
  document.cookie = `funnelSessionId=${recoveredSessionId}; path=/; max-age=86400; SameSite=Lax`;
367
386
  console.log(`🍪 Funnel: Updated cookie with recovered session ID: ${recoveredSessionId}`);
368
387
  }
369
- // Create typed navigation result
388
+ // Create typed navigation result (only if we have URL)
370
389
  const navigationResult = {
371
390
  stepId: result.stepId,
372
- action: {
391
+ action: result.url ? {
373
392
  type: 'redirect', // Default action type
374
393
  url: result.url
375
- },
394
+ } : undefined,
376
395
  context: enrichedContext,
377
396
  tracking: result.tracking
378
397
  };
@@ -384,18 +403,27 @@ export function useFunnel(options = {}) {
384
403
  shouldPerformDefaultNavigation = false;
385
404
  }
386
405
  }
387
- // Perform default navigation if not overridden
388
- if (shouldPerformDefaultNavigation && navigationResult.action.url) {
389
- // Add URL parameters for cross-domain session continuity
390
- const urlWithParams = addSessionParams(navigationResult.action.url, enrichedContext.sessionId, effectiveFunnelId || options.funnelId);
391
- const updatedAction = { ...navigationResult.action, url: urlWithParams };
392
- performNavigation(updatedAction);
406
+ // Perform default navigation if not overridden and we have an action with URL
407
+ if (shouldPerformDefaultNavigation && navigationResult.action?.url) {
408
+ const action = navigationResult.action; // Type narrowing
409
+ const actionUrl = action.url; // Extract URL for type narrowing
410
+ if (actionUrl) {
411
+ // Add URL parameters for cross-domain session continuity
412
+ const urlWithParams = addSessionParams(actionUrl, enrichedContext.sessionId, effectiveFunnelId || options.funnelId);
413
+ const updatedAction = {
414
+ type: action.type || 'redirect', // Ensure type is defined
415
+ url: urlWithParams,
416
+ data: action.data,
417
+ };
418
+ performNavigation(updatedAction);
419
+ }
393
420
  }
394
421
  // Skip background refreshes if we are navigating away (full page reload)
395
422
  // This prevents "lingering" requests from the old page context
423
+ const action = navigationResult.action;
396
424
  const isFullNavigation = shouldPerformDefaultNavigation &&
397
- navigationResult.action.url &&
398
- (navigationResult.action.type === 'redirect' || navigationResult.action.type === 'replace');
425
+ action?.url &&
426
+ (action.type === 'redirect' || action.type === 'replace');
399
427
  if (!isFullNavigation) {
400
428
  // Fetch debug data if in debug mode
401
429
  if (debugMode) {
@@ -76,9 +76,9 @@ export interface UsePreviewOfferResult {
76
76
  checkoutUrl: string;
77
77
  }>;
78
78
  toCheckout: (mainOrderId?: string) => Promise<{
79
- checkoutSessionId?: string;
80
- checkoutToken?: string;
81
- checkoutUrl: string;
79
+ checkoutToken: string;
80
+ customerId: string;
81
+ status: 'processing';
82
82
  }>;
83
83
  }
84
84
  export declare function usePreviewOffer(options: UsePreviewOfferOptions): UsePreviewOfferResult;