@virex-tech/paywallo-sdk 2.0.2 → 2.2.1
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.d.mts +122 -7
- package/dist/index.d.ts +122 -7
- package/dist/index.js +1170 -617
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1144 -597
- package/dist/index.mjs.map +1 -1
- package/ios/PaywalloDevice.swift +29 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -212,6 +212,9 @@ function isAvailable() {
|
|
|
212
212
|
function clearCache() {
|
|
213
213
|
cachedDeviceInfo = null;
|
|
214
214
|
}
|
|
215
|
+
function getCachedDeviceInfo() {
|
|
216
|
+
return cachedDeviceInfo;
|
|
217
|
+
}
|
|
215
218
|
var import_react_native, FALLBACK, _debug, warnedOnce, cachedDeviceInfo, nativeDeviceInfo;
|
|
216
219
|
var init_NativeDeviceInfo = __esm({
|
|
217
220
|
"src/utils/NativeDeviceInfo.ts"() {
|
|
@@ -239,6 +242,7 @@ var init_NativeDeviceInfo = __esm({
|
|
|
239
242
|
cachedDeviceInfo = null;
|
|
240
243
|
nativeDeviceInfo = {
|
|
241
244
|
getDeviceInfo,
|
|
245
|
+
getCachedDeviceInfo,
|
|
242
246
|
getInstallReferrer,
|
|
243
247
|
isAvailable,
|
|
244
248
|
clearCache
|
|
@@ -499,7 +503,7 @@ var init_IdentityStorage = __esm({
|
|
|
499
503
|
});
|
|
500
504
|
|
|
501
505
|
// src/domains/identity/IdentityManager.ts
|
|
502
|
-
var EMAIL_REGEX, IdentityManager, identityManager;
|
|
506
|
+
var USER_PHONE_KEY, USER_FIRST_NAME_KEY, USER_LAST_NAME_KEY, USER_DOB_KEY, USER_GENDER_KEY, EMAIL_REGEX, IdentityManager, identityManager;
|
|
503
507
|
var init_IdentityManager = __esm({
|
|
504
508
|
"src/domains/identity/IdentityManager.ts"() {
|
|
505
509
|
"use strict";
|
|
@@ -509,6 +513,11 @@ var init_IdentityManager = __esm({
|
|
|
509
513
|
init_SecureStorage();
|
|
510
514
|
init_StorageMigration();
|
|
511
515
|
init_IdentityStorage();
|
|
516
|
+
USER_PHONE_KEY = "@panel:user_phone";
|
|
517
|
+
USER_FIRST_NAME_KEY = "@panel:user_first_name";
|
|
518
|
+
USER_LAST_NAME_KEY = "@panel:user_last_name";
|
|
519
|
+
USER_DOB_KEY = "@panel:user_dob";
|
|
520
|
+
USER_GENDER_KEY = "@panel:user_gender";
|
|
512
521
|
EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
513
522
|
IdentityManager = class {
|
|
514
523
|
constructor() {
|
|
@@ -516,6 +525,11 @@ var init_IdentityManager = __esm({
|
|
|
516
525
|
this.anonId = null;
|
|
517
526
|
this.email = null;
|
|
518
527
|
this.properties = {};
|
|
528
|
+
this.phone = null;
|
|
529
|
+
this.firstName = null;
|
|
530
|
+
this.lastName = null;
|
|
531
|
+
this.dateOfBirth = null;
|
|
532
|
+
this.gender = null;
|
|
519
533
|
this.apiClient = null;
|
|
520
534
|
this.secureStorage = null;
|
|
521
535
|
this.debug = false;
|
|
@@ -571,7 +585,7 @@ var init_IdentityManager = __esm({
|
|
|
571
585
|
let email;
|
|
572
586
|
let properties;
|
|
573
587
|
if (options) {
|
|
574
|
-
if ("email" in options || "properties" in options) {
|
|
588
|
+
if ("email" in options || "properties" in options || "phone" in options || "firstName" in options || "lastName" in options || "dateOfBirth" in options || "gender" in options) {
|
|
575
589
|
email = options.email;
|
|
576
590
|
properties = options.properties;
|
|
577
591
|
} else {
|
|
@@ -591,9 +605,36 @@ var init_IdentityManager = __esm({
|
|
|
591
605
|
this.properties = { ...this.properties, ...properties };
|
|
592
606
|
await this.secureStorage.set(USER_PROPERTIES_KEY, JSON.stringify(this.properties));
|
|
593
607
|
}
|
|
608
|
+
const opts = options;
|
|
609
|
+
if (opts?.phone) {
|
|
610
|
+
this.phone = opts.phone;
|
|
611
|
+
await this.secureStorage.set(USER_PHONE_KEY, this.phone);
|
|
612
|
+
}
|
|
613
|
+
if (opts?.firstName) {
|
|
614
|
+
this.firstName = opts.firstName;
|
|
615
|
+
await this.secureStorage.set(USER_FIRST_NAME_KEY, this.firstName);
|
|
616
|
+
}
|
|
617
|
+
if (opts?.lastName) {
|
|
618
|
+
this.lastName = opts.lastName;
|
|
619
|
+
await this.secureStorage.set(USER_LAST_NAME_KEY, this.lastName);
|
|
620
|
+
}
|
|
621
|
+
if (opts?.dateOfBirth) {
|
|
622
|
+
this.dateOfBirth = opts.dateOfBirth;
|
|
623
|
+
await this.secureStorage.set(USER_DOB_KEY, this.dateOfBirth);
|
|
624
|
+
}
|
|
625
|
+
if (opts?.gender) {
|
|
626
|
+
this.gender = opts.gender;
|
|
627
|
+
await this.secureStorage.set(USER_GENDER_KEY, this.gender);
|
|
628
|
+
}
|
|
594
629
|
if (this.apiClient && this.anonId) {
|
|
595
630
|
try {
|
|
596
|
-
await this.apiClient.identify(this.anonId, properties, email, this.deviceId ?? void 0
|
|
631
|
+
await this.apiClient.identify(this.anonId, properties, email, this.deviceId ?? void 0, {
|
|
632
|
+
phone: this.phone ?? void 0,
|
|
633
|
+
firstName: this.firstName ?? void 0,
|
|
634
|
+
lastName: this.lastName ?? void 0,
|
|
635
|
+
dateOfBirth: this.dateOfBirth ?? void 0,
|
|
636
|
+
gender: this.gender ?? void 0
|
|
637
|
+
});
|
|
597
638
|
} catch {
|
|
598
639
|
}
|
|
599
640
|
}
|
|
@@ -628,17 +669,32 @@ var init_IdentityManager = __esm({
|
|
|
628
669
|
this.distinctId = null;
|
|
629
670
|
this.email = null;
|
|
630
671
|
this.properties = {};
|
|
672
|
+
this.phone = null;
|
|
673
|
+
this.firstName = null;
|
|
674
|
+
this.lastName = null;
|
|
675
|
+
this.dateOfBirth = null;
|
|
676
|
+
this.gender = null;
|
|
631
677
|
await Promise.all([
|
|
632
678
|
this.secureStorage?.set(ANON_ID_KEY, newAnonId) ?? Promise.resolve(false),
|
|
633
679
|
this.secureStorage?.remove(USER_EMAIL_KEY) ?? Promise.resolve(false),
|
|
634
|
-
this.secureStorage?.remove(USER_PROPERTIES_KEY) ?? Promise.resolve(false)
|
|
680
|
+
this.secureStorage?.remove(USER_PROPERTIES_KEY) ?? Promise.resolve(false),
|
|
681
|
+
this.secureStorage?.remove(USER_PHONE_KEY) ?? Promise.resolve(false),
|
|
682
|
+
this.secureStorage?.remove(USER_FIRST_NAME_KEY) ?? Promise.resolve(false),
|
|
683
|
+
this.secureStorage?.remove(USER_LAST_NAME_KEY) ?? Promise.resolve(false),
|
|
684
|
+
this.secureStorage?.remove(USER_DOB_KEY) ?? Promise.resolve(false),
|
|
685
|
+
this.secureStorage?.remove(USER_GENDER_KEY) ?? Promise.resolve(false)
|
|
635
686
|
]);
|
|
636
687
|
}
|
|
637
688
|
getState() {
|
|
638
689
|
return {
|
|
639
690
|
deviceId: this.deviceId ?? "",
|
|
640
691
|
email: this.email,
|
|
641
|
-
properties: this.getProperties()
|
|
692
|
+
properties: this.getProperties(),
|
|
693
|
+
phone: this.phone,
|
|
694
|
+
firstName: this.firstName,
|
|
695
|
+
lastName: this.lastName,
|
|
696
|
+
dateOfBirth: this.dateOfBirth,
|
|
697
|
+
gender: this.gender
|
|
642
698
|
};
|
|
643
699
|
}
|
|
644
700
|
isSecureStorageAvailable() {
|
|
@@ -663,6 +719,18 @@ var init_IdentityManager = __esm({
|
|
|
663
719
|
if (state.email) this.email = state.email;
|
|
664
720
|
if (state.propertiesJson) this.properties = parseProperties(state.propertiesJson);
|
|
665
721
|
if (state.distinctId) this.distinctId = state.distinctId;
|
|
722
|
+
const [phone, firstName, lastName, dateOfBirth, gender] = await Promise.all([
|
|
723
|
+
this.secureStorage.get(USER_PHONE_KEY),
|
|
724
|
+
this.secureStorage.get(USER_FIRST_NAME_KEY),
|
|
725
|
+
this.secureStorage.get(USER_LAST_NAME_KEY),
|
|
726
|
+
this.secureStorage.get(USER_DOB_KEY),
|
|
727
|
+
this.secureStorage.get(USER_GENDER_KEY)
|
|
728
|
+
]);
|
|
729
|
+
if (phone) this.phone = phone;
|
|
730
|
+
if (firstName) this.firstName = firstName;
|
|
731
|
+
if (lastName) this.lastName = lastName;
|
|
732
|
+
if (dateOfBirth) this.dateOfBirth = dateOfBirth;
|
|
733
|
+
if (gender) this.gender = gender;
|
|
666
734
|
}
|
|
667
735
|
ensureInitialized() {
|
|
668
736
|
if (!this.initialized) {
|
|
@@ -803,7 +871,8 @@ var init_NativeStoreKit = __esm({
|
|
|
803
871
|
);
|
|
804
872
|
}
|
|
805
873
|
const distinctId = identityManager.getDistinctId();
|
|
806
|
-
const
|
|
874
|
+
const rawUuid = distinctId?.startsWith("$paywallo_anon:") ? distinctId.slice("$paywallo_anon:".length) : distinctId;
|
|
875
|
+
const appAccountToken = isValidUUIDv4(rawUuid) ? rawUuid : null;
|
|
807
876
|
if (distinctId && appAccountToken === null) {
|
|
808
877
|
if (PaywalloClient.getConfig()?.debug) console.log("[Paywallo] distinctId is not a valid UUID v4 \u2014 passing null to appAccountToken:", distinctId);
|
|
809
878
|
}
|
|
@@ -2283,6 +2352,7 @@ var init_usePaywallTracking = __esm({
|
|
|
2283
2352
|
// src/domains/paywall/usePaywallActions.ts
|
|
2284
2353
|
function usePaywallActions(placement, paywallConfig, onResult, variantKey, campaignId, openAnim, variantId) {
|
|
2285
2354
|
const [isPurchasing, setIsPurchasing] = (0, import_react2.useState)(false);
|
|
2355
|
+
const isPurchasingRef = (0, import_react2.useRef)(false);
|
|
2286
2356
|
const [isClosing, setIsClosing] = (0, import_react2.useState)(false);
|
|
2287
2357
|
const slideAnim = (0, import_react2.useRef)(new import_react_native7.Animated.Value(0)).current;
|
|
2288
2358
|
const presentedAtRef = (0, import_react2.useRef)(Date.now());
|
|
@@ -2314,6 +2384,7 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
|
|
|
2314
2384
|
}, [isClosing, closeWithReason]);
|
|
2315
2385
|
(0, import_react2.useEffect)(() => {
|
|
2316
2386
|
const sub = import_react_native7.AppState.addEventListener("change", (nextState) => {
|
|
2387
|
+
if (isPurchasingRef.current) return;
|
|
2317
2388
|
if (nextState === "background" || nextState === "inactive") {
|
|
2318
2389
|
closeWithReason("backgrounded");
|
|
2319
2390
|
}
|
|
@@ -2329,6 +2400,7 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
|
|
|
2329
2400
|
const handlePurchase = (0, import_react2.useCallback)(async (productId) => {
|
|
2330
2401
|
if (isPurchasing) return;
|
|
2331
2402
|
setIsPurchasing(true);
|
|
2403
|
+
isPurchasingRef.current = true;
|
|
2332
2404
|
try {
|
|
2333
2405
|
if (paywallConfig) trackProductSelected({ placement, paywallId: paywallConfig.id, productId, variantKey, campaignId, variantId });
|
|
2334
2406
|
const result = await getIAPService().purchase(productId, {
|
|
@@ -2351,12 +2423,14 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
|
|
|
2351
2423
|
} catch (error) {
|
|
2352
2424
|
onResult({ presented: true, purchased: false, cancelled: false, restored: false });
|
|
2353
2425
|
} finally {
|
|
2426
|
+
isPurchasingRef.current = false;
|
|
2354
2427
|
setIsPurchasing(false);
|
|
2355
2428
|
}
|
|
2356
2429
|
}, [isPurchasing, onResult, paywallConfig, placement, trackDismissed, trackProductSelected, trackPurchased, variantKey, campaignId, variantId]);
|
|
2357
2430
|
const handleRestore = (0, import_react2.useCallback)(async () => {
|
|
2358
2431
|
if (isPurchasing) return;
|
|
2359
2432
|
setIsPurchasing(true);
|
|
2433
|
+
isPurchasingRef.current = true;
|
|
2360
2434
|
try {
|
|
2361
2435
|
const transactions = await getIAPService().restore();
|
|
2362
2436
|
if (transactions.length > 0) {
|
|
@@ -2371,6 +2445,7 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
|
|
|
2371
2445
|
} catch (error) {
|
|
2372
2446
|
onResult({ presented: true, purchased: false, cancelled: false, restored: false });
|
|
2373
2447
|
} finally {
|
|
2448
|
+
isPurchasingRef.current = false;
|
|
2374
2449
|
setIsPurchasing(false);
|
|
2375
2450
|
}
|
|
2376
2451
|
}, [isPurchasing, onResult, paywallConfig, placement, trackDismissed, variantKey, campaignId, variantId]);
|
|
@@ -2473,7 +2548,8 @@ function usePaywallLoader(placement, visible, preloadedConfig, preloadedProducts
|
|
|
2473
2548
|
if (!trackingDoneRef.current && !cancelled) {
|
|
2474
2549
|
trackingDoneRef.current = true;
|
|
2475
2550
|
const sessionId = PaywalloClient.getSessionId();
|
|
2476
|
-
|
|
2551
|
+
const distinctId = PaywalloClient.getDistinctId();
|
|
2552
|
+
await apiClient.trackEvent("$paywall_viewed", distinctId, {
|
|
2477
2553
|
placement,
|
|
2478
2554
|
paywallId: config.id,
|
|
2479
2555
|
...sessionId && { sessionId },
|
|
@@ -2481,6 +2557,16 @@ function usePaywallLoader(placement, visible, preloadedConfig, preloadedProducts
|
|
|
2481
2557
|
...campaignId && { campaignId },
|
|
2482
2558
|
...variantId && { variant_id: variantId }
|
|
2483
2559
|
});
|
|
2560
|
+
await apiClient.trackEvent("paywall", distinctId, {
|
|
2561
|
+
type: "open",
|
|
2562
|
+
paywall_id: config.id,
|
|
2563
|
+
placement,
|
|
2564
|
+
opened_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2565
|
+
...sessionId && { sessionId },
|
|
2566
|
+
...variantKey && { variant_key: variantKey },
|
|
2567
|
+
...campaignId && { campaign_id: campaignId },
|
|
2568
|
+
...variantId && { variant_id: variantId }
|
|
2569
|
+
});
|
|
2484
2570
|
}
|
|
2485
2571
|
} catch (err) {
|
|
2486
2572
|
if (cancelled) return;
|
|
@@ -2657,15 +2743,21 @@ var init_paywallScripts = __esm({
|
|
|
2657
2743
|
|
|
2658
2744
|
// src/domains/paywall/PaywallWebView.tsx
|
|
2659
2745
|
function getNativeWebView() {
|
|
2660
|
-
if (
|
|
2746
|
+
if (NativeWebViewComponent) return NativeWebViewComponent;
|
|
2747
|
+
if (nativeWebViewLookupFailed) return null;
|
|
2748
|
+
try {
|
|
2661
2749
|
NativeWebViewComponent = (0, import_react_native9.requireNativeComponent)("PaywalloWebView");
|
|
2750
|
+
return NativeWebViewComponent;
|
|
2751
|
+
} catch {
|
|
2752
|
+
nativeWebViewLookupFailed = true;
|
|
2753
|
+
return null;
|
|
2662
2754
|
}
|
|
2663
|
-
return NativeWebViewComponent;
|
|
2664
2755
|
}
|
|
2665
2756
|
function getWebViewEmitter() {
|
|
2666
|
-
if (
|
|
2667
|
-
|
|
2668
|
-
|
|
2757
|
+
if (webViewEmitter) return webViewEmitter;
|
|
2758
|
+
const mod = import_react_native9.NativeModules.PaywalloWebViewModule;
|
|
2759
|
+
if (!mod) return null;
|
|
2760
|
+
webViewEmitter = new import_react_native9.NativeEventEmitter(mod);
|
|
2669
2761
|
return webViewEmitter;
|
|
2670
2762
|
}
|
|
2671
2763
|
function parseErrorEvent(raw) {
|
|
@@ -2697,6 +2789,14 @@ function PaywallWebView({
|
|
|
2697
2789
|
const onReadyRef = (0, import_react4.useRef)(onReady);
|
|
2698
2790
|
onReadyRef.current = onReady;
|
|
2699
2791
|
const NativeWebView = (0, import_react4.useMemo)(() => getNativeWebView(), []);
|
|
2792
|
+
(0, import_react4.useEffect)(() => {
|
|
2793
|
+
if (!NativeWebView) {
|
|
2794
|
+
onErrorRef.current?.({
|
|
2795
|
+
code: -1,
|
|
2796
|
+
description: "Paywallo native module not linked. Run `pod install` (iOS) or rebuild the Android app."
|
|
2797
|
+
});
|
|
2798
|
+
}
|
|
2799
|
+
}, [NativeWebView]);
|
|
2700
2800
|
const [resolvedWebUrl, setResolvedWebUrl] = (0, import_react4.useState)(
|
|
2701
2801
|
() => webUrlProp ?? PaywalloClient.getWebUrl()
|
|
2702
2802
|
);
|
|
@@ -2788,6 +2888,7 @@ function PaywallWebView({
|
|
|
2788
2888
|
);
|
|
2789
2889
|
(0, import_react4.useEffect)(() => {
|
|
2790
2890
|
const emitter = getWebViewEmitter();
|
|
2891
|
+
if (!emitter) return;
|
|
2791
2892
|
const loadEndSub = emitter.addListener("PaywalloWebViewLoadEnd", () => {
|
|
2792
2893
|
if (!loadEndReceived.current) {
|
|
2793
2894
|
loadEndReceived.current = true;
|
|
@@ -2854,7 +2955,7 @@ function PaywallWebView({
|
|
|
2854
2955
|
if (!paywallDataSent.current) return;
|
|
2855
2956
|
setScriptToInject(buildPurchaseStateScript(isPurchasing));
|
|
2856
2957
|
}, [isPurchasing]);
|
|
2857
|
-
if (!resolvedWebUrl) return null;
|
|
2958
|
+
if (!resolvedWebUrl || !NativeWebView) return null;
|
|
2858
2959
|
const paywallUrl = `${resolvedWebUrl}/paywall/${paywallId}`;
|
|
2859
2960
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native9.View, { style: styles.container, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2860
2961
|
NativeWebView,
|
|
@@ -2868,7 +2969,7 @@ function PaywallWebView({
|
|
|
2868
2969
|
}
|
|
2869
2970
|
) });
|
|
2870
2971
|
}
|
|
2871
|
-
var import_react4, import_react_native9, import_jsx_runtime, NativeWebViewComponent, webViewEmitter, styles;
|
|
2972
|
+
var import_react4, import_react_native9, import_jsx_runtime, NativeWebViewComponent, nativeWebViewLookupFailed, webViewEmitter, styles;
|
|
2872
2973
|
var init_PaywallWebView = __esm({
|
|
2873
2974
|
"src/domains/paywall/PaywallWebView.tsx"() {
|
|
2874
2975
|
"use strict";
|
|
@@ -2879,6 +2980,7 @@ var init_PaywallWebView = __esm({
|
|
|
2879
2980
|
init_paywallScripts();
|
|
2880
2981
|
import_jsx_runtime = require("react/jsx-runtime");
|
|
2881
2982
|
NativeWebViewComponent = null;
|
|
2983
|
+
nativeWebViewLookupFailed = false;
|
|
2882
2984
|
webViewEmitter = null;
|
|
2883
2985
|
styles = import_react_native9.StyleSheet.create({
|
|
2884
2986
|
container: { flex: 1 },
|
|
@@ -3196,7 +3298,8 @@ function usePaywallPresenter(preloadedWebView, setPreloadedWebView) {
|
|
|
3196
3298
|
const apiClient = PaywalloClient.getApiClient();
|
|
3197
3299
|
if (apiClient && preloadedWebView) {
|
|
3198
3300
|
const sessionId = PaywalloClient.getSessionId();
|
|
3199
|
-
|
|
3301
|
+
const distinctId = PaywalloClient.getDistinctId();
|
|
3302
|
+
void apiClient.trackEvent("$paywall_viewed", distinctId, {
|
|
3200
3303
|
placement: preloadedWebView.placement,
|
|
3201
3304
|
paywallId: preloadedWebView.paywallId,
|
|
3202
3305
|
preloaded: true,
|
|
@@ -3206,6 +3309,18 @@ function usePaywallPresenter(preloadedWebView, setPreloadedWebView) {
|
|
|
3206
3309
|
...sessionId && { sessionId }
|
|
3207
3310
|
}).catch(() => {
|
|
3208
3311
|
});
|
|
3312
|
+
void apiClient.trackEvent("paywall", distinctId, {
|
|
3313
|
+
type: "open",
|
|
3314
|
+
paywall_id: preloadedWebView.paywallId,
|
|
3315
|
+
placement: preloadedWebView.placement,
|
|
3316
|
+
opened_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3317
|
+
preloaded: true,
|
|
3318
|
+
...preloadedWebView.variantKey && { variant_key: preloadedWebView.variantKey },
|
|
3319
|
+
...preloadedWebView.campaignId && { campaign_id: preloadedWebView.campaignId },
|
|
3320
|
+
...preloadedWebView.variantId && { variant_id: preloadedWebView.variantId },
|
|
3321
|
+
...sessionId && { sessionId }
|
|
3322
|
+
}).catch(() => {
|
|
3323
|
+
});
|
|
3209
3324
|
}
|
|
3210
3325
|
});
|
|
3211
3326
|
}, [preloadedWebView]);
|
|
@@ -3300,6 +3415,8 @@ var init_CampaignGateService = __esm({
|
|
|
3300
3415
|
constructor() {
|
|
3301
3416
|
this.preloadedCampaigns = /* @__PURE__ */ new Map();
|
|
3302
3417
|
this.pendingPreloads = /* @__PURE__ */ new Set();
|
|
3418
|
+
this.apiClientRef = null;
|
|
3419
|
+
this.STALE_THRESHOLD = 0.8;
|
|
3303
3420
|
this.activePreloadPromises = /* @__PURE__ */ new Map();
|
|
3304
3421
|
}
|
|
3305
3422
|
async getCampaign(apiClient, placement, context) {
|
|
@@ -3382,12 +3499,29 @@ var init_CampaignGateService = __esm({
|
|
|
3382
3499
|
getPreloadedCampaign(placement) {
|
|
3383
3500
|
const cached = this.preloadedCampaigns.get(placement);
|
|
3384
3501
|
if (!cached) return null;
|
|
3385
|
-
|
|
3502
|
+
const age = Date.now() - cached.preloadedAt;
|
|
3503
|
+
if (age >= PRELOAD_CACHE_TTL_MS) {
|
|
3386
3504
|
this.preloadedCampaigns.delete(placement);
|
|
3387
3505
|
return null;
|
|
3388
3506
|
}
|
|
3507
|
+
if (age >= PRELOAD_CACHE_TTL_MS * this.STALE_THRESHOLD && this.apiClientRef) {
|
|
3508
|
+
void this.preloadCampaign(this.apiClientRef, placement).catch(() => {
|
|
3509
|
+
});
|
|
3510
|
+
}
|
|
3389
3511
|
return cached.campaign;
|
|
3390
3512
|
}
|
|
3513
|
+
async preloadAllActive(apiClient, debug) {
|
|
3514
|
+
this.apiClientRef = apiClient;
|
|
3515
|
+
const placements = await apiClient.getActivePlacements();
|
|
3516
|
+
if (placements.length === 0) return;
|
|
3517
|
+
if (debug) console.log(`[Paywallo PRELOAD] auto-preloading ${placements.length} placements`);
|
|
3518
|
+
for (let i = 0; i < placements.length; i++) {
|
|
3519
|
+
if (i > 0) await new Promise((r) => setTimeout(r, 500));
|
|
3520
|
+
void this.preloadCampaign(apiClient, placements[i]).catch((err) => {
|
|
3521
|
+
if (debug) console.log(`[Paywallo PRELOAD] failed ${placements[i]}:`, err);
|
|
3522
|
+
});
|
|
3523
|
+
}
|
|
3524
|
+
}
|
|
3391
3525
|
clearPreloaded() {
|
|
3392
3526
|
this.preloadedCampaigns.clear();
|
|
3393
3527
|
this.pendingPreloads.clear();
|
|
@@ -3407,7 +3541,7 @@ var init_campaign = __esm({
|
|
|
3407
3541
|
});
|
|
3408
3542
|
|
|
3409
3543
|
// src/domains/identity/AdvertisingIdManager.ts
|
|
3410
|
-
var import_react_native11, ZERO_IDFA, AdvertisingIdManager;
|
|
3544
|
+
var import_react_native11, ZERO_IDFA, AdvertisingIdManager, advertisingIdManager;
|
|
3411
3545
|
var init_AdvertisingIdManager = __esm({
|
|
3412
3546
|
"src/domains/identity/AdvertisingIdManager.ts"() {
|
|
3413
3547
|
"use strict";
|
|
@@ -3418,6 +3552,14 @@ var init_AdvertisingIdManager = __esm({
|
|
|
3418
3552
|
constructor() {
|
|
3419
3553
|
this.cached = null;
|
|
3420
3554
|
}
|
|
3555
|
+
/**
|
|
3556
|
+
* Synchronous accessor for the cached collect() result. Returns null until
|
|
3557
|
+
* `collect()` resolves at least once. Used by the V2 envelope context
|
|
3558
|
+
* provider — which is sync — to populate `context.ids` without awaiting.
|
|
3559
|
+
*/
|
|
3560
|
+
getCached() {
|
|
3561
|
+
return this.cached;
|
|
3562
|
+
}
|
|
3421
3563
|
async collect(requestATT = false) {
|
|
3422
3564
|
if (this.cached) return this.cached;
|
|
3423
3565
|
const fallback = { idfv: null, idfa: null, gaid: null, attStatus: "unavailable" };
|
|
@@ -3468,136 +3610,26 @@ var init_AdvertisingIdManager = __esm({
|
|
|
3468
3610
|
return id;
|
|
3469
3611
|
}
|
|
3470
3612
|
};
|
|
3613
|
+
advertisingIdManager = new AdvertisingIdManager();
|
|
3471
3614
|
}
|
|
3472
3615
|
});
|
|
3473
3616
|
|
|
3474
|
-
// src/domains/
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
NativeBridge = import_react_native12.NativeModules.PaywalloFBBridge ?? null;
|
|
3482
|
-
MetaBridge = class {
|
|
3483
|
-
async getAnonymousID() {
|
|
3484
|
-
if (!NativeBridge) return null;
|
|
3485
|
-
try {
|
|
3486
|
-
let timerId;
|
|
3487
|
-
const timeout = new Promise((resolve) => {
|
|
3488
|
-
timerId = setTimeout(() => resolve(null), TIMEOUT_MS);
|
|
3489
|
-
});
|
|
3490
|
-
const result = await Promise.race([NativeBridge.getAnonymousID(), timeout]);
|
|
3491
|
-
clearTimeout(timerId);
|
|
3492
|
-
return result;
|
|
3493
|
-
} catch {
|
|
3494
|
-
return null;
|
|
3495
|
-
}
|
|
3496
|
-
}
|
|
3497
|
-
async logEvent(name, params = {}) {
|
|
3498
|
-
if (!NativeBridge) return;
|
|
3499
|
-
try {
|
|
3500
|
-
await NativeBridge.logEvent(name, params);
|
|
3501
|
-
} catch (error) {
|
|
3502
|
-
console.warn("[Paywallo:MetaBridge] logEvent failed", { name, error });
|
|
3503
|
-
}
|
|
3504
|
-
}
|
|
3505
|
-
async logPurchase(amount, currency, params = {}) {
|
|
3506
|
-
if (!NativeBridge) return;
|
|
3507
|
-
try {
|
|
3508
|
-
await NativeBridge.logPurchase(amount, currency, params);
|
|
3509
|
-
} catch (error) {
|
|
3510
|
-
console.warn("[Paywallo:MetaBridge] logPurchase failed", { amount, currency, error });
|
|
3511
|
-
}
|
|
3512
|
-
}
|
|
3513
|
-
setUserID(userId) {
|
|
3514
|
-
if (!NativeBridge) return;
|
|
3515
|
-
try {
|
|
3516
|
-
NativeBridge.setUserID(userId);
|
|
3517
|
-
} catch (error) {
|
|
3518
|
-
console.warn("[Paywallo:MetaBridge] setUserID failed", { error });
|
|
3519
|
-
}
|
|
3520
|
-
}
|
|
3521
|
-
flush() {
|
|
3522
|
-
if (!NativeBridge) return;
|
|
3523
|
-
try {
|
|
3524
|
-
NativeBridge.flush();
|
|
3525
|
-
} catch (error) {
|
|
3526
|
-
console.warn("[Paywallo:MetaBridge] flush failed", { error });
|
|
3527
|
-
}
|
|
3528
|
-
}
|
|
3529
|
-
};
|
|
3530
|
-
metaBridge = new MetaBridge();
|
|
3617
|
+
// src/domains/session/distinctIdGuard.ts
|
|
3618
|
+
async function waitForDistinctId(provider, retries = DISTINCT_ID_WAIT_RETRIES, intervalMs = DISTINCT_ID_WAIT_INTERVAL_MS) {
|
|
3619
|
+
if (!provider) return true;
|
|
3620
|
+
if (provider()) return true;
|
|
3621
|
+
for (let attempt = 0; attempt < retries; attempt++) {
|
|
3622
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
3623
|
+
if (provider()) return true;
|
|
3531
3624
|
}
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
var
|
|
3536
|
-
|
|
3537
|
-
"src/domains/identity/InstallReferrerManager.ts"() {
|
|
3625
|
+
return false;
|
|
3626
|
+
}
|
|
3627
|
+
var DISTINCT_ID_WAIT_RETRIES, DISTINCT_ID_WAIT_INTERVAL_MS;
|
|
3628
|
+
var init_distinctIdGuard = __esm({
|
|
3629
|
+
"src/domains/session/distinctIdGuard.ts"() {
|
|
3538
3630
|
"use strict";
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
REFERRER_TIMEOUT_MS = 5e3;
|
|
3542
|
-
InstallReferrerManager = class {
|
|
3543
|
-
async getReferrer() {
|
|
3544
|
-
if (import_react_native13.Platform.OS !== "android") {
|
|
3545
|
-
return this.emptyResult();
|
|
3546
|
-
}
|
|
3547
|
-
let timerId;
|
|
3548
|
-
const timeoutPromise = new Promise((resolve) => {
|
|
3549
|
-
timerId = setTimeout(() => resolve(this.emptyResult()), REFERRER_TIMEOUT_MS);
|
|
3550
|
-
});
|
|
3551
|
-
const fetchPromise = this.fetchReferrer();
|
|
3552
|
-
const result = await Promise.race([fetchPromise, timeoutPromise]);
|
|
3553
|
-
clearTimeout(timerId);
|
|
3554
|
-
return result;
|
|
3555
|
-
}
|
|
3556
|
-
async fetchReferrer() {
|
|
3557
|
-
try {
|
|
3558
|
-
const referrer = await nativeDeviceInfo.getInstallReferrer();
|
|
3559
|
-
if (!referrer) return this.emptyResult();
|
|
3560
|
-
const capped = referrer.slice(0, 2048);
|
|
3561
|
-
const params = this.parseReferrer(capped);
|
|
3562
|
-
return {
|
|
3563
|
-
rawReferrer: capped,
|
|
3564
|
-
trackingId: params["tracking_id"] || null,
|
|
3565
|
-
fbclid: params["fbclid"] || null,
|
|
3566
|
-
utmSource: params["utm_source"] || null,
|
|
3567
|
-
utmMedium: params["utm_medium"] || null,
|
|
3568
|
-
utmCampaign: params["utm_campaign"] || null
|
|
3569
|
-
};
|
|
3570
|
-
} catch {
|
|
3571
|
-
return this.emptyResult();
|
|
3572
|
-
}
|
|
3573
|
-
}
|
|
3574
|
-
parseReferrer(referrer) {
|
|
3575
|
-
const result = {};
|
|
3576
|
-
for (const pair of referrer.split("&")) {
|
|
3577
|
-
const eqIndex = pair.indexOf("=");
|
|
3578
|
-
if (eqIndex === -1) continue;
|
|
3579
|
-
try {
|
|
3580
|
-
const key = decodeURIComponent(pair.slice(0, eqIndex).replace(/\+/g, " "));
|
|
3581
|
-
const raw = pair.slice(eqIndex + 1).replace(/\+/g, " ");
|
|
3582
|
-
const value = decodeURIComponent(raw);
|
|
3583
|
-
if (key) result[key] = value;
|
|
3584
|
-
} catch {
|
|
3585
|
-
}
|
|
3586
|
-
}
|
|
3587
|
-
return result;
|
|
3588
|
-
}
|
|
3589
|
-
emptyResult() {
|
|
3590
|
-
return {
|
|
3591
|
-
rawReferrer: null,
|
|
3592
|
-
trackingId: null,
|
|
3593
|
-
fbclid: null,
|
|
3594
|
-
utmSource: null,
|
|
3595
|
-
utmMedium: null,
|
|
3596
|
-
utmCampaign: null
|
|
3597
|
-
};
|
|
3598
|
-
}
|
|
3599
|
-
};
|
|
3600
|
-
installReferrerManager = new InstallReferrerManager();
|
|
3631
|
+
DISTINCT_ID_WAIT_RETRIES = 10;
|
|
3632
|
+
DISTINCT_ID_WAIT_INTERVAL_MS = 100;
|
|
3601
3633
|
}
|
|
3602
3634
|
});
|
|
3603
3635
|
|
|
@@ -3622,25 +3654,6 @@ var init_SessionError = __esm({
|
|
|
3622
3654
|
}
|
|
3623
3655
|
});
|
|
3624
3656
|
|
|
3625
|
-
// src/domains/session/distinctIdGuard.ts
|
|
3626
|
-
async function waitForDistinctId(provider, retries = DISTINCT_ID_WAIT_RETRIES, intervalMs = DISTINCT_ID_WAIT_INTERVAL_MS) {
|
|
3627
|
-
if (!provider) return true;
|
|
3628
|
-
if (provider()) return true;
|
|
3629
|
-
for (let attempt = 0; attempt < retries; attempt++) {
|
|
3630
|
-
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
3631
|
-
if (provider()) return true;
|
|
3632
|
-
}
|
|
3633
|
-
return false;
|
|
3634
|
-
}
|
|
3635
|
-
var DISTINCT_ID_WAIT_RETRIES, DISTINCT_ID_WAIT_INTERVAL_MS;
|
|
3636
|
-
var init_distinctIdGuard = __esm({
|
|
3637
|
-
"src/domains/session/distinctIdGuard.ts"() {
|
|
3638
|
-
"use strict";
|
|
3639
|
-
DISTINCT_ID_WAIT_RETRIES = 10;
|
|
3640
|
-
DISTINCT_ID_WAIT_INTERVAL_MS = 100;
|
|
3641
|
-
}
|
|
3642
|
-
});
|
|
3643
|
-
|
|
3644
3657
|
// src/utils/deviceInfo.ts
|
|
3645
3658
|
var deviceInfo_exports = {};
|
|
3646
3659
|
__export(deviceInfo_exports, {
|
|
@@ -3651,7 +3664,9 @@ async function collectDeviceInfo() {
|
|
|
3651
3664
|
return {
|
|
3652
3665
|
appVersion: result.appVersion,
|
|
3653
3666
|
deviceModel: result.model,
|
|
3654
|
-
osVersion: result.systemVersion
|
|
3667
|
+
osVersion: result.systemVersion,
|
|
3668
|
+
darwinVersion: result.darwinVersion,
|
|
3669
|
+
webkitVersion: result.webkitVersion
|
|
3655
3670
|
};
|
|
3656
3671
|
}
|
|
3657
3672
|
var init_deviceInfo = __esm({
|
|
@@ -3719,11 +3734,11 @@ var init_sessionTracking = __esm({
|
|
|
3719
3734
|
});
|
|
3720
3735
|
|
|
3721
3736
|
// src/domains/session/SessionManager.ts
|
|
3722
|
-
var
|
|
3737
|
+
var import_react_native12, SESSION_ID_KEY, SESSION_START_KEY, EMERGENCY_PAYWALL_SHOWN_KEY, LEGACY_SESSION_ID_KEY, LEGACY_SESSION_START_KEY, SESSION_TIMEOUT_MS, BACKGROUND_FLUSH_TIMEOUT_MS, SessionManager, sessionManager;
|
|
3723
3738
|
var init_SessionManager = __esm({
|
|
3724
3739
|
"src/domains/session/SessionManager.ts"() {
|
|
3725
3740
|
"use strict";
|
|
3726
|
-
|
|
3741
|
+
import_react_native12 = require("react-native");
|
|
3727
3742
|
init_SessionError();
|
|
3728
3743
|
init_uuid();
|
|
3729
3744
|
init_distinctIdGuard();
|
|
@@ -3882,7 +3897,7 @@ var init_SessionManager = __esm({
|
|
|
3882
3897
|
if (this.appStateSubscription) {
|
|
3883
3898
|
this.appStateSubscription.remove();
|
|
3884
3899
|
}
|
|
3885
|
-
this.appStateSubscription =
|
|
3900
|
+
this.appStateSubscription = import_react_native12.AppState.addEventListener("change", this.handleAppStateChange);
|
|
3886
3901
|
}
|
|
3887
3902
|
async handleForeground() {
|
|
3888
3903
|
const elapsed = this.backgroundTimestamp ? Date.now() - this.backgroundTimestamp : null;
|
|
@@ -3951,57 +3966,6 @@ var init_SessionManager = __esm({
|
|
|
3951
3966
|
}
|
|
3952
3967
|
});
|
|
3953
3968
|
|
|
3954
|
-
// src/domains/identity/InstallIdempotency.ts
|
|
3955
|
-
async function checkAndArmInstallGuard(storage) {
|
|
3956
|
-
const alreadyTracked = await storage.get(INSTALL_KEYS.INSTALL_TRACKED);
|
|
3957
|
-
if (alreadyTracked) return true;
|
|
3958
|
-
let fallbackTracked = null;
|
|
3959
|
-
try {
|
|
3960
|
-
fallbackTracked = await nativeStorage.get(INSTALL_KEYS.LEGACY_INSTALL_TRACKED);
|
|
3961
|
-
} catch {
|
|
3962
|
-
}
|
|
3963
|
-
if (fallbackTracked) return true;
|
|
3964
|
-
await nativeStorage.set(INSTALL_KEYS.INSTALL_SENT, "1");
|
|
3965
|
-
return false;
|
|
3966
|
-
}
|
|
3967
|
-
async function markInstallTracked(storage, installedAt) {
|
|
3968
|
-
await storage.set(INSTALL_KEYS.INSTALL_TRACKED, String(installedAt));
|
|
3969
|
-
try {
|
|
3970
|
-
await nativeStorage.set(INSTALL_KEYS.LEGACY_INSTALL_TRACKED, String(installedAt));
|
|
3971
|
-
} catch {
|
|
3972
|
-
}
|
|
3973
|
-
}
|
|
3974
|
-
async function getOrCreateInstallEventId() {
|
|
3975
|
-
const existing = await nativeStorage.get(INSTALL_KEYS.INSTALL_EVENT_ID);
|
|
3976
|
-
if (existing) return existing;
|
|
3977
|
-
const { generateUUID: generateUUID2 } = await Promise.resolve().then(() => (init_uuid(), uuid_exports));
|
|
3978
|
-
const id = generateUUID2();
|
|
3979
|
-
await nativeStorage.set(INSTALL_KEYS.INSTALL_EVENT_ID, id).catch(() => {
|
|
3980
|
-
});
|
|
3981
|
-
return id;
|
|
3982
|
-
}
|
|
3983
|
-
var INSTALL_KEYS;
|
|
3984
|
-
var init_InstallIdempotency = __esm({
|
|
3985
|
-
"src/domains/identity/InstallIdempotency.ts"() {
|
|
3986
|
-
"use strict";
|
|
3987
|
-
init_NativeStorage();
|
|
3988
|
-
INSTALL_KEYS = {
|
|
3989
|
-
/** Primary flag — set AFTER a successful $app_installed dispatch. */
|
|
3990
|
-
INSTALL_TRACKED: "@panel:install_tracked",
|
|
3991
|
-
/** Legacy fallback flag written by older SDK versions. */
|
|
3992
|
-
LEGACY_INSTALL_TRACKED: "@paywallo:install_tracked",
|
|
3993
|
-
/** Pre-send guard — set BEFORE dispatching to survive concurrent cold-starts. */
|
|
3994
|
-
INSTALL_SENT: "@paywallo:app_installed_sent",
|
|
3995
|
-
/** Stable event ID for backend dedup — generated once, reused on retries. */
|
|
3996
|
-
INSTALL_EVENT_ID: "@panel:install_event_id",
|
|
3997
|
-
/** Deferred match flag — set once iOS fingerprint match succeeds. */
|
|
3998
|
-
DEFERRED_MATCH_DONE: "@panel:deferred_match_done",
|
|
3999
|
-
/** Anonymous ID fallback when FB SDK not available. */
|
|
4000
|
-
ANON_ID: "@panel:anon_id"
|
|
4001
|
-
};
|
|
4002
|
-
}
|
|
4003
|
-
});
|
|
4004
|
-
|
|
4005
3969
|
// src/domains/identity/AttributionTracker.ts
|
|
4006
3970
|
function hasAnyField(data) {
|
|
4007
3971
|
return Object.values(data).some((v) => v !== void 0 && v !== null && v !== "");
|
|
@@ -4073,21 +4037,212 @@ var init_AttributionTracker = __esm({
|
|
|
4073
4037
|
}
|
|
4074
4038
|
});
|
|
4075
4039
|
|
|
4076
|
-
// src/domains/identity/
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4040
|
+
// src/domains/identity/InstallIdempotency.ts
|
|
4041
|
+
async function checkAndArmInstallGuard(storage) {
|
|
4042
|
+
const alreadyTracked = await storage.get(INSTALL_KEYS.INSTALL_TRACKED);
|
|
4043
|
+
if (alreadyTracked) return true;
|
|
4044
|
+
let fallbackTracked = null;
|
|
4045
|
+
try {
|
|
4046
|
+
fallbackTracked = await nativeStorage.get(INSTALL_KEYS.LEGACY_INSTALL_TRACKED);
|
|
4047
|
+
} catch {
|
|
4048
|
+
}
|
|
4049
|
+
if (fallbackTracked) return true;
|
|
4050
|
+
await nativeStorage.set(INSTALL_KEYS.INSTALL_SENT, "1");
|
|
4051
|
+
return false;
|
|
4052
|
+
}
|
|
4053
|
+
async function markInstallTracked(storage, installedAt) {
|
|
4054
|
+
await storage.set(INSTALL_KEYS.INSTALL_TRACKED, String(installedAt));
|
|
4055
|
+
try {
|
|
4056
|
+
await nativeStorage.set(INSTALL_KEYS.LEGACY_INSTALL_TRACKED, String(installedAt));
|
|
4057
|
+
} catch {
|
|
4058
|
+
}
|
|
4059
|
+
}
|
|
4060
|
+
async function getOrCreateInstallEventId() {
|
|
4061
|
+
const existing = await nativeStorage.get(INSTALL_KEYS.INSTALL_EVENT_ID);
|
|
4062
|
+
if (existing) return existing;
|
|
4063
|
+
const { generateUUID: generateUUID2 } = await Promise.resolve().then(() => (init_uuid(), uuid_exports));
|
|
4064
|
+
const id = generateUUID2();
|
|
4065
|
+
await nativeStorage.set(INSTALL_KEYS.INSTALL_EVENT_ID, id).catch(() => {
|
|
4066
|
+
});
|
|
4067
|
+
return id;
|
|
4068
|
+
}
|
|
4069
|
+
var INSTALL_KEYS;
|
|
4070
|
+
var init_InstallIdempotency = __esm({
|
|
4071
|
+
"src/domains/identity/InstallIdempotency.ts"() {
|
|
4072
|
+
"use strict";
|
|
4073
|
+
init_NativeStorage();
|
|
4074
|
+
INSTALL_KEYS = {
|
|
4075
|
+
/** Primary flag — set AFTER a successful $app_installed dispatch. */
|
|
4076
|
+
INSTALL_TRACKED: "@panel:install_tracked",
|
|
4077
|
+
/** Legacy fallback flag written by older SDK versions. */
|
|
4078
|
+
LEGACY_INSTALL_TRACKED: "@paywallo:install_tracked",
|
|
4079
|
+
/** Pre-send guard — set BEFORE dispatching to survive concurrent cold-starts. */
|
|
4080
|
+
INSTALL_SENT: "@paywallo:app_installed_sent",
|
|
4081
|
+
/** Stable event ID for backend dedup — generated once, reused on retries. */
|
|
4082
|
+
INSTALL_EVENT_ID: "@panel:install_event_id",
|
|
4083
|
+
/** Deferred match flag — set once iOS fingerprint match succeeds. */
|
|
4084
|
+
DEFERRED_MATCH_DONE: "@panel:deferred_match_done",
|
|
4085
|
+
/** Anonymous ID fallback when FB SDK not available. */
|
|
4086
|
+
ANON_ID: "@panel:anon_id"
|
|
4087
|
+
};
|
|
4088
|
+
}
|
|
4089
|
+
});
|
|
4090
|
+
|
|
4091
|
+
// src/domains/identity/InstallReferrerManager.ts
|
|
4092
|
+
var import_react_native13, REFERRER_TIMEOUT_MS, InstallReferrerManager, installReferrerManager;
|
|
4093
|
+
var init_InstallReferrerManager = __esm({
|
|
4094
|
+
"src/domains/identity/InstallReferrerManager.ts"() {
|
|
4095
|
+
"use strict";
|
|
4096
|
+
import_react_native13 = require("react-native");
|
|
4097
|
+
init_NativeDeviceInfo();
|
|
4098
|
+
REFERRER_TIMEOUT_MS = 5e3;
|
|
4099
|
+
InstallReferrerManager = class {
|
|
4100
|
+
async getReferrer() {
|
|
4101
|
+
if (import_react_native13.Platform.OS !== "android") {
|
|
4102
|
+
return this.emptyResult();
|
|
4103
|
+
}
|
|
4104
|
+
let timerId;
|
|
4105
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
4106
|
+
timerId = setTimeout(() => resolve(this.emptyResult()), REFERRER_TIMEOUT_MS);
|
|
4107
|
+
});
|
|
4108
|
+
const fetchPromise = this.fetchReferrer();
|
|
4109
|
+
const result = await Promise.race([fetchPromise, timeoutPromise]);
|
|
4110
|
+
clearTimeout(timerId);
|
|
4111
|
+
return result;
|
|
4112
|
+
}
|
|
4113
|
+
async fetchReferrer() {
|
|
4114
|
+
try {
|
|
4115
|
+
const referrer = await nativeDeviceInfo.getInstallReferrer();
|
|
4116
|
+
if (!referrer) return this.emptyResult();
|
|
4117
|
+
const capped = referrer.slice(0, 2048);
|
|
4118
|
+
const params = this.parseReferrer(capped);
|
|
4119
|
+
return {
|
|
4120
|
+
rawReferrer: capped,
|
|
4121
|
+
trackingId: params["tracking_id"] || null,
|
|
4122
|
+
fbclid: params["fbclid"] || null,
|
|
4123
|
+
utmSource: params["utm_source"] || null,
|
|
4124
|
+
utmMedium: params["utm_medium"] || null,
|
|
4125
|
+
utmCampaign: params["utm_campaign"] || null
|
|
4126
|
+
};
|
|
4127
|
+
} catch {
|
|
4128
|
+
return this.emptyResult();
|
|
4129
|
+
}
|
|
4130
|
+
}
|
|
4131
|
+
parseReferrer(referrer) {
|
|
4132
|
+
const result = {};
|
|
4133
|
+
for (const pair of referrer.split("&")) {
|
|
4134
|
+
const eqIndex = pair.indexOf("=");
|
|
4135
|
+
if (eqIndex === -1) continue;
|
|
4136
|
+
try {
|
|
4137
|
+
const key = decodeURIComponent(pair.slice(0, eqIndex).replace(/\+/g, " "));
|
|
4138
|
+
const raw = pair.slice(eqIndex + 1).replace(/\+/g, " ");
|
|
4139
|
+
const value = decodeURIComponent(raw);
|
|
4140
|
+
if (key) result[key] = value;
|
|
4141
|
+
} catch {
|
|
4142
|
+
}
|
|
4143
|
+
}
|
|
4144
|
+
return result;
|
|
4145
|
+
}
|
|
4146
|
+
emptyResult() {
|
|
4147
|
+
return {
|
|
4148
|
+
rawReferrer: null,
|
|
4149
|
+
trackingId: null,
|
|
4150
|
+
fbclid: null,
|
|
4151
|
+
utmSource: null,
|
|
4152
|
+
utmMedium: null,
|
|
4153
|
+
utmCampaign: null
|
|
4154
|
+
};
|
|
4155
|
+
}
|
|
4156
|
+
};
|
|
4157
|
+
installReferrerManager = new InstallReferrerManager();
|
|
4158
|
+
}
|
|
4159
|
+
});
|
|
4160
|
+
|
|
4161
|
+
// src/domains/identity/MetaBridge.ts
|
|
4162
|
+
var import_react_native14, TIMEOUT_MS, NativeBridge, MetaBridge, metaBridge;
|
|
4163
|
+
var init_MetaBridge = __esm({
|
|
4164
|
+
"src/domains/identity/MetaBridge.ts"() {
|
|
4165
|
+
"use strict";
|
|
4166
|
+
import_react_native14 = require("react-native");
|
|
4167
|
+
TIMEOUT_MS = 2e3;
|
|
4168
|
+
NativeBridge = import_react_native14.NativeModules.PaywalloFBBridge ?? null;
|
|
4169
|
+
MetaBridge = class {
|
|
4170
|
+
constructor() {
|
|
4171
|
+
this.cachedAnonId = null;
|
|
4172
|
+
}
|
|
4173
|
+
/** Sync read of the cached anonymous ID. Returns null until `getAnonymousID()` resolves once. */
|
|
4174
|
+
getCachedAnonymousID() {
|
|
4175
|
+
return this.cachedAnonId;
|
|
4176
|
+
}
|
|
4177
|
+
async getAnonymousID() {
|
|
4178
|
+
if (this.cachedAnonId) return this.cachedAnonId;
|
|
4179
|
+
if (!NativeBridge) return null;
|
|
4180
|
+
try {
|
|
4181
|
+
let timerId;
|
|
4182
|
+
const timeout = new Promise((resolve) => {
|
|
4183
|
+
timerId = setTimeout(() => resolve(null), TIMEOUT_MS);
|
|
4184
|
+
});
|
|
4185
|
+
const result = await Promise.race([NativeBridge.getAnonymousID(), timeout]);
|
|
4186
|
+
clearTimeout(timerId);
|
|
4187
|
+
if (result) this.cachedAnonId = result;
|
|
4188
|
+
return result;
|
|
4189
|
+
} catch {
|
|
4190
|
+
return null;
|
|
4191
|
+
}
|
|
4192
|
+
}
|
|
4193
|
+
async logEvent(name, params = {}) {
|
|
4194
|
+
if (!NativeBridge) return;
|
|
4195
|
+
try {
|
|
4196
|
+
await NativeBridge.logEvent(name, params);
|
|
4197
|
+
} catch (error) {
|
|
4198
|
+
console.warn("[Paywallo:MetaBridge] logEvent failed", { name, error });
|
|
4199
|
+
}
|
|
4200
|
+
}
|
|
4201
|
+
async logPurchase(amount, currency, params = {}) {
|
|
4202
|
+
if (!NativeBridge) return;
|
|
4203
|
+
try {
|
|
4204
|
+
await NativeBridge.logPurchase(amount, currency, params);
|
|
4205
|
+
} catch (error) {
|
|
4206
|
+
console.warn("[Paywallo:MetaBridge] logPurchase failed", { amount, currency, error });
|
|
4207
|
+
}
|
|
4208
|
+
}
|
|
4209
|
+
setUserID(userId) {
|
|
4210
|
+
if (!NativeBridge) return;
|
|
4211
|
+
try {
|
|
4212
|
+
NativeBridge.setUserID(userId);
|
|
4213
|
+
} catch (error) {
|
|
4214
|
+
console.warn("[Paywallo:MetaBridge] setUserID failed", { error });
|
|
4215
|
+
}
|
|
4216
|
+
}
|
|
4217
|
+
flush() {
|
|
4218
|
+
if (!NativeBridge) return;
|
|
4219
|
+
try {
|
|
4220
|
+
NativeBridge.flush();
|
|
4221
|
+
} catch (error) {
|
|
4222
|
+
console.warn("[Paywallo:MetaBridge] flush failed", { error });
|
|
4223
|
+
}
|
|
4224
|
+
}
|
|
4225
|
+
};
|
|
4226
|
+
metaBridge = new MetaBridge();
|
|
4227
|
+
}
|
|
4228
|
+
});
|
|
4229
|
+
|
|
4230
|
+
// src/domains/identity/InstallTracker.ts
|
|
4231
|
+
var import_react_native15, InstallTracker;
|
|
4232
|
+
var init_InstallTracker = __esm({
|
|
4233
|
+
"src/domains/identity/InstallTracker.ts"() {
|
|
4234
|
+
"use strict";
|
|
4235
|
+
import_react_native15 = require("react-native");
|
|
4236
|
+
init_SecureStorage();
|
|
4237
|
+
init_NativeDeviceInfo();
|
|
4089
4238
|
init_distinctIdGuard();
|
|
4239
|
+
init_SessionManager();
|
|
4240
|
+
init_AdvertisingIdManager();
|
|
4241
|
+
init_AttributionTracker();
|
|
4242
|
+
init_IdentityManager();
|
|
4090
4243
|
init_InstallIdempotency();
|
|
4244
|
+
init_InstallReferrerManager();
|
|
4245
|
+
init_MetaBridge();
|
|
4091
4246
|
init_AttributionTracker();
|
|
4092
4247
|
InstallTracker = class {
|
|
4093
4248
|
constructor(debug = false, optionsOrManager) {
|
|
@@ -4098,7 +4253,7 @@ var init_InstallTracker = __esm({
|
|
|
4098
4253
|
this.distinctIdProvider = () => identityManager.getDistinctId();
|
|
4099
4254
|
} else {
|
|
4100
4255
|
const opts = optionsOrManager ?? {};
|
|
4101
|
-
this.advertisingIdManager = opts.advertisingIdManager ??
|
|
4256
|
+
this.advertisingIdManager = opts.advertisingIdManager ?? advertisingIdManager;
|
|
4102
4257
|
this.distinctIdProvider = opts.distinctIdProvider ?? (() => identityManager.getDistinctId());
|
|
4103
4258
|
}
|
|
4104
4259
|
}
|
|
@@ -4136,6 +4291,7 @@ var init_InstallTracker = __esm({
|
|
|
4136
4291
|
const screen = import_react_native15.Dimensions.get("screen");
|
|
4137
4292
|
const screenWidth = Math.round(screen.width ?? 0);
|
|
4138
4293
|
const screenHeight = Math.round(screen.height ?? 0);
|
|
4294
|
+
const screenDensity = import_react_native15.PixelRatio.get();
|
|
4139
4295
|
const locale = Intl.DateTimeFormat().resolvedOptions().locale ?? "unknown";
|
|
4140
4296
|
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone ?? "unknown";
|
|
4141
4297
|
const info = await nativeDeviceInfo.getDeviceInfo();
|
|
@@ -4182,6 +4338,7 @@ var init_InstallTracker = __esm({
|
|
|
4182
4338
|
buildNumber,
|
|
4183
4339
|
...screenWidth > 0 && { screenWidth },
|
|
4184
4340
|
...screenHeight > 0 && { screenHeight },
|
|
4341
|
+
...screenDensity > 0 && { screenDensity },
|
|
4185
4342
|
timezone,
|
|
4186
4343
|
locale,
|
|
4187
4344
|
...carrier !== "unknown" && { carrier },
|
|
@@ -4199,6 +4356,16 @@ var init_InstallTracker = __esm({
|
|
|
4199
4356
|
this.advertisingIdManager.collect(requestATT),
|
|
4200
4357
|
getOrCreateInstallEventId()
|
|
4201
4358
|
]);
|
|
4359
|
+
if (referrer.fbclid || referrer.utmSource || referrer.utmMedium || referrer.utmCampaign) {
|
|
4360
|
+
attributionTracker.capture({
|
|
4361
|
+
...referrer.fbclid && { fbclid: referrer.fbclid },
|
|
4362
|
+
...referrer.utmSource && { utmSource: referrer.utmSource },
|
|
4363
|
+
...referrer.utmMedium && { utmMedium: referrer.utmMedium },
|
|
4364
|
+
...referrer.utmCampaign && { utmCampaign: referrer.utmCampaign },
|
|
4365
|
+
...referrer.rawReferrer && { referrer: referrer.rawReferrer }
|
|
4366
|
+
}).catch(() => {
|
|
4367
|
+
});
|
|
4368
|
+
}
|
|
4202
4369
|
let effectiveAnonId = fbAnonId;
|
|
4203
4370
|
if (!effectiveAnonId) {
|
|
4204
4371
|
const stored = await storage.get(INSTALL_KEYS.ANON_ID);
|
|
@@ -4243,7 +4410,7 @@ var init_InstallTracker = __esm({
|
|
|
4243
4410
|
const baseUrl = apiClient.getBaseUrl();
|
|
4244
4411
|
const appKey = apiClient.getAppKey();
|
|
4245
4412
|
const referrer = await installReferrerManager.getReferrer();
|
|
4246
|
-
await fetch(`${baseUrl}/attribution/deferred-match/${appKey}`, {
|
|
4413
|
+
await fetch(`${baseUrl}/sdk/attribution/deferred-match/${appKey}`, {
|
|
4247
4414
|
method: "POST",
|
|
4248
4415
|
headers: { "Content-Type": "application/json", "X-App-Key": appKey },
|
|
4249
4416
|
body: JSON.stringify({
|
|
@@ -4374,6 +4541,9 @@ var init_identity = __esm({
|
|
|
4374
4541
|
});
|
|
4375
4542
|
|
|
4376
4543
|
// src/domains/notifications/bridges/NativePushBridge.ts
|
|
4544
|
+
function isNativePushAvailable() {
|
|
4545
|
+
return !!import_react_native17.NativeModules.PaywalloNotifications;
|
|
4546
|
+
}
|
|
4377
4547
|
function mapStatusToNumber(status) {
|
|
4378
4548
|
switch (status) {
|
|
4379
4549
|
case "granted":
|
|
@@ -4891,6 +5061,16 @@ var init_PermissionManager = __esm({
|
|
|
4891
5061
|
}
|
|
4892
5062
|
});
|
|
4893
5063
|
|
|
5064
|
+
// src/core/constants.ts
|
|
5065
|
+
var DEFAULT_API_URL, DEFAULT_WEB_URL;
|
|
5066
|
+
var init_constants = __esm({
|
|
5067
|
+
"src/core/constants.ts"() {
|
|
5068
|
+
"use strict";
|
|
5069
|
+
DEFAULT_API_URL = "https://panel.lucasqueiroga.shop";
|
|
5070
|
+
DEFAULT_WEB_URL = "https://paywallo.com.br";
|
|
5071
|
+
}
|
|
5072
|
+
});
|
|
5073
|
+
|
|
4894
5074
|
// src/domains/notifications/config.ts
|
|
4895
5075
|
function resolveApiBaseUrl(config) {
|
|
4896
5076
|
if (config.apiBaseUrl) return config.apiBaseUrl;
|
|
@@ -4901,8 +5081,9 @@ var DEFAULT_API_BASE_URL, SANDBOX_API_BASE_URL;
|
|
|
4901
5081
|
var init_config = __esm({
|
|
4902
5082
|
"src/domains/notifications/config.ts"() {
|
|
4903
5083
|
"use strict";
|
|
4904
|
-
|
|
4905
|
-
|
|
5084
|
+
init_constants();
|
|
5085
|
+
DEFAULT_API_BASE_URL = DEFAULT_API_URL;
|
|
5086
|
+
SANDBOX_API_BASE_URL = DEFAULT_API_URL;
|
|
4906
5087
|
}
|
|
4907
5088
|
});
|
|
4908
5089
|
|
|
@@ -4996,6 +5177,9 @@ function mapPermissionStatus2(status) {
|
|
|
4996
5177
|
function detectPlatform2() {
|
|
4997
5178
|
return import_react_native20.Platform.OS === "ios" ? "ios" : "android";
|
|
4998
5179
|
}
|
|
5180
|
+
function detectEnvironment() {
|
|
5181
|
+
return typeof __DEV__ !== "undefined" && __DEV__ ? "sandbox" : "production";
|
|
5182
|
+
}
|
|
4999
5183
|
async function getAppVersion() {
|
|
5000
5184
|
try {
|
|
5001
5185
|
const { collectDeviceInfo: collectDeviceInfo2 } = await Promise.resolve().then(() => (init_deviceInfo(), deviceInfo_exports));
|
|
@@ -5024,8 +5208,8 @@ var init_utils = __esm({
|
|
|
5024
5208
|
// src/core/version.ts
|
|
5025
5209
|
function resolveVersion() {
|
|
5026
5210
|
try {
|
|
5027
|
-
if ("2.
|
|
5028
|
-
return "2.
|
|
5211
|
+
if ("2.2.1") {
|
|
5212
|
+
return "2.2.1";
|
|
5029
5213
|
}
|
|
5030
5214
|
} catch {
|
|
5031
5215
|
}
|
|
@@ -5064,7 +5248,8 @@ async function buildRegistration(token, getDeviceId, getDistinctId) {
|
|
|
5064
5248
|
sdk_version: SDK_VERSION,
|
|
5065
5249
|
deviceId: getDeviceId?.() ?? void 0,
|
|
5066
5250
|
locale: getLocale(),
|
|
5067
|
-
timezone: getTimezone2()
|
|
5251
|
+
timezone: getTimezone2(),
|
|
5252
|
+
environment: detectEnvironment()
|
|
5068
5253
|
};
|
|
5069
5254
|
}
|
|
5070
5255
|
async function registerToken(deps, token) {
|
|
@@ -5106,7 +5291,7 @@ var init_TokenRegistration = __esm({
|
|
|
5106
5291
|
init_utils();
|
|
5107
5292
|
init_version();
|
|
5108
5293
|
FCM_TOKEN_KEY = "@panel:push_token";
|
|
5109
|
-
TOKEN_ENDPOINT = "/push-tokens";
|
|
5294
|
+
TOKEN_ENDPOINT = "/sdk/push-tokens";
|
|
5110
5295
|
}
|
|
5111
5296
|
});
|
|
5112
5297
|
|
|
@@ -5398,58 +5583,400 @@ var init_NotificationsManager = __esm({
|
|
|
5398
5583
|
this.currentToken = null;
|
|
5399
5584
|
}
|
|
5400
5585
|
};
|
|
5401
|
-
notificationsManager = new NotificationsManager();
|
|
5586
|
+
notificationsManager = new NotificationsManager();
|
|
5587
|
+
}
|
|
5588
|
+
});
|
|
5589
|
+
|
|
5590
|
+
// src/domains/notifications/index.ts
|
|
5591
|
+
var init_notifications = __esm({
|
|
5592
|
+
"src/domains/notifications/index.ts"() {
|
|
5593
|
+
"use strict";
|
|
5594
|
+
init_NotificationsManager();
|
|
5595
|
+
init_NativePushBridge();
|
|
5596
|
+
init_NotificationsError();
|
|
5597
|
+
}
|
|
5598
|
+
});
|
|
5599
|
+
|
|
5600
|
+
// src/domains/session/index.ts
|
|
5601
|
+
var init_session = __esm({
|
|
5602
|
+
"src/domains/session/index.ts"() {
|
|
5603
|
+
"use strict";
|
|
5604
|
+
init_SessionManager();
|
|
5605
|
+
init_SessionError();
|
|
5606
|
+
}
|
|
5607
|
+
});
|
|
5608
|
+
|
|
5609
|
+
// src/core/PaywalloState.ts
|
|
5610
|
+
function createPaywalloState() {
|
|
5611
|
+
return {
|
|
5612
|
+
config: null,
|
|
5613
|
+
apiClient: null,
|
|
5614
|
+
initPromise: null,
|
|
5615
|
+
readyPromise: null,
|
|
5616
|
+
resolveReady: null,
|
|
5617
|
+
paywallPresenter: null,
|
|
5618
|
+
campaignPresenter: null,
|
|
5619
|
+
subscriptionGetter: null,
|
|
5620
|
+
activeChecker: null,
|
|
5621
|
+
restoreHandler: null,
|
|
5622
|
+
lastOnboardingStepTimestamp: null,
|
|
5623
|
+
pendingConfig: null,
|
|
5624
|
+
networkCleanup: null,
|
|
5625
|
+
initAttempts: 0,
|
|
5626
|
+
autoPreloadedPlacement: null,
|
|
5627
|
+
autoPreloadPlacementPromise: null,
|
|
5628
|
+
sessionFlagsMap: /* @__PURE__ */ new Map(),
|
|
5629
|
+
pendingIdentifies: []
|
|
5630
|
+
};
|
|
5631
|
+
}
|
|
5632
|
+
var MAX_INIT_RETRIES, RETRY_DELAYS;
|
|
5633
|
+
var init_PaywalloState = __esm({
|
|
5634
|
+
"src/core/PaywalloState.ts"() {
|
|
5635
|
+
"use strict";
|
|
5636
|
+
MAX_INIT_RETRIES = 3;
|
|
5637
|
+
RETRY_DELAYS = [2e3, 5e3, 1e4];
|
|
5638
|
+
}
|
|
5639
|
+
});
|
|
5640
|
+
|
|
5641
|
+
// src/domains/plan/PlanCache.ts
|
|
5642
|
+
var DEFAULT_TTL, PlanCache, planCache;
|
|
5643
|
+
var init_PlanCache = __esm({
|
|
5644
|
+
"src/domains/plan/PlanCache.ts"() {
|
|
5645
|
+
"use strict";
|
|
5646
|
+
DEFAULT_TTL = 5 * 60 * 1e3;
|
|
5647
|
+
PlanCache = class {
|
|
5648
|
+
constructor() {
|
|
5649
|
+
this.cache = null;
|
|
5650
|
+
this.ttl = DEFAULT_TTL;
|
|
5651
|
+
}
|
|
5652
|
+
get() {
|
|
5653
|
+
if (!this.cache) return null;
|
|
5654
|
+
const isStale = Date.now() - this.cache.cachedAt > this.ttl;
|
|
5655
|
+
return { ...this.cache, isStale };
|
|
5656
|
+
}
|
|
5657
|
+
set(data) {
|
|
5658
|
+
this.cache = { data, cachedAt: Date.now(), isStale: false };
|
|
5659
|
+
}
|
|
5660
|
+
invalidate() {
|
|
5661
|
+
this.cache = null;
|
|
5662
|
+
}
|
|
5663
|
+
setTTL(ttl) {
|
|
5664
|
+
this.ttl = ttl;
|
|
5665
|
+
}
|
|
5666
|
+
};
|
|
5667
|
+
planCache = new PlanCache();
|
|
5668
|
+
}
|
|
5669
|
+
});
|
|
5670
|
+
|
|
5671
|
+
// src/domains/plan/PlanError.ts
|
|
5672
|
+
var PlanError, PLAN_ERROR_CODES;
|
|
5673
|
+
var init_PlanError = __esm({
|
|
5674
|
+
"src/domains/plan/PlanError.ts"() {
|
|
5675
|
+
"use strict";
|
|
5676
|
+
init_PaywalloError();
|
|
5677
|
+
PlanError = class extends PaywalloError {
|
|
5678
|
+
constructor(code, message) {
|
|
5679
|
+
super("plan", code, message);
|
|
5680
|
+
this.name = "PlanError";
|
|
5681
|
+
}
|
|
5682
|
+
};
|
|
5683
|
+
PLAN_ERROR_CODES = {
|
|
5684
|
+
NOT_INITIALIZED: "PLAN_NOT_INITIALIZED",
|
|
5685
|
+
FETCH_FAILED: "PLAN_FETCH_FAILED"
|
|
5686
|
+
};
|
|
5687
|
+
}
|
|
5688
|
+
});
|
|
5689
|
+
|
|
5690
|
+
// src/domains/plan/PlanService.ts
|
|
5691
|
+
var PlanService_exports = {};
|
|
5692
|
+
__export(PlanService_exports, {
|
|
5693
|
+
PlanService: () => PlanService,
|
|
5694
|
+
planService: () => planService
|
|
5695
|
+
});
|
|
5696
|
+
function mapProduct(raw) {
|
|
5697
|
+
return {
|
|
5698
|
+
id: raw.id,
|
|
5699
|
+
name: raw.name,
|
|
5700
|
+
description: raw.description,
|
|
5701
|
+
type: raw.type,
|
|
5702
|
+
appleProductId: raw.apple_product_id,
|
|
5703
|
+
googleProductId: raw.google_product_id,
|
|
5704
|
+
billingPeriod: raw.billing_period,
|
|
5705
|
+
trialDays: raw.trial_days,
|
|
5706
|
+
priceUsd: raw.price_usd,
|
|
5707
|
+
regionalPrices: raw.regional_prices,
|
|
5708
|
+
displayOrder: raw.display_order,
|
|
5709
|
+
isActive: raw.is_active
|
|
5710
|
+
};
|
|
5711
|
+
}
|
|
5712
|
+
function mapPlan(raw) {
|
|
5713
|
+
return {
|
|
5714
|
+
id: raw.id,
|
|
5715
|
+
identifier: raw.identifier,
|
|
5716
|
+
name: raw.name,
|
|
5717
|
+
description: raw.description,
|
|
5718
|
+
metadata: raw.metadata,
|
|
5719
|
+
products: raw.products.map(mapProduct)
|
|
5720
|
+
};
|
|
5721
|
+
}
|
|
5722
|
+
var PlanService, planService;
|
|
5723
|
+
var init_PlanService = __esm({
|
|
5724
|
+
"src/domains/plan/PlanService.ts"() {
|
|
5725
|
+
"use strict";
|
|
5726
|
+
init_PlanCache();
|
|
5727
|
+
init_PlanError();
|
|
5728
|
+
PlanService = class {
|
|
5729
|
+
constructor() {
|
|
5730
|
+
this.config = null;
|
|
5731
|
+
this.cache = planCache;
|
|
5732
|
+
}
|
|
5733
|
+
init(config) {
|
|
5734
|
+
this.config = config;
|
|
5735
|
+
}
|
|
5736
|
+
async getCurrentPlan(forceRefresh = false) {
|
|
5737
|
+
if (!forceRefresh) {
|
|
5738
|
+
const cached = this.cache.get();
|
|
5739
|
+
if (cached && !cached.isStale) {
|
|
5740
|
+
const current = cached.data.plans.find(
|
|
5741
|
+
(p) => p.identifier === cached.data.currentIdentifier
|
|
5742
|
+
);
|
|
5743
|
+
return current ?? null;
|
|
5744
|
+
}
|
|
5745
|
+
}
|
|
5746
|
+
return this.fetchCurrentPlan();
|
|
5747
|
+
}
|
|
5748
|
+
async getAllPlans(forceRefresh = false) {
|
|
5749
|
+
if (!forceRefresh) {
|
|
5750
|
+
const cached = this.cache.get();
|
|
5751
|
+
if (cached && !cached.isStale) return cached.data;
|
|
5752
|
+
}
|
|
5753
|
+
return this.fetchAllPlans();
|
|
5754
|
+
}
|
|
5755
|
+
invalidateCache() {
|
|
5756
|
+
this.cache.invalidate();
|
|
5757
|
+
}
|
|
5758
|
+
getApiClient() {
|
|
5759
|
+
if (!this.config) {
|
|
5760
|
+
throw new PlanError(PLAN_ERROR_CODES.NOT_INITIALIZED, "PlanService not initialized. Call Paywallo.init() first");
|
|
5761
|
+
}
|
|
5762
|
+
return this.config.apiClient;
|
|
5763
|
+
}
|
|
5764
|
+
async fetchCurrentPlan() {
|
|
5765
|
+
try {
|
|
5766
|
+
const res = await this.getApiClient().get("/sdk/plans");
|
|
5767
|
+
if (!res.ok) {
|
|
5768
|
+
this.log("fetchCurrentPlan failed", res.status);
|
|
5769
|
+
return null;
|
|
5770
|
+
}
|
|
5771
|
+
const raw = res.data.data.plan;
|
|
5772
|
+
return raw ? mapPlan(raw) : null;
|
|
5773
|
+
} catch (err) {
|
|
5774
|
+
this.log("fetchCurrentPlan error", err);
|
|
5775
|
+
return null;
|
|
5776
|
+
}
|
|
5777
|
+
}
|
|
5778
|
+
async fetchAllPlans() {
|
|
5779
|
+
try {
|
|
5780
|
+
const res = await this.getApiClient().get("/sdk/plans/all");
|
|
5781
|
+
if (!res.ok) {
|
|
5782
|
+
this.log("fetchAllPlans failed", res.status);
|
|
5783
|
+
return { plans: [], currentIdentifier: null };
|
|
5784
|
+
}
|
|
5785
|
+
const result = {
|
|
5786
|
+
plans: res.data.data.plans.map(mapPlan),
|
|
5787
|
+
currentIdentifier: res.data.data.current_identifier
|
|
5788
|
+
};
|
|
5789
|
+
this.cache.set(result);
|
|
5790
|
+
return result;
|
|
5791
|
+
} catch (err) {
|
|
5792
|
+
this.log("fetchAllPlans error", err);
|
|
5793
|
+
return { plans: [], currentIdentifier: null };
|
|
5794
|
+
}
|
|
5795
|
+
}
|
|
5796
|
+
log(...args) {
|
|
5797
|
+
if (this.config?.debug) console.log("[Paywallo Plans]", ...args);
|
|
5798
|
+
}
|
|
5799
|
+
};
|
|
5800
|
+
planService = new PlanService();
|
|
5801
|
+
}
|
|
5802
|
+
});
|
|
5803
|
+
|
|
5804
|
+
// src/domains/plan/index.ts
|
|
5805
|
+
var init_plan = __esm({
|
|
5806
|
+
"src/domains/plan/index.ts"() {
|
|
5807
|
+
"use strict";
|
|
5808
|
+
init_PlanCache();
|
|
5809
|
+
init_PlanService();
|
|
5810
|
+
}
|
|
5811
|
+
});
|
|
5812
|
+
|
|
5813
|
+
// src/domains/onboarding/OnboardingError.ts
|
|
5814
|
+
var OnboardingError, ONBOARDING_ERROR_CODES;
|
|
5815
|
+
var init_OnboardingError = __esm({
|
|
5816
|
+
"src/domains/onboarding/OnboardingError.ts"() {
|
|
5817
|
+
"use strict";
|
|
5818
|
+
init_PaywalloError();
|
|
5819
|
+
OnboardingError = class extends PaywalloError {
|
|
5820
|
+
constructor(code, message) {
|
|
5821
|
+
super("onboarding", code, message);
|
|
5822
|
+
this.name = "OnboardingError";
|
|
5823
|
+
}
|
|
5824
|
+
};
|
|
5825
|
+
ONBOARDING_ERROR_CODES = {
|
|
5826
|
+
NOT_INITIALIZED: "ONBOARDING_NOT_INITIALIZED",
|
|
5827
|
+
INVALID_STEP_NAME: "ONBOARDING_INVALID_STEP_NAME"
|
|
5828
|
+
};
|
|
5829
|
+
}
|
|
5830
|
+
});
|
|
5831
|
+
|
|
5832
|
+
// src/domains/onboarding/OnboardingManager.ts
|
|
5833
|
+
var OnboardingManager, onboardingManager;
|
|
5834
|
+
var init_OnboardingManager = __esm({
|
|
5835
|
+
"src/domains/onboarding/OnboardingManager.ts"() {
|
|
5836
|
+
"use strict";
|
|
5837
|
+
init_OnboardingError();
|
|
5838
|
+
OnboardingManager = class {
|
|
5839
|
+
constructor() {
|
|
5840
|
+
this.pipeline = null;
|
|
5841
|
+
this.debug = false;
|
|
5842
|
+
this.lastStep = null;
|
|
5843
|
+
this.finished = false;
|
|
5844
|
+
}
|
|
5845
|
+
/**
|
|
5846
|
+
* Injects runtime dependencies. Called by PaywalloClient during init.
|
|
5847
|
+
*/
|
|
5848
|
+
injectDeps(config) {
|
|
5849
|
+
this.pipeline = config.pipeline;
|
|
5850
|
+
this.debug = config.debug ?? false;
|
|
5851
|
+
}
|
|
5852
|
+
/**
|
|
5853
|
+
* Tracks an onboarding step view.
|
|
5854
|
+
* Saves the step name internally for implicit drop detection on the backend.
|
|
5855
|
+
*
|
|
5856
|
+
* @param stepName - Unique name for this onboarding step.
|
|
5857
|
+
*/
|
|
5858
|
+
async step(stepName) {
|
|
5859
|
+
this.assertConfig();
|
|
5860
|
+
this.validateStepName(stepName, "step");
|
|
5861
|
+
this.lastStep = stepName;
|
|
5862
|
+
const payload = {
|
|
5863
|
+
family: "onboarding",
|
|
5864
|
+
type: "step",
|
|
5865
|
+
...{ step_name: stepName }
|
|
5866
|
+
};
|
|
5867
|
+
return this.emit("onboarding", payload, "step");
|
|
5868
|
+
}
|
|
5869
|
+
/**
|
|
5870
|
+
* Tracks successful completion of the onboarding flow.
|
|
5871
|
+
* Marks the flow as finished.
|
|
5872
|
+
*/
|
|
5873
|
+
async complete() {
|
|
5874
|
+
this.assertConfig();
|
|
5875
|
+
this.finished = true;
|
|
5876
|
+
return this.emit("onboarding", { family: "onboarding", type: "complete" }, "complete");
|
|
5877
|
+
}
|
|
5878
|
+
/**
|
|
5879
|
+
* Tracks an explicit drop (abandonment) at the given step.
|
|
5880
|
+
* Marks the flow as finished.
|
|
5881
|
+
*
|
|
5882
|
+
* @param stepName - The step name where the user dropped off.
|
|
5883
|
+
*/
|
|
5884
|
+
async drop(stepName) {
|
|
5885
|
+
this.assertConfig();
|
|
5886
|
+
this.validateStepName(stepName, "drop");
|
|
5887
|
+
this.finished = true;
|
|
5888
|
+
const payload = {
|
|
5889
|
+
family: "onboarding",
|
|
5890
|
+
type: "drop",
|
|
5891
|
+
...{ step_name: stepName }
|
|
5892
|
+
};
|
|
5893
|
+
return this.emit("onboarding", payload, "drop");
|
|
5894
|
+
}
|
|
5895
|
+
/** Returns the last step name seen, or null if no step was tracked yet. */
|
|
5896
|
+
getLastStep() {
|
|
5897
|
+
return this.lastStep;
|
|
5898
|
+
}
|
|
5899
|
+
/** Returns whether the flow has been marked as finished (complete or drop). */
|
|
5900
|
+
isFinished() {
|
|
5901
|
+
return this.finished;
|
|
5902
|
+
}
|
|
5903
|
+
async emit(eventName, properties, logLabel) {
|
|
5904
|
+
const pipeline = this.pipeline;
|
|
5905
|
+
const distinctId = pipeline.getDistinctId();
|
|
5906
|
+
if (!distinctId) {
|
|
5907
|
+
if (this.debug) console.log(`[Paywallo:Onboarding] skipped (no distinctId): ${logLabel}`);
|
|
5908
|
+
return;
|
|
5909
|
+
}
|
|
5910
|
+
await pipeline.trackEvent(eventName, distinctId, properties);
|
|
5911
|
+
if (this.debug) {
|
|
5912
|
+
console.log(`[Paywallo:Onboarding] event emitted: ${eventName}.${logLabel}`, properties);
|
|
5913
|
+
}
|
|
5914
|
+
}
|
|
5915
|
+
assertConfig() {
|
|
5916
|
+
if (!this.pipeline) {
|
|
5917
|
+
throw new OnboardingError(
|
|
5918
|
+
ONBOARDING_ERROR_CODES.NOT_INITIALIZED,
|
|
5919
|
+
"OnboardingManager not initialized. Call Paywallo.init() first."
|
|
5920
|
+
);
|
|
5921
|
+
}
|
|
5922
|
+
}
|
|
5923
|
+
validateStepName(stepName, method) {
|
|
5924
|
+
if (typeof stepName !== "string" || stepName.trim().length === 0) {
|
|
5925
|
+
throw new OnboardingError(
|
|
5926
|
+
ONBOARDING_ERROR_CODES.INVALID_STEP_NAME,
|
|
5927
|
+
`OnboardingManager.${method}(): stepName must be a non-empty string.`
|
|
5928
|
+
);
|
|
5929
|
+
}
|
|
5930
|
+
}
|
|
5931
|
+
};
|
|
5932
|
+
onboardingManager = new OnboardingManager();
|
|
5402
5933
|
}
|
|
5403
5934
|
});
|
|
5404
5935
|
|
|
5405
|
-
// src/domains/
|
|
5406
|
-
var
|
|
5407
|
-
"src/domains/
|
|
5936
|
+
// src/domains/onboarding/index.ts
|
|
5937
|
+
var init_onboarding = __esm({
|
|
5938
|
+
"src/domains/onboarding/index.ts"() {
|
|
5408
5939
|
"use strict";
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
init_NotificationsError();
|
|
5940
|
+
init_OnboardingManager();
|
|
5941
|
+
init_OnboardingError();
|
|
5412
5942
|
}
|
|
5413
5943
|
});
|
|
5414
5944
|
|
|
5415
|
-
// src/domains/
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5945
|
+
// src/domains/paywall/paywallHeartbeatRecovery.ts
|
|
5946
|
+
async function recoverPaywallHeartbeat(apiClient, distinctId, sessionId, debug) {
|
|
5947
|
+
const snapshot = await readPersistedHeartbeat();
|
|
5948
|
+
if (!snapshot) return false;
|
|
5949
|
+
try {
|
|
5950
|
+
const closedAt = new Date(snapshot.lastSeen);
|
|
5951
|
+
const durationS = Math.max(0, Math.round((snapshot.lastSeen - snapshot.presentedAt) / 1e3));
|
|
5952
|
+
await apiClient.trackEvent("paywall", distinctId, {
|
|
5953
|
+
type: "closed",
|
|
5954
|
+
paywall_id: snapshot.paywallId,
|
|
5955
|
+
placement: snapshot.placement,
|
|
5956
|
+
closed_at: closedAt.toISOString(),
|
|
5957
|
+
duration_s: durationS,
|
|
5958
|
+
close_reason: "error",
|
|
5959
|
+
...snapshot.variantId && { variant_id: snapshot.variantId },
|
|
5960
|
+
...snapshot.variantKey && { variant_key: snapshot.variantKey },
|
|
5961
|
+
...snapshot.campaignId && { campaign_id: snapshot.campaignId },
|
|
5962
|
+
...sessionId && { sessionId }
|
|
5963
|
+
});
|
|
5964
|
+
if (debug) console.log("[Paywallo HEARTBEAT] recovered orphan paywall close", {
|
|
5965
|
+
paywallId: snapshot.paywallId,
|
|
5966
|
+
durationS
|
|
5967
|
+
});
|
|
5968
|
+
return true;
|
|
5969
|
+
} catch (err) {
|
|
5970
|
+
if (debug) console.log("[Paywallo HEARTBEAT] recovery failed", err);
|
|
5971
|
+
return false;
|
|
5972
|
+
} finally {
|
|
5973
|
+
await clearPersistedHeartbeat();
|
|
5421
5974
|
}
|
|
5422
|
-
});
|
|
5423
|
-
|
|
5424
|
-
// src/core/PaywalloState.ts
|
|
5425
|
-
function createPaywalloState() {
|
|
5426
|
-
return {
|
|
5427
|
-
config: null,
|
|
5428
|
-
apiClient: null,
|
|
5429
|
-
initPromise: null,
|
|
5430
|
-
readyPromise: null,
|
|
5431
|
-
resolveReady: null,
|
|
5432
|
-
paywallPresenter: null,
|
|
5433
|
-
campaignPresenter: null,
|
|
5434
|
-
subscriptionGetter: null,
|
|
5435
|
-
activeChecker: null,
|
|
5436
|
-
restoreHandler: null,
|
|
5437
|
-
lastOnboardingStepTimestamp: null,
|
|
5438
|
-
pendingConfig: null,
|
|
5439
|
-
networkCleanup: null,
|
|
5440
|
-
initAttempts: 0,
|
|
5441
|
-
autoPreloadedPlacement: null,
|
|
5442
|
-
autoPreloadPlacementPromise: null,
|
|
5443
|
-
sessionFlagsMap: /* @__PURE__ */ new Map(),
|
|
5444
|
-
pendingIdentifies: []
|
|
5445
|
-
};
|
|
5446
5975
|
}
|
|
5447
|
-
var
|
|
5448
|
-
|
|
5449
|
-
"src/core/PaywalloState.ts"() {
|
|
5976
|
+
var init_paywallHeartbeatRecovery = __esm({
|
|
5977
|
+
"src/domains/paywall/paywallHeartbeatRecovery.ts"() {
|
|
5450
5978
|
"use strict";
|
|
5451
|
-
|
|
5452
|
-
RETRY_DELAYS = [2e3, 5e3, 1e4];
|
|
5979
|
+
init_paywallHeartbeat();
|
|
5453
5980
|
}
|
|
5454
5981
|
});
|
|
5455
5982
|
|
|
@@ -5457,7 +5984,7 @@ var init_PaywalloState = __esm({
|
|
|
5457
5984
|
function keyFor(distinctId) {
|
|
5458
5985
|
return `${CACHE_KEY_PREFIX}${distinctId}`;
|
|
5459
5986
|
}
|
|
5460
|
-
var LEGACY_CACHE_KEY, CACHE_KEY_PREFIX, CACHE_INDEX_KEY,
|
|
5987
|
+
var LEGACY_CACHE_KEY, CACHE_KEY_PREFIX, CACHE_INDEX_KEY, DEFAULT_TTL2, SubscriptionCache, subscriptionCache;
|
|
5461
5988
|
var init_SubscriptionCache = __esm({
|
|
5462
5989
|
"src/domains/subscription/SubscriptionCache.ts"() {
|
|
5463
5990
|
"use strict";
|
|
@@ -5465,9 +5992,9 @@ var init_SubscriptionCache = __esm({
|
|
|
5465
5992
|
LEGACY_CACHE_KEY = "@panel:subscription_cache";
|
|
5466
5993
|
CACHE_KEY_PREFIX = "subscription_cache:";
|
|
5467
5994
|
CACHE_INDEX_KEY = "subscription_cache:__index__";
|
|
5468
|
-
|
|
5995
|
+
DEFAULT_TTL2 = 24 * 60 * 60 * 1e3;
|
|
5469
5996
|
SubscriptionCache = class {
|
|
5470
|
-
constructor(ttl =
|
|
5997
|
+
constructor(ttl = DEFAULT_TTL2) {
|
|
5471
5998
|
this.memoryCache = /* @__PURE__ */ new Map();
|
|
5472
5999
|
this.legacyCleanupDone = false;
|
|
5473
6000
|
this.ttl = ttl;
|
|
@@ -5674,7 +6201,7 @@ var init_SubscriptionManager = __esm({
|
|
|
5674
6201
|
if (!this.config) {
|
|
5675
6202
|
return this.getEmptyStatus();
|
|
5676
6203
|
}
|
|
5677
|
-
const url = new URL(`${this.config.serverUrl}/purchases/status/${this.config.appKey}`);
|
|
6204
|
+
const url = new URL(`${this.config.serverUrl}/sdk/purchases/status/${this.config.appKey}`);
|
|
5678
6205
|
if (this.userId) {
|
|
5679
6206
|
url.searchParams.set("distinctId", this.userId);
|
|
5680
6207
|
}
|
|
@@ -5758,11 +6285,10 @@ function buildConditionalFlagUrl(baseUrl, flagKey, context) {
|
|
|
5758
6285
|
if (context.distinctId) url.searchParams.set("distinctId", context.distinctId);
|
|
5759
6286
|
return url.toString();
|
|
5760
6287
|
}
|
|
5761
|
-
var DEFAULT_WEB_URL;
|
|
5762
6288
|
var init_apiUrlUtils = __esm({
|
|
5763
6289
|
"src/core/apiUrlUtils.ts"() {
|
|
5764
6290
|
"use strict";
|
|
5765
|
-
|
|
6291
|
+
init_constants();
|
|
5766
6292
|
}
|
|
5767
6293
|
});
|
|
5768
6294
|
|
|
@@ -5915,7 +6441,7 @@ async function getSubscriptionStatus(client, baseUrl, appKey, distinctId) {
|
|
|
5915
6441
|
}
|
|
5916
6442
|
async function getEmergencyPaywall(client) {
|
|
5917
6443
|
try {
|
|
5918
|
-
const response = await client.get("/emergency-paywall");
|
|
6444
|
+
const response = await client.get("/sdk/emergency-paywall");
|
|
5919
6445
|
if (response.status === 404) return { enabled: false };
|
|
5920
6446
|
return response.data;
|
|
5921
6447
|
} catch {
|
|
@@ -6532,7 +7058,7 @@ var init_EventBatcher = __esm({
|
|
|
6532
7058
|
BATCH_MAX_SIZE = 25;
|
|
6533
7059
|
BATCH_FLUSH_MS = 1e4;
|
|
6534
7060
|
EVENT_NAME_REGEX = /^(\$[a-zA-Z0-9_]+|[a-z][a-z0-9_]*)$/;
|
|
6535
|
-
V2_BATCH_ENDPOINT = "/ingest/batch";
|
|
7061
|
+
V2_BATCH_ENDPOINT = "/sdk/ingest/batch";
|
|
6536
7062
|
V1_BATCH_ENDPOINT = "/sdk/events/batch";
|
|
6537
7063
|
V1_SINGLE_ENDPOINT = "/sdk/events";
|
|
6538
7064
|
EventBatcher = class {
|
|
@@ -6896,7 +7422,7 @@ var init_ApiClient = __esm({
|
|
|
6896
7422
|
dispose() {
|
|
6897
7423
|
this.batcher.dispose();
|
|
6898
7424
|
}
|
|
6899
|
-
async identify(distinctId, properties, email, deviceId) {
|
|
7425
|
+
async identify(distinctId, properties, email, deviceId, pii) {
|
|
6900
7426
|
await postWithQueue(
|
|
6901
7427
|
{
|
|
6902
7428
|
isOfflineQueueEnabled: () => this.offlineQueueEnabled,
|
|
@@ -6904,8 +7430,19 @@ var init_ApiClient = __esm({
|
|
|
6904
7430
|
isDebug: () => this.debug,
|
|
6905
7431
|
post: (path, body, skipRetry) => this.post(path, body, skipRetry)
|
|
6906
7432
|
},
|
|
6907
|
-
"/identify",
|
|
6908
|
-
{
|
|
7433
|
+
"/sdk/identify",
|
|
7434
|
+
{
|
|
7435
|
+
distinctId,
|
|
7436
|
+
properties: properties ?? {},
|
|
7437
|
+
email,
|
|
7438
|
+
platform: import_react_native23.Platform.OS,
|
|
7439
|
+
...deviceId && { deviceId },
|
|
7440
|
+
...pii?.phone && { phone: pii.phone },
|
|
7441
|
+
...pii?.firstName && { firstName: pii.firstName },
|
|
7442
|
+
...pii?.lastName && { lastName: pii.lastName },
|
|
7443
|
+
...pii?.dateOfBirth && { dateOfBirth: pii.dateOfBirth },
|
|
7444
|
+
...pii?.gender && { gender: pii.gender }
|
|
7445
|
+
},
|
|
6909
7446
|
"identify"
|
|
6910
7447
|
);
|
|
6911
7448
|
}
|
|
@@ -6930,248 +7467,87 @@ var init_ApiClient = __esm({
|
|
|
6930
7467
|
return stale !== void 0 ? stale : null;
|
|
6931
7468
|
}
|
|
6932
7469
|
this.cache.setPaywall(placement, res.data);
|
|
6933
|
-
return res.data;
|
|
6934
|
-
} catch {
|
|
6935
|
-
const stale = this.cache.getStalePaywall(placement);
|
|
6936
|
-
return stale !== void 0 ? stale : null;
|
|
6937
|
-
}
|
|
6938
|
-
}
|
|
6939
|
-
async getEmergencyPaywall() {
|
|
6940
|
-
return getEmergencyPaywall(this);
|
|
6941
|
-
}
|
|
6942
|
-
async getCampaign(placement, distinctId, context) {
|
|
6943
|
-
const key = `${placement}:${distinctId}`;
|
|
6944
|
-
const hit = this.cache.getCampaign(key);
|
|
6945
|
-
if (hit !== void 0) return hit;
|
|
6946
|
-
try {
|
|
6947
|
-
const result = await getCampaignData(this, this.baseUrl, placement, distinctId, context);
|
|
6948
|
-
if (!result) {
|
|
6949
|
-
this.cache.setCampaign(key, null, this.cache.nullTTL);
|
|
6950
|
-
return null;
|
|
6951
|
-
}
|
|
6952
|
-
this.cache.setCampaign(key, result);
|
|
6953
|
-
return result;
|
|
6954
|
-
} catch {
|
|
6955
|
-
const stale = this.cache.getStaleCampaign(key);
|
|
6956
|
-
return stale !== void 0 ? stale : null;
|
|
6957
|
-
}
|
|
6958
|
-
}
|
|
6959
|
-
async getPrimaryCampaign(distinctId) {
|
|
6960
|
-
const key = `primary:${distinctId}`;
|
|
6961
|
-
const hit = this.cache.getCampaign(key);
|
|
6962
|
-
if (hit !== void 0) return hit;
|
|
6963
|
-
try {
|
|
6964
|
-
const res = await this.get(`/campaigns/public/primary?distinctId=${encodeURIComponent(distinctId)}`);
|
|
6965
|
-
if (res.status === 404) {
|
|
6966
|
-
this.cache.setCampaign(key, null, this.cache.nullTTL);
|
|
6967
|
-
return null;
|
|
6968
|
-
}
|
|
6969
|
-
if (!res.ok) {
|
|
6970
|
-
const stale = this.cache.getStaleCampaign(key);
|
|
6971
|
-
return stale !== void 0 ? stale : null;
|
|
6972
|
-
}
|
|
6973
|
-
this.cache.setCampaign(key, res.data);
|
|
6974
|
-
return res.data;
|
|
6975
|
-
} catch {
|
|
6976
|
-
const stale = this.cache.getStaleCampaign(key);
|
|
6977
|
-
return stale !== void 0 ? stale : null;
|
|
6978
|
-
}
|
|
6979
|
-
}
|
|
6980
|
-
async validatePurchase(platform, receipt, productId, transactionId, priceLocal, currency, country, distinctId, paywallPlacement, variantKey) {
|
|
6981
|
-
return validatePurchase(this, this.appKey, platform, receipt, productId, transactionId, priceLocal, currency, country, distinctId, paywallPlacement, variantKey);
|
|
6982
|
-
}
|
|
6983
|
-
async getSubscriptionStatus(distinctId) {
|
|
6984
|
-
return getSubscriptionStatus(this, this.baseUrl, this.appKey, distinctId);
|
|
6985
|
-
}
|
|
6986
|
-
async evaluateFlags(keys, distinctId) {
|
|
6987
|
-
return evaluateFlags(this.flagDeps(), keys, distinctId);
|
|
6988
|
-
}
|
|
6989
|
-
async getConditionalFlag(flagKey, context) {
|
|
6990
|
-
return getConditionalFlag(this.flagDeps(), flagKey, context);
|
|
6991
|
-
}
|
|
6992
|
-
async getVariantFromCache(flagKey, distinctId) {
|
|
6993
|
-
return getVariantFromCache(this.flagDeps(), flagKey, distinctId);
|
|
6994
|
-
}
|
|
6995
|
-
flagDeps() {
|
|
6996
|
-
return {
|
|
6997
|
-
get: (path) => this.get(path),
|
|
6998
|
-
httpClient: this.httpClient,
|
|
6999
|
-
cache: this.cache,
|
|
7000
|
-
appKey: this.appKey,
|
|
7001
|
-
baseUrl: this.baseUrl
|
|
7002
|
-
};
|
|
7003
|
-
}
|
|
7004
|
-
};
|
|
7005
|
-
}
|
|
7006
|
-
});
|
|
7007
|
-
|
|
7008
|
-
// src/domains/onboarding/OnboardingError.ts
|
|
7009
|
-
var OnboardingError, ONBOARDING_ERROR_CODES;
|
|
7010
|
-
var init_OnboardingError = __esm({
|
|
7011
|
-
"src/domains/onboarding/OnboardingError.ts"() {
|
|
7012
|
-
"use strict";
|
|
7013
|
-
init_PaywalloError();
|
|
7014
|
-
OnboardingError = class extends PaywalloError {
|
|
7015
|
-
constructor(code, message) {
|
|
7016
|
-
super("onboarding", code, message);
|
|
7017
|
-
this.name = "OnboardingError";
|
|
7018
|
-
}
|
|
7019
|
-
};
|
|
7020
|
-
ONBOARDING_ERROR_CODES = {
|
|
7021
|
-
NOT_INITIALIZED: "ONBOARDING_NOT_INITIALIZED",
|
|
7022
|
-
INVALID_STEP_NAME: "ONBOARDING_INVALID_STEP_NAME"
|
|
7023
|
-
};
|
|
7024
|
-
}
|
|
7025
|
-
});
|
|
7026
|
-
|
|
7027
|
-
// src/domains/onboarding/OnboardingManager.ts
|
|
7028
|
-
var OnboardingManager, onboardingManager;
|
|
7029
|
-
var init_OnboardingManager = __esm({
|
|
7030
|
-
"src/domains/onboarding/OnboardingManager.ts"() {
|
|
7031
|
-
"use strict";
|
|
7032
|
-
init_OnboardingError();
|
|
7033
|
-
OnboardingManager = class {
|
|
7034
|
-
constructor() {
|
|
7035
|
-
this.pipeline = null;
|
|
7036
|
-
this.debug = false;
|
|
7037
|
-
this.lastStep = null;
|
|
7038
|
-
this.finished = false;
|
|
7039
|
-
}
|
|
7040
|
-
/**
|
|
7041
|
-
* Injects runtime dependencies. Called by PaywalloClient during init.
|
|
7042
|
-
*/
|
|
7043
|
-
injectDeps(config) {
|
|
7044
|
-
this.pipeline = config.pipeline;
|
|
7045
|
-
this.debug = config.debug ?? false;
|
|
7046
|
-
}
|
|
7047
|
-
/**
|
|
7048
|
-
* Tracks an onboarding step view.
|
|
7049
|
-
* Saves the step name internally for implicit drop detection on the backend.
|
|
7050
|
-
*
|
|
7051
|
-
* @param stepName - Unique name for this onboarding step.
|
|
7052
|
-
*/
|
|
7053
|
-
async step(stepName) {
|
|
7054
|
-
this.assertConfig();
|
|
7055
|
-
this.validateStepName(stepName, "step");
|
|
7056
|
-
this.lastStep = stepName;
|
|
7057
|
-
const payload = {
|
|
7058
|
-
family: "onboarding",
|
|
7059
|
-
type: "step",
|
|
7060
|
-
...{ step_name: stepName }
|
|
7061
|
-
};
|
|
7062
|
-
return this.emit("onboarding", payload, "step");
|
|
7063
|
-
}
|
|
7064
|
-
/**
|
|
7065
|
-
* Tracks successful completion of the onboarding flow.
|
|
7066
|
-
* Marks the flow as finished.
|
|
7067
|
-
*/
|
|
7068
|
-
async complete() {
|
|
7069
|
-
this.assertConfig();
|
|
7070
|
-
this.finished = true;
|
|
7071
|
-
return this.emit("onboarding", { family: "onboarding", type: "complete" }, "complete");
|
|
7072
|
-
}
|
|
7073
|
-
/**
|
|
7074
|
-
* Tracks an explicit drop (abandonment) at the given step.
|
|
7075
|
-
* Marks the flow as finished.
|
|
7076
|
-
*
|
|
7077
|
-
* @param stepName - The step name where the user dropped off.
|
|
7078
|
-
*/
|
|
7079
|
-
async drop(stepName) {
|
|
7080
|
-
this.assertConfig();
|
|
7081
|
-
this.validateStepName(stepName, "drop");
|
|
7082
|
-
this.finished = true;
|
|
7083
|
-
const payload = {
|
|
7084
|
-
family: "onboarding",
|
|
7085
|
-
type: "drop",
|
|
7086
|
-
...{ step_name: stepName }
|
|
7087
|
-
};
|
|
7088
|
-
return this.emit("onboarding", payload, "drop");
|
|
7089
|
-
}
|
|
7090
|
-
/** Returns the last step name seen, or null if no step was tracked yet. */
|
|
7091
|
-
getLastStep() {
|
|
7092
|
-
return this.lastStep;
|
|
7093
|
-
}
|
|
7094
|
-
/** Returns whether the flow has been marked as finished (complete or drop). */
|
|
7095
|
-
isFinished() {
|
|
7096
|
-
return this.finished;
|
|
7097
|
-
}
|
|
7098
|
-
async emit(eventName, properties, logLabel) {
|
|
7099
|
-
const pipeline = this.pipeline;
|
|
7100
|
-
const distinctId = pipeline.getDistinctId();
|
|
7101
|
-
if (!distinctId) {
|
|
7102
|
-
if (this.debug) console.log(`[Paywallo:Onboarding] skipped (no distinctId): ${logLabel}`);
|
|
7103
|
-
return;
|
|
7470
|
+
return res.data;
|
|
7471
|
+
} catch {
|
|
7472
|
+
const stale = this.cache.getStalePaywall(placement);
|
|
7473
|
+
return stale !== void 0 ? stale : null;
|
|
7104
7474
|
}
|
|
7105
|
-
|
|
7106
|
-
|
|
7107
|
-
|
|
7475
|
+
}
|
|
7476
|
+
async getEmergencyPaywall() {
|
|
7477
|
+
return getEmergencyPaywall(this);
|
|
7478
|
+
}
|
|
7479
|
+
async getCampaign(placement, distinctId, context) {
|
|
7480
|
+
const key = `${placement}:${distinctId}`;
|
|
7481
|
+
const hit = this.cache.getCampaign(key);
|
|
7482
|
+
if (hit !== void 0) return hit;
|
|
7483
|
+
try {
|
|
7484
|
+
const result = await getCampaignData(this, this.baseUrl, placement, distinctId, context);
|
|
7485
|
+
if (!result) {
|
|
7486
|
+
this.cache.setCampaign(key, null, this.cache.nullTTL);
|
|
7487
|
+
return null;
|
|
7488
|
+
}
|
|
7489
|
+
this.cache.setCampaign(key, result);
|
|
7490
|
+
return result;
|
|
7491
|
+
} catch {
|
|
7492
|
+
const stale = this.cache.getStaleCampaign(key);
|
|
7493
|
+
return stale !== void 0 ? stale : null;
|
|
7108
7494
|
}
|
|
7109
7495
|
}
|
|
7110
|
-
|
|
7111
|
-
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7496
|
+
async getActivePlacements() {
|
|
7497
|
+
try {
|
|
7498
|
+
const res = await this.get("/sdk/campaigns/placements");
|
|
7499
|
+
if (!res.ok || !Array.isArray(res.data?.data)) return [];
|
|
7500
|
+
return res.data.data;
|
|
7501
|
+
} catch {
|
|
7502
|
+
return [];
|
|
7116
7503
|
}
|
|
7117
7504
|
}
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7123
|
-
);
|
|
7505
|
+
async getPrimaryCampaign(distinctId) {
|
|
7506
|
+
const key = `primary:${distinctId}`;
|
|
7507
|
+
const hit = this.cache.getCampaign(key);
|
|
7508
|
+
if (hit !== void 0) return hit;
|
|
7509
|
+
try {
|
|
7510
|
+
const res = await this.get(`/sdk/campaigns/public/primary?distinctId=${encodeURIComponent(distinctId)}`);
|
|
7511
|
+
if (res.status === 404) {
|
|
7512
|
+
this.cache.setCampaign(key, null, this.cache.nullTTL);
|
|
7513
|
+
return null;
|
|
7514
|
+
}
|
|
7515
|
+
if (!res.ok) {
|
|
7516
|
+
const stale = this.cache.getStaleCampaign(key);
|
|
7517
|
+
return stale !== void 0 ? stale : null;
|
|
7518
|
+
}
|
|
7519
|
+
this.cache.setCampaign(key, res.data);
|
|
7520
|
+
return res.data;
|
|
7521
|
+
} catch {
|
|
7522
|
+
const stale = this.cache.getStaleCampaign(key);
|
|
7523
|
+
return stale !== void 0 ? stale : null;
|
|
7124
7524
|
}
|
|
7125
7525
|
}
|
|
7526
|
+
async validatePurchase(platform, receipt, productId, transactionId, priceLocal, currency, country, distinctId, paywallPlacement, variantKey) {
|
|
7527
|
+
return validatePurchase(this, this.appKey, platform, receipt, productId, transactionId, priceLocal, currency, country, distinctId, paywallPlacement, variantKey);
|
|
7528
|
+
}
|
|
7529
|
+
async getSubscriptionStatus(distinctId) {
|
|
7530
|
+
return getSubscriptionStatus(this, this.baseUrl, this.appKey, distinctId);
|
|
7531
|
+
}
|
|
7532
|
+
async evaluateFlags(keys, distinctId) {
|
|
7533
|
+
return evaluateFlags(this.flagDeps(), keys, distinctId);
|
|
7534
|
+
}
|
|
7535
|
+
async getConditionalFlag(flagKey, context) {
|
|
7536
|
+
return getConditionalFlag(this.flagDeps(), flagKey, context);
|
|
7537
|
+
}
|
|
7538
|
+
async getVariantFromCache(flagKey, distinctId) {
|
|
7539
|
+
return getVariantFromCache(this.flagDeps(), flagKey, distinctId);
|
|
7540
|
+
}
|
|
7541
|
+
flagDeps() {
|
|
7542
|
+
return {
|
|
7543
|
+
get: (path) => this.get(path),
|
|
7544
|
+
httpClient: this.httpClient,
|
|
7545
|
+
cache: this.cache,
|
|
7546
|
+
appKey: this.appKey,
|
|
7547
|
+
baseUrl: this.baseUrl
|
|
7548
|
+
};
|
|
7549
|
+
}
|
|
7126
7550
|
};
|
|
7127
|
-
onboardingManager = new OnboardingManager();
|
|
7128
|
-
}
|
|
7129
|
-
});
|
|
7130
|
-
|
|
7131
|
-
// src/domains/onboarding/index.ts
|
|
7132
|
-
var init_onboarding = __esm({
|
|
7133
|
-
"src/domains/onboarding/index.ts"() {
|
|
7134
|
-
"use strict";
|
|
7135
|
-
init_OnboardingManager();
|
|
7136
|
-
init_OnboardingError();
|
|
7137
|
-
}
|
|
7138
|
-
});
|
|
7139
|
-
|
|
7140
|
-
// src/domains/paywall/paywallHeartbeatRecovery.ts
|
|
7141
|
-
async function recoverPaywallHeartbeat(apiClient, distinctId, sessionId, debug) {
|
|
7142
|
-
const snapshot = await readPersistedHeartbeat();
|
|
7143
|
-
if (!snapshot) return false;
|
|
7144
|
-
try {
|
|
7145
|
-
const closedAt = new Date(snapshot.lastSeen);
|
|
7146
|
-
const durationS = Math.max(0, Math.round((snapshot.lastSeen - snapshot.presentedAt) / 1e3));
|
|
7147
|
-
await apiClient.trackEvent("paywall", distinctId, {
|
|
7148
|
-
type: "closed",
|
|
7149
|
-
paywall_id: snapshot.paywallId,
|
|
7150
|
-
placement: snapshot.placement,
|
|
7151
|
-
closed_at: closedAt.toISOString(),
|
|
7152
|
-
duration_s: durationS,
|
|
7153
|
-
close_reason: "error",
|
|
7154
|
-
...snapshot.variantId && { variant_id: snapshot.variantId },
|
|
7155
|
-
...snapshot.variantKey && { variant_key: snapshot.variantKey },
|
|
7156
|
-
...snapshot.campaignId && { campaign_id: snapshot.campaignId },
|
|
7157
|
-
...sessionId && { sessionId }
|
|
7158
|
-
});
|
|
7159
|
-
if (debug) console.log("[Paywallo HEARTBEAT] recovered orphan paywall close", {
|
|
7160
|
-
paywallId: snapshot.paywallId,
|
|
7161
|
-
durationS
|
|
7162
|
-
});
|
|
7163
|
-
return true;
|
|
7164
|
-
} catch (err) {
|
|
7165
|
-
if (debug) console.log("[Paywallo HEARTBEAT] recovery failed", err);
|
|
7166
|
-
return false;
|
|
7167
|
-
} finally {
|
|
7168
|
-
await clearPersistedHeartbeat();
|
|
7169
|
-
}
|
|
7170
|
-
}
|
|
7171
|
-
var init_paywallHeartbeatRecovery = __esm({
|
|
7172
|
-
"src/domains/paywall/paywallHeartbeatRecovery.ts"() {
|
|
7173
|
-
"use strict";
|
|
7174
|
-
init_paywallHeartbeat();
|
|
7175
7551
|
}
|
|
7176
7552
|
});
|
|
7177
7553
|
|
|
@@ -7215,6 +7591,8 @@ var init_eventPipelineBridge = __esm({
|
|
|
7215
7591
|
|
|
7216
7592
|
// src/core/PaywalloInitHelpers.ts
|
|
7217
7593
|
function setupNotifications(apiClient, config, environment, eventPipeline) {
|
|
7594
|
+
if (config.notifications === false) return;
|
|
7595
|
+
if (config.notifications === void 0 && !isNativePushAvailable()) return;
|
|
7218
7596
|
try {
|
|
7219
7597
|
notificationsManager.injectDeps({
|
|
7220
7598
|
httpClient: apiClient.getHttpClient(),
|
|
@@ -7256,7 +7634,10 @@ function setupAutoPreload(state, apiClient, config, distinctId) {
|
|
|
7256
7634
|
return null;
|
|
7257
7635
|
}).catch(() => null);
|
|
7258
7636
|
}
|
|
7259
|
-
|
|
7637
|
+
function startBatchPreload(apiClient, debug) {
|
|
7638
|
+
void campaignGateService.preloadAllActive(apiClient, debug).catch(() => {
|
|
7639
|
+
});
|
|
7640
|
+
}
|
|
7260
7641
|
var init_PaywalloInitHelpers = __esm({
|
|
7261
7642
|
"src/core/PaywalloInitHelpers.ts"() {
|
|
7262
7643
|
"use strict";
|
|
@@ -7264,7 +7645,8 @@ var init_PaywalloInitHelpers = __esm({
|
|
|
7264
7645
|
init_identity();
|
|
7265
7646
|
init_notifications();
|
|
7266
7647
|
init_SecureStorage();
|
|
7267
|
-
|
|
7648
|
+
init_NativePushBridge();
|
|
7649
|
+
init_constants();
|
|
7268
7650
|
}
|
|
7269
7651
|
});
|
|
7270
7652
|
|
|
@@ -7313,7 +7695,7 @@ function reportInitFailure(state, config, error, reason) {
|
|
|
7313
7695
|
try {
|
|
7314
7696
|
const tempClient = new ApiClient(
|
|
7315
7697
|
config.appKey,
|
|
7316
|
-
config.apiUrl ??
|
|
7698
|
+
config.apiUrl ?? DEFAULT_API_URL,
|
|
7317
7699
|
config.debug
|
|
7318
7700
|
);
|
|
7319
7701
|
void tempClient.reportError("INIT_FAILED", reason, {
|
|
@@ -7357,7 +7739,7 @@ async function doInit(state, config) {
|
|
|
7357
7739
|
]);
|
|
7358
7740
|
const apiClient = new ApiClient(
|
|
7359
7741
|
config.appKey,
|
|
7360
|
-
config.apiUrl ??
|
|
7742
|
+
config.apiUrl ?? DEFAULT_API_URL,
|
|
7361
7743
|
config.debug,
|
|
7362
7744
|
environment,
|
|
7363
7745
|
offlineQueueEnabled,
|
|
@@ -7377,6 +7759,7 @@ async function doInit(state, config) {
|
|
|
7377
7759
|
cacheTTL: config.subscriptionCacheTTL,
|
|
7378
7760
|
debug: config.debug
|
|
7379
7761
|
});
|
|
7762
|
+
planService.init({ apiClient, debug: config.debug ?? false });
|
|
7380
7763
|
await identityManager.initialize(apiClient, config.debug);
|
|
7381
7764
|
if (state.pendingIdentifies.length > 0) {
|
|
7382
7765
|
for (const pending of state.pendingIdentifies) {
|
|
@@ -7399,6 +7782,9 @@ async function doInit(state, config) {
|
|
|
7399
7782
|
} catch (err) {
|
|
7400
7783
|
if (config.debug) console.log("[Paywallo ATTR] start error", err);
|
|
7401
7784
|
}
|
|
7785
|
+
void nativeDeviceInfo.getDeviceInfo().catch(() => null);
|
|
7786
|
+
void advertisingIdManager.collect(false).catch(() => null);
|
|
7787
|
+
void metaBridge.getAnonymousID().catch(() => null);
|
|
7402
7788
|
apiClient.setEventContextProvider(() => {
|
|
7403
7789
|
const attr = attributionTracker.get();
|
|
7404
7790
|
const attrEntries = attr ? [
|
|
@@ -7413,11 +7799,35 @@ async function doInit(state, config) {
|
|
|
7413
7799
|
["referrer", attr.referrer]
|
|
7414
7800
|
].filter((pair) => pair[1] !== void 0 && pair[1] !== "") : [];
|
|
7415
7801
|
const attribution = attrEntries.length > 0 ? Object.fromEntries(attrEntries) : void 0;
|
|
7802
|
+
const adIds = advertisingIdManager.getCached();
|
|
7803
|
+
const fbAnonId = metaBridge.getCachedAnonymousID();
|
|
7804
|
+
const idsEntries = [
|
|
7805
|
+
["idfa", adIds?.idfa ?? null],
|
|
7806
|
+
["idfv", adIds?.idfv ?? null],
|
|
7807
|
+
["gaid", adIds?.gaid ?? null],
|
|
7808
|
+
["fb_anon_id", fbAnonId]
|
|
7809
|
+
].filter((pair) => pair[1] !== null && pair[1] !== "");
|
|
7810
|
+
const ids = idsEntries.length > 0 ? Object.fromEntries(idsEntries) : void 0;
|
|
7811
|
+
const device = nativeDeviceInfo.getCachedDeviceInfo();
|
|
7812
|
+
let locale;
|
|
7813
|
+
let timezone;
|
|
7814
|
+
try {
|
|
7815
|
+
const opts = Intl.DateTimeFormat().resolvedOptions();
|
|
7816
|
+
locale = opts.locale || void 0;
|
|
7817
|
+
timezone = opts.timeZone || void 0;
|
|
7818
|
+
} catch {
|
|
7819
|
+
}
|
|
7416
7820
|
return {
|
|
7417
7821
|
distinct_id: identityManager.getDistinctId() || void 0,
|
|
7418
7822
|
device_id: identityManager.getDeviceId() ?? void 0,
|
|
7419
7823
|
session_id: sessionManager.getSessionId() ?? void 0,
|
|
7420
|
-
|
|
7824
|
+
app_version: device?.appVersion && device.appVersion !== "0.0.0" ? device.appVersion : void 0,
|
|
7825
|
+
os_version: device?.systemVersion && device.systemVersion !== "0.0.0" ? device.systemVersion : void 0,
|
|
7826
|
+
device_model: device?.modelId || device?.model || void 0,
|
|
7827
|
+
timezone,
|
|
7828
|
+
locale,
|
|
7829
|
+
...attribution && Object.keys(attribution).length > 0 && { attribution },
|
|
7830
|
+
...ids && Object.keys(ids).length > 0 && { ids }
|
|
7421
7831
|
};
|
|
7422
7832
|
});
|
|
7423
7833
|
await sessionManager.initialize(
|
|
@@ -7451,7 +7861,7 @@ async function doInit(state, config) {
|
|
|
7451
7861
|
state.resolveReady();
|
|
7452
7862
|
state.resolveReady = null;
|
|
7453
7863
|
}
|
|
7454
|
-
|
|
7864
|
+
console.warn("[Paywallo] initialized successfully");
|
|
7455
7865
|
if (distinctId) {
|
|
7456
7866
|
apiClient.getSubscriptionStatus(distinctId).then(() => {
|
|
7457
7867
|
if (config.debug) console.log("[Paywallo SUB] preloaded on boot");
|
|
@@ -7462,27 +7872,30 @@ async function doInit(state, config) {
|
|
|
7462
7872
|
});
|
|
7463
7873
|
}
|
|
7464
7874
|
setupAutoPreload(state, apiClient, config, distinctId);
|
|
7875
|
+
startBatchPreload(apiClient, config.debug);
|
|
7465
7876
|
}
|
|
7466
|
-
var DEFAULT_API_URL2;
|
|
7467
7877
|
var init_PaywalloInitializer = __esm({
|
|
7468
7878
|
"src/core/PaywalloInitializer.ts"() {
|
|
7469
7879
|
"use strict";
|
|
7470
|
-
init_SubscriptionManager();
|
|
7471
|
-
init_ApiClient();
|
|
7472
7880
|
init_identity();
|
|
7881
|
+
init_plan();
|
|
7882
|
+
init_AdvertisingIdManager();
|
|
7473
7883
|
init_DeepLinkAttributionCapture();
|
|
7474
7884
|
init_InstallTracker();
|
|
7475
|
-
|
|
7476
|
-
init_queue();
|
|
7477
|
-
init_session();
|
|
7885
|
+
init_MetaBridge();
|
|
7478
7886
|
init_onboarding();
|
|
7479
|
-
init_NativeStorage();
|
|
7480
|
-
init_NativeDeviceInfo();
|
|
7481
7887
|
init_paywallHeartbeatRecovery();
|
|
7888
|
+
init_session();
|
|
7889
|
+
init_SubscriptionManager();
|
|
7890
|
+
init_NativeDeviceInfo();
|
|
7891
|
+
init_ApiClient();
|
|
7892
|
+
init_constants();
|
|
7482
7893
|
init_eventPipelineBridge();
|
|
7483
|
-
|
|
7894
|
+
init_network();
|
|
7484
7895
|
init_PaywalloInitHelpers();
|
|
7485
|
-
|
|
7896
|
+
init_PaywalloState();
|
|
7897
|
+
init_queue();
|
|
7898
|
+
init_NativeStorage();
|
|
7486
7899
|
}
|
|
7487
7900
|
});
|
|
7488
7901
|
|
|
@@ -7736,6 +8149,7 @@ var init_PaywalloClient = __esm({
|
|
|
7736
8149
|
init_PaywalloAnalytics();
|
|
7737
8150
|
init_PaywalloSubscription();
|
|
7738
8151
|
init_PaywalloFlags();
|
|
8152
|
+
init_plan();
|
|
7739
8153
|
PaywalloClientClass = class {
|
|
7740
8154
|
constructor() {
|
|
7741
8155
|
this.state = createPaywalloState();
|
|
@@ -7987,6 +8401,14 @@ var init_PaywalloClient = __esm({
|
|
|
7987
8401
|
async processOfflineQueue() {
|
|
7988
8402
|
return queueProcessor.processQueue();
|
|
7989
8403
|
}
|
|
8404
|
+
async getPlans() {
|
|
8405
|
+
this.ensureInitialized();
|
|
8406
|
+
return planService.getAllPlans();
|
|
8407
|
+
}
|
|
8408
|
+
async getCurrentPlan() {
|
|
8409
|
+
this.ensureInitialized();
|
|
8410
|
+
return planService.getCurrentPlan();
|
|
8411
|
+
}
|
|
7990
8412
|
getApiClientOrThrow() {
|
|
7991
8413
|
if (!this.state.config || !this.state.apiClient) throw new ClientError(CLIENT_ERROR_CODES.NOT_INITIALIZED, "SDK not initialized. Call Paywallo.init() first");
|
|
7992
8414
|
return this.state.apiClient;
|
|
@@ -8029,6 +8451,8 @@ __export(index_exports, {
|
|
|
8029
8451
|
PaywalloContext: () => PaywalloContext,
|
|
8030
8452
|
PaywalloError: () => PaywalloError,
|
|
8031
8453
|
PaywalloProvider: () => PaywalloProvider,
|
|
8454
|
+
PlanCache: () => PlanCache,
|
|
8455
|
+
PlanService: () => PlanService,
|
|
8032
8456
|
PurchaseError: () => PurchaseError,
|
|
8033
8457
|
SESSION_ERROR_CODES: () => SESSION_ERROR_CODES,
|
|
8034
8458
|
SessionError: () => SessionError,
|
|
@@ -8051,6 +8475,8 @@ __export(index_exports, {
|
|
|
8051
8475
|
offlineQueue: () => offlineQueue,
|
|
8052
8476
|
onboardingManager: () => onboardingManager,
|
|
8053
8477
|
parseVariables: () => parseVariables,
|
|
8478
|
+
planCache: () => planCache,
|
|
8479
|
+
planService: () => planService,
|
|
8054
8480
|
queueProcessor: () => queueProcessor,
|
|
8055
8481
|
resolveText: () => resolveText,
|
|
8056
8482
|
sessionManager: () => sessionManager,
|
|
@@ -8060,6 +8486,8 @@ __export(index_exports, {
|
|
|
8060
8486
|
useOnboarding: () => useOnboarding,
|
|
8061
8487
|
usePaywallContext: () => usePaywallContext,
|
|
8062
8488
|
usePaywallo: () => usePaywallo,
|
|
8489
|
+
usePlanPurchase: () => usePlanPurchase,
|
|
8490
|
+
usePlans: () => usePlans,
|
|
8063
8491
|
useProducts: () => useProducts,
|
|
8064
8492
|
usePurchase: () => usePurchase,
|
|
8065
8493
|
useSubscription: () => useSubscription
|
|
@@ -8134,8 +8562,124 @@ function usePaywallo() {
|
|
|
8134
8562
|
return context;
|
|
8135
8563
|
}
|
|
8136
8564
|
|
|
8137
|
-
// src/hooks/
|
|
8565
|
+
// src/hooks/usePlans.ts
|
|
8138
8566
|
var import_react13 = require("react");
|
|
8567
|
+
async function getPlanService() {
|
|
8568
|
+
try {
|
|
8569
|
+
const mod = await Promise.resolve().then(() => (init_PlanService(), PlanService_exports));
|
|
8570
|
+
return mod.planService ?? null;
|
|
8571
|
+
} catch {
|
|
8572
|
+
return null;
|
|
8573
|
+
}
|
|
8574
|
+
}
|
|
8575
|
+
function usePlans() {
|
|
8576
|
+
const [allPlans, setAllPlans] = (0, import_react13.useState)([]);
|
|
8577
|
+
const [currentPlan, setCurrentPlan] = (0, import_react13.useState)(null);
|
|
8578
|
+
const [isLoading, setIsLoading] = (0, import_react13.useState)(true);
|
|
8579
|
+
const [error, setError] = (0, import_react13.useState)(null);
|
|
8580
|
+
const fetchPlans = (0, import_react13.useCallback)(async (forceRefresh = false) => {
|
|
8581
|
+
setIsLoading(true);
|
|
8582
|
+
setError(null);
|
|
8583
|
+
try {
|
|
8584
|
+
const service = await getPlanService();
|
|
8585
|
+
if (!service) {
|
|
8586
|
+
throw new PurchaseError(PURCHASE_ERROR_CODES.PURCHASE_FAILED, "PlanService not available");
|
|
8587
|
+
}
|
|
8588
|
+
const response = await service.getAllPlans(forceRefresh);
|
|
8589
|
+
const { plans, currentIdentifier } = response;
|
|
8590
|
+
setAllPlans(plans);
|
|
8591
|
+
setCurrentPlan(
|
|
8592
|
+
currentIdentifier != null ? plans.find((p) => p.identifier === currentIdentifier) ?? null : null
|
|
8593
|
+
);
|
|
8594
|
+
} catch (err) {
|
|
8595
|
+
const e = err instanceof PurchaseError ? err : new PurchaseError(PURCHASE_ERROR_CODES.PURCHASE_FAILED, String(err));
|
|
8596
|
+
setError(e);
|
|
8597
|
+
} finally {
|
|
8598
|
+
setIsLoading(false);
|
|
8599
|
+
}
|
|
8600
|
+
}, []);
|
|
8601
|
+
const refresh = (0, import_react13.useCallback)(() => {
|
|
8602
|
+
return fetchPlans(true);
|
|
8603
|
+
}, [fetchPlans]);
|
|
8604
|
+
(0, import_react13.useEffect)(() => {
|
|
8605
|
+
void fetchPlans(false);
|
|
8606
|
+
}, [fetchPlans]);
|
|
8607
|
+
return { currentPlan, allPlans, isLoading, error, refresh };
|
|
8608
|
+
}
|
|
8609
|
+
|
|
8610
|
+
// src/hooks/usePlanPurchase.ts
|
|
8611
|
+
var import_react14 = require("react");
|
|
8612
|
+
async function invalidatePlanCache() {
|
|
8613
|
+
try {
|
|
8614
|
+
const mod = await Promise.resolve().then(() => (init_PlanService(), PlanService_exports));
|
|
8615
|
+
mod.planService?.invalidateCache();
|
|
8616
|
+
} catch {
|
|
8617
|
+
}
|
|
8618
|
+
}
|
|
8619
|
+
function usePlanPurchase() {
|
|
8620
|
+
const [state, setState] = (0, import_react14.useState)("idle");
|
|
8621
|
+
const [error, setError] = (0, import_react14.useState)(null);
|
|
8622
|
+
const purchase = (0, import_react14.useCallback)(async (productId) => {
|
|
8623
|
+
setState("purchasing");
|
|
8624
|
+
setError(null);
|
|
8625
|
+
try {
|
|
8626
|
+
const iapService = getIAPService();
|
|
8627
|
+
const result = await iapService.purchase(productId);
|
|
8628
|
+
setState("idle");
|
|
8629
|
+
if (result.success) {
|
|
8630
|
+
await invalidatePlanCache();
|
|
8631
|
+
}
|
|
8632
|
+
return result.success ? {
|
|
8633
|
+
success: true,
|
|
8634
|
+
purchase: result.purchase ? {
|
|
8635
|
+
productId: result.purchase.productId,
|
|
8636
|
+
transactionId: result.purchase.transactionId ?? "",
|
|
8637
|
+
transactionDate: result.purchase.transactionDate,
|
|
8638
|
+
receipt: result.purchase.receipt,
|
|
8639
|
+
platform: "ios"
|
|
8640
|
+
} : void 0
|
|
8641
|
+
} : { success: false, error: result.error };
|
|
8642
|
+
} catch (err) {
|
|
8643
|
+
const purchaseError = err instanceof PurchaseError ? err : createPurchaseError("PURCHASE_FAILED", err instanceof Error ? err.message : String(err));
|
|
8644
|
+
if (purchaseError.userCancelled) {
|
|
8645
|
+
setState("idle");
|
|
8646
|
+
return null;
|
|
8647
|
+
}
|
|
8648
|
+
setError(purchaseError);
|
|
8649
|
+
setState("error");
|
|
8650
|
+
return { success: false, error: purchaseError };
|
|
8651
|
+
}
|
|
8652
|
+
}, []);
|
|
8653
|
+
const restore = (0, import_react14.useCallback)(async () => {
|
|
8654
|
+
setState("restoring");
|
|
8655
|
+
setError(null);
|
|
8656
|
+
try {
|
|
8657
|
+
const iapService = getIAPService();
|
|
8658
|
+
const transactions = await iapService.restore();
|
|
8659
|
+
setState("idle");
|
|
8660
|
+
await invalidatePlanCache();
|
|
8661
|
+
return {
|
|
8662
|
+
restoredCount: transactions.length,
|
|
8663
|
+
productIds: transactions.map((tx) => tx.productId)
|
|
8664
|
+
};
|
|
8665
|
+
} catch (err) {
|
|
8666
|
+
const e = err instanceof PurchaseError ? err : createPurchaseError("RESTORE_FAILED", String(err));
|
|
8667
|
+
setError(e);
|
|
8668
|
+
setState("error");
|
|
8669
|
+
return null;
|
|
8670
|
+
}
|
|
8671
|
+
}, []);
|
|
8672
|
+
return {
|
|
8673
|
+
purchase,
|
|
8674
|
+
restore,
|
|
8675
|
+
isPurchasing: state === "purchasing",
|
|
8676
|
+
isRestoring: state === "restoring",
|
|
8677
|
+
error
|
|
8678
|
+
};
|
|
8679
|
+
}
|
|
8680
|
+
|
|
8681
|
+
// src/hooks/useProducts.ts
|
|
8682
|
+
var import_react15 = require("react");
|
|
8139
8683
|
|
|
8140
8684
|
// src/utils/productMappers.ts
|
|
8141
8685
|
function mapToIAPProduct(product) {
|
|
@@ -8174,11 +8718,11 @@ function mapToFormattedProduct(product) {
|
|
|
8174
8718
|
|
|
8175
8719
|
// src/hooks/useProducts.ts
|
|
8176
8720
|
function useProducts(initialProductIds) {
|
|
8177
|
-
const [products, setProducts] = (0,
|
|
8178
|
-
const [formattedProducts, setFormattedProducts] = (0,
|
|
8179
|
-
const [isLoading, setIsLoading] = (0,
|
|
8180
|
-
const [error, setError] = (0,
|
|
8181
|
-
const loadProducts = (0,
|
|
8721
|
+
const [products, setProducts] = (0, import_react15.useState)([]);
|
|
8722
|
+
const [formattedProducts, setFormattedProducts] = (0, import_react15.useState)([]);
|
|
8723
|
+
const [isLoading, setIsLoading] = (0, import_react15.useState)(false);
|
|
8724
|
+
const [error, setError] = (0, import_react15.useState)(null);
|
|
8725
|
+
const loadProducts = (0, import_react15.useCallback)(async (productIds) => {
|
|
8182
8726
|
setIsLoading(true);
|
|
8183
8727
|
setError(null);
|
|
8184
8728
|
try {
|
|
@@ -8192,24 +8736,24 @@ function useProducts(initialProductIds) {
|
|
|
8192
8736
|
setIsLoading(false);
|
|
8193
8737
|
}
|
|
8194
8738
|
}, []);
|
|
8195
|
-
(0,
|
|
8739
|
+
(0, import_react15.useEffect)(() => {
|
|
8196
8740
|
if (initialProductIds && initialProductIds.length > 0) {
|
|
8197
8741
|
void loadProducts(initialProductIds);
|
|
8198
8742
|
}
|
|
8199
8743
|
}, []);
|
|
8200
|
-
const getProduct = (0,
|
|
8744
|
+
const getProduct = (0, import_react15.useCallback)(
|
|
8201
8745
|
(productId) => {
|
|
8202
8746
|
return products.find((p) => p.productId === productId);
|
|
8203
8747
|
},
|
|
8204
8748
|
[products]
|
|
8205
8749
|
);
|
|
8206
|
-
const getFormattedProduct = (0,
|
|
8750
|
+
const getFormattedProduct = (0, import_react15.useCallback)(
|
|
8207
8751
|
(productId) => {
|
|
8208
8752
|
return formattedProducts.find((p) => p.productId === productId);
|
|
8209
8753
|
},
|
|
8210
8754
|
[formattedProducts]
|
|
8211
8755
|
);
|
|
8212
|
-
const getPriceInfo = (0,
|
|
8756
|
+
const getPriceInfo = (0, import_react15.useCallback)(
|
|
8213
8757
|
(productId) => {
|
|
8214
8758
|
const p = formattedProducts.find((fp) => fp.productId === productId);
|
|
8215
8759
|
if (!p) return void 0;
|
|
@@ -8238,11 +8782,11 @@ function useProducts(initialProductIds) {
|
|
|
8238
8782
|
}
|
|
8239
8783
|
|
|
8240
8784
|
// src/hooks/usePurchase.ts
|
|
8241
|
-
var
|
|
8785
|
+
var import_react16 = require("react");
|
|
8242
8786
|
function usePurchase() {
|
|
8243
|
-
const [state, setState] = (0,
|
|
8244
|
-
const [error, setError] = (0,
|
|
8245
|
-
const purchase = (0,
|
|
8787
|
+
const [state, setState] = (0, import_react16.useState)("idle");
|
|
8788
|
+
const [error, setError] = (0, import_react16.useState)(null);
|
|
8789
|
+
const purchase = (0, import_react16.useCallback)(async (productId) => {
|
|
8246
8790
|
setState("purchasing");
|
|
8247
8791
|
setError(null);
|
|
8248
8792
|
try {
|
|
@@ -8278,7 +8822,7 @@ function usePurchase() {
|
|
|
8278
8822
|
return { status: "failed", error: purchaseError };
|
|
8279
8823
|
}
|
|
8280
8824
|
}, []);
|
|
8281
|
-
const restore = (0,
|
|
8825
|
+
const restore = (0, import_react16.useCallback)(async () => {
|
|
8282
8826
|
setState("restoring");
|
|
8283
8827
|
setError(null);
|
|
8284
8828
|
try {
|
|
@@ -8309,14 +8853,14 @@ function usePurchase() {
|
|
|
8309
8853
|
}
|
|
8310
8854
|
|
|
8311
8855
|
// src/hooks/useSubscription.ts
|
|
8312
|
-
var
|
|
8856
|
+
var import_react17 = require("react");
|
|
8313
8857
|
init_SubscriptionManager();
|
|
8314
8858
|
var EMPTY_ENTITLEMENTS = [];
|
|
8315
8859
|
function useSubscription() {
|
|
8316
|
-
const [status, setStatus] = (0,
|
|
8317
|
-
const [isLoading, setIsLoading] = (0,
|
|
8318
|
-
const [error, setError] = (0,
|
|
8319
|
-
const refresh = (0,
|
|
8860
|
+
const [status, setStatus] = (0, import_react17.useState)(null);
|
|
8861
|
+
const [isLoading, setIsLoading] = (0, import_react17.useState)(true);
|
|
8862
|
+
const [error, setError] = (0, import_react17.useState)(null);
|
|
8863
|
+
const refresh = (0, import_react17.useCallback)(async () => {
|
|
8320
8864
|
setIsLoading(true);
|
|
8321
8865
|
setError(null);
|
|
8322
8866
|
try {
|
|
@@ -8329,7 +8873,7 @@ function useSubscription() {
|
|
|
8329
8873
|
setIsLoading(false);
|
|
8330
8874
|
}
|
|
8331
8875
|
}, []);
|
|
8332
|
-
const restore = (0,
|
|
8876
|
+
const restore = (0, import_react17.useCallback)(async () => {
|
|
8333
8877
|
setIsLoading(true);
|
|
8334
8878
|
setError(null);
|
|
8335
8879
|
try {
|
|
@@ -8342,7 +8886,7 @@ function useSubscription() {
|
|
|
8342
8886
|
setIsLoading(false);
|
|
8343
8887
|
}
|
|
8344
8888
|
}, []);
|
|
8345
|
-
(0,
|
|
8889
|
+
(0, import_react17.useEffect)(() => {
|
|
8346
8890
|
void subscriptionManager.getSubscriptionStatus().then((s) => {
|
|
8347
8891
|
setStatus(s);
|
|
8348
8892
|
setIsLoading(false);
|
|
@@ -8369,8 +8913,11 @@ function useSubscription() {
|
|
|
8369
8913
|
};
|
|
8370
8914
|
}
|
|
8371
8915
|
|
|
8916
|
+
// src/index.ts
|
|
8917
|
+
init_plan();
|
|
8918
|
+
|
|
8372
8919
|
// src/PaywalloProvider.tsx
|
|
8373
|
-
var
|
|
8920
|
+
var import_react23 = require("react");
|
|
8374
8921
|
var import_react_native24 = require("react-native");
|
|
8375
8922
|
init_paywall();
|
|
8376
8923
|
init_paywall();
|
|
@@ -8378,7 +8925,7 @@ init_paywall();
|
|
|
8378
8925
|
init_PaywalloClient();
|
|
8379
8926
|
|
|
8380
8927
|
// src/hooks/useAppAutoEvents.ts
|
|
8381
|
-
var
|
|
8928
|
+
var import_react18 = require("react");
|
|
8382
8929
|
var FIRST_SEEN_KEY = "@panel:firstSeen";
|
|
8383
8930
|
var DEBOUNCE_MS = 1e3;
|
|
8384
8931
|
async function detectPlatform3() {
|
|
@@ -8408,8 +8955,8 @@ function useAppAutoEvents(config) {
|
|
|
8408
8955
|
storageSet,
|
|
8409
8956
|
debug
|
|
8410
8957
|
} = config;
|
|
8411
|
-
const didRunRef = (0,
|
|
8412
|
-
(0,
|
|
8958
|
+
const didRunRef = (0, import_react18.useRef)(false);
|
|
8959
|
+
(0, import_react18.useEffect)(() => {
|
|
8413
8960
|
if (!isInitialized || didRunRef.current) return;
|
|
8414
8961
|
const timer = setTimeout(() => {
|
|
8415
8962
|
if (didRunRef.current) return;
|
|
@@ -8454,7 +9001,7 @@ function useAppAutoEvents(config) {
|
|
|
8454
9001
|
}
|
|
8455
9002
|
|
|
8456
9003
|
// src/hooks/useCampaignPreload.ts
|
|
8457
|
-
var
|
|
9004
|
+
var import_react19 = require("react");
|
|
8458
9005
|
init_PaywalloClient();
|
|
8459
9006
|
init_CampaignError();
|
|
8460
9007
|
|
|
@@ -8525,17 +9072,17 @@ function getCacheEntry(cache, placement) {
|
|
|
8525
9072
|
|
|
8526
9073
|
// src/hooks/useCampaignPreload.ts
|
|
8527
9074
|
function useCampaignPreload() {
|
|
8528
|
-
const [preloadedWebView, setPreloadedWebView] = (0,
|
|
8529
|
-
const preloadedCampaignsRef = (0,
|
|
8530
|
-
const isPreloadValid = (0,
|
|
9075
|
+
const [preloadedWebView, setPreloadedWebView] = (0, import_react19.useState)(null);
|
|
9076
|
+
const preloadedCampaignsRef = (0, import_react19.useRef)(/* @__PURE__ */ new Map());
|
|
9077
|
+
const isPreloadValid = (0, import_react19.useCallback)(
|
|
8531
9078
|
(placement) => isCacheEntryValid(preloadedCampaignsRef.current.get(placement)),
|
|
8532
9079
|
[]
|
|
8533
9080
|
);
|
|
8534
|
-
const consumePreloadedCampaign = (0,
|
|
9081
|
+
const consumePreloadedCampaign = (0, import_react19.useCallback)(
|
|
8535
9082
|
(placement) => getCacheEntry(preloadedCampaignsRef.current, placement),
|
|
8536
9083
|
[]
|
|
8537
9084
|
);
|
|
8538
|
-
const preloadCampaign = (0,
|
|
9085
|
+
const preloadCampaign = (0, import_react19.useCallback)(
|
|
8539
9086
|
async (placement, context) => {
|
|
8540
9087
|
try {
|
|
8541
9088
|
const campaign = await PaywalloClient.getCampaign(placement, context);
|
|
@@ -8609,12 +9156,12 @@ init_SecureStorage();
|
|
|
8609
9156
|
init_paywall();
|
|
8610
9157
|
|
|
8611
9158
|
// src/hooks/useProductLoader.ts
|
|
8612
|
-
var
|
|
9159
|
+
var import_react20 = require("react");
|
|
8613
9160
|
init_PaywalloClient();
|
|
8614
9161
|
function useProductLoader() {
|
|
8615
|
-
const [products, setProducts] = (0,
|
|
8616
|
-
const [isLoadingProducts, setIsLoadingProducts] = (0,
|
|
8617
|
-
const refreshProducts = (0,
|
|
9162
|
+
const [products, setProducts] = (0, import_react20.useState)(/* @__PURE__ */ new Map());
|
|
9163
|
+
const [isLoadingProducts, setIsLoadingProducts] = (0, import_react20.useState)(false);
|
|
9164
|
+
const refreshProducts = (0, import_react20.useCallback)(async (productIds) => {
|
|
8618
9165
|
setIsLoadingProducts(true);
|
|
8619
9166
|
try {
|
|
8620
9167
|
const iapService = getIAPService();
|
|
@@ -8632,12 +9179,12 @@ function useProductLoader() {
|
|
|
8632
9179
|
}
|
|
8633
9180
|
|
|
8634
9181
|
// src/hooks/usePurchaseOrchestrator.ts
|
|
8635
|
-
var
|
|
9182
|
+
var import_react21 = require("react");
|
|
8636
9183
|
init_PaywalloClient();
|
|
8637
9184
|
init_paywall();
|
|
8638
9185
|
function usePurchaseOrchestrator(preloadedWebView, resolvePreloadedPaywall, clearPreloadedWebView, setShowingPreloadedWebView, presentedAtRef, invalidateSubscriptionCache) {
|
|
8639
9186
|
const { trackDismissed, trackProductSelected, trackPurchased } = usePaywallTracking();
|
|
8640
|
-
const handlePreloadedPurchase = (0,
|
|
9187
|
+
const handlePreloadedPurchase = (0, import_react21.useCallback)(
|
|
8641
9188
|
async (productId) => {
|
|
8642
9189
|
try {
|
|
8643
9190
|
if (preloadedWebView) {
|
|
@@ -8675,7 +9222,7 @@ function usePurchaseOrchestrator(preloadedWebView, resolvePreloadedPaywall, clea
|
|
|
8675
9222
|
},
|
|
8676
9223
|
[preloadedWebView, resolvePreloadedPaywall, clearPreloadedWebView, setShowingPreloadedWebView, presentedAtRef, trackDismissed, trackProductSelected, trackPurchased, invalidateSubscriptionCache]
|
|
8677
9224
|
);
|
|
8678
|
-
const handlePreloadedRestore = (0,
|
|
9225
|
+
const handlePreloadedRestore = (0, import_react21.useCallback)(async () => {
|
|
8679
9226
|
try {
|
|
8680
9227
|
const transactions = await getIAPService().restore();
|
|
8681
9228
|
if (transactions.length === 0) return;
|
|
@@ -8698,7 +9245,7 @@ function usePurchaseOrchestrator(preloadedWebView, resolvePreloadedPaywall, clea
|
|
|
8698
9245
|
}
|
|
8699
9246
|
|
|
8700
9247
|
// src/hooks/useSubscriptionSync.ts
|
|
8701
|
-
var
|
|
9248
|
+
var import_react22 = require("react");
|
|
8702
9249
|
init_PaywalloClient();
|
|
8703
9250
|
init_SubscriptionCache();
|
|
8704
9251
|
var CACHE_TTL_MS2 = 5 * 60 * 1e3;
|
|
@@ -8765,14 +9312,14 @@ function isActiveCacheEntry(entry) {
|
|
|
8765
9312
|
return isSubscriptionStillActive(entry.data);
|
|
8766
9313
|
}
|
|
8767
9314
|
function useSubscriptionSync() {
|
|
8768
|
-
const [subscription, setSubscription] = (0,
|
|
8769
|
-
const cacheRef = (0,
|
|
8770
|
-
const invalidateCache = (0,
|
|
9315
|
+
const [subscription, setSubscription] = (0, import_react22.useState)(null);
|
|
9316
|
+
const cacheRef = (0, import_react22.useRef)(null);
|
|
9317
|
+
const invalidateCache = (0, import_react22.useCallback)(() => {
|
|
8771
9318
|
cacheRef.current = null;
|
|
8772
9319
|
const distinctId = PaywalloClient.getDistinctId();
|
|
8773
9320
|
if (distinctId) void subscriptionCache.invalidate(distinctId);
|
|
8774
9321
|
}, []);
|
|
8775
|
-
const fetchAndCache = (0,
|
|
9322
|
+
const fetchAndCache = (0, import_react22.useCallback)(async () => {
|
|
8776
9323
|
const apiClient = PaywalloClient.getApiClient();
|
|
8777
9324
|
const distinctId = PaywalloClient.getDistinctId();
|
|
8778
9325
|
if (!apiClient || !distinctId) return null;
|
|
@@ -8786,7 +9333,7 @@ function useSubscriptionSync() {
|
|
|
8786
9333
|
void subscriptionCache.set(distinctId, toDomainResponse(status));
|
|
8787
9334
|
return sub;
|
|
8788
9335
|
}, []);
|
|
8789
|
-
const hasActiveSubscription = (0,
|
|
9336
|
+
const hasActiveSubscription = (0, import_react22.useCallback)(async () => {
|
|
8790
9337
|
const apiClient = PaywalloClient.getApiClient();
|
|
8791
9338
|
const distinctId = PaywalloClient.getDistinctId();
|
|
8792
9339
|
if (!apiClient || !distinctId) return false;
|
|
@@ -8829,7 +9376,7 @@ function useSubscriptionSync() {
|
|
|
8829
9376
|
return resolveOfflineFromCache(distinctId);
|
|
8830
9377
|
}
|
|
8831
9378
|
}, []);
|
|
8832
|
-
const getSubscription = (0,
|
|
9379
|
+
const getSubscription = (0, import_react22.useCallback)(async () => {
|
|
8833
9380
|
const apiClient = PaywalloClient.getApiClient();
|
|
8834
9381
|
const distinctId = PaywalloClient.getDistinctId();
|
|
8835
9382
|
if (!apiClient || !distinctId) return null;
|
|
@@ -8856,20 +9403,20 @@ init_ClientError();
|
|
|
8856
9403
|
init_localization();
|
|
8857
9404
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
8858
9405
|
function PaywalloProvider({ children, config }) {
|
|
8859
|
-
const [isInitialized, setIsInitialized] = (0,
|
|
8860
|
-
const [initError, setInitError] = (0,
|
|
8861
|
-
const [distinctId, setDistinctId] = (0,
|
|
8862
|
-
const [activePaywall, setActivePaywall] = (0,
|
|
9406
|
+
const [isInitialized, setIsInitialized] = (0, import_react23.useState)(false);
|
|
9407
|
+
const [initError, setInitError] = (0, import_react23.useState)(null);
|
|
9408
|
+
const [distinctId, setDistinctId] = (0, import_react23.useState)(null);
|
|
9409
|
+
const [activePaywall, setActivePaywall] = (0, import_react23.useState)(null);
|
|
8863
9410
|
const { products, isLoadingProducts, refreshProducts } = useProductLoader();
|
|
8864
9411
|
const { subscription, hasActiveSubscription, getSubscription, invalidateCache } = useSubscriptionSync();
|
|
8865
9412
|
const { preloadedWebView, setPreloadedWebView, preloadCampaign, consumePreloadedCampaign, isPreloadValid } = useCampaignPreload();
|
|
8866
|
-
const clearPreloadedWebView = (0,
|
|
8867
|
-
const autoPreloadTriggeredRef = (0,
|
|
8868
|
-
const preloadedWebViewRef = (0,
|
|
8869
|
-
const pollTimerRef = (0,
|
|
8870
|
-
const pollCancelledRef = (0,
|
|
8871
|
-
const secureStorageRef = (0,
|
|
8872
|
-
(0,
|
|
9413
|
+
const clearPreloadedWebView = (0, import_react23.useCallback)(() => setPreloadedWebView(null), [setPreloadedWebView]);
|
|
9414
|
+
const autoPreloadTriggeredRef = (0, import_react23.useRef)(false);
|
|
9415
|
+
const preloadedWebViewRef = (0, import_react23.useRef)(preloadedWebView);
|
|
9416
|
+
const pollTimerRef = (0, import_react23.useRef)(null);
|
|
9417
|
+
const pollCancelledRef = (0, import_react23.useRef)(false);
|
|
9418
|
+
const secureStorageRef = (0, import_react23.useRef)(new SecureStorage(config.debug));
|
|
9419
|
+
(0, import_react23.useEffect)(() => {
|
|
8873
9420
|
preloadedWebViewRef.current = preloadedWebView;
|
|
8874
9421
|
}, [preloadedWebView]);
|
|
8875
9422
|
useAppAutoEvents({
|
|
@@ -8885,20 +9432,20 @@ function PaywalloProvider({ children, config }) {
|
|
|
8885
9432
|
storageSet: (key, value) => secureStorageRef.current.set(key, value),
|
|
8886
9433
|
debug: config.debug
|
|
8887
9434
|
});
|
|
8888
|
-
const triggerRepreload = (0,
|
|
9435
|
+
const triggerRepreload = (0, import_react23.useCallback)((placement) => {
|
|
8889
9436
|
void PaywalloClient.preloadCampaign(placement).catch(() => {
|
|
8890
9437
|
});
|
|
8891
9438
|
}, []);
|
|
8892
9439
|
const { showingPreloadedWebView, presentPreloadedWebView, resolvePreloadedPaywall, handlePreloadedWebViewReady: baseHandlePreloadedWebViewReady, handlePreloadedClose: baseHandlePreloadedClose, setShowingPreloadedWebView, presentedAtRef } = usePaywallPresenter(preloadedWebView, setPreloadedWebView);
|
|
8893
|
-
const SCREEN_HEIGHT = (0,
|
|
8894
|
-
const slideAnim = (0,
|
|
8895
|
-
const handlePreloadedWebViewReady = (0,
|
|
9440
|
+
const SCREEN_HEIGHT = (0, import_react23.useMemo)(() => import_react_native24.Dimensions.get("window").height, []);
|
|
9441
|
+
const slideAnim = (0, import_react23.useRef)(new import_react_native24.Animated.Value(SCREEN_HEIGHT)).current;
|
|
9442
|
+
const handlePreloadedWebViewReady = (0, import_react23.useCallback)(() => {
|
|
8896
9443
|
if (PaywalloClient.getConfig()?.debug) {
|
|
8897
9444
|
console.log(`[Paywallo WEBVIEW] loaded \u2014 placement: ${preloadedWebView?.placement}`);
|
|
8898
9445
|
}
|
|
8899
9446
|
baseHandlePreloadedWebViewReady();
|
|
8900
9447
|
}, [preloadedWebView?.placement, baseHandlePreloadedWebViewReady]);
|
|
8901
|
-
const handlePreloadedClose = (0,
|
|
9448
|
+
const handlePreloadedClose = (0, import_react23.useCallback)(() => {
|
|
8902
9449
|
const placement = preloadedWebView?.placement;
|
|
8903
9450
|
import_react_native24.Animated.timing(slideAnim, { toValue: SCREEN_HEIGHT, duration: 200, easing: import_react_native24.Easing.in(import_react_native24.Easing.cubic), useNativeDriver: true }).start(() => {
|
|
8904
9451
|
baseHandlePreloadedClose();
|
|
@@ -8913,8 +9460,8 @@ function PaywalloProvider({ children, config }) {
|
|
|
8913
9460
|
presentedAtRef,
|
|
8914
9461
|
invalidateCache
|
|
8915
9462
|
);
|
|
8916
|
-
const [isPreloadPurchasing, setIsPreloadPurchasing] = (0,
|
|
8917
|
-
const handlePreloadedPurchase = (0,
|
|
9463
|
+
const [isPreloadPurchasing, setIsPreloadPurchasing] = (0, import_react23.useState)(false);
|
|
9464
|
+
const handlePreloadedPurchase = (0, import_react23.useCallback)(async (productId) => {
|
|
8918
9465
|
setIsPreloadPurchasing(true);
|
|
8919
9466
|
try {
|
|
8920
9467
|
await rawPreloadedPurchase(productId);
|
|
@@ -8922,8 +9469,8 @@ function PaywalloProvider({ children, config }) {
|
|
|
8922
9469
|
setIsPreloadPurchasing(false);
|
|
8923
9470
|
}
|
|
8924
9471
|
}, [rawPreloadedPurchase]);
|
|
8925
|
-
const configRef = (0,
|
|
8926
|
-
(0,
|
|
9472
|
+
const configRef = (0, import_react23.useRef)(config);
|
|
9473
|
+
(0, import_react23.useEffect)(() => {
|
|
8927
9474
|
let mounted = true;
|
|
8928
9475
|
initLocalization({ detectDevice: true });
|
|
8929
9476
|
PaywalloClient.init(configRef.current).then(async () => {
|
|
@@ -8944,14 +9491,14 @@ function PaywalloProvider({ children, config }) {
|
|
|
8944
9491
|
mounted = false;
|
|
8945
9492
|
};
|
|
8946
9493
|
}, [preloadCampaign]);
|
|
8947
|
-
const getPaywallConfig = (0,
|
|
9494
|
+
const getPaywallConfig = (0, import_react23.useCallback)(async (p) => {
|
|
8948
9495
|
const api = PaywalloClient.getApiClient();
|
|
8949
9496
|
return api ? api.getPaywall(p) : null;
|
|
8950
9497
|
}, []);
|
|
8951
|
-
const presentPaywall = (0,
|
|
9498
|
+
const presentPaywall = (0, import_react23.useCallback)((placement) => {
|
|
8952
9499
|
return new Promise((resolve) => setActivePaywall({ placement, resolver: resolve }));
|
|
8953
9500
|
}, []);
|
|
8954
|
-
const trackCampaignImpression = (0,
|
|
9501
|
+
const trackCampaignImpression = (0, import_react23.useCallback)((placement, variantKey, campaignId) => {
|
|
8955
9502
|
const api = PaywalloClient.getApiClient();
|
|
8956
9503
|
if (!api) return;
|
|
8957
9504
|
const sessionId = PaywalloClient.getSessionId();
|
|
@@ -8965,7 +9512,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
8965
9512
|
}).catch(() => {
|
|
8966
9513
|
});
|
|
8967
9514
|
}, []);
|
|
8968
|
-
const presentCampaign = (0,
|
|
9515
|
+
const presentCampaign = (0, import_react23.useCallback)(
|
|
8969
9516
|
async (placement, context) => {
|
|
8970
9517
|
try {
|
|
8971
9518
|
if (preloadedWebView?.placement === placement && preloadedWebView.loaded && isPreloadValid(placement)) {
|
|
@@ -9039,7 +9586,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
9039
9586
|
},
|
|
9040
9587
|
[preloadedWebView, isPreloadValid, consumePreloadedCampaign, presentPreloadedWebView, trackCampaignImpression]
|
|
9041
9588
|
);
|
|
9042
|
-
const restorePurchases = (0,
|
|
9589
|
+
const restorePurchases = (0, import_react23.useCallback)(async () => {
|
|
9043
9590
|
invalidateCache();
|
|
9044
9591
|
try {
|
|
9045
9592
|
const txs = await getIAPService().restore();
|
|
@@ -9048,13 +9595,13 @@ function PaywalloProvider({ children, config }) {
|
|
|
9048
9595
|
return { success: false, restoredProducts: [], error: error instanceof Error ? error : new PurchaseError(PURCHASE_ERROR_CODES.RESTORE_FAILED, String(error)) };
|
|
9049
9596
|
}
|
|
9050
9597
|
}, [invalidateCache]);
|
|
9051
|
-
const handlePaywallResult = (0,
|
|
9598
|
+
const handlePaywallResult = (0, import_react23.useCallback)((result) => {
|
|
9052
9599
|
if (activePaywall) {
|
|
9053
9600
|
activePaywall.resolver(result);
|
|
9054
9601
|
setActivePaywall(null);
|
|
9055
9602
|
}
|
|
9056
9603
|
}, [activePaywall]);
|
|
9057
|
-
const bridgePaywallPresenter = (0,
|
|
9604
|
+
const bridgePaywallPresenter = (0, import_react23.useCallback)((placement) => {
|
|
9058
9605
|
if (PaywalloClient.getConfig()?.debug) {
|
|
9059
9606
|
console.log(`[Paywallo PRESENT] called \u2014 preloaded: ${preloadedWebViewRef.current?.loaded === true} placement: ${placement}`);
|
|
9060
9607
|
}
|
|
@@ -9083,7 +9630,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
9083
9630
|
}
|
|
9084
9631
|
return presentCampaign(placement);
|
|
9085
9632
|
}, [presentPreloadedWebView, presentCampaign]);
|
|
9086
|
-
(0,
|
|
9633
|
+
(0, import_react23.useEffect)(() => {
|
|
9087
9634
|
if (!isInitialized) return;
|
|
9088
9635
|
const onEmergency = async (id) => {
|
|
9089
9636
|
try {
|
|
@@ -9110,9 +9657,9 @@ function PaywalloProvider({ children, config }) {
|
|
|
9110
9657
|
};
|
|
9111
9658
|
}, [isInitialized, bridgePaywallPresenter, getSubscription, hasActiveSubscription, restorePurchases]);
|
|
9112
9659
|
const isReady = isInitialized && !isLoadingProducts;
|
|
9113
|
-
const noOp = (0,
|
|
9660
|
+
const noOp = (0, import_react23.useCallback)(() => {
|
|
9114
9661
|
}, []);
|
|
9115
|
-
const contextValue = (0,
|
|
9662
|
+
const contextValue = (0, import_react23.useMemo)(() => ({
|
|
9116
9663
|
config: PaywalloClient.getConfig(),
|
|
9117
9664
|
isInitialized,
|
|
9118
9665
|
isReady,
|
|
@@ -9146,7 +9693,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
9146
9693
|
getPaywallConfig,
|
|
9147
9694
|
refreshProducts
|
|
9148
9695
|
]);
|
|
9149
|
-
(0,
|
|
9696
|
+
(0, import_react23.useLayoutEffect)(() => {
|
|
9150
9697
|
if (showingPreloadedWebView) {
|
|
9151
9698
|
slideAnim.setValue(SCREEN_HEIGHT);
|
|
9152
9699
|
import_react_native24.Animated.timing(slideAnim, { toValue: 0, duration: 200, easing: import_react_native24.Easing.out(import_react_native24.Easing.cubic), useNativeDriver: true }).start();
|
|
@@ -9353,6 +9900,8 @@ var index_default = Paywallo;
|
|
|
9353
9900
|
PaywalloContext,
|
|
9354
9901
|
PaywalloError,
|
|
9355
9902
|
PaywalloProvider,
|
|
9903
|
+
PlanCache,
|
|
9904
|
+
PlanService,
|
|
9356
9905
|
PurchaseError,
|
|
9357
9906
|
SESSION_ERROR_CODES,
|
|
9358
9907
|
SessionError,
|
|
@@ -9374,6 +9923,8 @@ var index_default = Paywallo;
|
|
|
9374
9923
|
offlineQueue,
|
|
9375
9924
|
onboardingManager,
|
|
9376
9925
|
parseVariables,
|
|
9926
|
+
planCache,
|
|
9927
|
+
planService,
|
|
9377
9928
|
queueProcessor,
|
|
9378
9929
|
resolveText,
|
|
9379
9930
|
sessionManager,
|
|
@@ -9383,6 +9934,8 @@ var index_default = Paywallo;
|
|
|
9383
9934
|
useOnboarding,
|
|
9384
9935
|
usePaywallContext,
|
|
9385
9936
|
usePaywallo,
|
|
9937
|
+
usePlanPurchase,
|
|
9938
|
+
usePlans,
|
|
9386
9939
|
useProducts,
|
|
9387
9940
|
usePurchase,
|
|
9388
9941
|
useSubscription
|