@tagadapay/plugin-sdk 2.4.34 → 2.4.35

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.
@@ -0,0 +1,385 @@
1
+ import { useState, useCallback, useEffect } from 'react';
2
+ import { useTagadaContext } from '../providers/TagadaProvider';
3
+ /**
4
+ * React Hook for Funnel Navigation (Plugin SDK Version)
5
+ *
6
+ * Simplified funnel navigation using KV storage for funnel sessions.
7
+ * Integrates with TagadaPay authentication and plugin routing.
8
+ */
9
+ export function useFunnel(options) {
10
+ const { auth, apiService, store } = useTagadaContext();
11
+ const [isLoading, setIsLoading] = useState(false);
12
+ const [isInitialized, setIsInitialized] = useState(false);
13
+ const [context, setContext] = useState(null);
14
+ const [initializationAttempted, setInitializationAttempted] = useState(false);
15
+ const [initializationError, setInitializationError] = useState(null);
16
+ const currentStepId = options.currentStepId || context?.currentStepId;
17
+ // Check for URL parameter overrides
18
+ const urlParams = typeof window !== 'undefined' ? new URLSearchParams(window.location.search) : new URLSearchParams();
19
+ const urlFunnelId = urlParams.get('funnelId') || undefined;
20
+ const effectiveFunnelId = urlFunnelId || options.funnelId;
21
+ // Removed checkExistingSession - now handled in single initialize call
22
+ /**
23
+ * Set funnel session cookie
24
+ */
25
+ const setSessionCookie = useCallback((sessionId) => {
26
+ const maxAge = 24 * 60 * 60; // 24 hours
27
+ const expires = new Date(Date.now() + maxAge * 1000).toUTCString();
28
+ // Set cookie for same-domain scenarios
29
+ document.cookie = `tgd-funnel-session-id=${sessionId}; path=/; expires=${expires}; SameSite=Lax`;
30
+ console.log(`🍪 Funnel: Set session cookie: ${sessionId}`);
31
+ }, []);
32
+ /**
33
+ * Initialize funnel session
34
+ */
35
+ const initializeSession = useCallback(async (entryStepId) => {
36
+ if (!auth.session?.customerId || !store?.id) {
37
+ throw new Error('Authentication required for funnel session');
38
+ }
39
+ setIsLoading(true);
40
+ setInitializationAttempted(true);
41
+ setInitializationError(null);
42
+ try {
43
+ // Check for existing session ID in URL parameters
44
+ let existingSessionId = urlParams.get('funnelSessionId') || undefined;
45
+ if (existingSessionId) {
46
+ console.log(`🍪 Funnel: Found session ID in URL params: ${existingSessionId}`);
47
+ }
48
+ else {
49
+ // Fallback to cookie for same-domain scenarios
50
+ const funnelSessionCookie = document.cookie
51
+ .split('; ')
52
+ .find(row => row.startsWith('tgd-funnel-session-id='));
53
+ existingSessionId = funnelSessionCookie ? funnelSessionCookie.split('=')[1] : undefined;
54
+ if (existingSessionId) {
55
+ console.log(`🍪 Funnel: Found session in cookie: ${existingSessionId}`);
56
+ }
57
+ }
58
+ if (!existingSessionId) {
59
+ console.log(`🍪 Funnel: No existing session found in URL params or cookie`);
60
+ }
61
+ // Use URL funnel ID if provided, otherwise use options (or undefined for backend fallback)
62
+ const effectiveFunnelId = urlFunnelId || options.funnelId;
63
+ // Send minimal CMS session data
64
+ const cmsSessionData = {
65
+ customerId: auth.session.customerId,
66
+ storeId: store.id,
67
+ sessionId: auth.session.sessionId,
68
+ accountId: auth.session.accountId
69
+ };
70
+ // Get current pathname with fallback
71
+ const currentPathname = typeof window !== 'undefined' ? window.location.pathname : '/';
72
+ console.log(`🍪 Funnel: Current pathname: "${currentPathname}"`);
73
+ // Call API to initialize session - backend will restore existing or create new
74
+ const requestBody = {
75
+ cmsSession: cmsSessionData,
76
+ entryStepId, // Optional override
77
+ existingSessionId // Pass existing session ID from URL or cookie
78
+ };
79
+ // Only include funnelId if it's provided (for backend fallback)
80
+ if (effectiveFunnelId) {
81
+ requestBody.funnelId = effectiveFunnelId;
82
+ }
83
+ const response = await apiService.fetch('/api/v1/funnel/initialize', {
84
+ method: 'POST',
85
+ body: requestBody
86
+ });
87
+ if (response.success && response.context) {
88
+ // Backend returns the initialized session
89
+ setContext(response.context);
90
+ setIsInitialized(true);
91
+ // Set session cookie for persistence across page reloads
92
+ setSessionCookie(response.context.sessionId);
93
+ console.log(`🍪 Funnel: Initialized new session for funnel ${effectiveFunnelId || 'default'}`, response.context);
94
+ }
95
+ else {
96
+ throw new Error(response.error || 'Failed to initialize funnel session');
97
+ }
98
+ }
99
+ catch (error) {
100
+ const errorObj = error instanceof Error ? error : new Error(String(error));
101
+ setInitializationError(errorObj);
102
+ console.error('Error initializing funnel session:', error);
103
+ if (options.onError) {
104
+ options.onError(errorObj);
105
+ }
106
+ throw error;
107
+ }
108
+ finally {
109
+ setIsLoading(false);
110
+ }
111
+ }, [auth.session?.customerId, store?.id, effectiveFunnelId, apiService, options.onError]);
112
+ /**
113
+ * Navigate to next step based on event
114
+ */
115
+ const next = useCallback(async (event) => {
116
+ if (!context) {
117
+ throw new Error('Funnel session not initialized');
118
+ }
119
+ if (!context.sessionId) {
120
+ throw new Error('Funnel session ID missing - session may be corrupted');
121
+ }
122
+ setIsLoading(true);
123
+ try {
124
+ console.log(`🍪 Funnel: Navigating with session ID: ${context.sessionId}`);
125
+ const response = await apiService.fetch('/api/v1/funnel/navigate', {
126
+ method: 'POST',
127
+ body: {
128
+ sessionId: context.sessionId, // Send session ID for navigation
129
+ event: {
130
+ type: event.type,
131
+ data: event.data,
132
+ timestamp: event.timestamp?.toISOString() || new Date().toISOString()
133
+ },
134
+ contextUpdates: {
135
+ lastActivityAt: Date.now()
136
+ }
137
+ }
138
+ });
139
+ if (response.success && response.result) {
140
+ const result = response.result;
141
+ // Update local context
142
+ const newContext = {
143
+ ...context,
144
+ currentStepId: result.stepId,
145
+ previousStepId: context.currentStepId,
146
+ lastActivityAt: Date.now(),
147
+ metadata: {
148
+ ...context.metadata,
149
+ lastEvent: event.type,
150
+ lastTransition: new Date().toISOString()
151
+ }
152
+ };
153
+ setContext(newContext);
154
+ // Create typed navigation result
155
+ const navigationResult = {
156
+ stepId: result.stepId,
157
+ action: {
158
+ type: 'redirect', // Default action type
159
+ url: result.url
160
+ },
161
+ context: newContext,
162
+ tracking: result.tracking
163
+ };
164
+ // Handle navigation callback with override capability
165
+ let shouldPerformDefaultNavigation = true;
166
+ if (options.onNavigate) {
167
+ const callbackResult = options.onNavigate(navigationResult);
168
+ if (callbackResult === false) {
169
+ shouldPerformDefaultNavigation = false;
170
+ }
171
+ }
172
+ // Perform default navigation if not overridden
173
+ if (shouldPerformDefaultNavigation && navigationResult.action.url) {
174
+ // Add URL parameters for cross-domain session continuity
175
+ const urlWithParams = addSessionParams(navigationResult.action.url, newContext.sessionId, effectiveFunnelId || options.funnelId);
176
+ const updatedAction = { ...navigationResult.action, url: urlWithParams };
177
+ performNavigation(updatedAction);
178
+ }
179
+ console.log(`🍪 Funnel: Navigated from ${context.currentStepId} to ${result.stepId}`);
180
+ return result;
181
+ }
182
+ else {
183
+ throw new Error(response.error || 'Navigation failed');
184
+ }
185
+ }
186
+ catch (error) {
187
+ console.error('Funnel navigation error:', error);
188
+ if (options.onError) {
189
+ options.onError(error instanceof Error ? error : new Error(String(error)));
190
+ }
191
+ throw error;
192
+ }
193
+ finally {
194
+ setIsLoading(false);
195
+ }
196
+ }, [context, apiService, options.onNavigate, options.onError]);
197
+ /**
198
+ * Go directly to a specific step (bypass conditions)
199
+ */
200
+ const goToStep = useCallback(async (stepId) => {
201
+ return next({
202
+ type: 'direct_navigation',
203
+ data: { targetStepId: stepId },
204
+ timestamp: new Date()
205
+ });
206
+ }, [next]);
207
+ /**
208
+ * Update funnel context
209
+ */
210
+ const updateContext = useCallback(async (updates) => {
211
+ if (!context) {
212
+ throw new Error('Funnel session not initialized');
213
+ }
214
+ setIsLoading(true);
215
+ try {
216
+ const response = await apiService.fetch('/api/v1/funnel/context', {
217
+ method: 'PATCH',
218
+ body: {
219
+ contextUpdates: updates
220
+ }
221
+ });
222
+ if (response.success) {
223
+ const updatedContext = {
224
+ ...context,
225
+ ...updates,
226
+ lastActivityAt: Date.now()
227
+ };
228
+ setContext(updatedContext);
229
+ console.log(`🍪 Funnel: Updated context for step ${context.currentStepId}`);
230
+ }
231
+ else {
232
+ throw new Error(response.error || 'Context update failed');
233
+ }
234
+ }
235
+ catch (error) {
236
+ console.error('Error updating funnel context:', error);
237
+ if (options.onError) {
238
+ options.onError(error instanceof Error ? error : new Error(String(error)));
239
+ }
240
+ throw error;
241
+ }
242
+ finally {
243
+ setIsLoading(false);
244
+ }
245
+ }, [context, apiService, options.onError]);
246
+ /**
247
+ * End current funnel session
248
+ */
249
+ const endSession = useCallback(async () => {
250
+ if (!context) {
251
+ return;
252
+ }
253
+ try {
254
+ await apiService.fetch(`/api/v1/funnel/session/${context.sessionId}`, {
255
+ method: 'DELETE'
256
+ });
257
+ setContext(null);
258
+ setIsInitialized(false);
259
+ console.log(`🍪 Funnel: Ended session ${context.sessionId}`);
260
+ }
261
+ catch (error) {
262
+ console.error('Error ending funnel session:', error);
263
+ // Don't throw here - session ending is best effort
264
+ }
265
+ }, [context, apiService]);
266
+ /**
267
+ * Add session parameters to URL for cross-domain continuity
268
+ */
269
+ const addSessionParams = useCallback((url, sessionId, funnelId) => {
270
+ try {
271
+ const urlObj = new URL(url);
272
+ urlObj.searchParams.set('funnelSessionId', sessionId);
273
+ if (funnelId) {
274
+ urlObj.searchParams.set('funnelId', funnelId);
275
+ }
276
+ const urlWithParams = urlObj.toString();
277
+ console.log(`🍪 Funnel: Added session params to URL: ${url} → ${urlWithParams}`);
278
+ return urlWithParams;
279
+ }
280
+ catch (error) {
281
+ console.warn('Failed to add session params to URL:', error);
282
+ return url; // Return original URL if parsing fails
283
+ }
284
+ }, []);
285
+ /**
286
+ * Perform navigation based on action type
287
+ */
288
+ const performNavigation = useCallback((action) => {
289
+ if (!action.url)
290
+ return;
291
+ // Handle relative URLs by making them absolute
292
+ let targetUrl = action.url;
293
+ if (targetUrl.startsWith('/') && !targetUrl.startsWith('//')) {
294
+ // Relative URL - use current origin
295
+ targetUrl = window.location.origin + targetUrl;
296
+ }
297
+ switch (action.type) {
298
+ case 'redirect':
299
+ console.log(`🍪 Funnel: Redirecting to ${targetUrl}`);
300
+ window.location.href = targetUrl;
301
+ break;
302
+ case 'replace':
303
+ console.log(`🍪 Funnel: Replacing current page with ${targetUrl}`);
304
+ window.location.replace(targetUrl);
305
+ break;
306
+ case 'push':
307
+ console.log(`🍪 Funnel: Pushing to history: ${targetUrl}`);
308
+ window.history.pushState({}, '', targetUrl);
309
+ // Trigger a popstate event to update React Router
310
+ window.dispatchEvent(new PopStateEvent('popstate'));
311
+ break;
312
+ case 'external':
313
+ console.log(`🍪 Funnel: Opening external URL: ${targetUrl}`);
314
+ window.open(targetUrl, '_blank');
315
+ break;
316
+ case 'none':
317
+ console.log(`🍪 Funnel: No navigation action required`);
318
+ break;
319
+ default:
320
+ console.warn(`🍪 Funnel: Unknown navigation action type: ${action.type}`);
321
+ break;
322
+ }
323
+ }, []);
324
+ /**
325
+ * Retry initialization after fixing errors
326
+ */
327
+ const retryInitialization = useCallback(async () => {
328
+ setInitializationAttempted(false);
329
+ setInitializationError(null);
330
+ await initializeSession();
331
+ }, [initializeSession]);
332
+ // Auto-initialize if requested and not already initialized (prevent infinite loops)
333
+ useEffect(() => {
334
+ if (options.autoInitialize &&
335
+ !isInitialized &&
336
+ !initializationAttempted &&
337
+ !initializationError &&
338
+ auth.session?.customerId &&
339
+ store?.id) {
340
+ console.log('🍪 Funnel: Auto-initializing session...');
341
+ initializeSession().catch(error => {
342
+ console.error('Auto-initialization failed - will not retry:', error);
343
+ });
344
+ }
345
+ }, [
346
+ options.autoInitialize,
347
+ isInitialized,
348
+ initializationAttempted,
349
+ initializationError,
350
+ auth.session?.customerId,
351
+ store?.id,
352
+ initializeSession
353
+ ]);
354
+ return {
355
+ next,
356
+ goToStep,
357
+ updateContext,
358
+ currentStep: {
359
+ id: currentStepId || 'unknown'
360
+ },
361
+ context,
362
+ isLoading,
363
+ isInitialized,
364
+ initializeSession,
365
+ endSession,
366
+ retryInitialization,
367
+ initializationError
368
+ };
369
+ }
370
+ /**
371
+ * Simplified funnel hook for basic step tracking
372
+ */
373
+ export function useSimpleFunnel(funnelId, initialStepId) {
374
+ const funnel = useFunnel({
375
+ funnelId,
376
+ currentStepId: initialStepId,
377
+ autoInitialize: true
378
+ });
379
+ return {
380
+ currentStepId: funnel.currentStep.id,
381
+ next: funnel.next,
382
+ goToStep: funnel.goToStep,
383
+ isLoading: funnel.isLoading
384
+ };
385
+ }
@@ -14,29 +14,48 @@ export interface UseISODataResult {
14
14
  getRegions: (countryCode: string) => ISORegion[];
15
15
  findRegion: (countryCode: string, regionCode: string) => ISORegion | null;
16
16
  mapGoogleToISO: (googleState: string, googleStateLong: string, countryCode: string) => ISORegion | null;
17
+ isLanguageLoaded: boolean;
18
+ registeredLanguages: SupportedLanguage[];
17
19
  }
18
20
  /**
19
- * React hook for accessing ISO3166 countries and regions data
21
+ * React hook for accessing ISO3166 countries and regions data with dynamic language loading
20
22
  * @param language - Language code (supports: en, ru, de, fr, es, zh, hi, pt, ja, ar, it, he)
23
+ * @param autoImport - Whether to automatically import the language if not registered (default: true)
21
24
  * @param disputeSetting - Territorial dispute perspective (currently only UN is supported)
22
25
  * @returns Object with countries data and helper functions
23
26
  */
24
- export declare function useISOData(language?: SupportedLanguage, disputeSetting?: string): UseISODataResult;
27
+ export declare function useISOData(language?: SupportedLanguage, autoImport?: boolean, disputeSetting?: string): UseISODataResult;
25
28
  /**
26
29
  * Get available languages for ISO data
27
30
  */
28
31
  export declare function getAvailableLanguages(): SupportedLanguage[];
32
+ /**
33
+ * Hook to manually import and register a language
34
+ * @param language - Language code to import
35
+ * @returns Object with loading state and error handling
36
+ */
37
+ export declare function useLanguageImport(language: SupportedLanguage): {
38
+ importLanguage: () => Promise<void>;
39
+ isLoading: boolean;
40
+ error: string | null;
41
+ isRegistered: boolean;
42
+ };
29
43
  /**
30
44
  * Get list of countries as options for select components
45
+ * @param language - Language code (defaults to 'en')
46
+ * @param autoImport - Whether to automatically import the language if not registered (default: true)
31
47
  */
32
- export declare function useCountryOptions(language?: SupportedLanguage): {
48
+ export declare function useCountryOptions(language?: SupportedLanguage, autoImport?: boolean): {
33
49
  value: string;
34
50
  label: string;
35
51
  }[];
36
52
  /**
37
53
  * Get list of regions/states for a country as options for select components
54
+ * @param countryCode - ISO country code
55
+ * @param language - Language code (defaults to 'en')
56
+ * @param autoImport - Whether to automatically import the language if not registered (default: true)
38
57
  */
39
- export declare function useRegionOptions(countryCode: string, language?: SupportedLanguage): {
58
+ export declare function useRegionOptions(countryCode: string, language?: SupportedLanguage, autoImport?: boolean): {
40
59
  value: string;
41
60
  label: string;
42
61
  }[];
@@ -1,16 +1,32 @@
1
- import { useMemo } from 'react';
1
+ import { useMemo, useEffect, useState, useCallback } from 'react';
2
2
  // Import the pre-built ISO data functions
3
- import { getCountries, getStatesForCountry } from '../../data/iso3166';
3
+ import { getCountries, getStatesForCountry, importLanguage, isLanguageRegistered, getRegisteredLanguages } from '../../data/iso3166';
4
4
  /**
5
- * React hook for accessing ISO3166 countries and regions data
5
+ * React hook for accessing ISO3166 countries and regions data with dynamic language loading
6
6
  * @param language - Language code (supports: en, ru, de, fr, es, zh, hi, pt, ja, ar, it, he)
7
+ * @param autoImport - Whether to automatically import the language if not registered (default: true)
7
8
  * @param disputeSetting - Territorial dispute perspective (currently only UN is supported)
8
9
  * @returns Object with countries data and helper functions
9
10
  */
10
- export function useISOData(language = 'en', disputeSetting = 'UN') {
11
+ export function useISOData(language = 'en', autoImport = true, disputeSetting = 'UN') {
12
+ const [isLanguageLoaded, setIsLanguageLoaded] = useState(isLanguageRegistered(language));
13
+ const [registeredLanguages, setRegisteredLanguages] = useState(getRegisteredLanguages);
14
+ // Auto-import language if not registered and autoImport is true
15
+ useEffect(() => {
16
+ if (!isLanguageRegistered(language) && autoImport && language !== 'en') {
17
+ importLanguage(language)
18
+ .then(() => {
19
+ setIsLanguageLoaded(true);
20
+ setRegisteredLanguages(getRegisteredLanguages());
21
+ })
22
+ .catch((error) => {
23
+ console.error(`Failed to auto-import language ${language}:`, error);
24
+ });
25
+ }
26
+ }, [language, autoImport]);
11
27
  const data = useMemo(() => {
12
28
  try {
13
- // Get countries from pre-built data with language support (now synchronous)
29
+ // Get countries from pre-built data with language support
14
30
  const countriesArray = getCountries(language);
15
31
  // Transform to our expected format (Record<string, ISOCountry>)
16
32
  const countries = {};
@@ -66,6 +82,8 @@ export function useISOData(language = 'en', disputeSetting = 'UN') {
66
82
  getRegions,
67
83
  findRegion,
68
84
  mapGoogleToISO,
85
+ isLanguageLoaded,
86
+ registeredLanguages,
69
87
  };
70
88
  }
71
89
  catch (error) {
@@ -75,23 +93,58 @@ export function useISOData(language = 'en', disputeSetting = 'UN') {
75
93
  getRegions: () => [],
76
94
  findRegion: () => null,
77
95
  mapGoogleToISO: () => null,
96
+ isLanguageLoaded,
97
+ registeredLanguages,
78
98
  };
79
99
  }
80
- }, [language, disputeSetting]);
100
+ }, [language, disputeSetting, isLanguageLoaded, registeredLanguages]);
81
101
  return data;
82
102
  }
83
103
  /**
84
104
  * Get available languages for ISO data
85
105
  */
86
106
  export function getAvailableLanguages() {
87
- // Return all statically imported languages for browser compatibility
107
+ // Return all available languages (not just registered ones)
88
108
  return ['en', 'ru', 'de', 'fr', 'es', 'zh', 'hi', 'pt', 'ja', 'ar', 'it', 'he'];
89
109
  }
110
+ /**
111
+ * Hook to manually import and register a language
112
+ * @param language - Language code to import
113
+ * @returns Object with loading state and error handling
114
+ */
115
+ export function useLanguageImport(language) {
116
+ const [isLoading, setIsLoading] = useState(false);
117
+ const [error, setError] = useState(null);
118
+ const importLanguageData = useCallback(async () => {
119
+ if (isLanguageRegistered(language)) {
120
+ return; // Already registered
121
+ }
122
+ setIsLoading(true);
123
+ setError(null);
124
+ try {
125
+ await importLanguage(language);
126
+ }
127
+ catch (err) {
128
+ setError(err instanceof Error ? err.message : 'Failed to import language');
129
+ }
130
+ finally {
131
+ setIsLoading(false);
132
+ }
133
+ }, [language]);
134
+ return {
135
+ importLanguage: importLanguageData,
136
+ isLoading,
137
+ error,
138
+ isRegistered: isLanguageRegistered(language),
139
+ };
140
+ }
90
141
  /**
91
142
  * Get list of countries as options for select components
143
+ * @param language - Language code (defaults to 'en')
144
+ * @param autoImport - Whether to automatically import the language if not registered (default: true)
92
145
  */
93
- export function useCountryOptions(language = 'en') {
94
- const { countries } = useISOData(language);
146
+ export function useCountryOptions(language = 'en', autoImport = true) {
147
+ const { countries } = useISOData(language, autoImport);
95
148
  return useMemo(() => {
96
149
  return Object.entries(countries)
97
150
  .map(([code, country]) => ({
@@ -103,9 +156,12 @@ export function useCountryOptions(language = 'en') {
103
156
  }
104
157
  /**
105
158
  * Get list of regions/states for a country as options for select components
159
+ * @param countryCode - ISO country code
160
+ * @param language - Language code (defaults to 'en')
161
+ * @param autoImport - Whether to automatically import the language if not registered (default: true)
106
162
  */
107
- export function useRegionOptions(countryCode, language = 'en') {
108
- const { getRegions } = useISOData(language);
163
+ export function useRegionOptions(countryCode, language = 'en', autoImport = true) {
164
+ const { getRegions } = useISOData(language, autoImport);
109
165
  return useMemo(() => {
110
166
  if (!countryCode)
111
167
  return [];
@@ -1,7 +1,7 @@
1
1
  import { useCallback, useState } from 'react';
2
2
  import { useTagadaContext } from '../providers/TagadaProvider';
3
- import { setClientToken } from '../utils/tokenStorage';
4
3
  import { usePluginConfig } from './usePluginConfig';
4
+ import { setClientToken } from '../utils/tokenStorage';
5
5
  export function useLogin() {
6
6
  const [isLoading, setIsLoading] = useState(false);
7
7
  const [error, setError] = useState(null);
@@ -2,8 +2,21 @@
2
2
  * Plugin Configuration Hook
3
3
  *
4
4
  * Professional SDK approach to access plugin configuration:
5
+ * - Raw Config: Direct configuration passed via TagadaProvider (highest priority)
5
6
  * - Store ID, Account ID, Base Path: from .local.json (dev) or headers (production)
6
7
  * - Deployment Config: from config/*.json (dev) or meta tags (production)
8
+ *
9
+ * Usage:
10
+ * 1. Raw config (recommended for programmatic usage):
11
+ * <TagadaProvider rawPluginConfig={{ storeId: 'store_123', config: {...} }}>
12
+ *
13
+ * 2. File-based config (for development):
14
+ * - .local.json for store/account info
15
+ * - config/default.tgd.json for deployment config
16
+ *
17
+ * 3. Production config:
18
+ * - Headers for store/account info
19
+ * - Meta tags for deployment config
7
20
  */
8
21
  export interface PluginConfig<TConfig = Record<string, any>> {
9
22
  storeId?: string;
@@ -11,6 +24,12 @@ export interface PluginConfig<TConfig = Record<string, any>> {
11
24
  basePath?: string;
12
25
  config?: TConfig;
13
26
  }
27
+ export interface RawPluginConfig<TConfig = Record<string, any>> {
28
+ storeId?: string;
29
+ accountId?: string;
30
+ basePath?: string;
31
+ config?: TConfig;
32
+ }
14
33
  export interface LocalDevConfig {
15
34
  storeId: string;
16
35
  accountId: string;
@@ -18,9 +37,9 @@ export interface LocalDevConfig {
18
37
  }
19
38
  /**
20
39
  * Load plugin configuration (cached)
21
- * Tries local dev config first, then production config
40
+ * Tries raw config first, then local dev config, then production config
22
41
  */
23
- export declare const loadPluginConfig: (configVariant?: string) => Promise<PluginConfig>;
42
+ export declare const loadPluginConfig: (configVariant?: string, rawConfig?: RawPluginConfig) => Promise<PluginConfig>;
24
43
  /**
25
44
  * Main hook for plugin configuration
26
45
  * Gets config from TagadaProvider context (no parameters needed)
@@ -42,7 +61,7 @@ export declare const useBasePath: () => {
42
61
  /**
43
62
  * Get cached config directly (for non-React usage)
44
63
  */
45
- export declare const getPluginConfig: (configVariant?: string) => Promise<PluginConfig>;
64
+ export declare const getPluginConfig: (configVariant?: string, rawConfig?: RawPluginConfig) => Promise<PluginConfig>;
46
65
  /**
47
66
  * Clear the config cache (useful for testing)
48
67
  */
@@ -50,4 +69,4 @@ export declare const clearPluginConfigCache: () => void;
50
69
  /**
51
70
  * Development helper to log current configuration
52
71
  */
53
- export declare const debugPluginConfig: (configVariant?: string) => Promise<void>;
72
+ export declare const debugPluginConfig: (configVariant?: string, rawConfig?: RawPluginConfig) => Promise<void>;