expo-superwall 1.1.3 → 1.1.5
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/CHANGELOG.md +13 -0
- package/android/src/main/java/expo/modules/superwallexpo/SuperwallExpoModule.kt +14 -4
- package/android/src/main/java/expo/modules/superwallexpo/bridges/PurchaseControllerBridge.kt +2 -2
- package/android/src/main/java/expo/modules/superwallexpo/bridges/SuperwallDelegateBridge.kt +1 -1
- package/android/src/main/java/expo/modules/superwallexpo/json/PageViewData.kt +17 -0
- package/android/src/main/java/expo/modules/superwallexpo/json/SuperwallEvent.kt +5 -0
- package/build/package.json +1 -1
- package/build/src/compat/lib/PaywallOptions.d.ts +1 -0
- package/build/src/compat/lib/PaywallOptions.d.ts.map +1 -1
- package/build/src/compat/lib/PaywallOptions.js +5 -0
- package/build/src/compat/lib/PaywallOptions.js.map +1 -1
- package/build/src/useSuperwall.d.ts.map +1 -1
- package/build/src/useSuperwall.js +68 -3
- package/build/src/useSuperwall.js.map +1 -1
- package/ios/SuperwallExpo.podspec +31 -2
- package/ios/SuperwallExpoModule.swift +16 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 45be124: Fix purchase events being dropped on cold start when using a custom purchase controller, which left the paywall spinner stuck forever. The native module emitted events through a single static reference that was overwritten by every module instance, so when more than one app context exists (e.g. expo-dev-client's launcher plus the app) the reference could point at an instance whose JS runtime never subscribed and `onPurchase`/`onPurchaseRestore` were silently dropped. Native events are now emitted to every live module instance (tracked weakly) instead of only the most recently created one.
|
|
8
|
+
|
|
9
|
+
## 1.1.4
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- b23c170: Ensure that methods await for config finish before triggering
|
|
14
|
+
- 0aa884e: Update podspec to pick proper iOS target
|
|
15
|
+
|
|
3
16
|
## 1.1.3
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
|
@@ -36,12 +36,25 @@ import kotlinx.coroutines.launch
|
|
|
36
36
|
import kotlinx.coroutines.future.await
|
|
37
37
|
import kotlinx.coroutines.runBlocking
|
|
38
38
|
import android.util.Log
|
|
39
|
+
import java.util.Collections
|
|
40
|
+
import java.util.WeakHashMap
|
|
39
41
|
import java.util.concurrent.CompletableFuture
|
|
40
42
|
|
|
41
43
|
class SuperwallExpoModule : Module() {
|
|
42
44
|
|
|
43
45
|
companion object {
|
|
44
46
|
var instance: SuperwallExpoModule? = null
|
|
47
|
+
private val instances = Collections.newSetFromMap(WeakHashMap<SuperwallExpoModule, Boolean>())
|
|
48
|
+
|
|
49
|
+
// Events must reach every live module instance. More than one app context can
|
|
50
|
+
// exist at once (e.g. expo-dev-client's launcher plus the app), and `instance`
|
|
51
|
+
// may point at a module whose JS runtime never subscribed - sending only
|
|
52
|
+
// through it silently drops events like `onPurchase`, leaving the native
|
|
53
|
+
// purchase future incomplete forever.
|
|
54
|
+
fun emitEvent(name: String, body: Map<String, Any?>?) {
|
|
55
|
+
val liveInstances = synchronized(instances) { instances.toList() }
|
|
56
|
+
liveInstances.forEach { it.sendEvent(name, body ?: emptyMap()) }
|
|
57
|
+
}
|
|
45
58
|
}
|
|
46
59
|
|
|
47
60
|
val scope = CoroutineScope(Dispatchers.Main)
|
|
@@ -50,10 +63,7 @@ class SuperwallExpoModule : Module() {
|
|
|
50
63
|
|
|
51
64
|
init {
|
|
52
65
|
instance = this
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
fun emitEvent(name: String, body: Map<String, Any?>?) {
|
|
56
|
-
SuperwallExpoModule.instance?.sendEvent(name, body?:emptyMap())
|
|
66
|
+
synchronized(instances) { instances.add(this) }
|
|
57
67
|
}
|
|
58
68
|
|
|
59
69
|
private val onPaywallPresent = "onPaywallPresent"
|
package/android/src/main/java/expo/modules/superwallexpo/bridges/PurchaseControllerBridge.kt
CHANGED
|
@@ -41,7 +41,7 @@ class PurchaseControllerBridge(): PurchaseController {
|
|
|
41
41
|
"offerId" to offerId
|
|
42
42
|
)
|
|
43
43
|
|
|
44
|
-
SuperwallExpoModule.
|
|
44
|
+
SuperwallExpoModule.emitEvent(
|
|
45
45
|
"onPurchase",
|
|
46
46
|
productData
|
|
47
47
|
)
|
|
@@ -52,7 +52,7 @@ class PurchaseControllerBridge(): PurchaseController {
|
|
|
52
52
|
override suspend fun restorePurchases(): RestorationResult {
|
|
53
53
|
restorePromise = CompletableFuture()
|
|
54
54
|
|
|
55
|
-
SuperwallExpoModule.
|
|
55
|
+
SuperwallExpoModule.emitEvent("onPurchaseRestore", null)
|
|
56
56
|
|
|
57
57
|
return restorePromise!!.await()
|
|
58
58
|
}
|
|
@@ -95,7 +95,7 @@ class SuperwallDelegateBridge : SuperwallDelegate {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
private fun sendEvent(name: String, body: Map<String, Any?>) {
|
|
98
|
-
SuperwallExpoModule.
|
|
98
|
+
SuperwallExpoModule.emitEvent(name, body)
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
override fun willRedeemLink() {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package expo.modules.superwallexpo.json
|
|
2
|
+
|
|
3
|
+
import com.superwall.sdk.paywall.view.webview.messaging.PageViewData
|
|
4
|
+
|
|
5
|
+
fun PageViewData.toJson(): Map<String, Any> {
|
|
6
|
+
val map = mutableMapOf<String, Any>(
|
|
7
|
+
"pageNodeId" to pageNodeId,
|
|
8
|
+
"flowPosition" to flowPosition,
|
|
9
|
+
"pageName" to pageName,
|
|
10
|
+
"navigationNodeId" to navigationNodeId,
|
|
11
|
+
"navigationType" to navigationType,
|
|
12
|
+
)
|
|
13
|
+
previousPageNodeId?.let { map["previousPageNodeId"] = it }
|
|
14
|
+
previousFlowPosition?.let { map["previousFlowPosition"] = it }
|
|
15
|
+
timeOnPreviousPageMs?.let { map["timeOnPreviousPageMs"] = it }
|
|
16
|
+
return map
|
|
17
|
+
}
|
|
@@ -46,6 +46,11 @@ class SuperwallEvent {
|
|
|
46
46
|
map["event"] = "paywallClose"
|
|
47
47
|
map["paywallInfo"] = superwallPlacement.paywallInfo.toJson()
|
|
48
48
|
}
|
|
49
|
+
is SuperwallEvent.PaywallPageView -> {
|
|
50
|
+
map["event"] = "paywallPageView"
|
|
51
|
+
map["paywallInfo"] = superwallPlacement.paywallInfo.toJson()
|
|
52
|
+
map["data"] = superwallPlacement.data.toJson()
|
|
53
|
+
}
|
|
49
54
|
is SuperwallEvent.PaywallDecline -> {
|
|
50
55
|
map["event"] = "paywallDecline"
|
|
51
56
|
map["paywallInfo"] = superwallPlacement.paywallInfo.toJson()
|
package/build/package.json
CHANGED
|
@@ -31,6 +31,7 @@ export declare class PaywallOptions {
|
|
|
31
31
|
shouldPreload: boolean;
|
|
32
32
|
automaticallyDismiss: boolean;
|
|
33
33
|
transactionBackgroundView: TransactionBackgroundView;
|
|
34
|
+
shouldShowWebPurchaseConfirmationAlert: boolean;
|
|
34
35
|
onBackPressed?: (paywallInfo: PaywallInfo) => boolean;
|
|
35
36
|
constructor(init?: Partial<PaywallOptions>);
|
|
36
37
|
toJson(): object;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PaywallOptions.d.ts","sourceRoot":"","sources":["../../../../src/compat/lib/PaywallOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAahD;;;;GAIG;AACH,oBAAY,yBAAyB;IACnC,OAAO,YAAY;IACnB,IAAI,SAAS;CACd;AAED;;;;GAIG;AACH,qBAAa,aAAa;IACxB,KAAK,SAA0B;IAC/B,OAAO,SAA8D;IACrE,gBAAgB,SAAS;IAEzB,MAAM,IAAI,MAAM;CAOjB;AAED;;;;GAIG;AACH,qBAAa,cAAc;IACzB,uBAAuB,UAAO;IAC9B,aAAa,EAAE,aAAa,CAAsB;IAClD,8BAA8B,UAAO;IACrC,aAAa,UAAQ;IACrB,oBAAoB,UAAO;IAC3B,yBAAyB,EAAE,yBAAyB,CAAoC;IACxF,aAAa,CAAC,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAA;gBAEzC,IAAI,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"PaywallOptions.d.ts","sourceRoot":"","sources":["../../../../src/compat/lib/PaywallOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAahD;;;;GAIG;AACH,oBAAY,yBAAyB;IACnC,OAAO,YAAY;IACnB,IAAI,SAAS;CACd;AAED;;;;GAIG;AACH,qBAAa,aAAa;IACxB,KAAK,SAA0B;IAC/B,OAAO,SAA8D;IACrE,gBAAgB,SAAS;IAEzB,MAAM,IAAI,MAAM;CAOjB;AAED;;;;GAIG;AACH,qBAAa,cAAc;IACzB,uBAAuB,UAAO;IAC9B,aAAa,EAAE,aAAa,CAAsB;IAClD,8BAA8B,UAAO;IACrC,aAAa,UAAQ;IACrB,oBAAoB,UAAO;IAC3B,yBAAyB,EAAE,yBAAyB,CAAoC;IACxF,sCAAsC,UAAQ;IAC9C,aAAa,CAAC,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAA;gBAEzC,IAAI,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC;IAiC1C,MAAM,IAAI,MAAM;CAWjB"}
|
|
@@ -45,6 +45,7 @@ export class PaywallOptions {
|
|
|
45
45
|
shouldPreload = false;
|
|
46
46
|
automaticallyDismiss = true;
|
|
47
47
|
transactionBackgroundView = TransactionBackgroundView.spinner;
|
|
48
|
+
shouldShowWebPurchaseConfirmationAlert = false;
|
|
48
49
|
onBackPressed;
|
|
49
50
|
constructor(init) {
|
|
50
51
|
if (init) {
|
|
@@ -57,6 +58,9 @@ export class PaywallOptions {
|
|
|
57
58
|
if (init.shouldPreload !== undefined) {
|
|
58
59
|
this.shouldPreload = init.shouldPreload;
|
|
59
60
|
}
|
|
61
|
+
if (init.shouldShowWebPurchaseConfirmationAlert !== undefined) {
|
|
62
|
+
this.shouldShowWebPurchaseConfirmationAlert = init.shouldShowWebPurchaseConfirmationAlert;
|
|
63
|
+
}
|
|
60
64
|
if (init.automaticallyDismiss !== undefined) {
|
|
61
65
|
this.automaticallyDismiss = init.automaticallyDismiss;
|
|
62
66
|
}
|
|
@@ -83,6 +87,7 @@ export class PaywallOptions {
|
|
|
83
87
|
shouldPreload: this.shouldPreload,
|
|
84
88
|
automaticallyDismiss: this.automaticallyDismiss,
|
|
85
89
|
transactionBackgroundView: this.transactionBackgroundView,
|
|
90
|
+
shouldShowWebPurchaseConfirmationAlert: this.shouldShowWebPurchaseConfirmationAlert,
|
|
86
91
|
});
|
|
87
92
|
}
|
|
88
93
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PaywallOptions.js","sourceRoot":"","sources":["../../../../src/compat/lib/PaywallOptions.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"PaywallOptions.js","sourceRoot":"","sources":["../../../../src/compat/lib/PaywallOptions.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PaywallInfo } from \"./PaywallInfo\"\n\n/**\n * Helper function to remove undefined values from an object.\n * This is necessary for Android compatibility as the Expo bridge\n * cannot convert undefined to Kotlin types.\n */\nfunction filterUndefined<T extends Record<string, any>>(obj: T): Partial<T> {\n return Object.fromEntries(\n Object.entries(obj).filter(([_, value]) => value !== undefined),\n ) as Partial<T>\n}\n\n/**\n * @category Enums\n * @since 0.0.15\n * Defines the different types of views that can appear behind Apple's payment sheet during a transaction.\n */\nexport enum TransactionBackgroundView {\n spinner = \"spinner\",\n none = \"none\",\n}\n\n/**\n * @category Models\n * @since 0.0.15\n * Defines the messaging of the alert presented to the user when restoring a transaction fails.\n */\nexport class RestoreFailed {\n title = \"No Subscription Found\"\n message = \"We couldn't find an active subscription for your account.\"\n closeButtonTitle = \"Okay\"\n\n toJson(): object {\n return filterUndefined({\n title: this.title,\n message: this.message,\n closeButtonTitle: this.closeButtonTitle,\n })\n }\n}\n\n/**\n * @category Models\n * @since 0.0.15\n * Options for configuring the appearance and behavior of paywalls.\n */\nexport class PaywallOptions {\n isHapticFeedbackEnabled = true\n restoreFailed: RestoreFailed = new RestoreFailed()\n shouldShowPurchaseFailureAlert = true\n shouldPreload = false\n automaticallyDismiss = true\n transactionBackgroundView: TransactionBackgroundView = TransactionBackgroundView.spinner\n shouldShowWebPurchaseConfirmationAlert = false\n onBackPressed?: (paywallInfo: PaywallInfo) => boolean\n\n constructor(init?: Partial<PaywallOptions>) {\n if (init) {\n if (init.isHapticFeedbackEnabled !== undefined) {\n this.isHapticFeedbackEnabled = init.isHapticFeedbackEnabled\n }\n if (init.shouldShowPurchaseFailureAlert !== undefined) {\n this.shouldShowPurchaseFailureAlert = init.shouldShowPurchaseFailureAlert\n }\n if (init.shouldPreload !== undefined) {\n this.shouldPreload = init.shouldPreload\n }\n if (init.shouldShowWebPurchaseConfirmationAlert !== undefined) {\n this.shouldShowWebPurchaseConfirmationAlert = init.shouldShowWebPurchaseConfirmationAlert\n }\n if (init.automaticallyDismiss !== undefined) {\n this.automaticallyDismiss = init.automaticallyDismiss\n }\n if (init.transactionBackgroundView) {\n this.transactionBackgroundView = init.transactionBackgroundView\n }\n if (init.onBackPressed) {\n this.onBackPressed = init.onBackPressed\n }\n if (init.restoreFailed) {\n // Ensure restoreFailed is always a RestoreFailed instance\n this.restoreFailed =\n init.restoreFailed instanceof RestoreFailed\n ? init.restoreFailed\n : Object.assign(new RestoreFailed(), init.restoreFailed)\n }\n }\n }\n\n toJson(): object {\n return filterUndefined({\n isHapticFeedbackEnabled: this.isHapticFeedbackEnabled,\n restoreFailed: this.restoreFailed.toJson(),\n shouldShowPurchaseFailureAlert: this.shouldShowPurchaseFailureAlert,\n shouldPreload: this.shouldPreload,\n automaticallyDismiss: this.automaticallyDismiss,\n transactionBackgroundView: this.transactionBackgroundView,\n shouldShowWebPurchaseConfirmationAlert: this.shouldShowWebPurchaseConfirmationAlert,\n })\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSuperwall.d.ts","sourceRoot":"","sources":["../../src/useSuperwall.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AAGzE,OAAO,KAAK,EACV,gBAAgB,EAChB,qBAAqB,EACrB,yBAAyB,EACzB,kBAAkB,EACnB,MAAM,6BAA6B,CAAA;AACpC,OAAO,EAA2B,KAAK,uBAAuB,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"useSuperwall.d.ts","sourceRoot":"","sources":["../../src/useSuperwall.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,55 @@ import { resolveLocalResources } from "./localResources";
|
|
|
6
6
|
import SuperwallExpoModule from "./SuperwallExpoModule";
|
|
7
7
|
import { DefaultSuperwallOptions } from "./SuperwallOptions";
|
|
8
8
|
import { filterUndefined } from "./utils/filterUndefined";
|
|
9
|
+
const CONFIGURE_WAIT_TIMEOUT_MS = 10_000;
|
|
10
|
+
/**
|
|
11
|
+
* Blocks a native call until Superwall has finished configuring.
|
|
12
|
+
*
|
|
13
|
+
* Resolves as soon as `isConfigured` flips true, rejects if configuration failed
|
|
14
|
+
* (`configurationError`), and otherwise rejects after CONFIGURE_WAIT_TIMEOUT_MS.
|
|
15
|
+
* The timeout clock (re)starts when configure() begins — so a configure() called
|
|
16
|
+
* late still gets the full window — and the error distinguishes "never called"
|
|
17
|
+
* from "called but too slow". Subscribes to the store rather than polling.
|
|
18
|
+
*/
|
|
19
|
+
function awaitConfigured() {
|
|
20
|
+
const { isConfigured, configurationError } = useSuperwallStore.getState();
|
|
21
|
+
if (isConfigured)
|
|
22
|
+
return Promise.resolve();
|
|
23
|
+
if (configurationError)
|
|
24
|
+
return Promise.reject(new Error(configurationError));
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
let timer;
|
|
27
|
+
const settle = (fn) => {
|
|
28
|
+
clearTimeout(timer);
|
|
29
|
+
unsubscribe();
|
|
30
|
+
fn();
|
|
31
|
+
};
|
|
32
|
+
// Restart the clock when configure starts so a late configure() gets the full
|
|
33
|
+
// window instead of inheriting time already spent waiting before it ran.
|
|
34
|
+
const arm = () => {
|
|
35
|
+
clearTimeout(timer);
|
|
36
|
+
timer = setTimeout(() => {
|
|
37
|
+
const inFlight = useSuperwallStore.getState().isLoading;
|
|
38
|
+
settle(() => reject(new Error(inFlight
|
|
39
|
+
? `Superwall configure did not complete within ${CONFIGURE_WAIT_TIMEOUT_MS}ms.`
|
|
40
|
+
: `Superwall configure was not called within ${CONFIGURE_WAIT_TIMEOUT_MS}ms. Did you forget to call configure()?`)));
|
|
41
|
+
}, CONFIGURE_WAIT_TIMEOUT_MS);
|
|
42
|
+
};
|
|
43
|
+
const unsubscribe = useSuperwallStore.subscribe((state, prev) => {
|
|
44
|
+
if (state.isConfigured) {
|
|
45
|
+
settle(resolve);
|
|
46
|
+
}
|
|
47
|
+
else if (state.configurationError) {
|
|
48
|
+
const error = state.configurationError;
|
|
49
|
+
settle(() => reject(new Error(error)));
|
|
50
|
+
}
|
|
51
|
+
else if (state.isLoading && !prev.isLoading) {
|
|
52
|
+
arm();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
arm();
|
|
56
|
+
});
|
|
57
|
+
}
|
|
9
58
|
/**
|
|
10
59
|
* @category Store
|
|
11
60
|
* @since 0.0.15
|
|
@@ -69,6 +118,7 @@ export const useSuperwallStore = create((set, get) => ({
|
|
|
69
118
|
}
|
|
70
119
|
},
|
|
71
120
|
identify: async (userId, options) => {
|
|
121
|
+
await awaitConfigured();
|
|
72
122
|
await SuperwallExpoModule.identify(userId, options);
|
|
73
123
|
// TODO: Instead of setting users after identify, we should set this based on an event
|
|
74
124
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
@@ -79,58 +129,73 @@ export const useSuperwallStore = create((set, get) => ({
|
|
|
79
129
|
set({ user: currentUser, subscriptionStatus });
|
|
80
130
|
},
|
|
81
131
|
reset: async () => {
|
|
132
|
+
await awaitConfigured();
|
|
82
133
|
await SuperwallExpoModule.reset();
|
|
83
134
|
const currentUser = await SuperwallExpoModule.getUserAttributes();
|
|
84
135
|
const subscriptionStatus = await SuperwallExpoModule.getSubscriptionStatus();
|
|
85
136
|
set({ user: currentUser, subscriptionStatus });
|
|
86
137
|
},
|
|
87
138
|
registerPlacement: async (placement, params, handlerId = "default") => {
|
|
139
|
+
await awaitConfigured();
|
|
88
140
|
await SuperwallExpoModule.registerPlacement(placement, params, handlerId);
|
|
89
141
|
},
|
|
90
142
|
getPresentationResult: async (placement, params) => {
|
|
143
|
+
await awaitConfigured();
|
|
91
144
|
return SuperwallExpoModule.getPresentationResult(placement, params);
|
|
92
145
|
},
|
|
93
146
|
restorePurchases: async () => {
|
|
147
|
+
await awaitConfigured();
|
|
94
148
|
return SuperwallExpoModule.restorePurchases();
|
|
95
149
|
},
|
|
96
150
|
dismiss: async () => {
|
|
151
|
+
await awaitConfigured();
|
|
97
152
|
await SuperwallExpoModule.dismiss();
|
|
98
153
|
},
|
|
99
154
|
preloadAllPaywalls: async () => {
|
|
100
|
-
|
|
155
|
+
await awaitConfigured();
|
|
156
|
+
await SuperwallExpoModule.preloadAllPaywalls();
|
|
101
157
|
},
|
|
102
158
|
preloadPaywalls: async (placements) => {
|
|
103
|
-
|
|
159
|
+
await awaitConfigured();
|
|
160
|
+
await SuperwallExpoModule.preloadPaywalls(placements);
|
|
104
161
|
},
|
|
105
162
|
setUserAttributes: async (attrs) => {
|
|
163
|
+
await awaitConfigured();
|
|
106
164
|
await SuperwallExpoModule.setUserAttributes(filterUndefined(attrs));
|
|
107
165
|
const currentUser = await SuperwallExpoModule.getUserAttributes();
|
|
108
166
|
set({ user: currentUser });
|
|
109
167
|
},
|
|
110
168
|
getUserAttributes: async () => {
|
|
169
|
+
await awaitConfigured();
|
|
111
170
|
const attributes = await SuperwallExpoModule.getUserAttributes();
|
|
112
171
|
set({ user: attributes });
|
|
113
172
|
return attributes;
|
|
114
173
|
},
|
|
115
174
|
setLogLevel: async (level) => {
|
|
116
|
-
|
|
175
|
+
await awaitConfigured();
|
|
176
|
+
await SuperwallExpoModule.setLogLevel(level);
|
|
117
177
|
},
|
|
118
178
|
setIntegrationAttributes: async (attributes) => {
|
|
179
|
+
await awaitConfigured();
|
|
119
180
|
await SuperwallExpoModule.setIntegrationAttributes(attributes);
|
|
120
181
|
const currentUser = await SuperwallExpoModule.getUserAttributes();
|
|
121
182
|
set({ user: currentUser });
|
|
122
183
|
},
|
|
123
184
|
getIntegrationAttributes: async () => {
|
|
185
|
+
await awaitConfigured();
|
|
124
186
|
return SuperwallExpoModule.getIntegrationAttributes();
|
|
125
187
|
},
|
|
126
188
|
setSubscriptionStatus: async (status) => {
|
|
189
|
+
await awaitConfigured();
|
|
127
190
|
await SuperwallExpoModule.setSubscriptionStatus(status);
|
|
128
191
|
},
|
|
129
192
|
getDeviceAttributes: async () => {
|
|
193
|
+
await awaitConfigured();
|
|
130
194
|
const attributes = await SuperwallExpoModule.getDeviceAttributes();
|
|
131
195
|
return attributes;
|
|
132
196
|
},
|
|
133
197
|
getEntitlements: async () => {
|
|
198
|
+
await awaitConfigured();
|
|
134
199
|
const entitlements = await SuperwallExpoModule.getEntitlements();
|
|
135
200
|
return entitlements;
|
|
136
201
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSuperwall.js","sourceRoot":"","sources":["../../src/useSuperwall.ts"],"names":[],"mappings":"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","sourcesContent":["import { createContext, useContext } from \"react\"\nimport { create } from \"zustand\"\nimport { useShallow } from \"zustand/shallow\"\nimport pkg from \"../package.json\"\nimport type { PresentationResult } from \"./compat/lib/PresentationResult\"\nimport { resolveLocalResources } from \"./localResources\"\nimport SuperwallExpoModule from \"./SuperwallExpoModule\"\nimport type {\n EntitlementsInfo,\n IntegrationAttributes,\n RestorationResultResponse,\n SubscriptionStatus,\n} from \"./SuperwallExpoModule.types\"\nimport { DefaultSuperwallOptions, type PartialSuperwallOptions } from \"./SuperwallOptions\"\nimport { filterUndefined } from \"./utils/filterUndefined\"\n\n/**\n * @category Models\n * @since 0.0.15\n * Interface representing the attributes of a user.\n */\nexport interface UserAttributes {\n /** The user's alias ID, if set. */\n aliasId: string\n /** The user's application-specific user ID. */\n appUserId: string\n /** The ISO 8601 date string representation of when the application was installed on the user's device. */\n applicationInstalledAt: string\n /** A seed value associated with the user, used for consistent variant assignments in experiments. */\n seed: number\n /** Allows for custom attributes to be set for the user. These can be of any type. */\n [key: string]: any | null\n}\n\n/**\n * @category Models\n * @since 0.0.15\n * Options for the `identify` method.\n */\nexport interface IdentifyOptions {\n /**\n * Determines whether to restore paywall assignments from a previous session for the identified user.\n * If `true`, the SDK attempts to restore the assignments. Defaults to `false`.\n */\n restorePaywallAssignments?: boolean\n}\n\n/**\n * @category Store\n * @since 0.0.15\n * Defines the structure of the Superwall store, including its state and actions.\n * This store is managed by Zustand.\n */\nexport interface SuperwallStore {\n /* -------------------- State -------------------- */\n /** Indicates whether the Superwall SDK has been successfully configured. */\n isConfigured: boolean\n /** Indicates whether the SDK is currently performing a loading operation (e.g., configuring, fetching data). */\n isLoading: boolean\n /** Indicates whether the native event listeners have been initialized. */\n listenersInitialized: boolean\n\n /**\n * Contains error message if SDK configuration failed, `null` otherwise.\n * When this is set, the SDK is not configured and app should show error UI.\n */\n configurationError: string | null\n\n /**\n * The current user's attributes.\n * `null` if no user is identified or after `reset` is called.\n * `undefined` initially before any user data is fetched or set.\n */\n user?: UserAttributes | null\n\n /** The current subscription status of the user. */\n subscriptionStatus: SubscriptionStatus\n\n /* -------------------- Internal -------------------- */\n // Internal listener references for cleanup handled inside Provider effect.\n // Not reactive, so we store outside Zustand state to avoid unnecessary rerenders.\n\n /* -------------------- Actions -------------------- */\n /**\n * Configures the Superwall SDK with the provided API key and options.\n * This must be called before most other SDK functions can be used.\n * @param apiKey - Your Superwall API key.\n * @param options - Optional configuration settings for the SDK.\n * @returns A promise that resolves when configuration is complete.\n * @internal\n */\n configure: (\n apiKey: string,\n options?: PartialSuperwallOptions & {\n /** @deprecated Use manualPurchaseManagement instead */\n manualPurchaseManagment?: boolean\n },\n ) => Promise<void>\n /**\n * Identifies the current user with a unique ID.\n * @param userId - The unique identifier for the user.\n * @param options - Optional parameters for identification.\n * @returns A promise that resolves when identification is complete.\n */\n identify: (userId: string, options?: IdentifyOptions) => Promise<void>\n /**\n * Resets the user's identity and clears all user-specific data, effectively logging them out.\n * @internal\n */\n reset: () => Promise<void>\n\n /**\n * Registers a placement to potentially show a paywall.\n * The decision to show a paywall is determined by campaign rules and user assignments on the Superwall dashboard.\n * @param placement - The ID of the placement to register.\n * @param params - Optional parameters to pass with the placement.\n * @param handlerId - An optional identifier used to associate specific event handlers (e.g., from `usePlacement`). Defaults to \"default\".\n * @returns A promise that resolves when the placement registration is complete.\n */\n registerPlacement: (\n placement: string,\n params?: Record<string, any>,\n handlerId?: string | null,\n ) => Promise<void>\n /**\n * Retrieves the presentation result for a given placement.\n * This can be used to understand what would happen if a placement were to be registered, without actually registering it.\n * @param placement - The ID of the placement.\n * @param params - Optional parameters for the placement.\n * @returns A promise that resolves with the presentation result.\n */\n getPresentationResult: (\n placement: string,\n params?: Record<string, any>,\n ) => Promise<PresentationResult>\n /**\n * Programmatically restores purchases.\n * @returns A promise that resolves with a {@link RestorationResultResponse} indicating success or failure.\n */\n restorePurchases: () => Promise<RestorationResultResponse>\n\n /**\n * Dismisses any currently presented Superwall paywall.\n * @returns A promise that resolves when the dismissal is complete.\n */\n dismiss: () => Promise<void>\n\n /**\n * Preloads all paywalls configured in your Superwall dashboard.\n * @returns A promise that resolves when preloading is complete.\n */\n preloadAllPaywalls: () => Promise<void>\n /**\n * Preloads specific paywalls.\n * @param placements - An array of placement IDs for which to preload paywalls.\n * @returns A promise that resolves when preloading is complete.\n */\n preloadPaywalls: (placements: string[]) => Promise<void>\n\n /**\n * Sets custom attributes for the current user.\n * @param attrs - An object containing the attributes to set.\n * @returns A promise that resolves when attributes are set.\n */\n setUserAttributes: (attrs: Record<string, any | null>) => Promise<void>\n /**\n * Retrieves the current user's attributes.\n * @returns A promise that resolves with the user's attributes.\n */\n getUserAttributes: () => Promise<Record<string, any>>\n\n /**\n * Sets the logging level for the Superwall SDK.\n * @param level - The desired log level (e.g., \"debug\", \"info\", \"warn\", \"error\", \"none\").\n * @returns A promise that resolves when the log level is set.\n */\n setLogLevel: (level: string) => Promise<void>\n\n /**\n * Sets attributes for third-party integrations.\n * @param attributes - Object mapping IntegrationAttribute string values to their IDs\n * @returns A promise that resolves when attributes are set\n */\n setIntegrationAttributes: (attributes: IntegrationAttributes) => Promise<void>\n\n /**\n * Gets the currently set integration attributes.\n * @returns A promise that resolves with the current integration attributes\n */\n getIntegrationAttributes: () => Promise<Record<string, string>>\n\n /* -------------------- Listener helpers -------------------- */\n /**\n * Initializes native event listeners for the SDK.\n * This is typically called internally by the `SuperwallProvider`.\n * @returns A cleanup function to remove the listeners.\n * @internal\n */\n _initListeners: () => () => void\n\n setSubscriptionStatus: (status: SubscriptionStatus) => Promise<void>\n\n getDeviceAttributes: () => Promise<Record<string, any>>\n\n /**\n * Retrieves the user's entitlements from Superwall's servers.\n * This includes both active and inactive entitlements.\n * @returns A promise that resolves with the entitlements information.\n */\n getEntitlements: () => Promise<EntitlementsInfo>\n}\n\n/**\n * @category Store\n * @since 0.0.15\n * Zustand store for Superwall SDK state and actions.\n * @internal\n */\nexport const useSuperwallStore = create<SuperwallStore>((set, get) => ({\n /* -------------------- State -------------------- */\n isConfigured: false,\n isLoading: false,\n listenersInitialized: false,\n configurationError: null,\n\n user: null,\n subscriptionStatus: {\n status: \"UNKNOWN\",\n },\n\n /* -------------------- Actions -------------------- */\n configure: async (apiKey, options) => {\n set({ isLoading: true, configurationError: null })\n\n try {\n const { manualPurchaseManagement, manualPurchaseManagment, localResources, ...restOptions } =\n options || {}\n\n // Support both spellings for backward compatibility\n const isManualPurchaseManagement =\n manualPurchaseManagement ?? manualPurchaseManagment ?? false\n\n const resolvedLocalResources = await resolveLocalResources(localResources)\n\n // Deep merge partial options with defaults to ensure all required fields are present\n const mergedOptions = {\n ...DefaultSuperwallOptions,\n ...restOptions,\n ...(resolvedLocalResources ? { localResources: resolvedLocalResources } : {}),\n paywalls: {\n ...DefaultSuperwallOptions.paywalls,\n ...restOptions.paywalls,\n restoreFailed: {\n ...DefaultSuperwallOptions.paywalls.restoreFailed,\n ...restOptions.paywalls?.restoreFailed,\n },\n },\n logging: {\n ...DefaultSuperwallOptions.logging,\n ...restOptions.logging,\n },\n }\n\n await SuperwallExpoModule.configure(\n apiKey,\n mergedOptions,\n isManualPurchaseManagement,\n pkg.version,\n )\n\n const currentUser = await SuperwallExpoModule.getUserAttributes()\n const subscriptionStatus = await SuperwallExpoModule.getSubscriptionStatus()\n\n set({\n isConfigured: true,\n isLoading: false,\n configurationError: null,\n user: currentUser as UserAttributes,\n subscriptionStatus,\n })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n set({\n isLoading: false,\n configurationError: errorMessage,\n })\n // Don't throw - let developers handle via state or callback\n }\n },\n identify: async (userId, options) => {\n await SuperwallExpoModule.identify(userId, options)\n\n // TODO: Instead of setting users after identify, we should set this based on an event\n await new Promise((resolve) => setTimeout(resolve, 0))\n\n const [currentUser, subscriptionStatus] = await Promise.all([\n SuperwallExpoModule.getUserAttributes(),\n SuperwallExpoModule.getSubscriptionStatus(),\n ])\n\n set({ user: currentUser as UserAttributes, subscriptionStatus })\n },\n reset: async () => {\n await SuperwallExpoModule.reset()\n\n const currentUser = await SuperwallExpoModule.getUserAttributes()\n const subscriptionStatus = await SuperwallExpoModule.getSubscriptionStatus()\n\n set({ user: currentUser as UserAttributes, subscriptionStatus })\n },\n registerPlacement: async (placement, params, handlerId = \"default\") => {\n await SuperwallExpoModule.registerPlacement(placement, params, handlerId)\n },\n getPresentationResult: async (placement, params) => {\n return SuperwallExpoModule.getPresentationResult(placement, params)\n },\n restorePurchases: async () => {\n return SuperwallExpoModule.restorePurchases()\n },\n dismiss: async () => {\n await SuperwallExpoModule.dismiss()\n },\n preloadAllPaywalls: async () => {\n SuperwallExpoModule.preloadAllPaywalls()\n },\n preloadPaywalls: async (placements) => {\n SuperwallExpoModule.preloadPaywalls(placements)\n },\n setUserAttributes: async (attrs) => {\n await SuperwallExpoModule.setUserAttributes(filterUndefined(attrs))\n\n const currentUser = await SuperwallExpoModule.getUserAttributes()\n set({ user: currentUser as UserAttributes })\n },\n getUserAttributes: async () => {\n const attributes = await SuperwallExpoModule.getUserAttributes()\n set({ user: attributes as UserAttributes })\n return attributes\n },\n setLogLevel: async (level) => {\n SuperwallExpoModule.setLogLevel(level)\n },\n\n setIntegrationAttributes: async (attributes) => {\n await SuperwallExpoModule.setIntegrationAttributes(attributes)\n\n const currentUser = await SuperwallExpoModule.getUserAttributes()\n set({ user: currentUser as UserAttributes })\n },\n\n getIntegrationAttributes: async () => {\n return SuperwallExpoModule.getIntegrationAttributes()\n },\n\n setSubscriptionStatus: async (status) => {\n await SuperwallExpoModule.setSubscriptionStatus(status)\n },\n getDeviceAttributes: async () => {\n const attributes = await SuperwallExpoModule.getDeviceAttributes()\n return attributes\n },\n getEntitlements: async () => {\n const entitlements = await SuperwallExpoModule.getEntitlements()\n return entitlements as EntitlementsInfo\n },\n\n /* -------------------- Listener helpers -------------------- */\n _initListeners: (): (() => void) => {\n // Use get() to read the state from within the store\n if (get().listenersInitialized) {\n console.warn(\"[Superwall] Listeners already initialized. Skipping.\")\n return () => {} // Return no-op cleanup\n }\n\n const subscriptions: { remove: () => void }[] = []\n\n subscriptions.push(\n SuperwallExpoModule.addListener(\n \"subscriptionStatusDidChange\",\n ({ to }: { to: SubscriptionStatus }) => {\n set({ subscriptionStatus: to })\n },\n ),\n )\n\n // Listen for configuration events\n subscriptions.push(\n SuperwallExpoModule.addListener(\"handleSuperwallEvent\", ({ eventInfo }) => {\n if (eventInfo.event.event === \"configFail\") {\n set({\n configurationError: \"Failed to load Superwall configuration\",\n isLoading: false,\n })\n } else if (eventInfo.event.event === \"configRefresh\") {\n // Clear any previous errors on successful refresh\n set({ configurationError: null })\n }\n }),\n )\n\n set({ listenersInitialized: true })\n console.log(\"[Superwall] Initialized listeners\", subscriptions.length)\n\n return (): void => {\n console.log(\"[Superwall] Cleaning up listeners\", subscriptions.length)\n // biome-ignore lint/suspicious/useIterableCallbackReturn: forEach is used for side effects only\n subscriptions.forEach((s) => s.remove())\n // Reset the state on cleanup\n set({ listenersInitialized: false })\n }\n },\n}))\n\n/**\n * @category Store\n * @since 0.0.15\n * Public interface for the Superwall store, excluding internal methods.\n */\nexport type PublicSuperwallStore = Omit<SuperwallStore, \"configure\" | \"reset\" | \"_initListeners\">\n\nexport const SuperwallContext = createContext<boolean>(false)\n\n/**\n * @category Hooks\n * @since 0.0.15\n * Core React hook for interacting with the Superwall SDK.\n *\n * This hook provides access to the Superwall store, which includes SDK state\n * (like configuration status, user information, subscription status) and actions\n * (like `identify`, `reset`, `registerPlacement`).\n *\n * It must be used within a component that is a descendant of `<SuperwallProvider />`.\n *\n * @template T - Optional type parameter for the selected state. Defaults to the entire `PublicSuperwallStore`.\n * @param selector - An optional function to select a specific slice of the store's state.\n * This is useful for performance optimization, as components will only re-render\n * if the selected part of the state changes. Uses shallow equality checking\n * via `zustand/shallow`. If omitted, the entire store is returned.\n * @returns The selected slice of the Superwall store state, or the entire store if no selector is provided.\n * @throws Error if used outside of a `SuperwallProvider`.\n *\n * @example\n * // Get the entire store\n * const superwall = useSuperwall();\n * console.log(superwall.isConfigured);\n * superwall.identify(\"user_123\");\n *\n * @example\n * // Select specific state properties\n * const { user, subscriptionStatus } = useSuperwall(state => ({\n * user: state.user,\n * subscriptionStatus: state.subscriptionStatus,\n * }));\n * console.log(user?.appUserId, subscriptionStatus?.status);\n */\nexport function useSuperwall<T = PublicSuperwallStore>(selector?: (state: SuperwallStore) => T): T {\n const inProvider = useContext(SuperwallContext)\n if (!inProvider) {\n throw new Error(\"useSuperwall must be used within a SuperwallProvider\")\n }\n\n const identity = (state: SuperwallStore) => state as unknown as T\n // biome-ignore lint/correctness/useHookAtTopLevel: good here\n return useSuperwallStore(selector ? useShallow(selector) : identity)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"useSuperwall.js","sourceRoot":"","sources":["../../src/useSuperwall.ts"],"names":[],"mappings":"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","sourcesContent":["import { createContext, useContext } from \"react\"\nimport { create } from \"zustand\"\nimport { useShallow } from \"zustand/shallow\"\nimport pkg from \"../package.json\"\nimport type { PresentationResult } from \"./compat/lib/PresentationResult\"\nimport { resolveLocalResources } from \"./localResources\"\nimport SuperwallExpoModule from \"./SuperwallExpoModule\"\nimport type {\n EntitlementsInfo,\n IntegrationAttributes,\n RestorationResultResponse,\n SubscriptionStatus,\n} from \"./SuperwallExpoModule.types\"\nimport { DefaultSuperwallOptions, type PartialSuperwallOptions } from \"./SuperwallOptions\"\nimport { filterUndefined } from \"./utils/filterUndefined\"\n\nconst CONFIGURE_WAIT_TIMEOUT_MS = 10_000\n\n/**\n * Blocks a native call until Superwall has finished configuring.\n *\n * Resolves as soon as `isConfigured` flips true, rejects if configuration failed\n * (`configurationError`), and otherwise rejects after CONFIGURE_WAIT_TIMEOUT_MS.\n * The timeout clock (re)starts when configure() begins — so a configure() called\n * late still gets the full window — and the error distinguishes \"never called\"\n * from \"called but too slow\". Subscribes to the store rather than polling.\n */\nfunction awaitConfigured(): Promise<void> {\n const { isConfigured, configurationError } = useSuperwallStore.getState()\n if (isConfigured) return Promise.resolve()\n if (configurationError) return Promise.reject(new Error(configurationError))\n\n return new Promise<void>((resolve, reject) => {\n let timer: ReturnType<typeof setTimeout>\n\n const settle = (fn: () => void) => {\n clearTimeout(timer)\n unsubscribe()\n fn()\n }\n\n // Restart the clock when configure starts so a late configure() gets the full\n // window instead of inheriting time already spent waiting before it ran.\n const arm = () => {\n clearTimeout(timer)\n timer = setTimeout(() => {\n const inFlight = useSuperwallStore.getState().isLoading\n settle(() =>\n reject(\n new Error(\n inFlight\n ? `Superwall configure did not complete within ${CONFIGURE_WAIT_TIMEOUT_MS}ms.`\n : `Superwall configure was not called within ${CONFIGURE_WAIT_TIMEOUT_MS}ms. Did you forget to call configure()?`,\n ),\n ),\n )\n }, CONFIGURE_WAIT_TIMEOUT_MS)\n }\n\n const unsubscribe = useSuperwallStore.subscribe((state, prev) => {\n if (state.isConfigured) {\n settle(resolve)\n } else if (state.configurationError) {\n const error = state.configurationError\n settle(() => reject(new Error(error)))\n } else if (state.isLoading && !prev.isLoading) {\n arm()\n }\n })\n\n arm()\n })\n}\n\n/**\n * @category Models\n * @since 0.0.15\n * Interface representing the attributes of a user.\n */\nexport interface UserAttributes {\n /** The user's alias ID, if set. */\n aliasId: string\n /** The user's application-specific user ID. */\n appUserId: string\n /** The ISO 8601 date string representation of when the application was installed on the user's device. */\n applicationInstalledAt: string\n /** A seed value associated with the user, used for consistent variant assignments in experiments. */\n seed: number\n /** Allows for custom attributes to be set for the user. These can be of any type. */\n [key: string]: any | null\n}\n\n/**\n * @category Models\n * @since 0.0.15\n * Options for the `identify` method.\n */\nexport interface IdentifyOptions {\n /**\n * Determines whether to restore paywall assignments from a previous session for the identified user.\n * If `true`, the SDK attempts to restore the assignments. Defaults to `false`.\n */\n restorePaywallAssignments?: boolean\n}\n\n/**\n * @category Store\n * @since 0.0.15\n * Defines the structure of the Superwall store, including its state and actions.\n * This store is managed by Zustand.\n */\nexport interface SuperwallStore {\n /* -------------------- State -------------------- */\n /** Indicates whether the Superwall SDK has been successfully configured. */\n isConfigured: boolean\n /** Indicates whether the SDK is currently performing a loading operation (e.g., configuring, fetching data). */\n isLoading: boolean\n /** Indicates whether the native event listeners have been initialized. */\n listenersInitialized: boolean\n\n /**\n * Contains error message if SDK configuration failed, `null` otherwise.\n * When this is set, the SDK is not configured and app should show error UI.\n */\n configurationError: string | null\n\n /**\n * The current user's attributes.\n * `null` if no user is identified or after `reset` is called.\n * `undefined` initially before any user data is fetched or set.\n */\n user?: UserAttributes | null\n\n /** The current subscription status of the user. */\n subscriptionStatus: SubscriptionStatus\n\n /* -------------------- Internal -------------------- */\n // Internal listener references for cleanup handled inside Provider effect.\n // Not reactive, so we store outside Zustand state to avoid unnecessary rerenders.\n\n /* -------------------- Actions -------------------- */\n /**\n * Configures the Superwall SDK with the provided API key and options.\n * This must be called before most other SDK functions can be used.\n * @param apiKey - Your Superwall API key.\n * @param options - Optional configuration settings for the SDK.\n * @returns A promise that resolves when configuration is complete.\n * @internal\n */\n configure: (\n apiKey: string,\n options?: PartialSuperwallOptions & {\n /** @deprecated Use manualPurchaseManagement instead */\n manualPurchaseManagment?: boolean\n },\n ) => Promise<void>\n /**\n * Identifies the current user with a unique ID.\n * @param userId - The unique identifier for the user.\n * @param options - Optional parameters for identification.\n * @returns A promise that resolves when identification is complete.\n */\n identify: (userId: string, options?: IdentifyOptions) => Promise<void>\n /**\n * Resets the user's identity and clears all user-specific data, effectively logging them out.\n * @internal\n */\n reset: () => Promise<void>\n\n /**\n * Registers a placement to potentially show a paywall.\n * The decision to show a paywall is determined by campaign rules and user assignments on the Superwall dashboard.\n * @param placement - The ID of the placement to register.\n * @param params - Optional parameters to pass with the placement.\n * @param handlerId - An optional identifier used to associate specific event handlers (e.g., from `usePlacement`). Defaults to \"default\".\n * @returns A promise that resolves when the placement registration is complete.\n */\n registerPlacement: (\n placement: string,\n params?: Record<string, any>,\n handlerId?: string | null,\n ) => Promise<void>\n /**\n * Retrieves the presentation result for a given placement.\n * This can be used to understand what would happen if a placement were to be registered, without actually registering it.\n * @param placement - The ID of the placement.\n * @param params - Optional parameters for the placement.\n * @returns A promise that resolves with the presentation result.\n */\n getPresentationResult: (\n placement: string,\n params?: Record<string, any>,\n ) => Promise<PresentationResult>\n /**\n * Programmatically restores purchases.\n * @returns A promise that resolves with a {@link RestorationResultResponse} indicating success or failure.\n */\n restorePurchases: () => Promise<RestorationResultResponse>\n\n /**\n * Dismisses any currently presented Superwall paywall.\n * @returns A promise that resolves when the dismissal is complete.\n */\n dismiss: () => Promise<void>\n\n /**\n * Preloads all paywalls configured in your Superwall dashboard.\n * @returns A promise that resolves when preloading is complete.\n */\n preloadAllPaywalls: () => Promise<void>\n /**\n * Preloads specific paywalls.\n * @param placements - An array of placement IDs for which to preload paywalls.\n * @returns A promise that resolves when preloading is complete.\n */\n preloadPaywalls: (placements: string[]) => Promise<void>\n\n /**\n * Sets custom attributes for the current user.\n * @param attrs - An object containing the attributes to set.\n * @returns A promise that resolves when attributes are set.\n */\n setUserAttributes: (attrs: Record<string, any | null>) => Promise<void>\n /**\n * Retrieves the current user's attributes.\n * @returns A promise that resolves with the user's attributes.\n */\n getUserAttributes: () => Promise<Record<string, any>>\n\n /**\n * Sets the logging level for the Superwall SDK.\n * @param level - The desired log level (e.g., \"debug\", \"info\", \"warn\", \"error\", \"none\").\n * @returns A promise that resolves when the log level is set.\n */\n setLogLevel: (level: string) => Promise<void>\n\n /**\n * Sets attributes for third-party integrations.\n * @param attributes - Object mapping IntegrationAttribute string values to their IDs\n * @returns A promise that resolves when attributes are set\n */\n setIntegrationAttributes: (attributes: IntegrationAttributes) => Promise<void>\n\n /**\n * Gets the currently set integration attributes.\n * @returns A promise that resolves with the current integration attributes\n */\n getIntegrationAttributes: () => Promise<Record<string, string>>\n\n /* -------------------- Listener helpers -------------------- */\n /**\n * Initializes native event listeners for the SDK.\n * This is typically called internally by the `SuperwallProvider`.\n * @returns A cleanup function to remove the listeners.\n * @internal\n */\n _initListeners: () => () => void\n\n setSubscriptionStatus: (status: SubscriptionStatus) => Promise<void>\n\n getDeviceAttributes: () => Promise<Record<string, any>>\n\n /**\n * Retrieves the user's entitlements from Superwall's servers.\n * This includes both active and inactive entitlements.\n * @returns A promise that resolves with the entitlements information.\n */\n getEntitlements: () => Promise<EntitlementsInfo>\n}\n\n/**\n * @category Store\n * @since 0.0.15\n * Zustand store for Superwall SDK state and actions.\n * @internal\n */\nexport const useSuperwallStore = create<SuperwallStore>((set, get) => ({\n /* -------------------- State -------------------- */\n isConfigured: false,\n isLoading: false,\n listenersInitialized: false,\n configurationError: null,\n\n user: null,\n subscriptionStatus: {\n status: \"UNKNOWN\",\n },\n\n /* -------------------- Actions -------------------- */\n configure: async (apiKey, options) => {\n set({ isLoading: true, configurationError: null })\n\n try {\n const { manualPurchaseManagement, manualPurchaseManagment, localResources, ...restOptions } =\n options || {}\n\n // Support both spellings for backward compatibility\n const isManualPurchaseManagement =\n manualPurchaseManagement ?? manualPurchaseManagment ?? false\n\n const resolvedLocalResources = await resolveLocalResources(localResources)\n\n // Deep merge partial options with defaults to ensure all required fields are present\n const mergedOptions = {\n ...DefaultSuperwallOptions,\n ...restOptions,\n ...(resolvedLocalResources ? { localResources: resolvedLocalResources } : {}),\n paywalls: {\n ...DefaultSuperwallOptions.paywalls,\n ...restOptions.paywalls,\n restoreFailed: {\n ...DefaultSuperwallOptions.paywalls.restoreFailed,\n ...restOptions.paywalls?.restoreFailed,\n },\n },\n logging: {\n ...DefaultSuperwallOptions.logging,\n ...restOptions.logging,\n },\n }\n\n await SuperwallExpoModule.configure(\n apiKey,\n mergedOptions,\n isManualPurchaseManagement,\n pkg.version,\n )\n\n const currentUser = await SuperwallExpoModule.getUserAttributes()\n const subscriptionStatus = await SuperwallExpoModule.getSubscriptionStatus()\n\n set({\n isConfigured: true,\n isLoading: false,\n configurationError: null,\n user: currentUser as UserAttributes,\n subscriptionStatus,\n })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n set({\n isLoading: false,\n configurationError: errorMessage,\n })\n // Don't throw - let developers handle via state or callback\n }\n },\n identify: async (userId, options) => {\n await awaitConfigured()\n await SuperwallExpoModule.identify(userId, options)\n\n // TODO: Instead of setting users after identify, we should set this based on an event\n await new Promise((resolve) => setTimeout(resolve, 0))\n\n const [currentUser, subscriptionStatus] = await Promise.all([\n SuperwallExpoModule.getUserAttributes(),\n SuperwallExpoModule.getSubscriptionStatus(),\n ])\n\n set({ user: currentUser as UserAttributes, subscriptionStatus })\n },\n reset: async () => {\n await awaitConfigured()\n await SuperwallExpoModule.reset()\n\n const currentUser = await SuperwallExpoModule.getUserAttributes()\n const subscriptionStatus = await SuperwallExpoModule.getSubscriptionStatus()\n\n set({ user: currentUser as UserAttributes, subscriptionStatus })\n },\n registerPlacement: async (placement, params, handlerId = \"default\") => {\n await awaitConfigured()\n await SuperwallExpoModule.registerPlacement(placement, params, handlerId)\n },\n getPresentationResult: async (placement, params) => {\n await awaitConfigured()\n return SuperwallExpoModule.getPresentationResult(placement, params)\n },\n restorePurchases: async () => {\n await awaitConfigured()\n return SuperwallExpoModule.restorePurchases()\n },\n dismiss: async () => {\n await awaitConfigured()\n await SuperwallExpoModule.dismiss()\n },\n preloadAllPaywalls: async () => {\n await awaitConfigured()\n await SuperwallExpoModule.preloadAllPaywalls()\n },\n preloadPaywalls: async (placements) => {\n await awaitConfigured()\n await SuperwallExpoModule.preloadPaywalls(placements)\n },\n setUserAttributes: async (attrs) => {\n await awaitConfigured()\n await SuperwallExpoModule.setUserAttributes(filterUndefined(attrs))\n\n const currentUser = await SuperwallExpoModule.getUserAttributes()\n set({ user: currentUser as UserAttributes })\n },\n getUserAttributes: async () => {\n await awaitConfigured()\n const attributes = await SuperwallExpoModule.getUserAttributes()\n set({ user: attributes as UserAttributes })\n return attributes\n },\n setLogLevel: async (level) => {\n await awaitConfigured()\n await SuperwallExpoModule.setLogLevel(level)\n },\n\n setIntegrationAttributes: async (attributes) => {\n await awaitConfigured()\n await SuperwallExpoModule.setIntegrationAttributes(attributes)\n\n const currentUser = await SuperwallExpoModule.getUserAttributes()\n set({ user: currentUser as UserAttributes })\n },\n\n getIntegrationAttributes: async () => {\n await awaitConfigured()\n return SuperwallExpoModule.getIntegrationAttributes()\n },\n\n setSubscriptionStatus: async (status) => {\n await awaitConfigured()\n await SuperwallExpoModule.setSubscriptionStatus(status)\n },\n getDeviceAttributes: async () => {\n await awaitConfigured()\n const attributes = await SuperwallExpoModule.getDeviceAttributes()\n return attributes\n },\n getEntitlements: async () => {\n await awaitConfigured()\n const entitlements = await SuperwallExpoModule.getEntitlements()\n return entitlements as EntitlementsInfo\n },\n\n /* -------------------- Listener helpers -------------------- */\n _initListeners: (): (() => void) => {\n // Use get() to read the state from within the store\n if (get().listenersInitialized) {\n console.warn(\"[Superwall] Listeners already initialized. Skipping.\")\n return () => {} // Return no-op cleanup\n }\n\n const subscriptions: { remove: () => void }[] = []\n\n subscriptions.push(\n SuperwallExpoModule.addListener(\n \"subscriptionStatusDidChange\",\n ({ to }: { to: SubscriptionStatus }) => {\n set({ subscriptionStatus: to })\n },\n ),\n )\n\n // Listen for configuration events\n subscriptions.push(\n SuperwallExpoModule.addListener(\"handleSuperwallEvent\", ({ eventInfo }) => {\n if (eventInfo.event.event === \"configFail\") {\n set({\n configurationError: \"Failed to load Superwall configuration\",\n isLoading: false,\n })\n } else if (eventInfo.event.event === \"configRefresh\") {\n // Clear any previous errors on successful refresh\n set({ configurationError: null })\n }\n }),\n )\n\n set({ listenersInitialized: true })\n console.log(\"[Superwall] Initialized listeners\", subscriptions.length)\n\n return (): void => {\n console.log(\"[Superwall] Cleaning up listeners\", subscriptions.length)\n // biome-ignore lint/suspicious/useIterableCallbackReturn: forEach is used for side effects only\n subscriptions.forEach((s) => s.remove())\n // Reset the state on cleanup\n set({ listenersInitialized: false })\n }\n },\n}))\n\n/**\n * @category Store\n * @since 0.0.15\n * Public interface for the Superwall store, excluding internal methods.\n */\nexport type PublicSuperwallStore = Omit<SuperwallStore, \"configure\" | \"reset\" | \"_initListeners\">\n\nexport const SuperwallContext = createContext<boolean>(false)\n\n/**\n * @category Hooks\n * @since 0.0.15\n * Core React hook for interacting with the Superwall SDK.\n *\n * This hook provides access to the Superwall store, which includes SDK state\n * (like configuration status, user information, subscription status) and actions\n * (like `identify`, `reset`, `registerPlacement`).\n *\n * It must be used within a component that is a descendant of `<SuperwallProvider />`.\n *\n * @template T - Optional type parameter for the selected state. Defaults to the entire `PublicSuperwallStore`.\n * @param selector - An optional function to select a specific slice of the store's state.\n * This is useful for performance optimization, as components will only re-render\n * if the selected part of the state changes. Uses shallow equality checking\n * via `zustand/shallow`. If omitted, the entire store is returned.\n * @returns The selected slice of the Superwall store state, or the entire store if no selector is provided.\n * @throws Error if used outside of a `SuperwallProvider`.\n *\n * @example\n * // Get the entire store\n * const superwall = useSuperwall();\n * console.log(superwall.isConfigured);\n * superwall.identify(\"user_123\");\n *\n * @example\n * // Select specific state properties\n * const { user, subscriptionStatus } = useSuperwall(state => ({\n * user: state.user,\n * subscriptionStatus: state.subscriptionStatus,\n * }));\n * console.log(user?.appUserId, subscriptionStatus?.status);\n */\nexport function useSuperwall<T = PublicSuperwallStore>(selector?: (state: SuperwallStore) => T): T {\n const inProvider = useContext(SuperwallContext)\n if (!inProvider) {\n throw new Error(\"useSuperwall must be used within a SuperwallProvider\")\n }\n\n const identity = (state: SuperwallStore) => state as unknown as T\n // biome-ignore lint/correctness/useHookAtTopLevel: good here\n return useSuperwallStore(selector ? useShallow(selector) : identity)\n}\n"]}
|
|
@@ -2,6 +2,35 @@ require 'json'
|
|
|
2
2
|
|
|
3
3
|
package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
|
|
4
4
|
|
|
5
|
+
# expo-superwall supports Expo SDK 53+, and ExpoModulesCore's minimum iOS/tvOS
|
|
6
|
+
# deployment target differs per SDK (15.1 on SDK 53, 16.4 on SDK 56+). We have
|
|
7
|
+
# to land between two hard constraints:
|
|
8
|
+
# * Lower than ExpoModulesCore's target → Swift refuses to import it
|
|
9
|
+
# ("module 'ExpoModulesCore' has a minimum deployment target of iOS 16.4").
|
|
10
|
+
# * Higher than the host app's Podfile platform → CocoaPods refuses to
|
|
11
|
+
# install ("required a higher minimum deployment target").
|
|
12
|
+
# So we mirror the ExpoModulesCore that's actually installed, never dropping
|
|
13
|
+
# below our own 15.1 floor. One podspec stays correct across every supported
|
|
14
|
+
# SDK (and any future bump) without forcing a value on anyone.
|
|
15
|
+
expo_modules_core_podspec = begin
|
|
16
|
+
resolved = `node --print "require.resolve('expo-modules-core/package.json')" 2>/dev/null`.strip
|
|
17
|
+
[
|
|
18
|
+
(resolved.empty? ? nil : File.join(File.dirname(resolved), 'ExpoModulesCore.podspec')),
|
|
19
|
+
File.join(__dir__, '..', '..', 'expo-modules-core', 'ExpoModulesCore.podspec'),
|
|
20
|
+
].compact.find { |path| File.exist?(path) }
|
|
21
|
+
rescue StandardError
|
|
22
|
+
# `node` may be unavailable (e.g. resolving from a tarball); fall back to the
|
|
23
|
+
# 15.1 floor below.
|
|
24
|
+
nil
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
expo_modules_core_contents = expo_modules_core_podspec ? File.read(expo_modules_core_podspec) : ''
|
|
28
|
+
|
|
29
|
+
deployment_target = lambda do |platform, floor|
|
|
30
|
+
found = expo_modules_core_contents[/:#{platform}\s*=>\s*(['"])([\d.]+)\1/, 2]
|
|
31
|
+
[floor, found].compact.max_by { |version| Gem::Version.new(version) }
|
|
32
|
+
end
|
|
33
|
+
|
|
5
34
|
Pod::Spec.new do |s|
|
|
6
35
|
s.name = 'SuperwallExpo'
|
|
7
36
|
s.version = package['version']
|
|
@@ -11,8 +40,8 @@ Pod::Spec.new do |s|
|
|
|
11
40
|
s.author = package['author']
|
|
12
41
|
s.homepage = package['homepage']
|
|
13
42
|
s.platforms = {
|
|
14
|
-
:ios => '15.1',
|
|
15
|
-
:tvos => '15.1'
|
|
43
|
+
:ios => deployment_target.call(:ios, '15.1'),
|
|
44
|
+
:tvos => deployment_target.call(:tvos, '15.1')
|
|
16
45
|
}
|
|
17
46
|
s.swift_version = '5.4'
|
|
18
47
|
s.source = { git: 'https://github.com/superwall/expo-superwall' }
|
|
@@ -19,6 +19,8 @@ private final class AtomicFlag {
|
|
|
19
19
|
|
|
20
20
|
public class SuperwallExpoModule: Module {
|
|
21
21
|
public static var shared: SuperwallExpoModule?
|
|
22
|
+
private static let instancesLock = NSLock()
|
|
23
|
+
private static let instances = NSHashTable<SuperwallExpoModule>.weakObjects()
|
|
22
24
|
|
|
23
25
|
private let purchaseController = PurchaseControllerBridge.shared
|
|
24
26
|
private var delegate: SuperwallDelegateBridge?
|
|
@@ -55,10 +57,23 @@ public class SuperwallExpoModule: Module {
|
|
|
55
57
|
public required init(appContext: AppContext) {
|
|
56
58
|
super.init(appContext: appContext)
|
|
57
59
|
SuperwallExpoModule.shared = self
|
|
60
|
+
SuperwallExpoModule.instancesLock.lock()
|
|
61
|
+
SuperwallExpoModule.instances.add(self)
|
|
62
|
+
SuperwallExpoModule.instancesLock.unlock()
|
|
58
63
|
}
|
|
59
64
|
|
|
65
|
+
// Events must reach every live module instance. More than one app context can
|
|
66
|
+
// exist at once (e.g. expo-dev-client's launcher plus the app), and `shared`
|
|
67
|
+
// may point at an instance whose JS runtime never subscribed - sending only
|
|
68
|
+
// through it silently drops events like `onPurchase`, leaving the native
|
|
69
|
+
// purchase continuation suspended forever.
|
|
60
70
|
public static func emitEvent(_ name: String, _ data: [String: Any]?) {
|
|
61
|
-
|
|
71
|
+
instancesLock.lock()
|
|
72
|
+
let liveInstances = instances.allObjects
|
|
73
|
+
instancesLock.unlock()
|
|
74
|
+
for instance in liveInstances {
|
|
75
|
+
instance.sendEvent(name, data ?? [:])
|
|
76
|
+
}
|
|
62
77
|
}
|
|
63
78
|
|
|
64
79
|
public func definition() -> ModuleDefinition {
|