@tagadapay/plugin-sdk 2.8.8 → 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 (41) 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 +14 -0
  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/react/components/DebugDrawer.js +90 -1
  30. package/dist/v2/react/hooks/__examples__/FunnelContextExample.d.ts +12 -0
  31. package/dist/v2/react/hooks/__examples__/FunnelContextExample.js +54 -0
  32. package/dist/v2/react/hooks/useFunnel.d.ts +1 -1
  33. package/dist/v2/react/hooks/useFunnel.js +209 -32
  34. package/dist/v2/react/hooks/useGoogleAutocomplete.js +26 -18
  35. package/dist/v2/react/hooks/useISOData.js +4 -2
  36. package/dist/v2/react/hooks/useOffersQuery.d.ts +24 -29
  37. package/dist/v2/react/hooks/useOffersQuery.js +164 -204
  38. package/dist/v2/react/hooks/usePaymentQuery.js +99 -6
  39. package/dist/v2/react/providers/TagadaProvider.d.ts +8 -21
  40. package/dist/v2/react/providers/TagadaProvider.js +79 -673
  41. 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');
@@ -391,6 +391,14 @@ export interface SimpleFunnelContext<TCustom = {}> {
391
391
  * Only moves forward, never backward - used for analytics
392
392
  */
393
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';
394
402
  startedAt: number;
395
403
  lastActivityAt: number;
396
404
  /**
@@ -416,6 +424,12 @@ export interface FunnelInitializeRequest {
416
424
  funnelId?: string;
417
425
  entryStepId?: string;
418
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;
419
433
  }
420
434
  export interface FunnelInitializeResponse {
421
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;
@@ -0,0 +1,271 @@
1
+ /**
2
+ * Types for the Tagada Pay SDK Core
3
+ */
4
+ export type Environment = 'production' | 'development' | 'local';
5
+ export interface ApiConfig {
6
+ baseUrl: string;
7
+ endpoints: {
8
+ checkout: {
9
+ sessionInit: string;
10
+ sessionStatus: string;
11
+ };
12
+ customer: {
13
+ profile: string;
14
+ session: string;
15
+ };
16
+ store: {
17
+ config: string;
18
+ };
19
+ };
20
+ }
21
+ export interface EnvironmentConfig {
22
+ environment: Environment;
23
+ apiConfig: ApiConfig;
24
+ }
25
+ export interface Customer {
26
+ id: string;
27
+ email?: string;
28
+ firstName?: string;
29
+ lastName?: string;
30
+ phone?: string;
31
+ isAuthenticated: boolean;
32
+ role: 'authenticated' | 'anonymous';
33
+ }
34
+ export type SessionRole = 'authenticated' | 'anonymous';
35
+ export interface Session {
36
+ sessionId: string;
37
+ storeId: string;
38
+ accountId: string;
39
+ customerId: string;
40
+ role: SessionRole;
41
+ isValid: boolean;
42
+ isLoading: boolean;
43
+ }
44
+ export interface AuthState {
45
+ isAuthenticated: boolean;
46
+ isLoading: boolean;
47
+ customer: Customer | null;
48
+ session: Session | null;
49
+ }
50
+ export interface Locale {
51
+ locale: string;
52
+ language: string;
53
+ region: string;
54
+ messages?: Record<string, string>;
55
+ }
56
+ export interface Currency {
57
+ code: string;
58
+ symbol: string;
59
+ name: string;
60
+ }
61
+ export interface Store {
62
+ id: string;
63
+ name: string;
64
+ domain: string;
65
+ currency: string;
66
+ locale: string;
67
+ presentmentCurrencies: string[];
68
+ chargeCurrencies: string[];
69
+ }
70
+ export interface PickupPoint {
71
+ id: string;
72
+ name: string;
73
+ country: string;
74
+ postal_code: string;
75
+ city: string;
76
+ address: string;
77
+ address2?: string;
78
+ house_number?: string;
79
+ phone?: string;
80
+ email?: string;
81
+ latitude?: number;
82
+ longitude?: number;
83
+ opening_hours?: string;
84
+ extra_info?: string;
85
+ }
86
+ export interface OrderItem {
87
+ id: string;
88
+ productId: string;
89
+ variantId: string;
90
+ quantity: number;
91
+ unitAmount: number;
92
+ amount: number;
93
+ adjustedAmount: number;
94
+ currency: string;
95
+ recurring?: boolean;
96
+ interval?: 'day' | 'week' | 'month' | 'year' | null;
97
+ intervalCount?: number | null;
98
+ orderLineItemProduct?: {
99
+ name: string;
100
+ };
101
+ orderLineItemVariant?: {
102
+ name: string;
103
+ imageUrl: string | null;
104
+ };
105
+ subscriptionSettings?: {
106
+ trial?: boolean;
107
+ };
108
+ }
109
+ export interface OrderSummary {
110
+ currency: string;
111
+ totalPromotionAmount: number;
112
+ totalTaxAmount: number;
113
+ shippingCost: number;
114
+ shippingCostIsFree: boolean;
115
+ subtotalAmount: number;
116
+ subtotalAdjustedAmount: number;
117
+ totalAdjustedAmount: number;
118
+ adjustments?: {
119
+ type: string;
120
+ amount: number;
121
+ description: string;
122
+ }[];
123
+ }
124
+ export interface OrderAddress {
125
+ firstName: string;
126
+ lastName: string;
127
+ address1: string;
128
+ address2?: string;
129
+ city: string;
130
+ state: string;
131
+ postal: string;
132
+ country: string;
133
+ phone?: string;
134
+ }
135
+ export interface Order {
136
+ id: string;
137
+ currency: string;
138
+ paidAmount: number;
139
+ status: string;
140
+ createdAt: string;
141
+ metadata?: Record<string, any>;
142
+ items: OrderItem[];
143
+ summaries?: OrderSummary[];
144
+ shippingAddress?: OrderAddress;
145
+ billingAddress?: OrderAddress;
146
+ pickupAddress?: PickupPoint;
147
+ checkoutSession?: {
148
+ returnUrl?: string;
149
+ [key: string]: any;
150
+ };
151
+ relatedOrders?: Order[];
152
+ }
153
+ export interface PaymentSummary {
154
+ id: string;
155
+ status: string;
156
+ amount: number;
157
+ currency: string;
158
+ createdAt: string;
159
+ updatedAt?: string;
160
+ provider?: string;
161
+ metadata?: Record<string, any>;
162
+ }
163
+ export interface PromotionSummary {
164
+ id: string;
165
+ code?: string | null;
166
+ type?: string;
167
+ amount?: number;
168
+ description?: string | null;
169
+ }
170
+ export interface OrderAdjustmentSummary {
171
+ type: string;
172
+ amount: number;
173
+ description: string;
174
+ }
175
+ export interface OrderWithRelations extends Order {
176
+ customer?: Customer;
177
+ store?: Store;
178
+ account?: {
179
+ id: string;
180
+ name?: string;
181
+ } | undefined;
182
+ items: OrderItem[];
183
+ payments?: PaymentSummary[];
184
+ summaries: OrderSummary[];
185
+ checkoutSession?: {
186
+ id?: string;
187
+ returnUrl?: string;
188
+ [key: string]: any;
189
+ };
190
+ promotions?: PromotionSummary[];
191
+ subscriptions?: any[];
192
+ adjustments: OrderAdjustmentSummary[];
193
+ }
194
+ export interface CustomerAddress {
195
+ company?: string;
196
+ firstName: string;
197
+ lastName: string;
198
+ address1: string;
199
+ city: string;
200
+ country: string;
201
+ state: string;
202
+ postal: string;
203
+ phone?: string;
204
+ email?: string;
205
+ }
206
+ export interface CustomerOrderSummary {
207
+ id: string;
208
+ storeId: string;
209
+ accountId: string;
210
+ createdAt: string;
211
+ updatedAt: string;
212
+ status: string;
213
+ cancelledAt: string | null;
214
+ cancelledReason: string | null;
215
+ paidAt: string | null;
216
+ paidAmount: number | null;
217
+ openAt: string | null;
218
+ abandonedAt: string | null;
219
+ currency: string;
220
+ externalCustomerType: string | null;
221
+ externalCustomerId: string | null;
222
+ externalOrderId: string | null;
223
+ billingAddress: CustomerAddress;
224
+ shippingAddress: Omit<CustomerAddress, 'email'>;
225
+ pickupAddress: any | null;
226
+ taxesIncluded: boolean;
227
+ draft: boolean;
228
+ checkoutSessionId: string | null;
229
+ sessionHash: string | null;
230
+ customerId: string;
231
+ createdFrom: string | null;
232
+ paymentInstrumentId: string | null;
233
+ refundedAt: string | null;
234
+ refundedAmount: number | null;
235
+ metadata?: Record<string, any>;
236
+ }
237
+ export interface CustomerInfos {
238
+ customer: {
239
+ id: string;
240
+ email: string | null;
241
+ firstName: string | null;
242
+ lastName: string | null;
243
+ externalCustomerId: string | null;
244
+ lastOrderId: string | null;
245
+ accountId: string;
246
+ storeId: string;
247
+ billingAddress: CustomerAddress | null;
248
+ shippingAddress: Omit<CustomerAddress, 'email'> | null;
249
+ currency: string | null;
250
+ locale: string | null;
251
+ draft: boolean;
252
+ acceptsMarketing: boolean;
253
+ createdAt: string;
254
+ updatedAt: string;
255
+ metadata: Record<string, any>;
256
+ device: any | null;
257
+ orders: CustomerOrderSummary[];
258
+ subscriptions: any[];
259
+ };
260
+ promotionCodes: any[];
261
+ }
262
+ export interface SessionInitResponse {
263
+ store: Store;
264
+ locale: string;
265
+ messages?: Record<string, string>;
266
+ customer?: Customer;
267
+ session?: Session;
268
+ }
269
+ export interface AnonymousTokenResponse {
270
+ token: string;
271
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Types for the Tagada Pay SDK Core
3
+ */
4
+ export {};
@@ -0,0 +1,39 @@
1
+ export interface DeviceInfo {
2
+ userAgent: {
3
+ browser: {
4
+ name: string;
5
+ version: string;
6
+ };
7
+ os: {
8
+ name: string;
9
+ version: string;
10
+ };
11
+ device?: {
12
+ type: string;
13
+ model: string;
14
+ };
15
+ };
16
+ screenResolution: {
17
+ width: number;
18
+ height: number;
19
+ };
20
+ timeZone: string;
21
+ }
22
+ /**
23
+ * Get browser locale
24
+ */
25
+ export declare function getBrowserLocale(): string;
26
+ /**
27
+ * Collect all device information
28
+ */
29
+ export declare function collectDeviceInfo(): DeviceInfo;
30
+ /**
31
+ * Get URL parameters for session initialization
32
+ */
33
+ export declare function getUrlParams(): {
34
+ locale?: string;
35
+ currency?: string;
36
+ utmSource?: string;
37
+ utmMedium?: string;
38
+ utmCampaign?: string;
39
+ };
@@ -0,0 +1,162 @@
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
+ }
89
+ /**
90
+ * Get screen resolution
91
+ */
92
+ function getScreenResolution() {
93
+ return {
94
+ width: window.screen.width,
95
+ height: window.screen.height,
96
+ };
97
+ }
98
+ /**
99
+ * Get timezone
100
+ */
101
+ function getTimeZone() {
102
+ try {
103
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
104
+ }
105
+ catch (error) {
106
+ console.error('Failed to get timezone:', error);
107
+ return 'UTC';
108
+ }
109
+ }
110
+ /**
111
+ * Get browser locale
112
+ */
113
+ export function getBrowserLocale() {
114
+ try {
115
+ return navigator.language || 'en-US';
116
+ }
117
+ catch (error) {
118
+ console.error('Failed to get browser locale:', error);
119
+ return 'en-US';
120
+ }
121
+ }
122
+ /**
123
+ * Collect all device information
124
+ */
125
+ export function collectDeviceInfo() {
126
+ if (typeof window === 'undefined') {
127
+ // Server-side fallback
128
+ return {
129
+ userAgent: {
130
+ browser: { name: 'unknown', version: 'unknown' },
131
+ os: { name: 'unknown', version: 'unknown' },
132
+ },
133
+ screenResolution: { width: 0, height: 0 },
134
+ timeZone: 'UTC',
135
+ };
136
+ }
137
+ return {
138
+ userAgent: {
139
+ browser: getBrowserInfo(),
140
+ os: getOSInfo(),
141
+ device: getDeviceInfo(),
142
+ },
143
+ screenResolution: getScreenResolution(),
144
+ timeZone: getTimeZone(),
145
+ };
146
+ }
147
+ /**
148
+ * Get URL parameters for session initialization
149
+ */
150
+ export function getUrlParams() {
151
+ if (typeof window === 'undefined') {
152
+ return {};
153
+ }
154
+ const params = new URLSearchParams(window.location.search);
155
+ return {
156
+ locale: params.get('locale') || undefined,
157
+ currency: params.get('currency') || undefined,
158
+ utmSource: params.get('utm_source') || undefined,
159
+ utmMedium: params.get('utm_medium') || undefined,
160
+ utmCampaign: params.get('utm_campaign') || undefined,
161
+ };
162
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Simple event dispatcher for handling state changes in the SDK
3
+ */
4
+ export type Listener<T> = (data: T) => void;
5
+ export declare class EventDispatcher<T> {
6
+ private listeners;
7
+ subscribe(listener: Listener<T>): () => void;
8
+ notify(data: T): void;
9
+ clear(): void;
10
+ }
@@ -0,0 +1,24 @@
1
+ export class EventDispatcher {
2
+ constructor() {
3
+ this.listeners = new Set();
4
+ }
5
+ subscribe(listener) {
6
+ this.listeners.add(listener);
7
+ return () => {
8
+ this.listeners.delete(listener);
9
+ };
10
+ }
11
+ notify(data) {
12
+ this.listeners.forEach((listener) => {
13
+ try {
14
+ listener(data);
15
+ }
16
+ catch (error) {
17
+ console.error('Error in event listener:', error);
18
+ }
19
+ });
20
+ }
21
+ clear() {
22
+ this.listeners.clear();
23
+ }
24
+ }
@@ -0,0 +1,14 @@
1
+ import { Session } from '../types';
2
+ /**
3
+ * Decode a JWT token to extract session information
4
+ * This is a simple client-side decoder - do not use for security validation
5
+ */
6
+ export declare function decodeJWTClient(token: string): Session | null;
7
+ /**
8
+ * Check if a JWT token is expired
9
+ */
10
+ export declare function isTokenExpired(token: string): boolean;
11
+ /**
12
+ * Get token expiration time
13
+ */
14
+ export declare function getTokenExpiration(token: string): Date | null;