@tagadapay/plugin-sdk 2.6.17 → 2.7.0

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 (30) hide show
  1. package/dist/v2/core/resources/customer.d.ts +150 -0
  2. package/dist/v2/core/resources/customer.js +53 -0
  3. package/dist/v2/core/resources/index.d.ts +3 -1
  4. package/dist/v2/core/resources/index.js +3 -1
  5. package/dist/v2/core/resources/session.d.ts +27 -0
  6. package/dist/v2/core/resources/session.js +56 -0
  7. package/dist/v2/index.d.ts +9 -2
  8. package/dist/v2/index.js +1 -1
  9. package/dist/v2/react/hooks/useAuth.d.ts +8 -0
  10. package/dist/v2/react/hooks/useAuth.js +9 -0
  11. package/dist/v2/react/hooks/useClubOffers.d.ts +101 -0
  12. package/dist/v2/react/hooks/useClubOffers.js +126 -0
  13. package/dist/v2/react/hooks/useCustomer.d.ts +11 -0
  14. package/dist/v2/react/hooks/useCustomer.js +11 -0
  15. package/dist/v2/react/hooks/useCustomerInfos.d.ts +12 -0
  16. package/dist/v2/react/hooks/useCustomerInfos.js +53 -0
  17. package/dist/v2/react/hooks/useCustomerOrders.d.ts +17 -0
  18. package/dist/v2/react/hooks/useCustomerOrders.js +51 -0
  19. package/dist/v2/react/hooks/useCustomerSubscriptions.d.ts +23 -0
  20. package/dist/v2/react/hooks/useCustomerSubscriptions.js +94 -0
  21. package/dist/v2/react/hooks/useLogin.d.ts +53 -0
  22. package/dist/v2/react/hooks/useLogin.js +75 -0
  23. package/dist/v2/react/hooks/useTranslation.js +1 -1
  24. package/dist/v2/react/index.d.ts +15 -4
  25. package/dist/v2/react/index.js +8 -2
  26. package/dist/v2/react/providers/TagadaProvider.d.ts +0 -3
  27. package/dist/v2/react/providers/TagadaProvider.js +44 -32
  28. package/package.json +1 -1
  29. package/dist/v2/react/hooks/useDiscountQuery.d.ts +0 -79
  30. package/dist/v2/react/hooks/useDiscountQuery.js +0 -24
@@ -0,0 +1,53 @@
1
+ 'use client';
2
+ /**
3
+ * useCustomerInfos - Hook to fetch customer information (v2)
4
+ * Fetches customer infos from `/api/v1/customers/{customerId}` with `storeId` param
5
+ */
6
+ import { useQuery } from '@tanstack/react-query';
7
+ import { useMemo } from 'react';
8
+ import { CustomerResource } from '../../core/resources/customer';
9
+ import { useTagadaContext } from '../providers/TagadaProvider';
10
+ import { getGlobalApiClient } from './useApiQuery';
11
+ import { usePluginConfig } from './usePluginConfig';
12
+ export function useCustomerInfos(options = {}) {
13
+ const { storeId } = usePluginConfig();
14
+ const { isSessionInitialized } = useTagadaContext();
15
+ const { customerId = null, enabled = true } = options;
16
+ // Create customer resource client
17
+ const customerResource = useMemo(() => {
18
+ try {
19
+ return new CustomerResource(getGlobalApiClient());
20
+ }
21
+ catch (error) {
22
+ throw new Error('Failed to initialize customer resource: ' +
23
+ (error instanceof Error ? error.message : 'Unknown error'));
24
+ }
25
+ }, []);
26
+ // Determine if query should be enabled
27
+ const isEnabled = useMemo(() => {
28
+ return Boolean(enabled && customerId && storeId && isSessionInitialized);
29
+ }, [enabled, customerId, storeId, isSessionInitialized]);
30
+ // Create query key
31
+ const queryKey = useMemo(() => ['customer-infos', { customerId, storeId }], [customerId, storeId]);
32
+ // Fetch customer infos using TanStack Query
33
+ const { data = null, isLoading, error, refetch, } = useQuery({
34
+ queryKey,
35
+ enabled: isEnabled,
36
+ queryFn: async () => {
37
+ if (!customerId || !storeId) {
38
+ return null;
39
+ }
40
+ return await customerResource.getCustomerInfos(customerId, storeId);
41
+ },
42
+ staleTime: 5 * 60 * 1000, // 5 minutes
43
+ refetchOnWindowFocus: false,
44
+ });
45
+ return {
46
+ data,
47
+ isLoading,
48
+ error,
49
+ refetch: async () => {
50
+ await refetch();
51
+ },
52
+ };
53
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * useCustomerOrders - Hook to fetch customer orders (v2)
3
+ */
4
+ import { OrderWithRelations } from '../../core/resources/customer';
5
+ export interface UseCustomerOrdersOptions {
6
+ customerId?: string | null;
7
+ enabled?: boolean;
8
+ }
9
+ export interface UseCustomerOrdersResult {
10
+ data: {
11
+ orders: OrderWithRelations[];
12
+ } | null;
13
+ isLoading: boolean;
14
+ error: Error | null;
15
+ refetch: () => Promise<void>;
16
+ }
17
+ export declare function useCustomerOrders(options?: UseCustomerOrdersOptions): UseCustomerOrdersResult;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * useCustomerOrders - Hook to fetch customer orders (v2)
3
+ */
4
+ import { useQuery } from '@tanstack/react-query';
5
+ import { useMemo } from 'react';
6
+ import { CustomerResource } from '../../core/resources/customer';
7
+ import { useTagadaContext } from '../providers/TagadaProvider';
8
+ import { getGlobalApiClient } from './useApiQuery';
9
+ import { usePluginConfig } from './usePluginConfig';
10
+ export function useCustomerOrders(options = {}) {
11
+ const { storeId } = usePluginConfig();
12
+ const { isSessionInitialized } = useTagadaContext();
13
+ const { customerId = null, enabled = true } = options;
14
+ // Create customer resource client
15
+ const customerResource = useMemo(() => {
16
+ try {
17
+ return new CustomerResource(getGlobalApiClient());
18
+ }
19
+ catch (error) {
20
+ throw new Error('Failed to initialize customer resource: ' +
21
+ (error instanceof Error ? error.message : 'Unknown error'));
22
+ }
23
+ }, []);
24
+ // Determine if query should be enabled
25
+ const isEnabled = useMemo(() => {
26
+ return Boolean(enabled && customerId && storeId && isSessionInitialized);
27
+ }, [enabled, customerId, storeId, isSessionInitialized]);
28
+ // Create query key
29
+ const queryKey = useMemo(() => ['customer-orders', { customerId, storeId }], [customerId, storeId]);
30
+ // Fetch customer orders using TanStack Query
31
+ const { data = null, isLoading, error, refetch, } = useQuery({
32
+ queryKey,
33
+ enabled: isEnabled,
34
+ queryFn: async () => {
35
+ if (!customerId || !storeId) {
36
+ return null;
37
+ }
38
+ return await customerResource.getCustomerOrders(customerId, storeId);
39
+ },
40
+ staleTime: 5 * 60 * 1000, // 5 minutes
41
+ refetchOnWindowFocus: false,
42
+ });
43
+ return {
44
+ data,
45
+ isLoading,
46
+ error,
47
+ refetch: async () => {
48
+ await refetch();
49
+ },
50
+ };
51
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * useCustomerSubscriptions - Hook to manage customer subscriptions (v2)
3
+ */
4
+ import { SubscriptionsResponse } from '../../core/resources/customer';
5
+ export interface UseCustomerSubscriptionsOptions {
6
+ customerId?: string | null;
7
+ enabled?: boolean;
8
+ }
9
+ export interface UseCustomerSubscriptionsResult {
10
+ data: SubscriptionsResponse | null;
11
+ isLoading: boolean;
12
+ error: Error | null;
13
+ refetch: () => Promise<void>;
14
+ resumeSubscription: (subscriptionId: string) => Promise<{
15
+ success: boolean;
16
+ error?: string;
17
+ }>;
18
+ cancelSubscription: (subscriptionId: string) => Promise<{
19
+ success: boolean;
20
+ error?: string;
21
+ }>;
22
+ }
23
+ export declare function useCustomerSubscriptions(options?: UseCustomerSubscriptionsOptions): UseCustomerSubscriptionsResult;
@@ -0,0 +1,94 @@
1
+ /**
2
+ * useCustomerSubscriptions - Hook to manage customer subscriptions (v2)
3
+ */
4
+ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
5
+ import { useCallback, useMemo } from 'react';
6
+ import { CustomerResource } from '../../core/resources/customer';
7
+ import { useTagadaContext } from '../providers/TagadaProvider';
8
+ import { getGlobalApiClient } from './useApiQuery';
9
+ export function useCustomerSubscriptions(options = {}) {
10
+ const { isSessionInitialized } = useTagadaContext();
11
+ const queryClient = useQueryClient();
12
+ const { customerId = null, enabled = true } = options;
13
+ // Create customer resource client
14
+ const customerResource = useMemo(() => {
15
+ try {
16
+ return new CustomerResource(getGlobalApiClient());
17
+ }
18
+ catch (error) {
19
+ throw new Error('Failed to initialize customer resource: ' +
20
+ (error instanceof Error ? error.message : 'Unknown error'));
21
+ }
22
+ }, []);
23
+ // Determine if query should be enabled
24
+ const isEnabled = useMemo(() => {
25
+ return Boolean(enabled && customerId && isSessionInitialized);
26
+ }, [enabled, customerId, isSessionInitialized]);
27
+ // Create query key
28
+ const queryKey = useMemo(() => ['customer-subscriptions', { customerId }], [customerId]);
29
+ // Fetch customer subscriptions using TanStack Query
30
+ const { data = null, isLoading, error, refetch, } = useQuery({
31
+ queryKey,
32
+ enabled: isEnabled,
33
+ queryFn: async () => {
34
+ if (!customerId) {
35
+ return null;
36
+ }
37
+ return await customerResource.getCustomerSubscriptions();
38
+ },
39
+ staleTime: 5 * 60 * 1000, // 5 minutes
40
+ refetchOnWindowFocus: false,
41
+ });
42
+ // Resume subscription mutation
43
+ const resumeMutation = useMutation({
44
+ mutationFn: async (subscriptionId) => {
45
+ return await customerResource.resumeSubscription(subscriptionId);
46
+ },
47
+ onSuccess: () => {
48
+ // Invalidate and refetch subscriptions
49
+ void queryClient.invalidateQueries({ queryKey });
50
+ },
51
+ });
52
+ // Cancel subscription mutation
53
+ const cancelMutation = useMutation({
54
+ mutationFn: async (subscriptionId) => {
55
+ return await customerResource.cancelSubscription(subscriptionId);
56
+ },
57
+ onSuccess: () => {
58
+ // Invalidate and refetch subscriptions
59
+ void queryClient.invalidateQueries({ queryKey });
60
+ },
61
+ });
62
+ // Resume subscription
63
+ const resumeSubscription = useCallback(async (subscriptionId) => {
64
+ try {
65
+ await resumeMutation.mutateAsync(subscriptionId);
66
+ return { success: true };
67
+ }
68
+ catch (err) {
69
+ const errorMessage = err instanceof Error ? err.message : 'Failed to resume subscription';
70
+ return { success: false, error: errorMessage };
71
+ }
72
+ }, [resumeMutation]);
73
+ // Cancel subscription
74
+ const cancelSubscription = useCallback(async (subscriptionId) => {
75
+ try {
76
+ await cancelMutation.mutateAsync(subscriptionId);
77
+ return { success: true };
78
+ }
79
+ catch (err) {
80
+ const errorMessage = err instanceof Error ? err.message : 'Failed to cancel subscription';
81
+ return { success: false, error: errorMessage };
82
+ }
83
+ }, [cancelMutation]);
84
+ return {
85
+ data,
86
+ isLoading,
87
+ error,
88
+ refetch: async () => {
89
+ await refetch();
90
+ },
91
+ resumeSubscription,
92
+ cancelSubscription,
93
+ };
94
+ }
@@ -0,0 +1,53 @@
1
+ export interface UseLoginOptions {
2
+ /**
3
+ * Callback when login is successful
4
+ */
5
+ onSuccess?: (token: string) => void;
6
+ /**
7
+ * Callback when an error occurs
8
+ */
9
+ onError?: (error: Error) => void;
10
+ }
11
+ export interface UseLoginResult {
12
+ /**
13
+ * Request verification code for email
14
+ */
15
+ requestCode: (email: string) => Promise<{
16
+ success: boolean;
17
+ error?: string;
18
+ }>;
19
+ /**
20
+ * Verify code and complete login
21
+ */
22
+ verifyCode: (email: string, code: string) => Promise<{
23
+ success: boolean;
24
+ token?: string;
25
+ sessionId?: string;
26
+ error?: string;
27
+ }>;
28
+ /**
29
+ * Combined loading state (true if either request or verify is loading)
30
+ */
31
+ isLoading: boolean;
32
+ /**
33
+ * Loading state for request code
34
+ */
35
+ isRequestingCode: boolean;
36
+ /**
37
+ * Loading state for verify code
38
+ */
39
+ isVerifyingCode: boolean;
40
+ /**
41
+ * Combined error state
42
+ */
43
+ error: Error | null;
44
+ /**
45
+ * Error from request code
46
+ */
47
+ requestCodeError: Error | null;
48
+ /**
49
+ * Error from verify code
50
+ */
51
+ verifyCodeError: Error | null;
52
+ }
53
+ export declare function useLogin(options?: UseLoginOptions): UseLoginResult;
@@ -0,0 +1,75 @@
1
+ 'use client';
2
+ /**
3
+ * useLogin - Hook for authentication (v2)
4
+ * Handles email/code authentication flow
5
+ */
6
+ import { useMutation } from '@tanstack/react-query';
7
+ import { useCallback, useMemo } from 'react';
8
+ import { setClientToken } from '../../../react/utils/tokenStorage';
9
+ import { SessionResource } from '../../core/resources/session';
10
+ import { getGlobalApiClient } from './useApiQuery';
11
+ import { usePluginConfig } from './usePluginConfig';
12
+ export function useLogin(options = {}) {
13
+ const { onSuccess, onError } = options;
14
+ const { storeId } = usePluginConfig();
15
+ // Create session resource client
16
+ const sessionResource = useMemo(() => {
17
+ try {
18
+ return new SessionResource(getGlobalApiClient());
19
+ }
20
+ catch (error) {
21
+ throw new Error('Failed to initialize session resource: ' +
22
+ (error instanceof Error ? error.message : 'Unknown error'));
23
+ }
24
+ }, []);
25
+ // Request code mutation
26
+ const requestCodeMutation = useMutation({
27
+ mutationFn: async (email) => {
28
+ if (!storeId) {
29
+ throw new Error('Store ID not found. Make sure the TagadaProvider is properly configured.');
30
+ }
31
+ return await sessionResource.requestCode(email, storeId);
32
+ },
33
+ onError: (error) => {
34
+ console.error('[SDK] Failed to request code:', error);
35
+ onError?.(error);
36
+ },
37
+ });
38
+ // Verify code mutation
39
+ const verifyCodeMutation = useMutation({
40
+ mutationFn: async ({ email, code }) => {
41
+ if (!storeId) {
42
+ throw new Error('Store ID not found. Make sure the TagadaProvider is properly configured.');
43
+ }
44
+ const result = await sessionResource.verifyCode(email, code, storeId);
45
+ if (result.success && result.token) {
46
+ // Store the token
47
+ setClientToken(result.token);
48
+ // Call success callback
49
+ onSuccess?.(result.token);
50
+ }
51
+ return result;
52
+ },
53
+ onError: (error) => {
54
+ console.error('[SDK] Failed to verify code:', error);
55
+ onError?.(error);
56
+ },
57
+ });
58
+ // Action functions
59
+ const requestCode = useCallback(async (email) => {
60
+ return await requestCodeMutation.mutateAsync(email);
61
+ }, [requestCodeMutation]);
62
+ const verifyCode = useCallback(async (email, code) => {
63
+ return await verifyCodeMutation.mutateAsync({ email, code });
64
+ }, [verifyCodeMutation]);
65
+ return {
66
+ requestCode,
67
+ verifyCode,
68
+ isLoading: requestCodeMutation.isPending || verifyCodeMutation.isPending,
69
+ isRequestingCode: requestCodeMutation.isPending,
70
+ isVerifyingCode: verifyCodeMutation.isPending,
71
+ error: requestCodeMutation.error || verifyCodeMutation.error,
72
+ requestCodeError: requestCodeMutation.error,
73
+ verifyCodeError: verifyCodeMutation.error,
74
+ };
75
+ }
@@ -29,7 +29,7 @@ export const useTranslation = (options = {}) => {
29
29
  // Check for language query parameter
30
30
  if (typeof window !== 'undefined') {
31
31
  const urlParams = new URLSearchParams(window.location.search);
32
- const langFromQuery = urlParams.get('language');
32
+ const langFromQuery = urlParams.get('locale');
33
33
  if (langFromQuery)
34
34
  return langFromQuery;
35
35
  }
@@ -6,17 +6,22 @@ export { ExpressPaymentMethodsProvider } from './providers/ExpressPaymentMethods
6
6
  export { TagadaProvider, useTagadaContext } from './providers/TagadaProvider';
7
7
  export { ApplePayButton } from './components/ApplePayButton';
8
8
  export { GooglePayButton } from './components/GooglePayButton';
9
+ export { useAuth } from './hooks/useAuth';
9
10
  export { useCheckoutToken } from './hooks/useCheckoutToken';
11
+ export { useClubOffers } from './hooks/useClubOffers';
12
+ export { useCustomer } from './hooks/useCustomer';
13
+ export { useCustomerInfos } from './hooks/useCustomerInfos';
14
+ export { useCustomerOrders } from './hooks/useCustomerOrders';
15
+ export { useCustomerSubscriptions } from './hooks/useCustomerSubscriptions';
10
16
  export { useExpressPaymentMethods } from './hooks/useExpressPaymentMethods';
11
17
  export { useGeoLocation } from './hooks/useGeoLocation';
12
18
  export { useGoogleAutocomplete } from './hooks/useGoogleAutocomplete';
13
19
  export { getAvailableLanguages, useCountryOptions, useISOData, useLanguageImport, useRegionOptions } from './hooks/useISOData';
20
+ export { useLogin } from './hooks/useLogin';
14
21
  export { usePluginConfig } from './hooks/usePluginConfig';
15
- export { useTranslation } from './hooks/useTranslation';
16
22
  export { queryKeys, useApiMutation, useApiQuery, useInvalidateQuery, usePreloadQuery } from './hooks/useApiQuery';
17
23
  export { useCheckoutQuery as useCheckout } from './hooks/useCheckoutQuery';
18
24
  export { useCurrency } from './hooks/useCurrency';
19
- export { useDiscountQuery as useDiscount } from './hooks/useDiscountQuery';
20
25
  export { useDiscountsQuery as useDiscounts } from './hooks/useDiscountsQuery';
21
26
  export { useOffersQuery as useOffers } from './hooks/useOffersQuery';
22
27
  export { useOrderBumpQuery as useOrderBump } from './hooks/useOrderBumpQuery';
@@ -29,19 +34,25 @@ export { useShippingRatesQuery as useShippingRates } from './hooks/useShippingRa
29
34
  export { useStoreConfigQuery as useStoreConfig } from './hooks/useStoreConfigQuery';
30
35
  export { useThreeds } from './hooks/useThreeds';
31
36
  export { useThreedsModal } from './hooks/useThreedsModal';
37
+ export { useTranslation } from './hooks/useTranslation';
32
38
  export { useVipOffersQuery as useVipOffers } from './hooks/useVipOffersQuery';
33
39
  export { useFunnel, useSimpleFunnel } from './hooks/useFunnel';
34
40
  export type { UseCheckoutTokenOptions, UseCheckoutTokenResult } from './hooks/useCheckoutToken';
41
+ export type { ClubOffer, ClubOfferItem, ClubOfferLineItem, ClubOfferSummary, UseClubOffersOptions, UseClubOffersResult } from './hooks/useClubOffers';
42
+ export type { UseCustomerResult } from './hooks/useCustomer';
43
+ export type { UseCustomerInfosOptions, UseCustomerInfosResult } from './hooks/useCustomerInfos';
44
+ export type { UseCustomerOrdersOptions, UseCustomerOrdersResult } from './hooks/useCustomerOrders';
45
+ export type { UseCustomerSubscriptionsOptions, UseCustomerSubscriptionsResult } from './hooks/useCustomerSubscriptions';
35
46
  export type { ExpressPaymentMethodsContextType, ExpressPaymentMethodsProviderProps } from './hooks/useExpressPaymentMethods';
47
+ export type { UseLoginOptions, UseLoginResult } from './hooks/useLogin';
36
48
  export type { ApplePayButtonProps } from './components/ApplePayButton';
37
49
  export type { GooglePayButtonProps } from './components/GooglePayButton';
38
50
  export type { GeoLocationData, UseGeoLocationOptions, UseGeoLocationReturn } from './hooks/useGeoLocation';
39
51
  export type { ExtractedAddress, GooglePlaceDetails, GooglePrediction, UseGoogleAutocompleteOptions, UseGoogleAutocompleteResult } from './hooks/useGoogleAutocomplete';
40
52
  export type { ISOCountry, ISORegion, UseISODataResult } from './hooks/useISOData';
41
53
  export type { UsePluginConfigOptions, UsePluginConfigResult } from './hooks/usePluginConfig';
42
- export type { TranslateFunction, TranslationText, UseTranslationOptions, UseTranslationResult } from './hooks/useTranslation';
54
+ export type { TranslateFunction, UseTranslationOptions, UseTranslationResult } from './hooks/useTranslation';
43
55
  export type { UseCheckoutQueryOptions as UseCheckoutOptions, UseCheckoutQueryResult as UseCheckoutResult } from './hooks/useCheckoutQuery';
44
- export type { StoreDiscount, UseDiscountQueryOptions as UseDiscountOptions, UseDiscountQueryResult as UseDiscountResult } from './hooks/useDiscountQuery';
45
56
  export type { UseDiscountsQueryOptions as UseDiscountsOptions, UseDiscountsQueryResult as UseDiscountsResult } from './hooks/useDiscountsQuery';
46
57
  export type { FunnelEvent, FunnelNavigationAction, FunnelNavigationResult, SimpleFunnelContext, UseFunnelOptions, UseFunnelResult } from './hooks/useFunnel';
47
58
  export type { UseOffersQueryOptions as UseOffersOptions, UseOffersQueryResult as UseOffersResult } from './hooks/useOffersQuery';
@@ -9,18 +9,23 @@ export { TagadaProvider, useTagadaContext } from './providers/TagadaProvider';
9
9
  export { ApplePayButton } from './components/ApplePayButton';
10
10
  export { GooglePayButton } from './components/GooglePayButton';
11
11
  // Hooks
12
+ export { useAuth } from './hooks/useAuth';
12
13
  export { useCheckoutToken } from './hooks/useCheckoutToken';
14
+ export { useClubOffers } from './hooks/useClubOffers';
15
+ export { useCustomer } from './hooks/useCustomer';
16
+ export { useCustomerInfos } from './hooks/useCustomerInfos';
17
+ export { useCustomerOrders } from './hooks/useCustomerOrders';
18
+ export { useCustomerSubscriptions } from './hooks/useCustomerSubscriptions';
13
19
  export { useExpressPaymentMethods } from './hooks/useExpressPaymentMethods';
14
20
  export { useGeoLocation } from './hooks/useGeoLocation';
15
21
  export { useGoogleAutocomplete } from './hooks/useGoogleAutocomplete';
16
22
  export { getAvailableLanguages, useCountryOptions, useISOData, useLanguageImport, useRegionOptions } from './hooks/useISOData';
23
+ export { useLogin } from './hooks/useLogin';
17
24
  export { usePluginConfig } from './hooks/usePluginConfig';
18
- export { useTranslation } from './hooks/useTranslation';
19
25
  // TanStack Query hooks (recommended)
20
26
  export { queryKeys, useApiMutation, useApiQuery, useInvalidateQuery, usePreloadQuery } from './hooks/useApiQuery';
21
27
  export { useCheckoutQuery as useCheckout } from './hooks/useCheckoutQuery';
22
28
  export { useCurrency } from './hooks/useCurrency';
23
- export { useDiscountQuery as useDiscount } from './hooks/useDiscountQuery';
24
29
  export { useDiscountsQuery as useDiscounts } from './hooks/useDiscountsQuery';
25
30
  export { useOffersQuery as useOffers } from './hooks/useOffersQuery';
26
31
  export { useOrderBumpQuery as useOrderBump } from './hooks/useOrderBumpQuery';
@@ -33,6 +38,7 @@ export { useShippingRatesQuery as useShippingRates } from './hooks/useShippingRa
33
38
  export { useStoreConfigQuery as useStoreConfig } from './hooks/useStoreConfigQuery';
34
39
  export { useThreeds } from './hooks/useThreeds';
35
40
  export { useThreedsModal } from './hooks/useThreedsModal';
41
+ export { useTranslation } from './hooks/useTranslation';
36
42
  export { useVipOffersQuery as useVipOffers } from './hooks/useVipOffersQuery';
37
43
  // Funnel hooks
38
44
  export { useFunnel, useSimpleFunnel } from './hooks/useFunnel';
@@ -1,6 +1,3 @@
1
- /**
2
- * TagadaProvider - Main provider component for the Tagada Pay React SDK
3
- */
4
1
  import { ReactNode } from 'react';
5
2
  import { PluginConfig, RawPluginConfig } from '../../../react/hooks/usePluginConfig';
6
3
  import { ApiService } from '../../../react/services/apiService';
@@ -3,9 +3,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  /**
4
4
  * TagadaProvider - Main provider component for the Tagada Pay React SDK
5
5
  */
6
- import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from 'react';
7
6
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
8
- import { default as DebugDrawer } from '../components/DebugDrawer';
7
+ import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from 'react';
9
8
  import { detectEnvironment, getEnvironmentConfig } from '../../../react/config/environment';
10
9
  import { ApiService } from '../../../react/services/apiService';
11
10
  import { collectDeviceInfo, getBrowserLocale, getUrlParams } from '../../../react/utils/deviceInfo';
@@ -13,8 +12,9 @@ import { decodeJWTClient, isTokenExpired } from '../../../react/utils/jwtDecoder
13
12
  import { convertCurrency, formatMoney, formatMoneyWithoutSymbol, formatSimpleMoney, getCurrencyInfo, minorUnitsToMajorUnits, moneyStringOrNumberToMinorUnits, } from '../../../react/utils/money';
14
13
  import { clearClientToken, getClientToken, setClientToken } from '../../../react/utils/tokenStorage';
15
14
  import { ApiClient } from '../../core/resources/apiClient';
16
- import { setGlobalApiClient, getGlobalApiClientOrNull } from '../hooks/useApiQuery';
17
15
  import { loadPluginConfig } from '../../core/utils/pluginConfig';
16
+ import { default as DebugDrawer } from '../components/DebugDrawer';
17
+ import { setGlobalApiClient } from '../hooks/useApiQuery';
18
18
  // Professional, subtle loading component for initialization
19
19
  const InitializationLoader = () => (_jsxs("div", { style: {
20
20
  position: 'fixed',
@@ -207,8 +207,9 @@ rawPluginConfig, }) {
207
207
  }
208
208
  return service;
209
209
  });
210
- // Initialize TanStack Query API client (global setup only)
211
- useEffect(() => {
210
+ // Initialize TanStack Query API client synchronously during provider initialization
211
+ // This ensures the global client is available immediately for hooks that use it in useMemo
212
+ const [apiClient] = useState(() => {
212
213
  const client = new ApiClient({
213
214
  baseURL: environmentConfig.apiConfig.baseUrl,
214
215
  headers: {
@@ -217,24 +218,40 @@ rawPluginConfig, }) {
217
218
  });
218
219
  // Set the global client for TanStack Query hooks
219
220
  setGlobalApiClient(client);
220
- console.log('[SDK] ApiClient initialized with baseURL:', environmentConfig.apiConfig.baseUrl);
221
- }, [environmentConfig]);
221
+ // Check for existing token and set it immediately
222
+ const existingToken = getClientToken();
223
+ if (existingToken && !isTokenExpired(existingToken)) {
224
+ client.updateToken(existingToken);
225
+ console.log('[SDK] ApiClient initialized with existing token:', existingToken.substring(0, 8) + '...');
226
+ }
227
+ else {
228
+ console.log('[SDK] ApiClient initialized with baseURL:', environmentConfig.apiConfig.baseUrl);
229
+ }
230
+ return client;
231
+ });
232
+ // Update API client when environment config changes
233
+ useEffect(() => {
234
+ apiClient.updateConfig({
235
+ baseURL: environmentConfig.apiConfig.baseUrl,
236
+ headers: {
237
+ 'Content-Type': 'application/json',
238
+ },
239
+ });
240
+ console.log('[SDK] ApiClient config updated with baseURL:', environmentConfig.apiConfig.baseUrl);
241
+ }, [environmentConfig, apiClient]);
222
242
  // Sync token updates between ApiService and ApiClient
223
243
  useEffect(() => {
224
- const client = getGlobalApiClientOrNull();
225
- if (client) {
226
- // Always use the token from ApiService as the source of truth
227
- const currentToken = apiService.getCurrentToken();
228
- if (currentToken && typeof currentToken === 'string') {
229
- client.updateToken(currentToken);
230
- console.log('[SDK] Token synced to ApiClient:', currentToken.substring(0, 8) + '...');
231
- }
232
- else {
233
- client.updateToken(null);
234
- console.log('[SDK] Token cleared from ApiClient');
235
- }
244
+ // Always use the token from ApiService as the source of truth
245
+ const currentToken = apiService.getCurrentToken();
246
+ if (currentToken && typeof currentToken === 'string') {
247
+ apiClient.updateToken(currentToken);
248
+ console.log('[SDK] Token synced to ApiClient:', currentToken.substring(0, 8) + '...');
249
+ }
250
+ else {
251
+ apiClient.updateToken(null);
252
+ console.log('[SDK] Token cleared from ApiClient');
236
253
  }
237
- }, [token, apiService]);
254
+ }, [token, apiService, apiClient]);
238
255
  // Update API service when config or token changes
239
256
  useEffect(() => {
240
257
  apiService.updateConfig(environmentConfig);
@@ -378,12 +395,6 @@ rawPluginConfig, }) {
378
395
  console.debug('[SDK][DEBUG] Auth state:', authState);
379
396
  }
380
397
  console.debug('[SDK] Session initialized successfully');
381
- // Update token to ApiClient immediately
382
- const client = getGlobalApiClientOrNull();
383
- if (client && token) {
384
- client.updateToken(token);
385
- console.log('[SDK] Token updated to ApiClient:', token.substring(0, 8) + '...');
386
- }
387
398
  setIsInitialized(true);
388
399
  setIsSessionInitialized(true); // Mark CMS session as ready
389
400
  setIsLoading(false);
@@ -425,6 +436,10 @@ rawPluginConfig, }) {
425
436
  setClientToken(response.token);
426
437
  // Update the API service with the new token
427
438
  apiService.updateToken(response.token);
439
+ // IMPORTANT: Immediately sync token to API client before marking session as ready
440
+ // This ensures any queries that become enabled after isSessionInitialized=true have the token
441
+ apiClient.updateToken(response.token);
442
+ console.log('[SDK] Token immediately synced to ApiClient:', response.token.substring(0, 8) + '...');
428
443
  // Decode the token to get session data
429
444
  const decodedSession = decodeJWTClient(response.token);
430
445
  if (decodedSession) {
@@ -441,12 +456,6 @@ rawPluginConfig, }) {
441
456
  setIsLoading(false);
442
457
  }
443
458
  console.log('[SDK] ✅ Phase 3 Complete - Session initialization completed successfully');
444
- // Update token to ApiClient immediately
445
- const client = getGlobalApiClientOrNull();
446
- if (client && token) {
447
- client.updateToken(token);
448
- console.log('[SDK] Token updated to ApiClient:', token.substring(0, 8) + '...');
449
- }
450
459
  setIsSessionInitialized(true); // Mark CMS session as ready
451
460
  }
452
461
  catch (error) {
@@ -508,6 +517,9 @@ rawPluginConfig, }) {
508
517
  setToken(tokenToUse);
509
518
  // Update the API service with the token
510
519
  apiService.updateToken(tokenToUse);
520
+ // IMPORTANT: Immediately sync token to API client
521
+ apiClient.updateToken(tokenToUse);
522
+ console.log('[SDK] Token immediately synced to ApiClient:', tokenToUse.substring(0, 8) + '...');
511
523
  // Decode token to get session data
512
524
  const decodedSession = decodeJWTClient(tokenToUse);
513
525
  if (decodedSession) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tagadapay/plugin-sdk",
3
- "version": "2.6.17",
3
+ "version": "2.7.0",
4
4
  "description": "Modern React SDK for building Tagada Pay plugins",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",