@tagadapay/plugin-sdk 3.0.2 → 3.0.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 (49) hide show
  1. package/build-cdn.js +113 -0
  2. package/dist/config/basisTheory.d.ts +26 -0
  3. package/dist/config/basisTheory.js +29 -0
  4. package/dist/external-tracker.js +4947 -0
  5. package/dist/external-tracker.min.js +11 -0
  6. package/dist/external-tracker.min.js.map +7 -0
  7. package/dist/react/config/payment.d.ts +8 -8
  8. package/dist/react/config/payment.js +17 -21
  9. package/dist/react/hooks/useApplePay.js +1 -1
  10. package/dist/react/hooks/usePayment.js +1 -3
  11. package/dist/react/hooks/useThreeds.js +2 -2
  12. package/dist/v2/core/client.d.ts +31 -3
  13. package/dist/v2/core/client.js +234 -9
  14. package/dist/v2/core/config/environment.d.ts +16 -3
  15. package/dist/v2/core/config/environment.js +72 -3
  16. package/dist/v2/core/funnelClient.d.ts +4 -0
  17. package/dist/v2/core/funnelClient.js +106 -4
  18. package/dist/v2/core/resources/funnel.d.ts +22 -0
  19. package/dist/v2/core/resources/offers.d.ts +64 -3
  20. package/dist/v2/core/resources/offers.js +112 -10
  21. package/dist/v2/core/resources/postPurchases.js +4 -1
  22. package/dist/v2/core/utils/configHotReload.d.ts +39 -0
  23. package/dist/v2/core/utils/configHotReload.js +75 -0
  24. package/dist/v2/core/utils/eventBus.d.ts +11 -0
  25. package/dist/v2/core/utils/eventBus.js +34 -0
  26. package/dist/v2/core/utils/pluginConfig.d.ts +14 -5
  27. package/dist/v2/core/utils/pluginConfig.js +74 -59
  28. package/dist/v2/core/utils/previewMode.d.ts +114 -0
  29. package/dist/v2/core/utils/previewMode.js +379 -0
  30. package/dist/v2/core/utils/sessionStorage.d.ts +5 -0
  31. package/dist/v2/core/utils/sessionStorage.js +22 -0
  32. package/dist/v2/index.d.ts +4 -1
  33. package/dist/v2/index.js +3 -1
  34. package/dist/v2/react/hooks/useOfferQuery.js +50 -17
  35. package/dist/v2/react/hooks/usePaymentQuery.js +1 -3
  36. package/dist/v2/react/hooks/usePreviewOffer.d.ts +84 -0
  37. package/dist/v2/react/hooks/usePreviewOffer.js +290 -0
  38. package/dist/v2/react/hooks/useThreeds.js +2 -2
  39. package/dist/v2/react/index.d.ts +2 -0
  40. package/dist/v2/react/index.js +1 -0
  41. package/dist/v2/react/providers/TagadaProvider.d.ts +1 -2
  42. package/dist/v2/react/providers/TagadaProvider.js +51 -34
  43. package/dist/v2/standalone/external-tracker.d.ts +119 -0
  44. package/dist/v2/standalone/external-tracker.js +260 -0
  45. package/dist/v2/standalone/index.d.ts +2 -0
  46. package/dist/v2/standalone/index.js +6 -0
  47. package/package.json +11 -3
  48. package/dist/v2/react/hooks/useOffersQuery.d.ts +0 -12
  49. package/dist/v2/react/hooks/useOffersQuery.js +0 -404
@@ -123,15 +123,25 @@ const getMetaContent = (name) => {
123
123
  return metaTag?.getAttribute('content') || undefined;
124
124
  };
125
125
  /**
126
- * Load production config from meta tags
126
+ * Load production config from meta tags (HIGHEST PRIORITY)
127
127
  * Meta tags are injected by the plugin middleware during HTML serving
128
128
  * This avoids making an additional HEAD request (~300ms savings)
129
+ *
130
+ * Returns null if meta tags are not present (not in production deployment)
129
131
  */
130
132
  const loadProductionConfig = async () => {
131
133
  try {
134
+ // Check if we're in a browser environment
135
+ if (typeof document === 'undefined') {
136
+ return null;
137
+ }
132
138
  // Read store/account info from meta tags (injected by middleware)
133
139
  const storeId = getMetaContent('x-plugin-store-id');
134
140
  const accountId = getMetaContent('x-plugin-account-id');
141
+ // If no store ID in meta tags, this is not a production deployment with injected config
142
+ if (!storeId) {
143
+ return null;
144
+ }
135
145
  const basePath = getMetaContent('x-plugin-base-path') || '/';
136
146
  // Get deployment config from meta tags
137
147
  let config = {};
@@ -143,42 +153,57 @@ const loadProductionConfig = async () => {
143
153
  }
144
154
  }
145
155
  catch (error) {
146
- console.warn('Failed to parse plugin config from meta tag:', error);
147
- }
148
- // Final validation and warnings
149
- if (!storeId) {
150
- console.warn('⚠️ Plugin config: Store ID not found in meta tags');
156
+ console.warn('⚠️ Failed to parse plugin config from meta tag:', error);
151
157
  }
158
+ // Final validation
152
159
  if (!accountId) {
153
160
  console.warn('⚠️ Plugin config: Account ID not found in meta tags');
154
161
  }
155
162
  const result = { storeId, accountId, basePath, config };
156
- console.log('🚀 Plugin config loaded from meta tags (no HEAD request needed):', {
163
+ console.log('🚀 [HIGHEST PRIORITY] Plugin config loaded from meta tags (runtime injected config):', {
157
164
  storeId,
158
165
  accountId,
159
166
  basePath,
160
- configKeys: Object.keys(config)
167
+ configKeys: Object.keys(config),
168
+ configSize: JSON.stringify(config).length
161
169
  });
162
170
  return result;
163
171
  }
164
172
  catch (error) {
165
- console.warn('⚠️ Failed to load production config from meta tags, using defaults:', error);
166
- return { basePath: '/', config: {} };
173
+ console.warn('⚠️ Error loading production config from meta tags:', error);
174
+ return null;
167
175
  }
168
176
  };
169
177
  /**
170
178
  * Core plugin config loading function
171
- * Handles local dev, production, and raw config
179
+ *
180
+ * PRIORITY ORDER (highest to lowest):
181
+ * 1. Injected meta tags (runtime config) - ALWAYS CHECK FIRST
182
+ * 2. Raw config parameter (programmatic override)
183
+ * 3. Environment variables (build-time config)
184
+ * 4. Local dev files (.local.json + config files)
185
+ * 5. Defaults
172
186
  */
173
187
  export const loadPluginConfig = async (configVariant = 'default', rawConfig) => {
174
188
  console.log('🔧 [V2] loadPluginConfig called with variant:', configVariant);
175
189
  // Load static resources first (only in local dev)
176
190
  const staticResources = await loadStaticResources();
177
- console.log('🔧 [V2] Static resources loaded:', {
178
- hasStaticResources: !!staticResources,
179
- staticResourcesKeys: staticResources ? Object.keys(staticResources) : [],
180
- });
181
- // If raw config is provided, use it directly
191
+ // ============================================================
192
+ // PRIORITY 1: Check meta tags FIRST (runtime injected config)
193
+ // This ensures deployed plugins always use injected config
194
+ // ============================================================
195
+ const productionConfig = await loadProductionConfig();
196
+ if (productionConfig) {
197
+ const result = {
198
+ ...productionConfig,
199
+ staticResources: staticResources ?? undefined,
200
+ };
201
+ console.log('✅ [V2] Using INJECTED config from meta tags (HIGHEST PRIORITY)');
202
+ return result;
203
+ }
204
+ // ============================================================
205
+ // PRIORITY 2: Raw config parameter (programmatic override)
206
+ // ============================================================
182
207
  if (rawConfig) {
183
208
  const result = {
184
209
  storeId: rawConfig.storeId,
@@ -187,54 +212,43 @@ export const loadPluginConfig = async (configVariant = 'default', rawConfig) =>
187
212
  config: rawConfig.config ?? {},
188
213
  staticResources: staticResources ?? undefined,
189
214
  };
190
- console.log('🔧 [V2] Final config (raw):', {
191
- hasStoreId: !!result.storeId,
192
- hasStaticResources: !!result.staticResources,
193
- staticResourcesKeys: result.staticResources ? Object.keys(result.staticResources) : [],
194
- });
215
+ console.log(' [V2] Using raw config parameter (PRIORITY 2)');
195
216
  return result;
196
217
  }
197
- else {
198
- const rawConfig = await createRawPluginConfig();
199
- if (rawConfig) {
200
- const result = {
201
- ...rawConfig,
202
- staticResources: staticResources ?? undefined,
203
- };
204
- console.log('🔧 [V2] Final config (createRawPluginConfig):', {
205
- hasStoreId: !!result.storeId,
206
- hasStaticResources: !!result.staticResources,
207
- staticResourcesKeys: result.staticResources ? Object.keys(result.staticResources) : [],
208
- });
209
- return result;
210
- }
218
+ // ============================================================
219
+ // PRIORITY 3: Environment variables (build-time config)
220
+ // Only in localhost - production should use meta tags
221
+ // ============================================================
222
+ const envConfig = await createRawPluginConfig();
223
+ if (envConfig) {
224
+ const result = {
225
+ ...envConfig,
226
+ staticResources: staticResources ?? undefined,
227
+ };
228
+ console.log('✅ [V2] Using environment variables config (PRIORITY 3 - build time)');
229
+ return result;
211
230
  }
212
- // Try local development config
231
+ // ============================================================
232
+ // PRIORITY 4: Local development config files
233
+ // ============================================================
213
234
  const localConfig = await loadLocalDevConfig(configVariant);
214
235
  if (localConfig) {
215
236
  const result = {
216
237
  ...localConfig,
217
238
  staticResources: staticResources ?? undefined,
218
239
  };
219
- console.log('🔧 [V2] Final config (local):', {
220
- hasStoreId: !!result.storeId,
221
- hasStaticResources: !!result.staticResources,
222
- staticResourcesKeys: result.staticResources ? Object.keys(result.staticResources) : [],
223
- });
240
+ console.log(' [V2] Using local dev config files (PRIORITY 4)');
224
241
  return result;
225
242
  }
226
- // Fall back to production config
227
- const productionConfig = await loadProductionConfig();
228
- const result = {
229
- ...productionConfig,
243
+ // ============================================================
244
+ // PRIORITY 5: Defaults (no config found)
245
+ // ============================================================
246
+ console.warn('⚠️ [V2] No plugin config found - using defaults');
247
+ return {
248
+ basePath: '/',
249
+ config: {},
230
250
  staticResources: staticResources ?? undefined,
231
251
  };
232
- console.log('🔧 [V2] Final config (production):', {
233
- hasStoreId: !!result.storeId,
234
- hasStaticResources: !!result.staticResources,
235
- staticResourcesKeys: result.staticResources ? Object.keys(result.staticResources) : [],
236
- });
237
- return result;
238
252
  };
239
253
  /**
240
254
  * Helper to load local config file for development (from /config directory)
@@ -276,15 +290,18 @@ export async function loadLocalConfig(configName = 'default', defaultConfig) {
276
290
  }
277
291
  }
278
292
  /**
279
- * Creates a RawPluginConfig object from provided options
280
- * @param options - Configuration options including storeId, accountId, basePath, configName, or a direct config object
281
- * @returns A RawPluginConfig object or undefined if required fields are missing
293
+ * Creates a RawPluginConfig from environment variables (build-time config)
294
+ *
295
+ * This should ONLY be used when:
296
+ * 1. Running in localhost development
297
+ * 2. Meta tags are not present (not a deployed plugin)
298
+ *
299
+ * @returns A RawPluginConfig object or undefined if not applicable
282
300
  */
283
301
  export async function createRawPluginConfig() {
284
302
  try {
285
- // Only run in true localhost - production should use meta tags
303
+ // Only run in true localhost - production MUST use meta tags
286
304
  if (!isLocalEnvironment()) {
287
- console.log('[createRawPluginConfig] Not localhost, skipping - will use meta tags in production');
288
305
  return undefined;
289
306
  }
290
307
  const storeId = resolveEnvValue('TAGADA_STORE_ID');
@@ -292,12 +309,10 @@ export async function createRawPluginConfig() {
292
309
  const basePath = resolveEnvValue('TAGADA_BASE_PATH');
293
310
  const configName = resolveEnvValue('TAGADA_CONFIG_NAME');
294
311
  if (!storeId || !accountId) {
295
- console.warn('[createRawPluginConfig] No storeId provided');
296
312
  return undefined;
297
313
  }
298
314
  const resolvedConfig = await loadLocalConfig(configName);
299
315
  if (!resolvedConfig) {
300
- console.warn('[createRawPluginConfig] No config found');
301
316
  return undefined;
302
317
  }
303
318
  const rawConfig = {
@@ -306,7 +321,7 @@ export async function createRawPluginConfig() {
306
321
  basePath: basePath || '/',
307
322
  config: resolvedConfig,
308
323
  };
309
- console.log('[createRawPluginConfig] Created raw plugin config:', {
324
+ console.log('🛠️ [createRawPluginConfig] Using environment variables (build-time config):', {
310
325
  hasStoreId: !!rawConfig.storeId,
311
326
  hasAccountId: !!rawConfig.accountId,
312
327
  basePath: rawConfig.basePath,
@@ -0,0 +1,114 @@
1
+ /**
2
+ * SDK Override Parameters
3
+ *
4
+ * Centralized parameter management for SDK behavior overrides.
5
+ * Parameters can come from URL query params, localStorage, or cookies.
6
+ *
7
+ * Key concepts:
8
+ * - forceReset: Clears all stored state (localStorage, cookies) - simulates hard refresh
9
+ * - draft: Marks customers/sessions as draft (for staging/preview/testing)
10
+ * - funnelTracking: Controls whether funnel events are tracked
11
+ * - tagadaClientEnv: Forces specific environment (production/development/local) - overrides auto-detection
12
+ * - tagadaClientBaseUrl: Forces custom API base URL - overrides environment-based URL
13
+ * - token: Authentication token (URL > localStorage)
14
+ * - funnelSessionId: Active funnel session (URL > cookie)
15
+ *
16
+ * Usage examples:
17
+ * - Force production API: ?tagadaClientEnv=production
18
+ * - Force development API: ?tagadaClientEnv=development
19
+ * - Force local API: ?tagadaClientEnv=local
20
+ * - Custom API URL: ?tagadaClientBaseUrl=https://tagada.loclx.io
21
+ * - Combined: ?tagadaClientEnv=local&tagadaClientBaseUrl=https://tagada.loclx.io
22
+ * - Hard reset + production: ?forceReset=true&tagadaClientEnv=production
23
+ */
24
+ /**
25
+ * SDK Override Parameters - centralized across all SDK functions
26
+ * Can be set via URL params, localStorage, or cookies
27
+ */
28
+ export interface SDKOverrideParams {
29
+ /** Force clean state (clear localStorage and cookies) - simulates hard refresh */
30
+ forceReset?: boolean;
31
+ /** Token from URL (overrides localStorage) */
32
+ token?: string | null;
33
+ /** Funnel session ID from URL (overrides cookie) */
34
+ funnelSessionId?: string | null;
35
+ /** Funnel ID from URL */
36
+ funnelId?: string | null;
37
+ /** Draft mode - marks customers/sessions as draft */
38
+ draft?: boolean;
39
+ /** Enable/disable funnel tracking events (false in config editor iframe, true in funnel previews) */
40
+ funnelTracking?: boolean;
41
+ /** Force specific environment (production/development/local) - overrides auto-detection */
42
+ tagadaClientEnv?: 'production' | 'development' | 'local';
43
+ /** Force custom API base URL - overrides environment-based URL */
44
+ tagadaClientBaseUrl?: string;
45
+ }
46
+ /**
47
+ * Check if force reset is active (simulates hard refresh)
48
+ */
49
+ export declare function isForceReset(): boolean;
50
+ /**
51
+ * Get SDK override parameters from all sources (URL, localStorage, cookies)
52
+ * Priority: URL > localStorage > Cookie
53
+ */
54
+ export declare function getSDKParams(): SDKOverrideParams;
55
+ /**
56
+ * Legacy alias for backward compatibility
57
+ * @deprecated Use getSDKParams() instead
58
+ */
59
+ export declare function getPreviewParams(): SDKOverrideParams;
60
+ /**
61
+ * Check if draft mode is active
62
+ * Uses centralized getSDKParams()
63
+ */
64
+ export declare function isDraftMode(): boolean;
65
+ /**
66
+ * Set draft mode in storage for persistence
67
+ */
68
+ export declare function setDraftMode(draft: boolean): void;
69
+ /**
70
+ * Initialize SDK with override parameters
71
+ *
72
+ * This function handles SDK initialization based on override params:
73
+ * 1. If forceReset flag is set: Clear all stored state (simulates hard refresh)
74
+ * 2. If token in URL: Use it (override localStorage)
75
+ * 3. If draft in URL: Persist it to storage
76
+ * 4. If funnelTracking in URL: Persist it to storage
77
+ *
78
+ * @returns True if force reset was activated and state was cleared
79
+ */
80
+ export declare function handlePreviewMode(debugMode?: boolean): boolean;
81
+ /**
82
+ * Set funnel tracking mode in storage for persistence
83
+ */
84
+ export declare function setFunnelTracking(enabled: boolean): void;
85
+ /**
86
+ * Set client environment override in storage for persistence
87
+ */
88
+ export declare function setClientEnvironment(env: 'production' | 'development' | 'local'): void;
89
+ /**
90
+ * Clear client environment override
91
+ */
92
+ export declare function clearClientEnvironment(): void;
93
+ /**
94
+ * Set custom API base URL override in storage for persistence
95
+ */
96
+ export declare function setClientBaseUrl(baseUrl: string): void;
97
+ /**
98
+ * Clear custom API base URL override
99
+ */
100
+ export declare function clearClientBaseUrl(): void;
101
+ /**
102
+ * Check if we should use URL params over stored values
103
+ *
104
+ * Returns true if:
105
+ * - Force reset is active, OR
106
+ * - Explicit token/sessionId in URL (indicating intentional override)
107
+ */
108
+ export declare function shouldUseUrlParams(): boolean;
109
+ /**
110
+ * Check if funnel tracking is enabled
111
+ * Uses centralized getSDKParams()
112
+ * Default is true for normal operations
113
+ */
114
+ export declare function isFunnelTrackingEnabled(): boolean;