@virex-tech/paywallo-sdk 1.0.0 → 1.1.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.
package/dist/index.js CHANGED
@@ -224,8 +224,8 @@ async function loadKeychain() {
224
224
  }
225
225
  var KEYCHAIN_SERVICE_PREFIX = "com.paywallo.sdk.";
226
226
  var SecureStorage = class {
227
- constructor(debug = false) {
228
- this.debug = debug;
227
+ // eslint-disable-next-line @typescript-eslint/no-useless-constructor
228
+ constructor(_debug = false) {
229
229
  }
230
230
  /**
231
231
  * Get a value, trying Keychain first (survives reinstalls on iOS), then AsyncStorage.
@@ -233,18 +233,15 @@ var SecureStorage = class {
233
233
  async get(key) {
234
234
  const keychainValue = await this.getFromKeychain(key);
235
235
  if (keychainValue) {
236
- this.log(`Retrieved ${key} from keychain`);
237
236
  return keychainValue;
238
237
  }
239
238
  try {
240
239
  const value = await import_async_storage.default.getItem(`@paywallo:${key}`);
241
240
  if (value) {
242
- this.log(`Retrieved ${key} from async storage`);
243
241
  await this.setToKeychain(key, value);
244
242
  }
245
243
  return value;
246
- } catch (error) {
247
- this.log(`Storage read failed for ${key}:`, error);
244
+ } catch {
248
245
  return null;
249
246
  }
250
247
  }
@@ -257,10 +254,8 @@ var SecureStorage = class {
257
254
  import_async_storage.default.setItem(`@paywallo:${key}`, value),
258
255
  this.setToKeychain(key, value)
259
256
  ]);
260
- this.log(`Stored ${key} in storage`);
261
257
  return true;
262
- } catch (error) {
263
- this.log(`Storage write failed for ${key}:`, error);
258
+ } catch {
264
259
  return false;
265
260
  }
266
261
  }
@@ -270,10 +265,8 @@ var SecureStorage = class {
270
265
  import_async_storage.default.removeItem(`@paywallo:${key}`),
271
266
  this.removeFromKeychain(key)
272
267
  ]);
273
- this.log(`Removed ${key} from storage`);
274
268
  return true;
275
- } catch (error) {
276
- this.log(`Storage remove failed for ${key}:`, error);
269
+ } catch {
277
270
  return false;
278
271
  }
279
272
  }
@@ -313,11 +306,6 @@ var SecureStorage = class {
313
306
  return false;
314
307
  }
315
308
  }
316
- log(...args) {
317
- if (this.debug) {
318
- console.warn("[Panel Storage]", ...args);
319
- }
320
- }
321
309
  };
322
310
  var secureStorage = new SecureStorage();
323
311
 
@@ -642,21 +630,13 @@ var IAPService = class {
642
630
  }
643
631
  async loadProducts(productIds) {
644
632
  if (!nativeStoreKit.isAvailable()) {
645
- if (this.debug) console.warn("[Paywallo][Products] StoreKit not available");
646
633
  return [];
647
634
  }
648
635
  try {
649
- if (this.debug) console.warn("[Paywallo][Products] Loading from StoreKit:", productIds);
650
636
  const products = await nativeStoreKit.getProducts(productIds);
651
- if (this.debug) console.warn("[Paywallo][Products] StoreKit returned:", products.length, "products");
652
637
  for (const product of products) {
653
- if (this.debug) console.warn("[Paywallo][Products]", product.productId, "\u2192", product.localizedPrice, "(", product.currency, ")");
654
638
  this.productsCache.set(product.productId, product);
655
639
  }
656
- if (products.length < productIds.length) {
657
- const missing = productIds.filter((id) => !products.find((p) => p.productId === id));
658
- if (this.debug) console.warn("[Paywallo][Products] Missing from StoreKit:", missing);
659
- }
660
640
  return products;
661
641
  } catch (error) {
662
642
  if (this.debug) console.warn("[Paywallo][Products] StoreKit error:", error);
@@ -674,7 +654,6 @@ var IAPService = class {
674
654
  const product = this.productsCache.get(productId);
675
655
  const platform = import_react_native2.Platform.OS;
676
656
  const distinctId = PaywalloClient.getDistinctId();
677
- if (this.debug) console.warn("[Paywallo][Purchase] Validating with server:", purchase.productId, "tx:", purchase.transactionId, "price:", product?.priceValue, product?.currency);
678
657
  const validation = await apiClient.validatePurchase(
679
658
  platform,
680
659
  purchase.receipt,
@@ -687,33 +666,28 @@ var IAPService = class {
687
666
  options?.paywallPlacement,
688
667
  options?.variantKey
689
668
  );
690
- if (this.debug) console.warn("[Paywallo][Purchase] Server validation result:", JSON.stringify(validation));
691
669
  return validation;
692
670
  }
693
671
  async finishTransaction(transactionId) {
694
672
  try {
695
- if (this.debug) console.warn("[Paywallo][Purchase] Finishing transaction:", transactionId);
696
673
  await nativeStoreKit.finishTransaction(transactionId);
697
- if (this.debug) console.warn("[Paywallo][Purchase] Transaction finished OK");
698
674
  } catch (finishError) {
699
675
  if (this.debug) console.warn("[Paywallo][Purchase] Failed to finish transaction:", finishError instanceof Error ? finishError.message : finishError);
700
676
  }
701
677
  }
702
678
  async purchase(productId, options) {
703
679
  if (!nativeStoreKit.isAvailable()) {
680
+ if (this.debug) console.warn("[Paywallo][Purchase] StoreKit not available");
704
681
  return {
705
682
  success: false,
706
683
  error: new PurchaseError(PURCHASE_ERROR_CODES.STORE_NOT_AVAILABLE, "In-app purchases are not available on this device")
707
684
  };
708
685
  }
709
686
  try {
710
- if (this.debug) console.warn("[Paywallo][Purchase] StoreKit purchase starting:", productId);
711
687
  const purchase = await nativeStoreKit.purchase(productId);
712
688
  if (!purchase) {
713
- if (this.debug) console.warn("[Paywallo][Purchase] StoreKit returned null (user cancelled or pending)");
714
689
  return { success: false };
715
690
  }
716
- if (this.debug) console.warn("[Paywallo][Purchase] StoreKit OK \u2014 tx:", purchase.transactionId, "product:", purchase.productId, "receipt length:", purchase.receipt?.length);
717
691
  let validation = null;
718
692
  try {
719
693
  validation = await this.validateWithServer(purchase, productId, options);
@@ -725,14 +699,12 @@ var IAPService = class {
725
699
  };
726
700
  }
727
701
  if (!validation?.success) {
728
- if (this.debug) console.warn("[Paywallo][Purchase] Validation returned failure:", validation?.error || "no validation result");
729
702
  return {
730
703
  success: false,
731
704
  error: new PurchaseError(PURCHASE_ERROR_CODES.VALIDATION_FAILED, validation?.error ? `Server validation: ${validation.error}` : "Server validation failed")
732
705
  };
733
706
  }
734
707
  await this.finishTransaction(purchase.transactionId);
735
- if (this.debug) console.warn("[Paywallo][Purchase] COMPLETE \u2014 validated & finished:", purchase.productId);
736
708
  return { success: true, purchase };
737
709
  } catch (error) {
738
710
  const e = error instanceof PurchaseError ? error : new PurchaseError(PURCHASE_ERROR_CODES.PURCHASE_FAILED, error instanceof Error ? error.message : String(error));
@@ -742,20 +714,16 @@ var IAPService = class {
742
714
  }
743
715
  async restore() {
744
716
  if (!nativeStoreKit.isAvailable()) {
745
- if (this.debug) console.warn("[Paywallo][Restore] StoreKit not available");
746
717
  return [];
747
718
  }
748
719
  try {
749
- if (this.debug) console.warn("[Paywallo][Restore] Getting active transactions...");
750
720
  const transactions = await nativeStoreKit.getActiveTransactions();
751
- if (this.debug) console.warn("[Paywallo][Restore] Found", transactions.length, "active transactions");
752
721
  const apiClient = this.getApiClient();
753
722
  const distinctId = PaywalloClient.getDistinctId();
754
723
  const platform = import_react_native2.Platform.OS;
755
724
  const results = await Promise.allSettled(
756
725
  transactions.map((tx) => {
757
726
  const product = this.productsCache.get(tx.productId);
758
- if (this.debug) console.warn("[Paywallo][Restore] Validating tx:", tx.transactionId, "product:", tx.productId);
759
727
  return apiClient.validatePurchase(
760
728
  platform,
761
729
  tx.receipt,
@@ -772,22 +740,18 @@ var IAPService = class {
772
740
  for (let i = 0; i < results.length; i++) {
773
741
  const r = results[i];
774
742
  const tx = transactions[i];
775
- if (this.debug) console.warn("[Paywallo][Restore] Validation:", r.status, r.status === "fulfilled" ? JSON.stringify(r.value) : r.reason?.message);
776
743
  if (r.status === "fulfilled" && r.value.success) {
777
744
  try {
778
745
  await nativeStoreKit.finishTransaction(tx.transactionId);
779
- if (this.debug) console.warn("[Paywallo][Restore] Finished tx:", tx.transactionId);
780
746
  } catch (finishError) {
781
747
  if (this.debug) console.warn("[Paywallo][Restore] Failed to finish tx:", tx.transactionId, finishError instanceof Error ? finishError.message : finishError);
782
748
  }
783
749
  validated.push(tx);
784
- } else {
785
- if (this.debug) console.warn("[Paywallo][Restore] Skipping unvalidated tx:", tx.transactionId);
786
750
  }
787
751
  }
788
752
  return validated;
789
753
  } catch (error) {
790
- if (this.debug) console.warn("[Paywallo][Restore] FAILED:", error instanceof Error ? error.message : error);
754
+ if (this.debug) console.warn("[Paywallo][Restore] \u274C FAILED:", error instanceof Error ? error.message : error);
791
755
  return [];
792
756
  }
793
757
  }
@@ -909,7 +873,6 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
909
873
  }
910
874
  onResult({ presented: true, purchased: false, cancelled: false, restored: true });
911
875
  } else {
912
- if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] No purchases to restore");
913
876
  onResult({ presented: true, purchased: false, cancelled: false, restored: false });
914
877
  }
915
878
  } catch (error) {
@@ -1045,7 +1008,7 @@ function buildPaywallInjectionScript(data) {
1045
1008
  secondaryProductId: data.secondaryProductId
1046
1009
  }
1047
1010
  };
1048
- return `(function(){var d=${JSON.stringify(paywallData)},a=0,m=50;function t(){a++;if(window.receiveNativeMessage){window.receiveNativeMessage(d);return;}if(a<m){setTimeout(t,100);}else{console.warn('[Panel WV] FAILED to inject after '+m+' attempts');}}t();})();true;`;
1011
+ return `(function(){var d=${JSON.stringify(paywallData)},a=0,m=50;function t(){a++;if(window.receiveNativeMessage){window.receiveNativeMessage(d);return;}if(a<m){setTimeout(t,100);}else{console.warn('[Paywallo WV] FAILED to inject after '+m+' attempts');}}t();})();true;`;
1049
1012
  }
1050
1013
  function buildPurchaseStateScript(isPurchasing) {
1051
1014
  return `if(window.receiveNativeMessage){window.receiveNativeMessage({type:"purchaseState",data:{isPurchasing:${isPurchasing}}});}true;`;
@@ -1204,16 +1167,13 @@ function PaywallModal({
1204
1167
  const openAnim = (0, import_react5.useRef)(new import_react_native5.Animated.Value(SCREEN_HEIGHT2)).current;
1205
1168
  (0, import_react5.useEffect)(() => {
1206
1169
  if (visible) {
1207
- if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] PaywallModal opening \u2014 starting slide-up animation (550ms)");
1208
1170
  openAnim.setValue(SCREEN_HEIGHT2);
1209
1171
  import_react_native5.Animated.timing(openAnim, {
1210
1172
  toValue: 0,
1211
1173
  duration: 550,
1212
1174
  easing: import_react_native5.Easing.out(import_react_native5.Easing.cubic),
1213
1175
  useNativeDriver: true
1214
- }).start(() => {
1215
- if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] PaywallModal slide-up animation completed");
1216
- });
1176
+ }).start();
1217
1177
  }
1218
1178
  }, [visible, openAnim]);
1219
1179
  if (!visible) return null;
@@ -1617,8 +1577,7 @@ function buildConditionalFlagUrl(baseUrl, flagKey, context) {
1617
1577
  }
1618
1578
 
1619
1579
  // src/domains/iap/apiPurchaseMethods.ts
1620
- async function validatePurchase(client, appKey, platform, receipt, productId, transactionId, priceLocal, currency, country, distinctId, paywallPlacement, variantKey, debug) {
1621
- if (debug) console.warn("[Paywallo][API] POST /purchases/validate", { platform, productId, transactionId, priceLocal, currency, country, distinctId, paywallPlacement, variantKey, receiptLen: receipt?.length });
1580
+ async function validatePurchase(client, appKey, platform, receipt, productId, transactionId, priceLocal, currency, country, distinctId, paywallPlacement, variantKey) {
1622
1581
  const response = await client.post(
1623
1582
  `/purchases/validate/${appKey}`,
1624
1583
  {
@@ -1635,7 +1594,6 @@ async function validatePurchase(client, appKey, platform, receipt, productId, tr
1635
1594
  },
1636
1595
  false
1637
1596
  );
1638
- if (debug) console.warn("[Paywallo][API] Validation response:", JSON.stringify(response.data));
1639
1597
  return response.data;
1640
1598
  }
1641
1599
  async function getSubscriptionStatus(client, baseUrl, appKey, distinctId) {
@@ -1713,11 +1671,6 @@ var HttpClient = class {
1713
1671
  if (state.attempt < retryConfig.maxRetries) {
1714
1672
  state.attempt++;
1715
1673
  const delay = this.calculateDelay(state.attempt, retryConfig);
1716
- this.log(`Retrying request (attempt ${state.attempt}/${retryConfig.maxRetries})`, {
1717
- url,
1718
- status: response.status,
1719
- delay
1720
- });
1721
1674
  await this.sleep(delay);
1722
1675
  continue;
1723
1676
  }
@@ -1728,11 +1681,6 @@ var HttpClient = class {
1728
1681
  if (this.isNetworkError(state.lastError) && state.attempt < retryConfig.maxRetries) {
1729
1682
  state.attempt++;
1730
1683
  const delay = this.calculateDelay(state.attempt, retryConfig);
1731
- this.log(`Network error, retrying (attempt ${state.attempt}/${retryConfig.maxRetries})`, {
1732
- url,
1733
- error: state.lastError.message,
1734
- delay
1735
- });
1736
1684
  await this.sleep(delay);
1737
1685
  continue;
1738
1686
  }
@@ -1750,11 +1698,6 @@ var HttpClient = class {
1750
1698
  controller.abort();
1751
1699
  }
1752
1700
  }, timeout);
1753
- this.log("Request starting", {
1754
- url,
1755
- method: options.method,
1756
- headers: options.headers
1757
- });
1758
1701
  try {
1759
1702
  const response = await fetch(url, {
1760
1703
  ...options,
@@ -1767,20 +1710,8 @@ var HttpClient = class {
1767
1710
  data = await response.json();
1768
1711
  } else {
1769
1712
  const textData = await response.text();
1770
- this.log("Non-JSON response received", {
1771
- url,
1772
- status: response.status,
1773
- contentType,
1774
- bodyPreview: textData.substring(0, 200)
1775
- });
1776
1713
  data = textData;
1777
1714
  }
1778
- this.log("Request completed", {
1779
- url,
1780
- status: response.status,
1781
- ok: response.ok,
1782
- contentType
1783
- });
1784
1715
  const headers = {};
1785
1716
  response.headers.forEach((value, key) => {
1786
1717
  headers[key] = value;
@@ -2063,7 +1994,6 @@ var OfflineQueueClass = class {
2063
1994
  this.cleanupExpired();
2064
1995
  this.cleanupTimer = setInterval(() => this.cleanupExpired(), 60 * 60 * 1e3);
2065
1996
  this.initialized = true;
2066
- this.log("OfflineQueue initialized", { queueSize: this.queue.length });
2067
1997
  }
2068
1998
  async loadFromStorage() {
2069
1999
  try {
@@ -2094,7 +2024,6 @@ var OfflineQueueClass = class {
2094
2024
  const before = this.queue.length;
2095
2025
  this.queue = this.queue.filter((item) => Date.now() - item.timestamp < this.config.maxAge);
2096
2026
  if (before !== this.queue.length) {
2097
- this.log("Cleaned up expired items", { removed: before - this.queue.length });
2098
2027
  void this.saveToStorage();
2099
2028
  }
2100
2029
  }
@@ -2111,7 +2040,6 @@ var OfflineQueueClass = class {
2111
2040
  };
2112
2041
  const existingIndex = this.findDuplicateIndex(item);
2113
2042
  if (existingIndex !== -1) {
2114
- this.log("Duplicate item found, updating timestamp", { id: this.queue[existingIndex].id });
2115
2043
  this.queue[existingIndex].timestamp = Date.now();
2116
2044
  await this.saveToStorage();
2117
2045
  return this.queue[existingIndex];
@@ -2119,14 +2047,12 @@ var OfflineQueueClass = class {
2119
2047
  if (this.queue.length >= this.config.maxItems) {
2120
2048
  const removed = this.queue.shift();
2121
2049
  if (removed) {
2122
- this.log("Queue full, evicted oldest item:", removed.url);
2123
2050
  this.emit({ type: "item:evicted", item: removed, queueSize: this.queue.length });
2124
2051
  }
2125
2052
  }
2126
2053
  this.queue.push(item);
2127
2054
  await this.saveToStorage();
2128
2055
  this.emit({ type: "item:added", item, queueSize: this.queue.length });
2129
- this.log("Item enqueued", { id: item.id, url: item.url });
2130
2056
  return item;
2131
2057
  }
2132
2058
  findDuplicateIndex(item) {
@@ -2155,7 +2081,6 @@ var OfflineQueueClass = class {
2155
2081
  this.processingLock = true;
2156
2082
  this.processing = true;
2157
2083
  this.emit({ type: "processing:start", queueSize: this.queue.length });
2158
- this.log("Processing queue", { items: this.queue.length });
2159
2084
  let processed = 0;
2160
2085
  let failed = 0;
2161
2086
  const delayMs = options?.delayBetweenItems ?? 100;
@@ -2172,7 +2097,6 @@ var OfflineQueueClass = class {
2172
2097
  await this.removeItem(item.id);
2173
2098
  processed++;
2174
2099
  this.emit({ type: "item:success", item, queueSize: this.queue.length });
2175
- this.log("Item processed successfully", { id: item.id });
2176
2100
  } else {
2177
2101
  const didFail = await this.handleItemFailure(item, void 0, permanent);
2178
2102
  if (didFail) failed++;
@@ -2187,7 +2111,6 @@ var OfflineQueueClass = class {
2187
2111
  this.processing = false;
2188
2112
  this.processingLock = false;
2189
2113
  this.emit({ type: "processing:end", queueSize: this.queue.length });
2190
- this.log("Queue processing complete", { processed, failed, remaining: this.queue.length });
2191
2114
  return { processed, failed };
2192
2115
  }
2193
2116
  /** Returns true if the item was permanently removed (counted as failed). */
@@ -2200,14 +2123,9 @@ var OfflineQueueClass = class {
2200
2123
  error: error ?? new ClientError(CLIENT_ERROR_CODES.UNKNOWN, permanent ? "Permanent failure" : "Max attempts reached"),
2201
2124
  queueSize: this.queue.length
2202
2125
  });
2203
- this.log(
2204
- permanent ? "Item failed permanently - removed" : "Item failed after max attempts",
2205
- { id: item.id, attempts: item.attempts }
2206
- );
2207
2126
  return true;
2208
2127
  }
2209
2128
  await this.saveToStorage();
2210
- this.log("Item will be retried", { id: item.id, attempts: item.attempts });
2211
2129
  return false;
2212
2130
  }
2213
2131
  sleep(ms) {
@@ -2228,7 +2146,6 @@ var OfflineQueueClass = class {
2228
2146
  async clear() {
2229
2147
  this.queue = [];
2230
2148
  await this.saveToStorage();
2231
- this.log("Queue cleared");
2232
2149
  }
2233
2150
  async clearItemsWithInvalidAppKey(validAppKey) {
2234
2151
  const before = this.queue.length;
@@ -2239,7 +2156,6 @@ var OfflineQueueClass = class {
2239
2156
  const removed = before - this.queue.length;
2240
2157
  if (removed > 0) {
2241
2158
  await this.saveToStorage();
2242
- this.log("Cleared items with invalid app key", { removed, validAppKey });
2243
2159
  }
2244
2160
  return removed;
2245
2161
  }
@@ -2420,6 +2336,8 @@ var ApiCache = class {
2420
2336
  constructor() {
2421
2337
  this.CACHE_TTL = 3e5;
2422
2338
  // 5 minutes
2339
+ this.CACHE_NULL_TTL = 3e4;
2340
+ // 30 seconds — for null/404 variants
2423
2341
  this.MAX_SIZE = 200;
2424
2342
  this.variantCache = /* @__PURE__ */ new Map();
2425
2343
  this.paywallCache = /* @__PURE__ */ new Map();
@@ -2428,27 +2346,34 @@ var ApiCache = class {
2428
2346
  getCached(cache, key) {
2429
2347
  const entry = cache.get(key);
2430
2348
  if (!entry) return void 0;
2431
- if (Date.now() - entry.ts < this.CACHE_TTL) return entry.value;
2349
+ const ttl = entry.ttl ?? this.CACHE_TTL;
2350
+ if (Date.now() - entry.ts < ttl) return entry.value;
2432
2351
  cache.delete(key);
2433
2352
  return void 0;
2434
2353
  }
2435
- setCached(cache, key, value) {
2436
- cache.set(key, { value, ts: Date.now() });
2354
+ setCached(cache, key, value, ttlOverride) {
2355
+ const entry = { value, ts: Date.now() };
2356
+ if (ttlOverride !== void 0) entry.ttl = ttlOverride;
2357
+ cache.set(key, entry);
2437
2358
  }
2438
2359
  evictExpiredEntries(cache) {
2439
2360
  if (cache.size <= this.MAX_SIZE) return;
2440
2361
  const now = Date.now();
2441
2362
  for (const [key, entry] of cache) {
2442
- if (now - entry.ts > this.CACHE_TTL) cache.delete(key);
2363
+ const ttl = entry.ttl ?? this.CACHE_TTL;
2364
+ if (now - entry.ts > ttl) cache.delete(key);
2443
2365
  }
2444
2366
  }
2445
2367
  getVariant(key) {
2446
2368
  return this.getCached(this.variantCache, key);
2447
2369
  }
2448
- setVariant(key, value) {
2449
- this.setCached(this.variantCache, key, value);
2370
+ setVariant(key, value, ttlOverride) {
2371
+ this.setCached(this.variantCache, key, value, ttlOverride);
2450
2372
  this.evictExpiredEntries(this.variantCache);
2451
2373
  }
2374
+ get nullTTL() {
2375
+ return this.CACHE_NULL_TTL;
2376
+ }
2452
2377
  getStaleVariant(key) {
2453
2378
  const entry = this.variantCache.get(key);
2454
2379
  if (entry && Date.now() - entry.ts < 864e5) return entry.value;
@@ -2457,8 +2382,8 @@ var ApiCache = class {
2457
2382
  getPaywall(key) {
2458
2383
  return this.getCached(this.paywallCache, key);
2459
2384
  }
2460
- setPaywall(key, value) {
2461
- this.setCached(this.paywallCache, key, value);
2385
+ setPaywall(key, value, ttlOverride) {
2386
+ this.setCached(this.paywallCache, key, value, ttlOverride);
2462
2387
  this.evictExpiredEntries(this.paywallCache);
2463
2388
  }
2464
2389
  getStalePaywall(key) {
@@ -2484,16 +2409,15 @@ var ApiCache = class {
2484
2409
  var SDK_VERSION = "1.0.0";
2485
2410
  var DEFAULT_BASE_URL = "https://panel.lucasqueiroga.shop";
2486
2411
  var ApiClient = class {
2487
- constructor(appKey, baseUrl, debug = false, environment = "Production", offlineQueueEnabled = true, timeout = 3e4) {
2412
+ constructor(appKey, debug = false, environment = "Production", offlineQueueEnabled = true, timeout = 3e4) {
2488
2413
  this.cache = new ApiCache();
2489
2414
  this.appKey = appKey;
2490
- this.baseUrl = baseUrl ?? DEFAULT_BASE_URL;
2415
+ this.baseUrl = DEFAULT_BASE_URL;
2491
2416
  this.webUrl = deriveWebUrl(this.baseUrl);
2492
2417
  this.debug = debug;
2493
2418
  this.environment = environment;
2494
2419
  this.offlineQueueEnabled = offlineQueueEnabled;
2495
2420
  this.httpClient = new HttpClient(this.baseUrl, { timeout, debug });
2496
- this.log("ApiClient initialized", { baseUrl: this.baseUrl, environment, offlineQueueEnabled });
2497
2421
  }
2498
2422
  // ─── Infrastructure ──────────────────────────────────────────────────────────
2499
2423
  /** Exposed only for QueueProcessor initialization. Prefer get()/post() for requests. */
@@ -2517,7 +2441,6 @@ var ApiClient = class {
2517
2441
  }
2518
2442
  setEnvironment(environment) {
2519
2443
  this.environment = environment;
2520
- this.log("Environment set to:", environment);
2521
2444
  }
2522
2445
  setDebug(debug) {
2523
2446
  this.debug = debug;
@@ -2547,7 +2470,6 @@ var ApiClient = class {
2547
2470
  }
2548
2471
  // ─── Business methods ────────────────────────────────────────────────────────
2549
2472
  async trackEvent(eventName, distinctId, properties, timestamp) {
2550
- this.log("Tracking event:", eventName);
2551
2473
  await this.postWithQueue("/api/v1/events", {
2552
2474
  eventName,
2553
2475
  distinctId,
@@ -2558,7 +2480,6 @@ var ApiClient = class {
2558
2480
  }
2559
2481
  async identify(distinctId, properties, email) {
2560
2482
  await this.postWithQueue("/api/v1/identify", { distinctId, properties: properties ?? {}, email, platform: import_react_native7.Platform.OS }, "identify");
2561
- this.log("Identity updated:", distinctId);
2562
2483
  }
2563
2484
  async startSession(distinctId, sessionId, platform) {
2564
2485
  await this.postWithQueue("/api/v1/sessions/start", {
@@ -2567,12 +2488,10 @@ var ApiClient = class {
2567
2488
  platform: platform ?? import_react_native7.Platform.OS,
2568
2489
  environment: this.environment.toLowerCase()
2569
2490
  }, `session.start:${sessionId}`);
2570
- this.log("Session started:", sessionId);
2571
2491
  return { success: true };
2572
2492
  }
2573
2493
  async endSession(sessionId, durationSeconds) {
2574
2494
  await this.postWithQueue("/api/v1/sessions/end", { sessionId, durationSeconds }, `session.end:${sessionId}`);
2575
- this.log("Session ended:", sessionId);
2576
2495
  return { success: true };
2577
2496
  }
2578
2497
  async getVariant(flagKey, distinctId) {
@@ -2580,15 +2499,18 @@ var ApiClient = class {
2580
2499
  const hit = this.cache.getVariant(key);
2581
2500
  if (hit !== void 0) return hit;
2582
2501
  try {
2583
- const url = new URL(`${this.baseUrl}/api/v1/flags/${flagKey}`);
2584
- url.searchParams.set("distinctId", distinctId);
2585
- const res = await this.get(url.toString());
2502
+ const res = await this.get(`/api/v1/flags/${flagKey}?distinctId=${encodeURIComponent(distinctId)}`);
2586
2503
  if (res.status === 404) {
2587
2504
  const v = { variant: null };
2588
- this.cache.setVariant(key, v);
2505
+ this.cache.setVariant(key, v, this.cache.nullTTL);
2589
2506
  return v;
2590
2507
  }
2591
- this.log("Got variant:", flagKey, res.data);
2508
+ if (!res.ok) {
2509
+ this.log("Non-OK response for variant:", flagKey, res.status);
2510
+ const stale = this.cache.getStaleVariant(key);
2511
+ if (stale !== void 0) return stale;
2512
+ return { variant: null };
2513
+ }
2592
2514
  this.cache.setVariant(key, res.data);
2593
2515
  return res.data;
2594
2516
  } catch (error) {
@@ -2604,10 +2526,15 @@ var ApiClient = class {
2604
2526
  try {
2605
2527
  const res = await this.get(`/api/v1/paywalls/${placement}`);
2606
2528
  if (res.status === 404) {
2607
- this.cache.setPaywall(placement, null);
2529
+ this.cache.setPaywall(placement, null, this.cache.nullTTL);
2530
+ return null;
2531
+ }
2532
+ if (!res.ok) {
2533
+ this.log("Non-OK response for paywall:", placement, res.status);
2534
+ const stale = this.cache.getStalePaywall(placement);
2535
+ if (stale !== void 0) return stale;
2608
2536
  return null;
2609
2537
  }
2610
- this.log("Got paywall:", placement);
2611
2538
  this.cache.setPaywall(placement, res.data);
2612
2539
  return res.data;
2613
2540
  } catch (error) {
@@ -2656,8 +2583,7 @@ var ApiClient = class {
2656
2583
  country,
2657
2584
  distinctId,
2658
2585
  paywallPlacement,
2659
- variantKey,
2660
- this.debug
2586
+ variantKey
2661
2587
  );
2662
2588
  this.log("Purchase validated:", result.success);
2663
2589
  return result;
@@ -2672,6 +2598,10 @@ var ApiClient = class {
2672
2598
  const url = buildConditionalFlagUrl(this.baseUrl, flagKey, context);
2673
2599
  const response = await this.get(url);
2674
2600
  if (response.status === 404) return { value: false, flagKey };
2601
+ if (!response.ok) {
2602
+ this.log("Non-OK response for conditional flag:", flagKey, response.status);
2603
+ return { value: false, flagKey };
2604
+ }
2675
2605
  this.log("Got conditional flag:", flagKey, response.data.value);
2676
2606
  return { value: response.data.value, flagKey };
2677
2607
  } catch {
@@ -2703,7 +2633,7 @@ var ApiClient = class {
2703
2633
  }
2704
2634
  }
2705
2635
  log(...args) {
2706
- if (this.debug) console.warn("[Panel API]", ...args);
2636
+ if (this.debug) console.warn("[Paywallo API]", ...args);
2707
2637
  }
2708
2638
  };
2709
2639
 
@@ -3029,7 +2959,6 @@ var SessionManager = class {
3029
2959
  this.setupAppStateListener();
3030
2960
  }
3031
2961
  this.initialized = true;
3032
- this.log("SessionManager initialized");
3033
2962
  }
3034
2963
  async startSession() {
3035
2964
  this.ensureInitialized();
@@ -3045,7 +2974,6 @@ var SessionManager = class {
3045
2974
  this.secureStorage.remove(EMERGENCY_PAYWALL_SHOWN_KEY)
3046
2975
  ]);
3047
2976
  await this.trackSessionStart();
3048
- this.log("Session started:", this.sessionId);
3049
2977
  return this.sessionId;
3050
2978
  }
3051
2979
  async endSession() {
@@ -3060,7 +2988,6 @@ var SessionManager = class {
3060
2988
  this.secureStorage.remove(SESSION_ID_KEY),
3061
2989
  this.secureStorage.remove(SESSION_START_KEY)
3062
2990
  ]);
3063
- this.log("Session ended");
3064
2991
  }
3065
2992
  getSessionId() {
3066
2993
  return this.sessionId;
@@ -3195,6 +3122,13 @@ var InstallTracker = class {
3195
3122
  const storage = new SecureStorage(this.debug);
3196
3123
  const alreadyTracked = await storage.get("install_tracked");
3197
3124
  if (alreadyTracked) return;
3125
+ let fallbackTracked = null;
3126
+ try {
3127
+ const AsyncStorage3 = (await import("@react-native-async-storage/async-storage")).default;
3128
+ fallbackTracked = await AsyncStorage3.getItem("@paywallo:install_tracked");
3129
+ } catch {
3130
+ }
3131
+ if (fallbackTracked) return;
3198
3132
  const distinctId = identityManager.getDistinctId();
3199
3133
  const sessionId = sessionManager.getSessionId();
3200
3134
  const installedAt = Date.now();
@@ -3256,12 +3190,13 @@ var InstallTracker = class {
3256
3190
  attStatus: adIds.attStatus
3257
3191
  });
3258
3192
  const stored = await storage.set("install_tracked", String(installedAt));
3259
- if (this.debug) {
3260
- if (stored) {
3261
- console.warn("[Paywallo] Install event tracked");
3262
- } else {
3263
- console.warn("[Paywallo] Install event tracked but flag storage failed \u2014 may re-track on next launch");
3264
- }
3193
+ try {
3194
+ const AsyncStorage3 = (await import("@react-native-async-storage/async-storage")).default;
3195
+ await AsyncStorage3.setItem("@paywallo:install_tracked", String(installedAt));
3196
+ } catch {
3197
+ }
3198
+ if (this.debug && !stored) {
3199
+ console.warn("[Paywallo] Install event tracked but flag storage failed \u2014 may re-track on next launch");
3265
3200
  }
3266
3201
  } catch (error) {
3267
3202
  if (this.debug) {
@@ -3276,7 +3211,7 @@ function isValidEventName(name) {
3276
3211
  if (name.startsWith("$")) return /^\$[a-z][a-z0-9]*(_[a-z0-9]+)*$/.test(name);
3277
3212
  return /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/.test(name);
3278
3213
  }
3279
- var PaywalloClientClass = class {
3214
+ var _PaywalloClientClass = class _PaywalloClientClass {
3280
3215
  constructor() {
3281
3216
  this.config = null;
3282
3217
  this.apiClient = null;
@@ -3287,45 +3222,121 @@ var PaywalloClientClass = class {
3287
3222
  this.activeChecker = null;
3288
3223
  this.restoreHandler = null;
3289
3224
  this.lastOnboardingStepTimestamp = null;
3225
+ this.pendingConfig = null;
3226
+ this.networkCleanup = null;
3227
+ this.initAttempts = 0;
3290
3228
  }
3291
3229
  async init(config) {
3292
- if (this.config && this.apiClient) return;
3230
+ console.warn("[Paywallo INIT]", "init() called \u2014 appKey:", config.appKey ? config.appKey.substring(0, 8) + "..." : "MISSING");
3231
+ if (this.config && this.apiClient) {
3232
+ console.warn("[Paywallo INIT]", "Already initialized \u2014 skipping");
3233
+ return;
3234
+ }
3293
3235
  if (this.initPromise) {
3236
+ console.warn("[Paywallo INIT]", "Init already in progress \u2014 awaiting...");
3294
3237
  await this.initPromise;
3238
+ console.warn("[Paywallo INIT]", "Awaited existing init \u2014 done");
3295
3239
  return;
3296
3240
  }
3297
3241
  if (!config.appKey) throw new ClientError(CLIENT_ERROR_CODES.MISSING_APP_KEY, "appKey is required");
3298
- this.initPromise = this.doInit(config);
3242
+ console.warn("[Paywallo INIT]", "Starting fresh init...");
3243
+ this.pendingConfig = config;
3244
+ this.initAttempts = 0;
3245
+ this.initPromise = this.initWithRetry(config);
3299
3246
  try {
3300
3247
  await this.initPromise;
3248
+ console.warn("[Paywallo INIT]", "init() SUCCESS");
3301
3249
  } catch (error) {
3250
+ console.warn("[Paywallo INIT]", "init() FAILED:", error instanceof Error ? error.message : String(error));
3302
3251
  this.initPromise = null;
3303
3252
  this.config = null;
3304
3253
  this.apiClient = null;
3254
+ this.reportInitFailure(config, error, "ALL_RETRIES_EXHAUSTED");
3255
+ this.setupNetworkRecovery(config);
3256
+ throw error;
3257
+ }
3258
+ }
3259
+ async initWithRetry(config) {
3260
+ while (this.initAttempts <= _PaywalloClientClass.MAX_INIT_RETRIES) {
3305
3261
  try {
3306
- const tempClient = new ApiClient(config.appKey, config.baseUrl, config.debug);
3307
- void tempClient.reportError("INIT_FAILED", error instanceof Error ? error.message : String(error));
3308
- } catch {
3262
+ await this.doInit(config);
3263
+ if (this.initAttempts > 0) {
3264
+ this.reportInitSuccess(config, this.initAttempts);
3265
+ }
3266
+ this.cleanupNetworkRecovery();
3267
+ this.pendingConfig = null;
3268
+ return;
3269
+ } catch (error) {
3270
+ this.initAttempts++;
3271
+ if (this.initAttempts > _PaywalloClientClass.MAX_INIT_RETRIES) throw error;
3272
+ const delay = _PaywalloClientClass.RETRY_DELAYS[this.initAttempts - 1] ?? 1e4;
3273
+ if (config.debug) console.warn("[Paywallo]", `Init attempt ${this.initAttempts} failed, retrying in ${delay}ms`, error);
3274
+ await new Promise((resolve) => setTimeout(resolve, delay));
3309
3275
  }
3310
- throw error;
3276
+ }
3277
+ }
3278
+ setupNetworkRecovery(config) {
3279
+ if (this.networkCleanup) return;
3280
+ if (!networkMonitor.isInitialized()) return;
3281
+ this.networkCleanup = networkMonitor.addListener((state) => {
3282
+ if (state !== "online") return;
3283
+ if (this.config && this.apiClient) return;
3284
+ if (config.debug) console.warn("[Paywallo]", "Network recovered \u2014 retrying init");
3285
+ this.initPromise = this.initWithRetry(config);
3286
+ this.initPromise.then(() => {
3287
+ if (config.debug) console.warn("[Paywallo]", "Init succeeded after network recovery");
3288
+ }).catch(() => {
3289
+ this.reportInitFailure(config, null, "NETWORK_RECOVERY_FAILED");
3290
+ });
3291
+ });
3292
+ }
3293
+ cleanupNetworkRecovery() {
3294
+ if (this.networkCleanup) {
3295
+ this.networkCleanup();
3296
+ this.networkCleanup = null;
3297
+ }
3298
+ }
3299
+ reportInitFailure(config, error, reason) {
3300
+ try {
3301
+ const tempClient = new ApiClient(config.appKey, config.debug);
3302
+ void tempClient.reportError("INIT_FAILED", reason, {
3303
+ attempts: this.initAttempts,
3304
+ error: error instanceof Error ? error.message : String(error)
3305
+ });
3306
+ } catch {
3307
+ }
3308
+ }
3309
+ reportInitSuccess(config, attempts) {
3310
+ try {
3311
+ if (this.apiClient) {
3312
+ void this.apiClient.reportError("INIT_RECOVERED", `Succeeded after ${attempts} retries`, { attempts });
3313
+ }
3314
+ } catch {
3311
3315
  }
3312
3316
  }
3313
3317
  async doInit(config) {
3314
3318
  const environment = config.environment ?? (typeof __DEV__ !== "undefined" && __DEV__ ? "Sandbox" : "Production");
3315
3319
  const offlineQueueEnabled = config.offlineQueueEnabled !== false;
3320
+ console.warn("[Paywallo INIT]", "Step 1: networkMonitor + offlineQueue...");
3316
3321
  await Promise.all([
3317
3322
  networkMonitor.initialize({ debug: config.debug }),
3318
3323
  offlineQueue.initialize({ debug: config.debug }).then(
3319
3324
  () => offlineQueue.clearItemsWithInvalidAppKey(config.appKey)
3320
3325
  )
3321
3326
  ]);
3322
- this.apiClient = new ApiClient(config.appKey, config.baseUrl, config.debug, environment, offlineQueueEnabled, config.timeout);
3327
+ console.warn("[Paywallo INIT]", "Step 1 DONE");
3328
+ console.warn("[Paywallo INIT]", "Step 2: ApiClient + queueProcessor + affiliate...");
3329
+ this.apiClient = new ApiClient(config.appKey, config.debug, environment, offlineQueueEnabled, config.timeout);
3323
3330
  queueProcessor.initialize(this.apiClient.getHttpClient(), { debug: config.debug });
3324
3331
  affiliateManager.initialize(this.apiClient, config.debug);
3332
+ console.warn("[Paywallo INIT]", "Step 2 DONE");
3333
+ console.warn("[Paywallo INIT]", "Step 3: identityManager + sessionManager...");
3325
3334
  await Promise.all([
3326
3335
  identityManager.initialize(this.apiClient, config.debug),
3327
3336
  sessionManager.initialize(this.apiClient, config.sessionConfig, config.debug)
3328
3337
  ]);
3338
+ const distinctId = identityManager.getDistinctId();
3339
+ console.warn("[Paywallo INIT]", "Step 3 DONE \u2014 distinctId:", distinctId ? distinctId.substring(0, 8) + "..." : "EMPTY");
3329
3340
  if (config.autoStartSession !== false) {
3330
3341
  sessionManager.startSession().catch(() => {
3331
3342
  if (config.debug) console.warn("[Paywallo]", "Session start failed during init \u2014 continuing");
@@ -3334,6 +3345,7 @@ var PaywalloClientClass = class {
3334
3345
  new InstallTracker(config.debug).trackIfNeeded(this.apiClient, config.requestATT === true).catch(() => {
3335
3346
  });
3336
3347
  this.config = config;
3348
+ console.warn("[Paywallo INIT]", "COMPLETE \u2014 SDK ready, environment:", environment);
3337
3349
  }
3338
3350
  async identify(options) {
3339
3351
  this.ensureInitialized();
@@ -3343,15 +3355,33 @@ var PaywalloClientClass = class {
3343
3355
  const apiClient = this.getApiClientOrThrow();
3344
3356
  const distinctId = identityManager.getDistinctId();
3345
3357
  if (!distinctId) {
3346
- if (this.config?.debug) console.warn("[Paywallo] Skipping event \u2014 no distinctId available");
3358
+ console.warn("[Paywallo TRACK]", "SKIPPED \u2014 no distinctId", eventName);
3347
3359
  return;
3348
3360
  }
3349
3361
  if (!isValidEventName(eventName)) {
3350
3362
  const msg = `Invalid event name: "${eventName}". Use snake_case or $reserved_name.`;
3351
- if (this.config?.debug) console.warn("[Paywallo]", msg);
3352
3363
  throw new ClientError(CLIENT_ERROR_CODES.INVALID_EVENT_NAME, msg);
3353
3364
  }
3354
3365
  const sessionId = sessionManager.getSessionId();
3366
+ if (eventName === "$purchase_completed") {
3367
+ console.warn("[Paywallo PURCHASE]", "tracking purchase:", JSON.stringify({
3368
+ distinctId: distinctId.substring(0, 8) + "...",
3369
+ productId: options?.properties?.productId,
3370
+ priceUsd: options?.properties?.priceUsd,
3371
+ price: options?.properties?.price,
3372
+ currency: options?.properties?.currency,
3373
+ placement: options?.properties?.placement
3374
+ }));
3375
+ } else if (eventName === "$paywall_viewed" || eventName === "$paywall_closed") {
3376
+ console.warn("[Paywallo PAYWALL]", eventName, JSON.stringify({
3377
+ distinctId: distinctId.substring(0, 8) + "...",
3378
+ placement: options?.properties?.placement,
3379
+ variantKey: options?.properties?.variantKey,
3380
+ timeOnPaywall: options?.properties?.timeOnPaywall
3381
+ }));
3382
+ } else {
3383
+ console.warn("[Paywallo TRACK]", eventName, "distinctId:", distinctId.substring(0, 8) + "...");
3384
+ }
3355
3385
  await apiClient.trackEvent(eventName, distinctId, {
3356
3386
  ...identityManager.getProperties(),
3357
3387
  ...options?.properties,
@@ -3367,7 +3397,6 @@ var PaywalloClientClass = class {
3367
3397
  }
3368
3398
  if (!Number.isInteger(index) || index < 0) {
3369
3399
  const msg = `Invalid stepIndex: "${index}". Must be a non-negative integer.`;
3370
- if (this.config?.debug) console.warn("[Paywallo]", msg);
3371
3400
  throw new AnalyticsError(ANALYTICS_ERROR_CODES.INVALID_STEP_INDEX, msg);
3372
3401
  }
3373
3402
  const now = Date.now();
@@ -3392,7 +3421,6 @@ var PaywalloClientClass = class {
3392
3421
  }
3393
3422
  if (!actionName || typeof actionName !== "string") {
3394
3423
  const msg = `Invalid actionName: "${actionName}". Must be a non-empty string.`;
3395
- if (this.config?.debug) console.warn("[Paywallo]", msg);
3396
3424
  throw new AnalyticsError(ANALYTICS_ERROR_CODES.INVALID_ACTION_NAME, msg);
3397
3425
  }
3398
3426
  const sessionId = sessionManager.getSessionId();
@@ -3404,15 +3432,32 @@ var PaywalloClientClass = class {
3404
3432
  });
3405
3433
  }
3406
3434
  async getVariant(flagKey) {
3407
- const distinctId = identityManager.getDistinctId();
3408
- if (!distinctId) return { variant: null };
3409
- return this.getApiClientOrThrow().getVariant(flagKey, distinctId);
3435
+ try {
3436
+ const distinctId = identityManager.getDistinctId();
3437
+ if (!distinctId) {
3438
+ console.warn("[Paywallo AB]", "getVariant SKIPPED \u2014 no distinctId", flagKey);
3439
+ return { variant: null };
3440
+ }
3441
+ const result = await this.getApiClientOrThrow().getVariant(flagKey, distinctId);
3442
+ console.warn("[Paywallo AB]", `getVariant("${flagKey}") =`, result.variant);
3443
+ return result;
3444
+ } catch (error) {
3445
+ if (this.config?.debug) console.warn("[Paywallo]", "getVariant failed \u2014 returning null", error);
3446
+ if (this.apiClient) void this.apiClient.reportError("GET_VARIANT_FAILED", error instanceof Error ? error.message : String(error));
3447
+ return { variant: null };
3448
+ }
3410
3449
  }
3411
3450
  async getConditionalFlag(flagKey, context) {
3412
- const distinctId = identityManager.getDistinctId();
3413
- if (!distinctId) return false;
3414
- const result = await this.getApiClientOrThrow().getConditionalFlag(flagKey, { distinctId, ...context });
3415
- return result.value;
3451
+ try {
3452
+ const distinctId = identityManager.getDistinctId();
3453
+ if (!distinctId) return false;
3454
+ const result = await this.getApiClientOrThrow().getConditionalFlag(flagKey, { distinctId, ...context });
3455
+ return result.value;
3456
+ } catch (error) {
3457
+ if (this.config?.debug) console.warn("[Paywallo]", "getConditionalFlag failed \u2014 returning false", error);
3458
+ if (this.apiClient) void this.apiClient.reportError("GET_CONDITIONAL_FLAG_FAILED", error instanceof Error ? error.message : String(error));
3459
+ return false;
3460
+ }
3416
3461
  }
3417
3462
  async getPaywall(placement) {
3418
3463
  return this.getApiClientOrThrow().getPaywall(placement);
@@ -3472,9 +3517,12 @@ var PaywalloClientClass = class {
3472
3517
  offlineQueue.dispose();
3473
3518
  networkMonitor.dispose();
3474
3519
  campaignGateService.clearPreloaded();
3520
+ this.cleanupNetworkRecovery();
3475
3521
  this.apiClient = null;
3476
3522
  this.config = null;
3477
3523
  this.initPromise = null;
3524
+ this.pendingConfig = null;
3525
+ this.initAttempts = 0;
3478
3526
  this.paywallPresenter = null;
3479
3527
  this.campaignPresenter = null;
3480
3528
  this.subscriptionGetter = null;
@@ -3590,6 +3638,9 @@ var PaywalloClientClass = class {
3590
3638
  if (!this.config || !this.apiClient) throw new ClientError(CLIENT_ERROR_CODES.NOT_INITIALIZED, "SDK not initialized. Call Paywallo.init() first");
3591
3639
  }
3592
3640
  };
3641
+ _PaywalloClientClass.MAX_INIT_RETRIES = 3;
3642
+ _PaywalloClientClass.RETRY_DELAYS = [2e3, 5e3, 1e4];
3643
+ var PaywalloClientClass = _PaywalloClientClass;
3593
3644
  var PaywalloClient = new PaywalloClientClass();
3594
3645
 
3595
3646
  // src/context/PaywalloContext.ts
@@ -3910,7 +3961,6 @@ var SubscriptionManagerClass = class {
3910
3961
  if (config.cacheTTL) {
3911
3962
  this.cache.setTTL(config.cacheTTL);
3912
3963
  }
3913
- this.log("SubscriptionManager initialized");
3914
3964
  }
3915
3965
  setUserId(userId) {
3916
3966
  if (this.userId !== userId) {
@@ -4243,7 +4293,7 @@ function useProductLoader() {
4243
4293
  for (const p of loaded) map.set(p.productId, p);
4244
4294
  setProducts(map);
4245
4295
  } catch (error) {
4246
- if (PaywalloClient.getConfig()?.debug) console.warn("[Panel] Product load failed:", error);
4296
+ if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] Product load failed:", error);
4247
4297
  } finally {
4248
4298
  setIsLoadingProducts(false);
4249
4299
  }
@@ -4282,7 +4332,7 @@ function usePurchaseOrchestrator(preloadedWebView, resolvePreloadedPaywall, clea
4282
4332
  clearPreloadedWebView();
4283
4333
  resolvePreloadedPaywall({ presented: true, purchased: true, cancelled: false, restored: false });
4284
4334
  } catch (error) {
4285
- if (PaywalloClient.getConfig()?.debug) console.warn("[Panel] Preloaded purchase error:", error);
4335
+ if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] Preloaded purchase error:", error);
4286
4336
  setShowingPreloadedWebView(false);
4287
4337
  clearPreloadedWebView();
4288
4338
  resolvePreloadedPaywall({ presented: true, purchased: false, cancelled: false, restored: false });
@@ -4302,7 +4352,7 @@ function usePurchaseOrchestrator(preloadedWebView, resolvePreloadedPaywall, clea
4302
4352
  clearPreloadedWebView();
4303
4353
  resolvePreloadedPaywall({ presented: true, purchased: false, cancelled: false, restored: true });
4304
4354
  } catch (error) {
4305
- if (PaywalloClient.getConfig()?.debug) console.warn("[Panel] Preloaded restore error:", error);
4355
+ if (PaywalloClient.getConfig()?.debug) console.warn("[Paywallo] Preloaded restore error:", error);
4306
4356
  setShowingPreloadedWebView(false);
4307
4357
  clearPreloadedWebView();
4308
4358
  resolvePreloadedPaywall({ presented: true, purchased: false, cancelled: false, restored: false });