@tagadapay/plugin-sdk 2.8.7 → 2.8.9

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 (43) hide show
  1. package/dist/react/config/environment.d.ts +1 -22
  2. package/dist/react/config/environment.js +1 -132
  3. package/dist/react/utils/deviceInfo.d.ts +1 -39
  4. package/dist/react/utils/deviceInfo.js +1 -163
  5. package/dist/react/utils/jwtDecoder.d.ts +1 -14
  6. package/dist/react/utils/jwtDecoder.js +1 -86
  7. package/dist/react/utils/tokenStorage.d.ts +1 -16
  8. package/dist/react/utils/tokenStorage.js +1 -53
  9. package/dist/v2/core/client.d.ts +92 -0
  10. package/dist/v2/core/client.js +386 -0
  11. package/dist/v2/core/config/environment.d.ts +22 -0
  12. package/dist/v2/core/config/environment.js +140 -0
  13. package/dist/v2/core/pathRemapping.js +61 -3
  14. package/dist/v2/core/resources/apiClient.d.ts +8 -0
  15. package/dist/v2/core/resources/apiClient.js +30 -9
  16. package/dist/v2/core/resources/funnel.d.ts +253 -16
  17. package/dist/v2/core/resources/payments.d.ts +23 -0
  18. package/dist/v2/core/types.d.ts +271 -0
  19. package/dist/v2/core/types.js +4 -0
  20. package/dist/v2/core/utils/deviceInfo.d.ts +39 -0
  21. package/dist/v2/core/utils/deviceInfo.js +162 -0
  22. package/dist/v2/core/utils/eventDispatcher.d.ts +10 -0
  23. package/dist/v2/core/utils/eventDispatcher.js +24 -0
  24. package/dist/v2/core/utils/jwtDecoder.d.ts +14 -0
  25. package/dist/v2/core/utils/jwtDecoder.js +85 -0
  26. package/dist/v2/core/utils/pluginConfig.js +6 -0
  27. package/dist/v2/core/utils/tokenStorage.d.ts +19 -0
  28. package/dist/v2/core/utils/tokenStorage.js +52 -0
  29. package/dist/v2/index.d.ts +2 -1
  30. package/dist/v2/index.js +1 -1
  31. package/dist/v2/react/components/DebugDrawer.js +90 -1
  32. package/dist/v2/react/hooks/__examples__/FunnelContextExample.d.ts +12 -0
  33. package/dist/v2/react/hooks/__examples__/FunnelContextExample.js +54 -0
  34. package/dist/v2/react/hooks/useFunnel.d.ts +2 -2
  35. package/dist/v2/react/hooks/useFunnel.js +209 -32
  36. package/dist/v2/react/hooks/useGoogleAutocomplete.js +26 -18
  37. package/dist/v2/react/hooks/useISOData.js +4 -2
  38. package/dist/v2/react/hooks/useOffersQuery.d.ts +24 -29
  39. package/dist/v2/react/hooks/useOffersQuery.js +164 -204
  40. package/dist/v2/react/hooks/usePaymentQuery.js +99 -6
  41. package/dist/v2/react/providers/TagadaProvider.d.ts +8 -21
  42. package/dist/v2/react/providers/TagadaProvider.js +79 -673
  43. package/package.json +1 -1
@@ -6,6 +6,7 @@ import axios from 'axios';
6
6
  export class ApiClient {
7
7
  constructor(config) {
8
8
  this.currentToken = null;
9
+ this.tokenProvider = null;
9
10
  this.axios = axios.create({
10
11
  baseURL: config.baseURL,
11
12
  timeout: config.timeout || 30000,
@@ -15,12 +16,28 @@ export class ApiClient {
15
16
  },
16
17
  });
17
18
  // Request interceptor for logging and auth
18
- this.axios.interceptors.request.use((config) => {
19
- console.log(`[SDK] Making ${config.method?.toUpperCase()} request to: ${config.baseURL}${config.url}`);
20
- console.log('[SDK] Request headers:', config.headers);
21
- if (config.data) {
22
- console.log('[SDK] Request body:', config.data);
19
+ this.axios.interceptors.request.use(async (config) => {
20
+ // Check if we need to wait for token
21
+ if (!config.skipAuth && !this.currentToken && this.tokenProvider) {
22
+ try {
23
+ console.log('[SDK] Waiting for token...');
24
+ const token = await this.tokenProvider();
25
+ if (token) {
26
+ this.updateToken(token);
27
+ // Ensure header is set on this specific request config
28
+ config.headers['x-cms-token'] = token;
29
+ }
30
+ }
31
+ catch (error) {
32
+ console.error('[SDK] Failed to get token from provider:', error);
33
+ }
23
34
  }
35
+ // Ensure token is in headers if we have it (and not skipped)
36
+ if (!config.skipAuth && this.currentToken) {
37
+ config.headers['x-cms-token'] = this.currentToken;
38
+ }
39
+ console.log(`[SDK] Making ${config.method?.toUpperCase()} request to: ${config.baseURL || ''}${config.url}`);
40
+ // console.log('[SDK] Request headers:', config.headers);
24
41
  return config;
25
42
  }, (error) => {
26
43
  console.error('[SDK] Request error:', error);
@@ -28,14 +45,18 @@ export class ApiClient {
28
45
  });
29
46
  // Response interceptor for logging
30
47
  this.axios.interceptors.response.use((response) => {
31
- console.log('[SDK] Response status:', response.status);
32
- console.log('[SDK] Response data:', response.data);
48
+ // console.log('[SDK] Response status:', response.status);
33
49
  return response;
34
50
  }, (error) => {
35
- console.error('[SDK] Response error:', error);
51
+ console.error('[SDK] Response error:', error.message);
36
52
  return Promise.reject(error instanceof Error ? error : new Error(String(error)));
37
53
  });
38
54
  }
55
+ // Set a provider that returns a promise resolving to the token
56
+ // This allows requests to wait until the token is ready
57
+ setTokenProvider(provider) {
58
+ this.tokenProvider = provider;
59
+ }
39
60
  // Convenience methods
40
61
  async get(url, config) {
41
62
  const response = await this.axios.get(url, config);
@@ -69,7 +90,7 @@ export class ApiClient {
69
90
  this.currentToken = token;
70
91
  if (token) {
71
92
  this.setHeader('x-cms-token', token);
72
- console.log('[SDK] Token updated in ApiClient:', token.substring(0, 8) + '...');
93
+ // console.log('[SDK] Token updated in ApiClient:', token.substring(0, 8) + '...');
73
94
  }
74
95
  else {
75
96
  this.removeHeader('x-cms-token');
@@ -33,13 +33,202 @@ export declare enum FunnelActionType {
33
33
  export type NextAction<T> = T & {
34
34
  [key: string]: any;
35
35
  };
36
- export interface DirectNavigationActionData {
36
+ /**
37
+ * Base resource data type - all resources must have an id and optional metadata
38
+ */
39
+ export interface FunnelResourceData {
40
+ id: string;
41
+ [key: string]: any;
42
+ }
43
+ /**
44
+ * Resource metadata for tracking, versioning, and relationships
45
+ */
46
+ export interface ResourceMetadata {
47
+ /** Plugin that created this resource */
48
+ source?: string;
49
+ /** Schema version for this resource */
50
+ version?: string;
51
+ /** Timestamp when resource was created */
52
+ timestamp?: number;
53
+ /** Scope: how long should this resource persist */
54
+ scope?: 'global' | 'session' | 'step' | 'ephemeral';
55
+ /** Tags for categorization and filtering */
56
+ tags?: string[];
57
+ /** Related resource IDs (for relationships) */
58
+ relatedTo?: string[];
59
+ /** Custom metadata */
60
+ [key: string]: any;
61
+ }
62
+ /**
63
+ * Wrapped resource with metadata
64
+ */
65
+ export interface ResourceWithMetadata<T extends FunnelResourceData = FunnelResourceData> {
66
+ data: T;
67
+ meta: ResourceMetadata;
68
+ }
69
+ /**
70
+ * Standard resource types for e-commerce (provides IntelliSense)
71
+ * These are SUGGESTIONS, not limitations - any key is allowed via index signature
72
+ */
73
+ export interface StandardResourceKeys {
74
+ order?: FunnelResourceData;
75
+ customer?: FunnelResourceData;
76
+ payment?: FunnelResourceData;
77
+ checkout?: FunnelResourceData;
78
+ cart?: FunnelResourceData;
79
+ subscription?: FunnelResourceData;
80
+ product?: FunnelResourceData;
81
+ variant?: FunnelResourceData;
82
+ mainOrder?: FunnelResourceData;
83
+ upsellOrder?: FunnelResourceData;
84
+ downsellOrder?: FunnelResourceData;
85
+ orders?: FunnelResourceData[];
86
+ customers?: FunnelResourceData[];
87
+ payments?: FunnelResourceData[];
88
+ }
89
+ /**
90
+ * Flexible resource map supporting:
91
+ * 1. Single resources (order)
92
+ * 2. Collections (orders[])
93
+ * 3. Wrapped resources with metadata
94
+ * 4. Completely custom keys
95
+ *
96
+ * @example Simple usage (backward compatible)
97
+ * ```typescript
98
+ * resources: {
99
+ * order: { id: '123', amount: 100 }
100
+ * }
101
+ * ```
102
+ *
103
+ * @example Multiple instances via collections
104
+ * ```typescript
105
+ * resources: {
106
+ * order: { id: 'main' }, // Hot context
107
+ * orders: [ // Full collection
108
+ * { id: 'main', type: 'initial' },
109
+ * { id: 'upsell1', type: 'addon' }
110
+ * ]
111
+ * }
112
+ * ```
113
+ *
114
+ * @example With metadata (opt-in)
115
+ * ```typescript
116
+ * resources: {
117
+ * order: {
118
+ * data: { id: '123', amount: 100 },
119
+ * meta: { source: 'checkout-plugin', version: '2.0' }
120
+ * }
121
+ * }
122
+ * ```
123
+ *
124
+ * @example Typed resources (opt-in strict typing)
125
+ * ```typescript
126
+ * interface MyResources {
127
+ * order: Order; // Your typed Order interface
128
+ * customer: Customer;
129
+ * }
130
+ *
131
+ * const result = await funnel.next<MyResources>({
132
+ * type: 'payment_success',
133
+ * data: {
134
+ * resources: {
135
+ * order: { id: '123', amount: 100 } // ✅ Type-checked!
136
+ * }
137
+ * }
138
+ * });
139
+ * ```
140
+ */
141
+ export type FunnelResourceMap<TCustom = {}> = StandardResourceKeys & {
142
+ /**
143
+ * Fully extensible - any key allowed
144
+ * Value can be:
145
+ * - Single resource: { id: '...' }
146
+ * - Collection: [{ id: '...' }, ...]
147
+ * - Wrapped: { data: {...}, meta: {...} }
148
+ */
149
+ [key: string]: FunnelResourceData | FunnelResourceData[] | ResourceWithMetadata | ResourceWithMetadata[] | undefined;
150
+ } & TCustom;
151
+ /**
152
+ * Typed resources structure for funnel actions
153
+ *
154
+ * 💡 RESOURCE PROTOCOL: Flexible & Scalable
155
+ *
156
+ * The system supports multiple patterns for maximum flexibility:
157
+ *
158
+ * 1. **Simple Pattern** (Default - Backward Compatible):
159
+ * ```typescript
160
+ * resources: { order: { id: '123' } }
161
+ * ```
162
+ *
163
+ * 2. **Aliasing Pattern** (For Hot + Named Context):
164
+ * ```typescript
165
+ * resources: {
166
+ * order: { id: '123' }, // Hot context (latest)
167
+ * mainOrder: { id: '123' } // Named (persistent)
168
+ * }
169
+ * ```
170
+ *
171
+ * 3. **Collection Pattern** (For Multiple Instances):
172
+ * ```typescript
173
+ * resources: {
174
+ * orders: [
175
+ * { id: 'main', label: 'Initial Order' },
176
+ * { id: 'upsell1', label: 'Upsell #1' }
177
+ * ]
178
+ * }
179
+ * ```
180
+ *
181
+ * 4. **Metadata Pattern** (For Versioning/Tracking):
182
+ * ```typescript
183
+ * resources: {
184
+ * order: {
185
+ * data: { id: '123', amount: 100 },
186
+ * meta: { version: '2.0', source: 'checkout' }
187
+ * }
188
+ * }
189
+ * ```
190
+ *
191
+ * 5. **Namespaced Pattern** (For Collision Prevention):
192
+ * ```typescript
193
+ * resources: {
194
+ * 'checkout:order': { id: '123' },
195
+ * 'subscription:order': { id: '456' }
196
+ * }
197
+ * ```
198
+ *
199
+ * 6. **Typed Pattern** (For Strict Type Safety):
200
+ * ```typescript
201
+ * interface StrictResources {
202
+ * order: Order; // Your interface
203
+ * customer: Customer;
204
+ * }
205
+ * funnel.next<StrictResources>({ ... })
206
+ * ```
207
+ *
208
+ * All patterns work together - choose what fits your use case!
209
+ */
210
+ export interface FunnelActionResources<TCustom = {}> {
211
+ /**
212
+ * Resource map - infinitely extensible
213
+ * - Standard keys provide IntelliSense
214
+ * - Custom keys allowed via index signature
215
+ * - Supports single resources, collections, and metadata
216
+ * - Optional: pass generic for strict typing
217
+ */
218
+ resources?: FunnelResourceMap<TCustom>;
219
+ /**
220
+ * Legacy top-level data (backward compatible)
221
+ * Will be automatically migrated to resources by orchestrator
222
+ */
223
+ [key: string]: any;
224
+ }
225
+ export interface DirectNavigationActionData extends FunnelActionResources {
37
226
  targetStepId: string;
38
227
  }
39
- export interface BackNavigationActionData {
228
+ export interface BackNavigationActionData extends FunnelActionResources {
40
229
  targetStepId: string;
41
230
  }
42
- export interface PaymentSuccessActionData {
231
+ export interface PaymentSuccessActionData extends FunnelActionResources {
43
232
  payment: {
44
233
  id: string;
45
234
  status: string;
@@ -53,34 +242,30 @@ export interface PaymentSuccessActionData {
53
242
  currency: string;
54
243
  [key: string]: any;
55
244
  };
56
- [key: string]: any;
57
245
  }
58
- export interface PaymentFailedActionData {
246
+ export interface PaymentFailedActionData extends FunnelActionResources {
59
247
  payment: {
60
248
  id: string;
61
249
  status: string;
62
250
  error?: string;
63
251
  [key: string]: any;
64
252
  };
65
- [key: string]: any;
66
253
  }
67
- export interface OfferAcceptedActionData {
254
+ export interface OfferAcceptedActionData extends FunnelActionResources {
68
255
  offer: {
69
256
  accepted: boolean;
70
257
  offerId?: string;
71
258
  [key: string]: any;
72
259
  };
73
- [key: string]: any;
74
260
  }
75
- export interface OfferDeclinedActionData {
261
+ export interface OfferDeclinedActionData extends FunnelActionResources {
76
262
  offer: {
77
263
  declined: boolean;
78
264
  offerId?: string;
79
265
  [key: string]: any;
80
266
  };
81
- [key: string]: any;
82
267
  }
83
- export interface CartUpdatedActionData {
268
+ export interface CartUpdatedActionData extends FunnelActionResources {
84
269
  cart: {
85
270
  hasSpecificItem?: boolean;
86
271
  itemIds?: string[];
@@ -88,13 +273,11 @@ export interface CartUpdatedActionData {
88
273
  total?: number;
89
274
  [key: string]: any;
90
275
  };
91
- [key: string]: any;
92
276
  }
93
- export interface FormSubmitActionData {
277
+ export interface FormSubmitActionData extends FunnelActionResources {
94
278
  form?: {
95
279
  [key: string]: any;
96
280
  };
97
- [key: string]: any;
98
281
  }
99
282
  /**
100
283
  * Base properties shared by all FunnelAction types
@@ -149,7 +332,10 @@ export type FunnelAction = BaseFunnelAction & (({
149
332
  data: NextAction<CartUpdatedActionData>;
150
333
  }) | ({
151
334
  type: FunnelActionType.CUSTOM;
152
- data: NextAction<any>;
335
+ data: NextAction<FunnelActionResources>;
336
+ }) | ({
337
+ type: string;
338
+ data?: NextAction<FunnelActionResources>;
153
339
  }));
154
340
  export interface FunnelNavigationAction {
155
341
  type: 'redirect' | 'replace' | 'push' | 'external' | 'none';
@@ -167,7 +353,33 @@ export interface FunnelNavigationResult {
167
353
  timestamp: string;
168
354
  };
169
355
  }
170
- export interface SimpleFunnelContext {
356
+ /**
357
+ * Funnel context available to plugins
358
+ * Contains current state, resources, and metadata about the funnel session
359
+ *
360
+ * @example Basic usage
361
+ * ```typescript
362
+ * const context = await funnel.getContext();
363
+ * const orderId = context.resources?.order?.id;
364
+ * ```
365
+ *
366
+ * @example Typed usage (opt-in strict typing)
367
+ * ```typescript
368
+ * interface MyResources {
369
+ * order: Order;
370
+ * customer: Customer;
371
+ * }
372
+ * const context = await funnel.getContext<MyResources>();
373
+ * const total = context.resources?.order.amount; // ✅ Type-safe!
374
+ * ```
375
+ *
376
+ * @example Collection access
377
+ * ```typescript
378
+ * const allOrders = context.resources?.orders; // FunnelResourceData[]
379
+ * const mainOrder = allOrders?.find(o => o.id === 'main');
380
+ * ```
381
+ */
382
+ export interface SimpleFunnelContext<TCustom = {}> {
171
383
  customerId: string;
172
384
  storeId: string;
173
385
  sessionId: string;
@@ -179,8 +391,27 @@ export interface SimpleFunnelContext {
179
391
  * Only moves forward, never backward - used for analytics
180
392
  */
181
393
  furthestStepId?: string;
394
+ /**
395
+ * ✅ Environment context (staging or production)
396
+ * - Determined at session initialization based on entry URL
397
+ * - Ensures all navigation stays in the same environment
398
+ * - 'staging': Uses funnel.config (alias domains like funnel--store.cdn.tagadapay.com)
399
+ * - 'production': Uses funnel.productionConfig (custom domains)
400
+ */
401
+ environment?: 'staging' | 'production';
182
402
  startedAt: number;
183
403
  lastActivityAt: number;
404
+ /**
405
+ * Typed resources map - infinitely extensible
406
+ * - Single resources, collections, or wrapped with metadata
407
+ * - Pass generic for strict typing: SimpleFunnelContext<MyResources>
408
+ * - Standard keys provide IntelliSense, custom keys always allowed
409
+ */
410
+ resources?: FunnelResourceMap<TCustom>;
411
+ /**
412
+ * Legacy/Custom metadata
413
+ * For backward compatibility and flexible unstructured data
414
+ */
184
415
  metadata?: Record<string, any>;
185
416
  }
186
417
  export interface FunnelInitializeRequest {
@@ -193,6 +424,12 @@ export interface FunnelInitializeRequest {
193
424
  funnelId?: string;
194
425
  entryStepId?: string;
195
426
  existingSessionId?: string;
427
+ /**
428
+ * Current URL for session synchronization (browser back/forward handling)
429
+ * If not provided, SDK will automatically use window.location.href
430
+ * @example '/checkout', 'https://store.com/payment'
431
+ */
432
+ currentUrl?: string;
196
433
  }
197
434
  export interface FunnelInitializeResponse {
198
435
  success: boolean;
@@ -76,9 +76,32 @@ export interface PaymentOptions {
76
76
  threedsProvider?: 'basis_theory';
77
77
  initiatedBy?: 'customer' | 'merchant';
78
78
  source?: 'upsell' | 'checkout' | 'offer' | 'missing_club' | 'forced';
79
+ /** @deprecated Use onPaymentSuccess instead - this will be removed in v3 */
79
80
  onSuccess?: (response: PaymentResponse) => void;
81
+ /** @deprecated Use onPaymentFailed instead - this will be removed in v3 */
80
82
  onFailure?: (error: string) => void;
81
83
  onRequireAction?: (payment: Payment) => void;
84
+ /**
85
+ * Called when payment succeeds (matches FunnelActionType.PAYMENT_SUCCESS)
86
+ * Use this with useFunnel's next() to navigate to the next step
87
+ * This replaces automatic redirects to /post or /thankyou
88
+ */
89
+ onPaymentSuccess?: (response: PaymentResponse) => void;
90
+ /**
91
+ * Called when payment fails (matches FunnelActionType.PAYMENT_FAILED)
92
+ * Use this to handle retry logic, show errors, or trigger funnel failure flows
93
+ */
94
+ onPaymentFailed?: (error: {
95
+ code: string;
96
+ message: string;
97
+ payment?: Payment;
98
+ }) => void;
99
+ /**
100
+ * Disable automatic redirects to /post or /thankyou (default: true)
101
+ * Set to false only for legacy implementations without funnel orchestrator
102
+ * The funnel orchestrator handles navigation automatically with useFunnel
103
+ */
104
+ disableAutoRedirect?: boolean;
82
105
  }
83
106
  export interface CardPaymentMethod {
84
107
  cardNumber: string;