@tagadapay/plugin-sdk 2.6.13 → 2.6.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,14 +30,10 @@ export interface RawPluginConfig<TConfig = Record<string, any>> {
30
30
  basePath?: string;
31
31
  config?: TConfig;
32
32
  }
33
- export interface LocalDevConfig {
34
- storeId: string;
35
- accountId: string;
36
- basePath: string;
37
- }
38
33
  /**
39
34
  * Load plugin configuration (cached)
40
- * Tries raw config first, then local dev config, then production config
35
+ * Tries raw config first, then production config
36
+ * Note: Local dev config should be passed via rawConfig parameter
41
37
  */
42
38
  export declare const loadPluginConfig: (configVariant?: string, rawConfig?: RawPluginConfig) => Promise<PluginConfig>;
43
39
  /**
@@ -22,88 +22,6 @@ import { useTagadaContext } from '../providers/TagadaProvider';
22
22
  // Simple cache for plugin configuration
23
23
  let cachedConfig = null;
24
24
  let configPromise = null;
25
- /**
26
- * Load local development configuration
27
- * Combines .local.json + config/default.tgd.json (or specified variant)
28
- */
29
- const loadLocalDevConfig = async (configVariant = 'default') => {
30
- try {
31
- // Only try to load local config in development
32
- // Use hostname-based detection for better Vite compatibility
33
- const isLocalDev = typeof window !== 'undefined' &&
34
- (window.location.hostname === 'localhost' ||
35
- window.location.hostname.includes('ngrok-free.app') ||
36
- window.location.hostname.includes('.localhost') ||
37
- window.location.hostname.includes('127.0.0.1'));
38
- if (!isLocalDev) {
39
- return null;
40
- }
41
- // Load local store/account config
42
- const localResponse = await fetch('/.local.json');
43
- if (!localResponse.ok) {
44
- return null;
45
- }
46
- const localConfig = await localResponse.json();
47
- // Load deployment config (specified variant or fallback to default)
48
- let config = {};
49
- let configLoaded = false;
50
- try {
51
- // Try .tgd.json first (new format), then fallback to .json
52
- let deploymentResponse = await fetch(`/config/${configVariant}.tgd.json`);
53
- if (!deploymentResponse.ok) {
54
- deploymentResponse = await fetch(`/config/${configVariant}.json`);
55
- }
56
- if (deploymentResponse.ok) {
57
- config = await deploymentResponse.json();
58
- configLoaded = true;
59
- }
60
- }
61
- catch {
62
- // Config fetch failed, will try fallback
63
- }
64
- // If config didn't load and it's not 'default', try fallback to default
65
- if (!configLoaded && configVariant !== 'default') {
66
- console.warn(`⚠️ Config variant '${configVariant}' not found, falling back to 'default'`);
67
- try {
68
- let defaultResponse = await fetch('/config/default.tgd.json');
69
- if (!defaultResponse.ok) {
70
- defaultResponse = await fetch('/config/default.json');
71
- }
72
- if (defaultResponse.ok) {
73
- config = await defaultResponse.json();
74
- configLoaded = true;
75
- console.log(`✅ Fallback to 'default' config successful`);
76
- }
77
- }
78
- catch {
79
- // Default config also failed
80
- }
81
- }
82
- // Final warning if no config was loaded
83
- if (!configLoaded) {
84
- if (configVariant === 'default') {
85
- console.warn(`⚠️ No 'default' config found. Create /config/default.tgd.json`);
86
- }
87
- else {
88
- console.warn(`⚠️ Neither '${configVariant}' nor 'default' config found. Create /config/default.tgd.json`);
89
- }
90
- }
91
- console.log('🛠️ Using local development plugin config:', {
92
- configName: config.configName || configVariant,
93
- local: localConfig,
94
- deployment: config
95
- });
96
- return {
97
- storeId: localConfig.storeId,
98
- accountId: localConfig.accountId,
99
- basePath: localConfig.basePath,
100
- config,
101
- };
102
- }
103
- catch {
104
- return null;
105
- }
106
- };
107
25
  /**
108
26
  * Load production config from headers and meta tags
109
27
  */
@@ -135,12 +53,18 @@ const loadProductionConfig = async () => {
135
53
  };
136
54
  /**
137
55
  * Load plugin configuration (cached)
138
- * Tries raw config first, then local dev config, then production config
56
+ * Tries raw config first, then production config
57
+ * Note: Local dev config should be passed via rawConfig parameter
139
58
  */
140
59
  export const loadPluginConfig = async (configVariant = 'default', rawConfig) => {
141
60
  // If raw config is provided, use it directly
142
61
  if (rawConfig) {
143
- console.log('🛠️ Using raw plugin config:', rawConfig);
62
+ console.log('🛠️ Using raw plugin config:', {
63
+ hasStoreId: !!rawConfig.storeId,
64
+ hasAccountId: !!rawConfig.accountId,
65
+ hasConfig: !!rawConfig.config,
66
+ configKeys: rawConfig.config ? Object.keys(rawConfig.config) : [],
67
+ });
144
68
  return {
145
69
  storeId: rawConfig.storeId,
146
70
  accountId: rawConfig.accountId,
@@ -148,12 +72,7 @@ export const loadPluginConfig = async (configVariant = 'default', rawConfig) =>
148
72
  config: rawConfig.config ?? {},
149
73
  };
150
74
  }
151
- // Try local development config
152
- const localConfig = await loadLocalDevConfig(configVariant);
153
- if (localConfig) {
154
- return localConfig;
155
- }
156
- // Fall back to production config
75
+ // Fall back to production config (from headers/meta tags)
157
76
  return loadProductionConfig();
158
77
  };
159
78
  /**
@@ -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
@@ -20,5 +20,6 @@ export type { ShippingRate, ShippingRatesResponse } from './core/resources/shipp
20
20
  export type { ApplyDiscountResponse, Discount, DiscountCodeValidation, RemoveDiscountResponse } from './core/resources/discounts';
21
21
  export type { ToggleOrderBumpResponse, VipOffer, VipPreviewResponse } from './core/resources/vipOffers';
22
22
  export type { StoreConfig } from './core/resources/storeConfig';
23
- export type { FunnelEvent, FunnelNavigationAction, FunnelNavigationResult, SimpleFunnelContext, FunnelInitializeRequest, FunnelInitializeResponse, FunnelNavigateRequest, FunnelNavigateResponse, FunnelContextUpdateRequest, FunnelContextUpdateResponse } from './core/resources/funnel';
24
- export { ApplePayButton, ExpressPaymentMethodsProvider, formatMoney, getAvailableLanguages, GooglePayButton, queryKeys, TagadaProvider, useApiMutation, useApiQuery, useCheckout, useCheckoutToken, useCountryOptions, useCurrency, useDiscounts, useExpressPaymentMethods, useGeoLocation, useGoogleAutocomplete, useInvalidateQuery, useISOData, useLanguageImport, useOffers, useOrder, useOrderBump, usePayment, usePluginConfig, usePostPurchases, usePreloadQuery, useProducts, usePromotions, useRegionOptions, useShippingRates, useStoreConfig, useTagadaContext, useThreeds, useThreedsModal, useVipOffers, useFunnel, useSimpleFunnel } from './react';
23
+ export type { FunnelContextUpdateRequest, FunnelContextUpdateResponse, FunnelEvent, FunnelInitializeRequest, FunnelInitializeResponse, FunnelNavigateRequest, FunnelNavigateResponse, FunnelNavigationAction, FunnelNavigationResult, SimpleFunnelContext } from './core/resources/funnel';
24
+ export { ApplePayButton, ExpressPaymentMethodsProvider, formatMoney, getAvailableLanguages, GooglePayButton, queryKeys, TagadaProvider, useApiMutation, useApiQuery, useCheckout, useCheckoutToken, useCountryOptions, useCurrency, useDiscount, useDiscounts, useExpressPaymentMethods, useFunnel, useGeoLocation, useGoogleAutocomplete, useInvalidateQuery, useISOData, useLanguageImport, useOffers, useOrder, useOrderBump, usePayment, usePluginConfig, usePostPurchases, usePreloadQuery, useProducts, usePromotions, useRegionOptions, useShippingRates, useSimpleFunnel, useStoreConfig, useTagadaContext, useThreeds, useThreedsModal, useVipOffers } from './react';
25
+ export type { StoreDiscount } from './react';
package/dist/v2/index.js CHANGED
@@ -12,4 +12,4 @@ export * from './core/utils/currency';
12
12
  export * from './core/utils/pluginConfig';
13
13
  export * from './core/utils/products';
14
14
  // React exports (hooks and components only, types are exported above)
15
- export { ApplePayButton, ExpressPaymentMethodsProvider, formatMoney, getAvailableLanguages, GooglePayButton, queryKeys, TagadaProvider, useApiMutation, useApiQuery, useCheckout, useCheckoutToken, useCountryOptions, useCurrency, useDiscounts, useExpressPaymentMethods, useGeoLocation, useGoogleAutocomplete, useInvalidateQuery, useISOData, useLanguageImport, useOffers, useOrder, useOrderBump, usePayment, usePluginConfig, usePostPurchases, usePreloadQuery, useProducts, usePromotions, useRegionOptions, useShippingRates, useStoreConfig, useTagadaContext, useThreeds, useThreedsModal, useVipOffers, useFunnel, useSimpleFunnel } from './react';
15
+ export { ApplePayButton, ExpressPaymentMethodsProvider, formatMoney, getAvailableLanguages, GooglePayButton, queryKeys, TagadaProvider, useApiMutation, useApiQuery, useCheckout, useCheckoutToken, useCountryOptions, useCurrency, useDiscount, useDiscounts, useExpressPaymentMethods, useFunnel, useGeoLocation, useGoogleAutocomplete, useInvalidateQuery, useISOData, useLanguageImport, useOffers, useOrder, useOrderBump, usePayment, usePluginConfig, usePostPurchases, usePreloadQuery, useProducts, usePromotions, useRegionOptions, useShippingRates, useSimpleFunnel, useStoreConfig, useTagadaContext, useThreeds, useThreedsModal, useVipOffers } from './react';
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Single Discount Hook using TanStack Query
3
+ * Fetches a specific discount for a given store
4
+ */
5
+ import { UseQueryResult } from '@tanstack/react-query';
6
+ export interface StoreDiscountRuleAmount {
7
+ rate: number;
8
+ amount: number;
9
+ lock: boolean;
10
+ date: string;
11
+ }
12
+ export interface StoreDiscountRule {
13
+ id: string;
14
+ createdAt: string;
15
+ updatedAt: string;
16
+ promotionId: string;
17
+ type: string;
18
+ productId: string | null;
19
+ minimumQuantity: number | null;
20
+ minimumAmount: Record<string, StoreDiscountRuleAmount> | null;
21
+ variantIds: string[] | null;
22
+ }
23
+ export interface StoreDiscountAction {
24
+ id: string;
25
+ createdAt: string;
26
+ updatedAt: string;
27
+ promotionId: string;
28
+ type: string;
29
+ adjustmentAmount: number | null;
30
+ adjustmentPercentage: number | null;
31
+ adjustmentType: string | null;
32
+ freeShipping: boolean | null;
33
+ priceIdToAdd: string | null;
34
+ productIdToAdd: string | null;
35
+ variantIdToAdd: string | null;
36
+ subscriptionFreeTrialDuration: number | null;
37
+ subscriptionFreeTrialDurationType: string | null;
38
+ targetProductId: string | null;
39
+ targetVariantIds: string[] | null;
40
+ maxQuantityDiscounted: number | null;
41
+ appliesOnEachItem: boolean | null;
42
+ }
43
+ export interface StoreDiscount {
44
+ id: string;
45
+ createdAt: string;
46
+ updatedAt: string;
47
+ storeId: string;
48
+ accountId: string;
49
+ name: string;
50
+ code: string;
51
+ automatic: boolean;
52
+ usageLimit: number | null;
53
+ usageCount: number;
54
+ startDate: string;
55
+ endDate: string | null;
56
+ enabled: boolean;
57
+ archived: boolean;
58
+ ruleOperator: string;
59
+ externalId: string | null;
60
+ combinesWithOrderLevelDiscounts: boolean;
61
+ combinesWithLineItemDiscounts: boolean;
62
+ combinesWithShippingDiscounts: boolean;
63
+ forceCombine: boolean;
64
+ isTemporary: boolean;
65
+ rules: StoreDiscountRule[];
66
+ actions: StoreDiscountAction[];
67
+ }
68
+ export interface UseDiscountQueryOptions {
69
+ storeId?: string;
70
+ discountId?: string;
71
+ enabled?: boolean;
72
+ }
73
+ export interface UseDiscountQueryResult<TData = StoreDiscount> {
74
+ discount: TData | undefined;
75
+ isLoading: boolean;
76
+ error: Error | null;
77
+ refetch: UseQueryResult<TData>['refetch'];
78
+ }
79
+ export declare function useDiscountQuery<TData = StoreDiscount>(options: UseDiscountQueryOptions): UseDiscountQueryResult<TData>;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Single Discount Hook using TanStack Query
3
+ * Fetches a specific discount for a given store
4
+ */
5
+ import { useMemo } from 'react';
6
+ import { useApiQuery } from './useApiQuery';
7
+ import { usePluginConfig } from './usePluginConfig';
8
+ export function useDiscountQuery(options) {
9
+ const { storeId: storeIdFromConfig } = usePluginConfig();
10
+ const { storeId = storeIdFromConfig, discountId, enabled = true } = options;
11
+ const key = useMemo(() => ['discount', storeId, discountId], [storeId, discountId]);
12
+ const url = useMemo(() => {
13
+ if (!storeId || !discountId)
14
+ return null;
15
+ return `/api/v1/stores/${storeId}/discounts/${discountId}`;
16
+ }, [storeId, discountId]);
17
+ const query = useApiQuery(key, url, { enabled });
18
+ return {
19
+ discount: query.data,
20
+ isLoading: query.isLoading,
21
+ error: query.error || null,
22
+ refetch: query.refetch,
23
+ };
24
+ }
@@ -15,6 +15,7 @@ export { usePluginConfig } from './hooks/usePluginConfig';
15
15
  export { queryKeys, useApiMutation, useApiQuery, useInvalidateQuery, usePreloadQuery } from './hooks/useApiQuery';
16
16
  export { useCheckoutQuery as useCheckout } from './hooks/useCheckoutQuery';
17
17
  export { useCurrency } from './hooks/useCurrency';
18
+ export { useDiscountQuery as useDiscount } from './hooks/useDiscountQuery';
18
19
  export { useDiscountsQuery as useDiscounts } from './hooks/useDiscountsQuery';
19
20
  export { useOffersQuery as useOffers } from './hooks/useOffersQuery';
20
21
  export { useOrderBumpQuery as useOrderBump } from './hooks/useOrderBumpQuery';
@@ -38,7 +39,9 @@ export type { ExtractedAddress, GooglePlaceDetails, GooglePrediction, UseGoogleA
38
39
  export type { ISOCountry, ISORegion, UseISODataResult } from './hooks/useISOData';
39
40
  export type { UsePluginConfigOptions, UsePluginConfigResult } from './hooks/usePluginConfig';
40
41
  export type { UseCheckoutQueryOptions as UseCheckoutOptions, UseCheckoutQueryResult as UseCheckoutResult } from './hooks/useCheckoutQuery';
42
+ export type { StoreDiscount, UseDiscountQueryOptions as UseDiscountOptions, UseDiscountQueryResult as UseDiscountResult } from './hooks/useDiscountQuery';
41
43
  export type { UseDiscountsQueryOptions as UseDiscountsOptions, UseDiscountsQueryResult as UseDiscountsResult } from './hooks/useDiscountsQuery';
44
+ export type { FunnelEvent, FunnelNavigationAction, FunnelNavigationResult, SimpleFunnelContext, UseFunnelOptions, UseFunnelResult } from './hooks/useFunnel';
42
45
  export type { UseOffersQueryOptions as UseOffersOptions, UseOffersQueryResult as UseOffersResult } from './hooks/useOffersQuery';
43
46
  export type { UseOrderBumpQueryOptions as UseOrderBumpOptions, UseOrderBumpQueryResult as UseOrderBumpResult } from './hooks/useOrderBumpQuery';
44
47
  export type { UseOrderQueryOptions as UseOrderOptions, UseOrderQueryResult as UseOrderResult } from './hooks/useOrderQuery';
@@ -50,6 +53,5 @@ export type { UseShippingRatesQueryOptions as UseShippingRatesOptions, UseShippi
50
53
  export type { UseStoreConfigQueryOptions as UseStoreConfigOptions, UseStoreConfigQueryResult as UseStoreConfigResult } from './hooks/useStoreConfigQuery';
51
54
  export type { PaymentInstrument, ThreedsChallenge, ThreedsHook, ThreedsOptions, ThreedsProvider, ThreedsSession } from './hooks/useThreeds';
52
55
  export type { UseVipOffersQueryOptions as UseVipOffersOptions, UseVipOffersQueryResult as UseVipOffersResult } from './hooks/useVipOffersQuery';
53
- export type { UseFunnelOptions, UseFunnelResult, FunnelEvent, FunnelNavigationAction, FunnelNavigationResult, SimpleFunnelContext } from './hooks/useFunnel';
54
56
  export { formatMoney } from '../../react/utils/money';
55
57
  export type OrderItem = import('../core/utils/order').OrderLineItem;
@@ -19,6 +19,7 @@ export { usePluginConfig } from './hooks/usePluginConfig';
19
19
  export { queryKeys, useApiMutation, useApiQuery, useInvalidateQuery, usePreloadQuery } from './hooks/useApiQuery';
20
20
  export { useCheckoutQuery as useCheckout } from './hooks/useCheckoutQuery';
21
21
  export { useCurrency } from './hooks/useCurrency';
22
+ export { useDiscountQuery as useDiscount } from './hooks/useDiscountQuery';
22
23
  export { useDiscountsQuery as useDiscounts } from './hooks/useDiscountsQuery';
23
24
  export { useOffersQuery as useOffers } from './hooks/useOffersQuery';
24
25
  export { useOrderBumpQuery as useOrderBump } from './hooks/useOrderBumpQuery';
@@ -52,12 +52,11 @@ interface TagadaProviderProps {
52
52
  environment?: Environment;
53
53
  customApiConfig?: Partial<EnvironmentConfig>;
54
54
  debugMode?: boolean;
55
- localConfig?: string;
56
55
  blockUntilSessionReady?: boolean;
57
56
  rawPluginConfig?: RawPluginConfig;
58
57
  }
59
58
  export declare function TagadaProvider({ children, environment, customApiConfig, debugMode, // Remove default, will be set based on environment
60
- localConfig, blockUntilSessionReady, // Default to new non-blocking behavior
59
+ blockUntilSessionReady, // Default to new non-blocking behavior
61
60
  rawPluginConfig, }: TagadaProviderProps): import("react/jsx-runtime").JSX.Element;
62
61
  export declare function useTagadaContext(): TagadaContextValue;
63
62
  export {};
@@ -41,18 +41,18 @@ const InitializationLoader = () => (_jsxs("div", { style: {
41
41
  borderTop: '1.5px solid #9ca3af',
42
42
  borderRadius: '50%',
43
43
  animation: 'tagada-spin 1s linear infinite',
44
- } }), _jsx("span", { children: "Loading..." }), _jsx("style", { children: `
45
- @keyframes tagada-spin {
46
- 0% { transform: rotate(0deg); }
47
- 100% { transform: rotate(360deg); }
48
- }
44
+ } }), _jsx("span", { children: "Loading..." }), _jsx("style", { children: `
45
+ @keyframes tagada-spin {
46
+ 0% { transform: rotate(0deg); }
47
+ 100% { transform: rotate(360deg); }
48
+ }
49
49
  ` })] }));
50
50
  const TagadaContext = createContext(null);
51
51
  // Global instance tracking for TagadaProvider
52
52
  let globalTagadaInstance = null;
53
53
  let globalTagadaInitialized = false;
54
54
  export function TagadaProvider({ children, environment, customApiConfig, debugMode, // Remove default, will be set based on environment
55
- localConfig, blockUntilSessionReady = false, // Default to new non-blocking behavior
55
+ blockUntilSessionReady = false, // Default to new non-blocking behavior
56
56
  rawPluginConfig, }) {
57
57
  // Instance tracking
58
58
  const [instanceId] = useState(() => {
@@ -81,20 +81,13 @@ rawPluginConfig, }) {
81
81
  }
82
82
  };
83
83
  }, [instanceId]);
84
- // LOCAL DEV ONLY: Use localConfig override if in local development, otherwise use default
85
- const isLocalDev = typeof window !== 'undefined' &&
86
- (window.location.hostname === 'localhost' ||
87
- window.location.hostname.includes('.localhost') ||
88
- window.location.hostname.includes('127.0.0.1'));
89
- const configVariant = isLocalDev ? localConfig || 'default' : 'default';
90
84
  // Debug logging (only log once during initial render)
91
85
  const hasLoggedRef = useRef(false);
92
86
  if (!hasLoggedRef.current) {
93
- console.log(`🔍 [TagadaProvider] Instance ${instanceId} Config Debug:`, {
87
+ console.log(`🔍 [TagadaProvider] Instance ${instanceId} Initializing with:`, {
94
88
  hostname: typeof window !== 'undefined' ? window.location.hostname : 'SSR',
95
- isLocalDev,
96
- localConfig,
97
- configVariant,
89
+ hasRawConfig: !!rawPluginConfig,
90
+ rawConfigStoreId: rawPluginConfig?.storeId,
98
91
  });
99
92
  hasLoggedRef.current = true;
100
93
  }
@@ -102,6 +95,10 @@ rawPluginConfig, }) {
102
95
  // Initialize with raw config if available to avoid empty config during loading
103
96
  const [pluginConfig, setPluginConfig] = useState(() => {
104
97
  if (rawPluginConfig) {
98
+ console.log('🛠️ [TagadaProvider] Using raw plugin config immediately:', {
99
+ storeId: rawPluginConfig.storeId,
100
+ accountId: rawPluginConfig.accountId,
101
+ });
105
102
  return {
106
103
  storeId: rawPluginConfig.storeId,
107
104
  accountId: rawPluginConfig.accountId,
@@ -109,9 +106,11 @@ rawPluginConfig, }) {
109
106
  config: rawPluginConfig.config ?? {},
110
107
  };
111
108
  }
109
+ console.log('⏳ [TagadaProvider] No raw config, will load from headers/files');
112
110
  return { basePath: '/', config: {} };
113
111
  });
114
112
  const [configLoading, setConfigLoading] = useState(!rawPluginConfig);
113
+ const [apiClientReady, setApiClientReady] = useState(false);
115
114
  // Load plugin config on mount with the specified variant
116
115
  useEffect(() => {
117
116
  // Prevent multiple config loads
@@ -121,8 +120,8 @@ rawPluginConfig, }) {
121
120
  }
122
121
  const loadConfig = async () => {
123
122
  try {
124
- // Use the v2 core loadPluginConfig function
125
- const config = await loadPluginConfig(configVariant, rawPluginConfig);
123
+ // Use the v2 core loadPluginConfig function (only used when no rawPluginConfig)
124
+ const config = await loadPluginConfig('default', rawPluginConfig);
126
125
  // Ensure we have required store ID before proceeding
127
126
  if (!config.storeId) {
128
127
  console.warn('⚠️ No store ID found in plugin config. This may cause hooks to fail.');
@@ -133,7 +132,7 @@ rawPluginConfig, }) {
133
132
  accountId: config.accountId,
134
133
  basePath: config.basePath,
135
134
  hasConfig: !!config.config,
136
- source: rawPluginConfig ? 'raw' : 'file',
135
+ source: rawPluginConfig ? 'raw' : 'headers/files',
137
136
  });
138
137
  if (blockUntilSessionReady) {
139
138
  console.log('⏳ Blocking mode: Children will render after Phase 3 (session init) completes');
@@ -151,7 +150,7 @@ rawPluginConfig, }) {
151
150
  }
152
151
  };
153
152
  void loadConfig();
154
- }, [configVariant, rawPluginConfig]);
153
+ }, [rawPluginConfig]);
155
154
  // Extract store/account IDs from plugin config (only source now)
156
155
  const storeId = pluginConfig.storeId;
157
156
  const _accountId = pluginConfig.accountId;
@@ -217,7 +216,8 @@ rawPluginConfig, }) {
217
216
  });
218
217
  // Set the global client for TanStack Query hooks
219
218
  setGlobalApiClient(client);
220
- console.log('[SDK] ApiClient initialized with baseURL:', environmentConfig.apiConfig.baseUrl);
219
+ setApiClientReady(true);
220
+ console.log('[SDK] ✅ ApiClient initialized with baseURL:', environmentConfig.apiConfig.baseUrl);
221
221
  }, [environmentConfig]);
222
222
  // Sync token updates between ApiService and ApiClient
223
223
  useEffect(() => {
@@ -669,9 +669,16 @@ rawPluginConfig, }) {
669
669
  // debugCheckout removed from deps to prevent unnecessary re-renders
670
670
  ]);
671
671
  // Determine if we should show loading
672
- // Always block until config is loaded (even if empty)
673
- const shouldShowLoading = configLoading;
674
- const canRenderChildren = !configLoading;
672
+ // Always block until BOTH config is loaded AND API client is ready
673
+ const shouldShowLoading = configLoading || !apiClientReady;
674
+ const canRenderChildren = !configLoading && apiClientReady;
675
+ if (!hasLoggedRef.current && canRenderChildren) {
676
+ console.log('✅ [TagadaProvider] All initialization complete, ready to render children:', {
677
+ configLoading,
678
+ apiClientReady,
679
+ hasStoreId: !!pluginConfig.storeId,
680
+ });
681
+ }
675
682
  // Initialize TanStack Query client
676
683
  const [queryClient] = useState(() => new QueryClient({
677
684
  defaultOptions: {
package/package.json CHANGED
@@ -1,91 +1,91 @@
1
- {
2
- "name": "@tagadapay/plugin-sdk",
3
- "version": "2.6.13",
4
- "description": "Modern React SDK for building Tagada Pay plugins",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "exports": {
8
- ".": {
9
- "types": "./dist/index.d.ts",
10
- "import": "./dist/index.js",
11
- "require": "./dist/index.js"
12
- },
13
- "./react": {
14
- "types": "./dist/react/index.d.ts",
15
- "import": "./dist/react/index.js",
16
- "require": "./dist/react/index.js"
17
- },
18
- "./v2": {
19
- "types": "./dist/v2/index.d.ts",
20
- "import": "./dist/v2/index.js",
21
- "require": "./dist/v2/index.js"
22
- }
23
- },
24
- "scripts": {
25
- "build": "tsc",
26
- "clean": "rm -rf dist",
27
- "lint": "echo \"No linting configured\"",
28
- "test": "echo \"No tests yet\" && exit 0",
29
- "dev": "tsc --watch",
30
- "prepublishOnly": "npm run clean && npm run build",
31
- "publish:patch": "npm version patch && npm publish",
32
- "publish:minor": "npm version minor && npm publish",
33
- "publish:major": "npm version major && npm publish",
34
- "publish:beta": "npm version prerelease --preid=beta && npm publish --tag beta",
35
- "publish:alpha": "npm version prerelease --preid=alpha && npm publish --tag alpha",
36
- "version:patch": "npm version patch",
37
- "version:minor": "npm version minor",
38
- "version:major": "npm version major",
39
- "version:beta": "npm version prerelease --preid=beta",
40
- "version:alpha": "npm version prerelease --preid=alpha",
41
- "version:check": "node version-sync.js check",
42
- "version:sync": "node version-sync.js sync",
43
- "version:list": "node version-sync.js list",
44
- "version:next": "node version-sync.js next",
45
- "postversion": "echo \"✅ Version updated to $(node -p 'require(\"./package.json\").version')\" && (git push && git push --tags || echo \"⚠️ Git push failed - you may need to pull and push manually\")"
46
- },
47
- "keywords": [
48
- "tagadapay",
49
- "cms",
50
- "plugin",
51
- "sdk",
52
- "react",
53
- "typescript"
54
- ],
55
- "author": "Tagada Pay",
56
- "license": "MIT",
57
- "dependencies": {
58
- "@basis-theory/apple-pay-js": "^2.0.2",
59
- "@basis-theory/basis-theory-js": "^4.30.0",
60
- "@basis-theory/basis-theory-react": "^1.32.5",
61
- "@basis-theory/web-threeds": "^1.0.1",
62
- "@google-pay/button-react": "^3.0.10",
63
- "@tanstack/react-query": "^5.90.2",
64
- "axios": "^1.10.0",
65
- "iso3166-2-db": "^2.3.11",
66
- "react-intl": "^7.1.11",
67
- "swr": "^2.3.6"
68
- },
69
- "devDependencies": {
70
- "@types/node": "^18.0.0",
71
- "@types/react": "^19",
72
- "@types/react-dom": "^19",
73
- "typescript": "^5.0.0"
74
- },
75
- "peerDependencies": {
76
- "react": "^18.0.0 || ^19.0.0",
77
- "react-dom": "^18.0.0 || ^19.0.0"
78
- },
79
- "files": [
80
- "dist/**/*",
81
- "README.md"
82
- ],
83
- "repository": {
84
- "type": "git",
85
- "url": "git+https://github.com/tagadapay/plugin-sdk.git"
86
- },
87
- "bugs": {
88
- "url": "https://github.com/tagadapay/plugin-sdk/issues"
89
- },
90
- "homepage": "https://github.com/tagadapay/plugin-sdk#readme"
91
- }
1
+ {
2
+ "name": "@tagadapay/plugin-sdk",
3
+ "version": "2.6.14",
4
+ "description": "Modern React SDK for building Tagada Pay plugins",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "require": "./dist/index.js"
12
+ },
13
+ "./react": {
14
+ "types": "./dist/react/index.d.ts",
15
+ "import": "./dist/react/index.js",
16
+ "require": "./dist/react/index.js"
17
+ },
18
+ "./v2": {
19
+ "types": "./dist/v2/index.d.ts",
20
+ "import": "./dist/v2/index.js",
21
+ "require": "./dist/v2/index.js"
22
+ }
23
+ },
24
+ "scripts": {
25
+ "build": "tsc",
26
+ "clean": "rm -rf dist",
27
+ "lint": "echo \"No linting configured\"",
28
+ "test": "echo \"No tests yet\" && exit 0",
29
+ "dev": "tsc --watch",
30
+ "prepublishOnly": "npm run clean && npm run build",
31
+ "publish:patch": "npm version patch && npm publish",
32
+ "publish:minor": "npm version minor && npm publish",
33
+ "publish:major": "npm version major && npm publish",
34
+ "publish:beta": "npm version prerelease --preid=beta && npm publish --tag beta",
35
+ "publish:alpha": "npm version prerelease --preid=alpha && npm publish --tag alpha",
36
+ "version:patch": "npm version patch",
37
+ "version:minor": "npm version minor",
38
+ "version:major": "npm version major",
39
+ "version:beta": "npm version prerelease --preid=beta",
40
+ "version:alpha": "npm version prerelease --preid=alpha",
41
+ "version:check": "node version-sync.js check",
42
+ "version:sync": "node version-sync.js sync",
43
+ "version:list": "node version-sync.js list",
44
+ "version:next": "node version-sync.js next",
45
+ "postversion": "echo \"✅ Version updated to $(node -p 'require(\"./package.json\").version')\" && (git push && git push --tags || echo \"⚠️ Git push failed - you may need to pull and push manually\")"
46
+ },
47
+ "keywords": [
48
+ "tagadapay",
49
+ "cms",
50
+ "plugin",
51
+ "sdk",
52
+ "react",
53
+ "typescript"
54
+ ],
55
+ "author": "Tagada Pay",
56
+ "license": "MIT",
57
+ "dependencies": {
58
+ "@basis-theory/apple-pay-js": "^2.0.2",
59
+ "@basis-theory/basis-theory-js": "^4.30.0",
60
+ "@basis-theory/basis-theory-react": "^1.32.5",
61
+ "@basis-theory/web-threeds": "^1.0.1",
62
+ "@google-pay/button-react": "^3.0.10",
63
+ "@tanstack/react-query": "^5.90.2",
64
+ "axios": "^1.10.0",
65
+ "iso3166-2-db": "^2.3.11",
66
+ "react-intl": "^7.1.11",
67
+ "swr": "^2.3.6"
68
+ },
69
+ "devDependencies": {
70
+ "@types/node": "^18.0.0",
71
+ "@types/react": "^19",
72
+ "@types/react-dom": "^19",
73
+ "typescript": "^5.0.0"
74
+ },
75
+ "peerDependencies": {
76
+ "react": "^18.0.0 || ^19.0.0",
77
+ "react-dom": "^18.0.0 || ^19.0.0"
78
+ },
79
+ "files": [
80
+ "dist/**/*",
81
+ "README.md"
82
+ ],
83
+ "repository": {
84
+ "type": "git",
85
+ "url": "git+https://github.com/tagadapay/plugin-sdk.git"
86
+ },
87
+ "bugs": {
88
+ "url": "https://github.com/tagadapay/plugin-sdk/issues"
89
+ },
90
+ "homepage": "https://github.com/tagadapay/plugin-sdk#readme"
91
+ }