@tagadapay/plugin-sdk 3.1.2 → 3.1.8
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/README.md +1129 -1129
- package/build-cdn.js +113 -113
- package/dist/external-tracker.js +1104 -491
- package/dist/external-tracker.min.js +2 -2
- package/dist/external-tracker.min.js.map +4 -4
- package/dist/react/hooks/useApplePay.js +25 -36
- package/dist/react/hooks/usePaymentPolling.d.ts +9 -3
- package/dist/react/providers/TagadaProvider.js +5 -5
- package/dist/react/utils/money.d.ts +4 -3
- package/dist/react/utils/money.js +39 -6
- package/dist/react/utils/trackingUtils.js +1 -0
- package/dist/v2/core/client.js +34 -2
- package/dist/v2/core/config/environment.js +9 -2
- package/dist/v2/core/funnelClient.d.ts +92 -1
- package/dist/v2/core/funnelClient.js +247 -3
- package/dist/v2/core/resources/apiClient.js +1 -1
- package/dist/v2/core/resources/checkout.d.ts +68 -0
- package/dist/v2/core/resources/funnel.d.ts +15 -0
- package/dist/v2/core/resources/payments.d.ts +50 -3
- package/dist/v2/core/resources/payments.js +38 -7
- package/dist/v2/core/utils/pluginConfig.js +40 -5
- package/dist/v2/core/utils/previewMode.d.ts +3 -0
- package/dist/v2/core/utils/previewMode.js +44 -14
- package/dist/v2/core/utils/previewModeIndicator.d.ts +19 -0
- package/dist/v2/core/utils/previewModeIndicator.js +414 -0
- package/dist/v2/core/utils/tokenStorage.d.ts +4 -0
- package/dist/v2/core/utils/tokenStorage.js +15 -1
- package/dist/v2/index.d.ts +6 -1
- package/dist/v2/index.js +6 -1
- package/dist/v2/react/components/ApplePayButton.d.ts +21 -121
- package/dist/v2/react/components/ApplePayButton.js +221 -290
- package/dist/v2/react/components/FunnelScriptInjector.d.ts +3 -1
- package/dist/v2/react/components/FunnelScriptInjector.js +128 -24
- package/dist/v2/react/components/PreviewModeIndicator.d.ts +46 -0
- package/dist/v2/react/components/PreviewModeIndicator.js +113 -0
- package/dist/v2/react/hooks/useApplePayCheckout.d.ts +16 -0
- package/dist/v2/react/hooks/useApplePayCheckout.js +193 -0
- package/dist/v2/react/hooks/useFunnel.d.ts +42 -6
- package/dist/v2/react/hooks/useFunnel.js +25 -5
- package/dist/v2/react/hooks/usePaymentPolling.d.ts +9 -3
- package/dist/v2/react/hooks/usePaymentPolling.js +31 -9
- package/dist/v2/react/hooks/usePaymentQuery.d.ts +32 -2
- package/dist/v2/react/hooks/usePaymentQuery.js +304 -7
- package/dist/v2/react/hooks/usePaymentRetrieve.d.ts +26 -0
- package/dist/v2/react/hooks/usePaymentRetrieve.js +175 -0
- package/dist/v2/react/hooks/useStepConfig.d.ts +62 -0
- package/dist/v2/react/hooks/useStepConfig.js +52 -0
- package/dist/v2/react/index.d.ts +9 -3
- package/dist/v2/react/index.js +5 -1
- package/dist/v2/react/providers/ExpressPaymentMethodsProvider.js +27 -19
- package/dist/v2/react/providers/TagadaProvider.js +7 -7
- package/dist/v2/standalone/external-tracker.d.ts +2 -0
- package/dist/v2/standalone/external-tracker.js +6 -3
- package/package.json +112 -112
- package/dist/v2/react/hooks/useApplePay.d.ts +0 -16
- package/dist/v2/react/hooks/useApplePay.js +0 -247
|
@@ -282,9 +282,7 @@ export function useApplePay(options = {}) {
|
|
|
282
282
|
// Tokenize the Apple Pay payment
|
|
283
283
|
const applePayToken = await tokenizeApplePay(event);
|
|
284
284
|
// Complete the Apple Pay session
|
|
285
|
-
session.completePayment(
|
|
286
|
-
status: window.ApplePaySession.STATUS_SUCCESS,
|
|
287
|
-
});
|
|
285
|
+
session.completePayment(window.ApplePaySession.STATUS_SUCCESS);
|
|
288
286
|
// Process the payment using the SDK's payment methods
|
|
289
287
|
await processApplePayPayment(checkoutSessionId, applePayToken, {
|
|
290
288
|
onSuccess: (payment) => {
|
|
@@ -300,9 +298,7 @@ export function useApplePay(options = {}) {
|
|
|
300
298
|
}
|
|
301
299
|
catch (error) {
|
|
302
300
|
console.error('Payment processing failed:', error);
|
|
303
|
-
session.completePayment(
|
|
304
|
-
status: window.ApplePaySession.STATUS_FAILURE,
|
|
305
|
-
});
|
|
301
|
+
session.completePayment(window.ApplePaySession.STATUS_FAILURE);
|
|
306
302
|
setProcessingPayment(false);
|
|
307
303
|
const errorMsg = error instanceof Error ? error.message : 'Payment processing failed';
|
|
308
304
|
setError(errorMsg);
|
|
@@ -321,18 +317,15 @@ export function useApplePay(options = {}) {
|
|
|
321
317
|
return;
|
|
322
318
|
}
|
|
323
319
|
const { lineItems: newLineItems, total: newTotal } = newOrderSummary;
|
|
324
|
-
session.completeShippingMethodSelection({
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
type: 'final',
|
|
334
|
-
})),
|
|
335
|
-
});
|
|
320
|
+
session.completeShippingMethodSelection(window.ApplePaySession.STATUS_SUCCESS, {
|
|
321
|
+
label: newTotal.label,
|
|
322
|
+
amount: newTotal.amount,
|
|
323
|
+
type: 'final',
|
|
324
|
+
}, newLineItems.map(item => ({
|
|
325
|
+
label: item.label,
|
|
326
|
+
amount: item.amount,
|
|
327
|
+
type: 'final',
|
|
328
|
+
})));
|
|
336
329
|
}
|
|
337
330
|
catch (error) {
|
|
338
331
|
console.error('Shipping method selection failed:', error);
|
|
@@ -358,24 +351,20 @@ export function useApplePay(options = {}) {
|
|
|
358
351
|
console.log('======= APPLE PAY ON SHIPPING CONTACT SELECTED ======');
|
|
359
352
|
console.log('newOrderSummary', newOrderSummary);
|
|
360
353
|
console.log(newLineItems, newTotal, newShippingMethods);
|
|
361
|
-
session.completeShippingContactSelection({
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
amount: item.amount,
|
|
376
|
-
type: 'final',
|
|
377
|
-
})),
|
|
378
|
-
});
|
|
354
|
+
session.completeShippingContactSelection(window.ApplePaySession.STATUS_SUCCESS, newShippingMethods.map(method => ({
|
|
355
|
+
label: method.label,
|
|
356
|
+
amount: method.amount,
|
|
357
|
+
detail: method.detail,
|
|
358
|
+
identifier: method.identifier,
|
|
359
|
+
})), {
|
|
360
|
+
label: newTotal.label,
|
|
361
|
+
amount: newTotal.amount,
|
|
362
|
+
type: 'final',
|
|
363
|
+
}, newLineItems.map(item => ({
|
|
364
|
+
label: item.label,
|
|
365
|
+
amount: item.amount,
|
|
366
|
+
type: 'final',
|
|
367
|
+
})));
|
|
379
368
|
}
|
|
380
369
|
catch (error) {
|
|
381
370
|
console.error('Shipping contact selection failed:', error);
|
|
@@ -2,14 +2,14 @@ export interface Payment {
|
|
|
2
2
|
id: string;
|
|
3
3
|
status: string;
|
|
4
4
|
subStatus: string;
|
|
5
|
-
requireAction: 'none' | 'redirect' | 'error';
|
|
5
|
+
requireAction: 'none' | 'redirect' | 'error' | 'radar';
|
|
6
6
|
requireActionData?: {
|
|
7
|
-
type: 'redirect' | 'threeds_auth' | 'processor_auth' | 'error';
|
|
7
|
+
type: 'redirect' | 'threeds_auth' | 'processor_auth' | 'error' | 'stripe_radar' | 'finix_radar';
|
|
8
8
|
url?: string;
|
|
9
9
|
processed: boolean;
|
|
10
10
|
processorId?: string;
|
|
11
11
|
metadata?: {
|
|
12
|
-
type: 'redirect';
|
|
12
|
+
type: 'redirect' | 'stripe_radar' | 'finix_radar';
|
|
13
13
|
redirect?: {
|
|
14
14
|
redirectUrl: string;
|
|
15
15
|
returnUrl: string;
|
|
@@ -20,6 +20,12 @@ export interface Payment {
|
|
|
20
20
|
acsTransID: string;
|
|
21
21
|
messageVersion: string;
|
|
22
22
|
};
|
|
23
|
+
radar?: {
|
|
24
|
+
merchantId: string;
|
|
25
|
+
environment: 'sandbox' | 'live';
|
|
26
|
+
orderId?: string;
|
|
27
|
+
publishableKey?: string;
|
|
28
|
+
};
|
|
23
29
|
};
|
|
24
30
|
redirectUrl?: string;
|
|
25
31
|
resumeToken?: string;
|
|
@@ -38,11 +38,11 @@ const InitializationLoader = () => (_jsxs("div", { style: {
|
|
|
38
38
|
borderTop: '1.5px solid #9ca3af',
|
|
39
39
|
borderRadius: '50%',
|
|
40
40
|
animation: 'tagada-spin 1s linear infinite',
|
|
41
|
-
} }), _jsx("span", { children: "Loading..." }), _jsx("style", { children: `
|
|
42
|
-
@keyframes tagada-spin {
|
|
43
|
-
0% { transform: rotate(0deg); }
|
|
44
|
-
100% { transform: rotate(360deg); }
|
|
45
|
-
}
|
|
41
|
+
} }), _jsx("span", { children: "Loading..." }), _jsx("style", { children: `
|
|
42
|
+
@keyframes tagada-spin {
|
|
43
|
+
0% { transform: rotate(0deg); }
|
|
44
|
+
100% { transform: rotate(360deg); }
|
|
45
|
+
}
|
|
46
46
|
` })] }));
|
|
47
47
|
const TagadaContext = createContext(null);
|
|
48
48
|
export function TagadaProvider({ children, environment, customApiConfig, debugMode, // Remove default, will be set based on environment
|
|
@@ -2251,12 +2251,11 @@ export declare function getCurrencyInfo(currencyCode: string): {
|
|
|
2251
2251
|
* Convert a money string or number to minor units
|
|
2252
2252
|
*/
|
|
2253
2253
|
export declare function moneyStringOrNumberToMinorUnits(moneyStringOrNumber: string | number, currencyCode: string): number;
|
|
2254
|
-
/**
|
|
2255
|
-
* Convert minor units to major units (decimal value)
|
|
2256
|
-
*/
|
|
2257
2254
|
export declare function minorUnitsToMajorUnits(amountMinorUnits: number, currencyCode: string): number;
|
|
2258
2255
|
/**
|
|
2259
2256
|
* Format money without currency symbol, just the numeric value
|
|
2257
|
+
* Note: The backend stores all amounts with 2 decimal places (multiplied by 100),
|
|
2258
|
+
* even for currencies with 0 decimal places like JPY.
|
|
2260
2259
|
*/
|
|
2261
2260
|
export declare const formatMoneyWithoutSymbol: ({ amount, currencyCode, fromCents, }: {
|
|
2262
2261
|
amount: number;
|
|
@@ -2269,5 +2268,7 @@ export declare const formatMoneyWithoutSymbol: ({ amount, currencyCode, fromCent
|
|
|
2269
2268
|
export declare const convertCurrency: (amount: number, fromCurrency: string, toCurrency: string, rate: number) => number;
|
|
2270
2269
|
/**
|
|
2271
2270
|
* Simple money formatter for quick use (similar to the existing useCurrency format function)
|
|
2271
|
+
* Note: The backend stores all amounts with 2 decimal places (multiplied by 100),
|
|
2272
|
+
* even for currencies with 0 decimal places like JPY.
|
|
2272
2273
|
*/
|
|
2273
2274
|
export declare function formatSimpleMoney(amount: number, currencyCode: string): string;
|
|
@@ -42,7 +42,22 @@ export function formatMoney(amountMinorUnits, currencyCode = 'USD', locale) {
|
|
|
42
42
|
throw new Error(`Currency ${currencyCode} not found in currency data.`);
|
|
43
43
|
}
|
|
44
44
|
// Convert minor units to major units
|
|
45
|
-
|
|
45
|
+
// Note: The backend stores all amounts with 2 decimal places (multiplied by 100),
|
|
46
|
+
// regardless of the currency's ISOdigits. This means:
|
|
47
|
+
// - For ISOdigits: 0 (JPY, KRW, etc.) → divide by 100 (not 10^0 = 1)
|
|
48
|
+
// - For ISOdigits: 2 (USD, EUR, etc.) → divide by 100 (matches 10^2)
|
|
49
|
+
// - For ISOdigits: 3 (KWD, BHD, etc.) → divide by 100 (not 10^3 = 1000)
|
|
50
|
+
// Note: This means currencies with 3 decimal places lose precision (3rd decimal is lost)
|
|
51
|
+
let value;
|
|
52
|
+
if (currencyInfo.ISOdigits === 0 || currencyInfo.ISOdigits === 3) {
|
|
53
|
+
// Backend stores amounts with 2 decimal places for all currencies
|
|
54
|
+
// For currencies with 0 or 3 decimal places, divide by 100 to convert from backend format
|
|
55
|
+
value = amountMinorUnits / 100;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
// For currencies with 2 decimal places (most common), use the standard conversion
|
|
59
|
+
value = amountMinorUnits / Math.pow(10, currencyInfo.ISOdigits);
|
|
60
|
+
}
|
|
46
61
|
return formatCurrency(value, safeLocale, currencyCode);
|
|
47
62
|
}
|
|
48
63
|
/**
|
|
@@ -63,23 +78,36 @@ export function moneyStringOrNumberToMinorUnits(moneyStringOrNumber, currencyCod
|
|
|
63
78
|
const value = typeof moneyStringOrNumber === 'string' ? parseFloat(moneyStringOrNumber) : moneyStringOrNumber;
|
|
64
79
|
return Math.round(value * Math.pow(10, currencyInfo.ISOdigits));
|
|
65
80
|
}
|
|
66
|
-
/**
|
|
67
|
-
* Convert minor units to major units (decimal value)
|
|
68
|
-
*/
|
|
69
81
|
export function minorUnitsToMajorUnits(amountMinorUnits, currencyCode) {
|
|
70
82
|
const currencyInfo = currencyData[currencyCode];
|
|
71
83
|
if (!currencyInfo) {
|
|
72
84
|
throw new Error(`Currency ${currencyCode} not found in currency data.`);
|
|
73
85
|
}
|
|
86
|
+
// Backend stores amounts with 2 decimal places for all currencies
|
|
87
|
+
// For currencies with 0 or 3 decimal places, divide by 100 to convert from backend format
|
|
88
|
+
if (currencyInfo.ISOdigits === 0 || currencyInfo.ISOdigits === 3) {
|
|
89
|
+
return amountMinorUnits / 100;
|
|
90
|
+
}
|
|
74
91
|
return amountMinorUnits / Math.pow(10, currencyInfo.ISOdigits);
|
|
75
92
|
}
|
|
76
93
|
/**
|
|
77
94
|
* Format money without currency symbol, just the numeric value
|
|
95
|
+
* Note: The backend stores all amounts with 2 decimal places (multiplied by 100),
|
|
96
|
+
* even for currencies with 0 decimal places like JPY.
|
|
78
97
|
*/
|
|
79
98
|
export const formatMoneyWithoutSymbol = ({ amount, currencyCode, fromCents = true, }) => {
|
|
80
99
|
const currencyInfo = currencyData[currencyCode];
|
|
81
100
|
const digits = currencyInfo?.ISOdigits || 2;
|
|
82
|
-
|
|
101
|
+
let value;
|
|
102
|
+
if (fromCents) {
|
|
103
|
+
// Backend stores amounts with 2 decimal places for all currencies
|
|
104
|
+
// For currencies with 0 or 3 decimal places, divide by 100 to convert from backend format
|
|
105
|
+
const divisor = digits === 0 || digits === 3 ? 100 : Math.pow(10, digits);
|
|
106
|
+
value = amount / divisor;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
value = amount;
|
|
110
|
+
}
|
|
83
111
|
return new Intl.NumberFormat('en-US', {
|
|
84
112
|
minimumFractionDigits: digits,
|
|
85
113
|
maximumFractionDigits: digits,
|
|
@@ -95,10 +123,15 @@ export const convertCurrency = (amount, fromCurrency, toCurrency, rate) => {
|
|
|
95
123
|
};
|
|
96
124
|
/**
|
|
97
125
|
* Simple money formatter for quick use (similar to the existing useCurrency format function)
|
|
126
|
+
* Note: The backend stores all amounts with 2 decimal places (multiplied by 100),
|
|
127
|
+
* even for currencies with 0 decimal places like JPY.
|
|
98
128
|
*/
|
|
99
129
|
export function formatSimpleMoney(amount, currencyCode) {
|
|
100
130
|
const currencyInfo = currencyData[currencyCode];
|
|
101
131
|
const symbol = currencyInfo?.symbol || currencyCode;
|
|
102
132
|
const digits = currencyInfo?.ISOdigits || 2;
|
|
103
|
-
|
|
133
|
+
// Backend stores amounts with 2 decimal places for all currencies
|
|
134
|
+
// For currencies with 0 or 3 decimal places, divide by 100 to convert from backend format
|
|
135
|
+
const divisor = digits === 0 || digits === 3 ? 100 : Math.pow(10, digits);
|
|
136
|
+
return `${symbol}${(amount / divisor).toFixed(digits)}`;
|
|
104
137
|
}
|
package/dist/v2/core/client.js
CHANGED
|
@@ -334,10 +334,22 @@ export class TagadaClient {
|
|
|
334
334
|
* Normal token initialization flow (no cross-domain handoff)
|
|
335
335
|
*/
|
|
336
336
|
async fallbackToNormalFlow() {
|
|
337
|
-
//
|
|
338
|
-
|
|
337
|
+
// 🔒 CRITICAL: Read URL token FIRST before any async operations
|
|
338
|
+
// This prevents race conditions where anonymous token creation overwrites URL token
|
|
339
339
|
const urlParams = new URLSearchParams(typeof window !== 'undefined' ? window.location.search : '');
|
|
340
340
|
const queryToken = urlParams.get('token');
|
|
341
|
+
// If URL has token, set it IMMEDIATELY to prevent any race condition
|
|
342
|
+
if (queryToken) {
|
|
343
|
+
if (this.state.debugMode) {
|
|
344
|
+
console.log(`[TagadaClient ${this.instanceId}] 🔒 URL token detected, setting immediately to prevent race condition`);
|
|
345
|
+
}
|
|
346
|
+
// Set token on API client immediately
|
|
347
|
+
this.apiClient.updateToken(queryToken);
|
|
348
|
+
// Also persist to localStorage
|
|
349
|
+
setClientToken(queryToken);
|
|
350
|
+
}
|
|
351
|
+
// Now check storage (which should have the URL token if we just set it)
|
|
352
|
+
const existingToken = getClientToken();
|
|
341
353
|
console.log(`[TagadaClient ${this.instanceId}] Initializing token (normal flow)...`, {
|
|
342
354
|
hasExistingToken: !!existingToken,
|
|
343
355
|
hasQueryToken: !!queryToken,
|
|
@@ -425,6 +437,26 @@ export class TagadaClient {
|
|
|
425
437
|
* Create anonymous token
|
|
426
438
|
*/
|
|
427
439
|
async createAnonymousToken(storeId) {
|
|
440
|
+
// 🔒 CRITICAL: Never create anonymous token if URL has a token
|
|
441
|
+
// This prevents race conditions during forceReset
|
|
442
|
+
if (typeof window !== 'undefined') {
|
|
443
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
444
|
+
const urlToken = urlParams.get('token');
|
|
445
|
+
if (urlToken) {
|
|
446
|
+
if (this.state.debugMode) {
|
|
447
|
+
console.log(`[TagadaClient ${this.instanceId}] 🔒 URL has token, skipping anonymous token creation`);
|
|
448
|
+
}
|
|
449
|
+
// Use the URL token instead
|
|
450
|
+
this.setToken(urlToken);
|
|
451
|
+
setClientToken(urlToken);
|
|
452
|
+
const decodedSession = decodeJWTClient(urlToken);
|
|
453
|
+
if (decodedSession) {
|
|
454
|
+
this.updateState({ session: decodedSession });
|
|
455
|
+
await this.initializeSession(decodedSession);
|
|
456
|
+
}
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
428
460
|
// Prevent concurrent anonymous token creation
|
|
429
461
|
if (this.isInitializingSession) {
|
|
430
462
|
if (this.state.debugMode) {
|
|
@@ -160,6 +160,7 @@ export function getEndpointUrl(config, category, endpoint) {
|
|
|
160
160
|
* 4. Default fallback - Production (safest)
|
|
161
161
|
*/
|
|
162
162
|
export function detectEnvironment() {
|
|
163
|
+
console.log('[SDK] detectEnvironment() called');
|
|
163
164
|
// Check if we're in browser
|
|
164
165
|
if (typeof window === 'undefined') {
|
|
165
166
|
return 'local'; // SSR fallback
|
|
@@ -185,15 +186,21 @@ export function detectEnvironment() {
|
|
|
185
186
|
}
|
|
186
187
|
const hostname = window.location.hostname;
|
|
187
188
|
const href = window.location.href;
|
|
189
|
+
console.log(`[SDK] detectEnvironment() - hostname: "${hostname}"`);
|
|
188
190
|
// 1. Check for LOCAL environment first (highest priority for dev)
|
|
189
|
-
// Local: localhost, local IPs, or local
|
|
191
|
+
// Local: localhost, local IPs, local domains, or ngrok tunnels (used for local dev)
|
|
190
192
|
if (hostname === 'localhost' ||
|
|
191
193
|
hostname.startsWith('127.') ||
|
|
192
194
|
hostname.startsWith('192.168.') ||
|
|
193
195
|
hostname.startsWith('10.') ||
|
|
194
196
|
hostname.includes('.local') ||
|
|
195
197
|
hostname === '' ||
|
|
196
|
-
hostname === '0.0.0.0'
|
|
198
|
+
hostname === '0.0.0.0' ||
|
|
199
|
+
hostname.includes('ngrok-free.dev') ||
|
|
200
|
+
hostname.includes('ngrok-free.app') ||
|
|
201
|
+
hostname.includes('ngrok.io') ||
|
|
202
|
+
hostname.includes('ngrok.app')) {
|
|
203
|
+
console.log('[SDK] detectEnvironment() - returning LOCAL');
|
|
197
204
|
// For local development, allow override via window.__TAGADA_ENV__ (injected by dev server)
|
|
198
205
|
if (typeof window !== 'undefined' && window?.__TAGADA_ENV__?.TAGADA_ENVIRONMENT) {
|
|
199
206
|
const override = window.__TAGADA_ENV__.TAGADA_ENVIRONMENT.toLowerCase();
|
|
@@ -1,6 +1,90 @@
|
|
|
1
1
|
import { ApiClient } from './resources/apiClient';
|
|
2
2
|
import { SimpleFunnelContext, FunnelAction, FunnelNavigationResult } from './resources/funnel';
|
|
3
3
|
import { PluginConfig } from './utils/pluginConfig';
|
|
4
|
+
/**
|
|
5
|
+
* Runtime step configuration injected from the CRM
|
|
6
|
+
* Contains payment flows, static resources, scripts, and pixel tracking configs
|
|
7
|
+
*/
|
|
8
|
+
export interface RuntimeStepConfig {
|
|
9
|
+
payment?: {
|
|
10
|
+
paymentFlowId?: string;
|
|
11
|
+
};
|
|
12
|
+
staticResources?: Record<string, string>;
|
|
13
|
+
scripts?: Array<{
|
|
14
|
+
name: string;
|
|
15
|
+
enabled: boolean;
|
|
16
|
+
content: string;
|
|
17
|
+
position?: 'head-start' | 'head-end' | 'body-start' | 'body-end';
|
|
18
|
+
}>;
|
|
19
|
+
pixels?: Record<string, string>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Local funnel configuration for development
|
|
23
|
+
* Loaded from /config/funnel.local.json
|
|
24
|
+
*/
|
|
25
|
+
export interface LocalFunnelConfig {
|
|
26
|
+
/** Funnel ID to use in local dev */
|
|
27
|
+
funnelId?: string;
|
|
28
|
+
/** Step ID to simulate */
|
|
29
|
+
stepId?: string;
|
|
30
|
+
/** Static resources (offer ID, product ID, etc.) */
|
|
31
|
+
staticResources?: Record<string, string>;
|
|
32
|
+
/** Payment flow ID override */
|
|
33
|
+
paymentFlowId?: string;
|
|
34
|
+
/** Custom scripts for local testing */
|
|
35
|
+
scripts?: RuntimeStepConfig['scripts'];
|
|
36
|
+
/** Pixel tracking config */
|
|
37
|
+
pixels?: Record<string, string>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Load local funnel config from /config/funnel.local.json (for local dev only)
|
|
41
|
+
* This replaces the old resources.static.json with a more complete structure
|
|
42
|
+
*
|
|
43
|
+
* Example funnel.local.json:
|
|
44
|
+
* {
|
|
45
|
+
* "funnelId": "funnelv2_xxx",
|
|
46
|
+
* "stepId": "step_checkout",
|
|
47
|
+
* "staticResources": {
|
|
48
|
+
* "offer": "offer_xxx",
|
|
49
|
+
* "product": "product_xxx"
|
|
50
|
+
* },
|
|
51
|
+
* "paymentFlowId": "flow_xxx"
|
|
52
|
+
* }
|
|
53
|
+
*/
|
|
54
|
+
export declare function loadLocalFunnelConfig(): Promise<LocalFunnelConfig | null>;
|
|
55
|
+
/**
|
|
56
|
+
* Get the cached local funnel config (sync access after loadLocalFunnelConfig)
|
|
57
|
+
*/
|
|
58
|
+
export declare function getLocalFunnelConfig(): LocalFunnelConfig | null;
|
|
59
|
+
/**
|
|
60
|
+
* Get the runtime step configuration
|
|
61
|
+
* Contains payment flow, static resources, scripts, and pixel tracking
|
|
62
|
+
*
|
|
63
|
+
* Priority:
|
|
64
|
+
* 1. Local funnel config (local dev only - /config/funnel.local.json) - HIGHEST in local dev
|
|
65
|
+
* 2. Window variable (production - HTML injection)
|
|
66
|
+
* 3. Meta tag (production - HTML injection fallback)
|
|
67
|
+
*
|
|
68
|
+
* This allows local developers to override injected config for testing.
|
|
69
|
+
*
|
|
70
|
+
* Returns undefined if not available
|
|
71
|
+
*/
|
|
72
|
+
export declare function getAssignedStepConfig(): RuntimeStepConfig | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* Get the assigned payment flow ID from step config or legacy injection
|
|
75
|
+
* Returns undefined if not available
|
|
76
|
+
*/
|
|
77
|
+
export declare function getAssignedPaymentFlowId(): string | undefined;
|
|
78
|
+
/**
|
|
79
|
+
* Get the assigned static resources from step config
|
|
80
|
+
* Returns undefined if not available
|
|
81
|
+
*/
|
|
82
|
+
export declare function getAssignedStaticResources(): Record<string, string> | undefined;
|
|
83
|
+
/**
|
|
84
|
+
* Get the assigned scripts from step config
|
|
85
|
+
* Returns only enabled scripts, filtered by position if specified
|
|
86
|
+
*/
|
|
87
|
+
export declare function getAssignedScripts(position?: 'head-start' | 'head-end' | 'body-start' | 'body-end'): RuntimeStepConfig['scripts'];
|
|
4
88
|
export interface FunnelClientConfig {
|
|
5
89
|
apiClient: ApiClient;
|
|
6
90
|
debugMode?: boolean;
|
|
@@ -86,16 +170,23 @@ export declare class FunnelClient {
|
|
|
86
170
|
* @param options.fireAndForget - If true, queues navigation to QStash and returns immediately without waiting for result
|
|
87
171
|
* @param options.customerTags - Customer tags to set (merged with existing customer tags)
|
|
88
172
|
* @param options.deviceId - Device ID for geo/device tag enrichment (optional, rarely needed)
|
|
173
|
+
* @param options.autoRedirect - Override global autoRedirect setting for this specific call (default: use config)
|
|
89
174
|
*/
|
|
90
175
|
navigate(event: FunnelAction, options?: {
|
|
91
176
|
fireAndForget?: boolean;
|
|
92
177
|
customerTags?: string[];
|
|
93
178
|
deviceId?: string;
|
|
179
|
+
autoRedirect?: boolean;
|
|
180
|
+
waitForSession?: boolean;
|
|
94
181
|
}): Promise<FunnelNavigationResult>;
|
|
95
182
|
/**
|
|
96
183
|
* Go to a specific step (direct navigation)
|
|
184
|
+
* @param stepId - Target step ID
|
|
185
|
+
* @param options - Navigation options (autoRedirect, etc.)
|
|
97
186
|
*/
|
|
98
|
-
goToStep(stepId: string
|
|
187
|
+
goToStep(stepId: string, options?: {
|
|
188
|
+
autoRedirect?: boolean;
|
|
189
|
+
}): Promise<FunnelNavigationResult>;
|
|
99
190
|
/**
|
|
100
191
|
* Refresh session data
|
|
101
192
|
*/
|