expo-superwall 0.6.11 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/README.md +103 -0
- package/android/src/main/java/expo/modules/superwallexpo/SuperwallExpoModule.kt +1 -1
- package/build/package.json +1 -1
- package/build/src/SuperwallProvider.d.ts +7 -1
- package/build/src/SuperwallProvider.d.ts.map +1 -1
- package/build/src/SuperwallProvider.js +39 -12
- package/build/src/SuperwallProvider.js.map +1 -1
- package/build/src/components/SuperwallLoading.d.ts +39 -0
- package/build/src/components/SuperwallLoading.d.ts.map +1 -1
- package/build/src/components/SuperwallLoading.js +53 -4
- package/build/src/components/SuperwallLoading.js.map +1 -1
- package/build/src/useSuperwall.d.ts +6 -1
- package/build/src/useSuperwall.d.ts.map +1 -1
- package/build/src/useSuperwall.js +39 -14
- package/build/src/useSuperwall.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 183a7d2: feat: comprehensive error handling for SDK configuration failures
|
|
8
|
+
|
|
9
|
+
Added robust error handling to prevent apps from hanging indefinitely when SDK configuration fails (e.g., during offline scenarios). This introduces three new ways for developers to handle configuration errors:
|
|
10
|
+
|
|
11
|
+
**New Features:**
|
|
12
|
+
|
|
13
|
+
- Added `configurationError` state to store for programmatic error access
|
|
14
|
+
- Added `onConfigurationError` callback prop to `SuperwallProvider` for error tracking/analytics
|
|
15
|
+
- Added `SuperwallError` component for declarative error UI rendering
|
|
16
|
+
- Listen to native `configFail` events to capture configuration failures
|
|
17
|
+
- Improved `SuperwallLoading` and `SuperwallLoaded` to respect error states
|
|
18
|
+
|
|
19
|
+
**Breaking Changes:** None - all changes are backward compatible
|
|
20
|
+
|
|
21
|
+
**Fixes:**
|
|
22
|
+
|
|
23
|
+
- Fixed app hanging in loading state when offline or configuration fails
|
|
24
|
+
- Fixed unhandled promise rejections in deep link initialization
|
|
25
|
+
- Fixed loading state not resetting on configuration failure
|
|
26
|
+
|
|
27
|
+
Developers can now gracefully handle offline scenarios and provide better UX when SDK initialization fails.
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- 4e246c9: fix: resolve Android handleDeepLink promise consistently with iOS
|
|
32
|
+
|
|
33
|
+
Fixed Android crash on app launch caused by "Not a superwall link" error. The Android implementation now resolves the handleDeepLink promise with a boolean value (matching iOS behavior) instead of rejecting it for non-Superwall links. This prevents unhandled promise rejections that were causing production app crashes.
|
|
34
|
+
|
|
35
|
+
Additionally added error handling in TypeScript as a safety net for any future edge cases.
|
|
36
|
+
|
|
37
|
+
- 4e246c9: fix: filter our expo specific deeplinks
|
|
38
|
+
|
|
3
39
|
## 0.6.11
|
|
4
40
|
|
|
5
41
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -56,6 +56,19 @@ export default function App() {
|
|
|
56
56
|
|
|
57
57
|
**Note:** You can find your API key in your Superwall dashboard.
|
|
58
58
|
|
|
59
|
+
### SuperwallProvider Props
|
|
60
|
+
|
|
61
|
+
The `SuperwallProvider` component accepts the following props:
|
|
62
|
+
|
|
63
|
+
- **`apiKeys`** (required): An object containing your Superwall API keys
|
|
64
|
+
- `ios?: string` - Your iOS API key
|
|
65
|
+
- `android?: string` - Your Android API key
|
|
66
|
+
- **`options`** (optional): Configuration options for the SDK (see `SuperwallOptions` type)
|
|
67
|
+
- **`onConfigurationError`** (optional): Callback function invoked when SDK configuration fails
|
|
68
|
+
- Useful for error tracking and analytics
|
|
69
|
+
- Example: `(error: Error) => void`
|
|
70
|
+
- **`children`**: Your app content
|
|
71
|
+
|
|
59
72
|
## Basic Usage
|
|
60
73
|
|
|
61
74
|
The SDK provides hooks to interact with Superwall's features.
|
|
@@ -98,6 +111,95 @@ function MainAppScreen() {
|
|
|
98
111
|
}
|
|
99
112
|
```
|
|
100
113
|
|
|
114
|
+
### Handling Configuration Errors
|
|
115
|
+
|
|
116
|
+
The SDK provides robust error handling for cases when configuration fails (e.g., during offline scenarios). You can handle errors in three ways:
|
|
117
|
+
|
|
118
|
+
#### 1. Using the `SuperwallError` Component
|
|
119
|
+
|
|
120
|
+
Display error UI declaratively when SDK initialization fails:
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
import {
|
|
124
|
+
SuperwallProvider,
|
|
125
|
+
SuperwallLoading,
|
|
126
|
+
SuperwallLoaded,
|
|
127
|
+
SuperwallError,
|
|
128
|
+
} from "expo-superwall";
|
|
129
|
+
import { ActivityIndicator, View, Text, Button } from "react-native";
|
|
130
|
+
|
|
131
|
+
const API_KEY = "YOUR_SUPERWALL_API_KEY";
|
|
132
|
+
|
|
133
|
+
export default function App() {
|
|
134
|
+
return (
|
|
135
|
+
<SuperwallProvider apiKeys={{ ios: API_KEY }}>
|
|
136
|
+
<SuperwallLoading>
|
|
137
|
+
<ActivityIndicator style={{ flex: 1 }} />
|
|
138
|
+
</SuperwallLoading>
|
|
139
|
+
|
|
140
|
+
<SuperwallError>
|
|
141
|
+
{(error) => (
|
|
142
|
+
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
|
|
143
|
+
<Text style={{ fontSize: 18, marginBottom: 10 }}>
|
|
144
|
+
Failed to initialize Superwall
|
|
145
|
+
</Text>
|
|
146
|
+
<Text style={{ color: "gray", marginBottom: 20 }}>{error}</Text>
|
|
147
|
+
<Button title="Retry" onPress={() => {/* retry logic */}} />
|
|
148
|
+
</View>
|
|
149
|
+
)}
|
|
150
|
+
</SuperwallError>
|
|
151
|
+
|
|
152
|
+
<SuperwallLoaded>
|
|
153
|
+
<MainAppScreen />
|
|
154
|
+
</SuperwallLoaded>
|
|
155
|
+
</SuperwallProvider>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
#### 2. Using the `onConfigurationError` Callback
|
|
161
|
+
|
|
162
|
+
Handle errors with a callback for logging or analytics:
|
|
163
|
+
|
|
164
|
+
```tsx
|
|
165
|
+
import { SuperwallProvider } from "expo-superwall";
|
|
166
|
+
|
|
167
|
+
export default function App() {
|
|
168
|
+
return (
|
|
169
|
+
<SuperwallProvider
|
|
170
|
+
apiKeys={{ ios: API_KEY }}
|
|
171
|
+
onConfigurationError={(error) => {
|
|
172
|
+
// Log to your error tracking service
|
|
173
|
+
console.error("Superwall config failed:", error);
|
|
174
|
+
// Sentry.captureException(error);
|
|
175
|
+
}}
|
|
176
|
+
>
|
|
177
|
+
<YourApp />
|
|
178
|
+
</SuperwallProvider>
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
#### 3. Accessing Error State Directly
|
|
184
|
+
|
|
185
|
+
Access the error state programmatically using `useSuperwall`:
|
|
186
|
+
|
|
187
|
+
```tsx
|
|
188
|
+
import { useSuperwall } from "expo-superwall";
|
|
189
|
+
|
|
190
|
+
function ErrorHandler() {
|
|
191
|
+
const configError = useSuperwall((state) => state.configurationError);
|
|
192
|
+
|
|
193
|
+
if (configError) {
|
|
194
|
+
return <Text>Configuration Error: {configError}</Text>;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Note:** The SDK will gracefully handle offline scenarios and other configuration failures, ensuring your app doesn't hang indefinitely in a loading state.
|
|
202
|
+
|
|
101
203
|
### Managing Users with `useUser`
|
|
102
204
|
|
|
103
205
|
The `useUser` hook provides functions to identify users, sign them out, update their attributes, and access user and subscription status information.
|
|
@@ -218,6 +320,7 @@ The hook returns an object representing the Superwall store. If a `selector` fun
|
|
|
218
320
|
- `isConfigured: boolean`: True if the Superwall SDK has been configured with an API key.
|
|
219
321
|
- `isLoading: boolean`: True when the SDK is performing an asynchronous operation like configuration.
|
|
220
322
|
- `listenersInitialized: boolean`: True if native event listeners have been initialized.
|
|
323
|
+
- `configurationError: string | null`: Contains error message if SDK configuration failed, `null` otherwise. When set, the SDK is not configured and app should show error UI.
|
|
221
324
|
- `user?: UserAttributes | null`: An object containing the current user's attributes.
|
|
222
325
|
- `UserAttributes`:
|
|
223
326
|
- `aliasId: string`: The alias ID of the user.
|
package/build/package.json
CHANGED
|
@@ -13,6 +13,12 @@ interface SuperwallProviderProps {
|
|
|
13
13
|
};
|
|
14
14
|
/** App content to render once configured */
|
|
15
15
|
children: ReactNode;
|
|
16
|
+
/**
|
|
17
|
+
* Optional callback invoked when SDK configuration fails.
|
|
18
|
+
* Use this to track errors, show custom UI, or implement retry logic.
|
|
19
|
+
* @param error - The error that occurred during configuration
|
|
20
|
+
*/
|
|
21
|
+
onConfigurationError?: (error: Error) => void;
|
|
16
22
|
}
|
|
17
23
|
/**
|
|
18
24
|
* @category Providers
|
|
@@ -35,6 +41,6 @@ interface SuperwallProviderProps {
|
|
|
35
41
|
* </SuperwallProvider>
|
|
36
42
|
* ```
|
|
37
43
|
*/
|
|
38
|
-
export declare function SuperwallProvider({ apiKeys, options, children, }: SuperwallProviderProps): import("react").JSX.Element;
|
|
44
|
+
export declare function SuperwallProvider({ apiKeys, options, children, onConfigurationError, }: SuperwallProviderProps): import("react").JSX.Element;
|
|
39
45
|
export {};
|
|
40
46
|
//# sourceMappingURL=SuperwallProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SuperwallProvider.d.ts","sourceRoot":"","sources":["../../src/SuperwallProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAqB,MAAM,OAAO,CAAA;AAKzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAG1D,UAAU,sBAAsB;IAC9B,6BAA6B;IAC7B,OAAO,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,GAAG,CAAC,EAAE,MAAM,CAAA;KACb,CAAA;IACD,8DAA8D;IAC9D,OAAO,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG;QACpC,uDAAuD;QACvD,uBAAuB,CAAC,EAAE,OAAO,CAAA;KAClC,CAAA;IACD,4CAA4C;IAC5C,QAAQ,EAAE,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"SuperwallProvider.d.ts","sourceRoot":"","sources":["../../src/SuperwallProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAqB,MAAM,OAAO,CAAA;AAKzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAG1D,UAAU,sBAAsB;IAC9B,6BAA6B;IAC7B,OAAO,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,GAAG,CAAC,EAAE,MAAM,CAAA;KACb,CAAA;IACD,8DAA8D;IAC9D,OAAO,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG;QACpC,uDAAuD;QACvD,uBAAuB,CAAC,EAAE,OAAO,CAAA;KAClC,CAAA;IACD,4CAA4C;IAC5C,QAAQ,EAAE,SAAS,CAAA;IACnB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAC9C;AAyBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,OAAO,EACP,QAAQ,EACR,oBAAoB,GACrB,EAAE,sBAAsB,+BAsFxB"}
|
|
@@ -46,46 +46,73 @@ const isExpoPlatformUrl = (url) => {
|
|
|
46
46
|
* </SuperwallProvider>
|
|
47
47
|
* ```
|
|
48
48
|
*/
|
|
49
|
-
export function SuperwallProvider({ apiKeys, options, children, }) {
|
|
49
|
+
export function SuperwallProvider({ apiKeys, options, children, onConfigurationError, }) {
|
|
50
50
|
const deepLinkEventHandlerRef = useRef(null);
|
|
51
51
|
const isUsingCustomPurchaseController = !!useCustomPurchaseController();
|
|
52
|
-
const { isConfigured, isLoading, configure } = useSuperwallStore(useShallow((state) => ({
|
|
52
|
+
const { isConfigured, isLoading, configure, configurationError } = useSuperwallStore(useShallow((state) => ({
|
|
53
53
|
isConfigured: state.isConfigured,
|
|
54
54
|
isLoading: state.isLoading,
|
|
55
55
|
configure: state.configure,
|
|
56
|
+
configurationError: state.configurationError,
|
|
56
57
|
})));
|
|
57
58
|
useEffect(() => {
|
|
58
|
-
if (!isConfigured && !isLoading) {
|
|
59
|
+
if (!isConfigured && !isLoading && !configurationError) {
|
|
59
60
|
const apiKey = apiKeys[Platform.OS];
|
|
60
61
|
if (!apiKey) {
|
|
61
|
-
|
|
62
|
+
const error = new Error(`No API key provided for platform ${Platform.OS}`);
|
|
63
|
+
console.error("Superwall configure failed", error);
|
|
64
|
+
onConfigurationError?.(error);
|
|
65
|
+
return;
|
|
62
66
|
}
|
|
63
67
|
configure(apiKey, {
|
|
64
68
|
...options,
|
|
65
69
|
manualPurchaseManagement: isUsingCustomPurchaseController,
|
|
66
|
-
}).catch((err) => {
|
|
67
|
-
console.error("Superwall configure failed", err);
|
|
68
70
|
});
|
|
69
71
|
}
|
|
70
|
-
}, [
|
|
72
|
+
}, [
|
|
73
|
+
isConfigured,
|
|
74
|
+
isUsingCustomPurchaseController,
|
|
75
|
+
isLoading,
|
|
76
|
+
configurationError,
|
|
77
|
+
apiKeys,
|
|
78
|
+
options,
|
|
79
|
+
configure,
|
|
80
|
+
onConfigurationError,
|
|
81
|
+
]);
|
|
82
|
+
// Notify callback when configuration error changes
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
if (configurationError && onConfigurationError) {
|
|
85
|
+
onConfigurationError(new Error(configurationError));
|
|
86
|
+
}
|
|
87
|
+
}, [configurationError, onConfigurationError]);
|
|
71
88
|
useEffect(() => {
|
|
72
89
|
const cleanup = useSuperwallStore.getState()._initListeners();
|
|
73
90
|
return cleanup;
|
|
74
91
|
}, []);
|
|
75
92
|
useEffect(() => {
|
|
76
93
|
const handleDeepLink = async () => {
|
|
77
|
-
|
|
94
|
+
try {
|
|
95
|
+
const url = await Linking.getInitialURL();
|
|
78
96
|
if (url && !isExpoDeepLink(url) && !isExpoPlatformUrl(url)) {
|
|
79
|
-
SuperwallExpoModule.handleDeepLink(url)
|
|
97
|
+
SuperwallExpoModule.handleDeepLink(url).catch((error) => {
|
|
98
|
+
console.debug("Superwall: Non-Superwall deep link ignored", url, error);
|
|
99
|
+
});
|
|
80
100
|
}
|
|
81
|
-
}
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
console.debug("Superwall: Failed to get initial URL", error);
|
|
104
|
+
}
|
|
82
105
|
deepLinkEventHandlerRef.current = Linking.addEventListener("url", (event) => {
|
|
83
106
|
if (!isExpoDeepLink(event.url) && !isExpoPlatformUrl(event.url)) {
|
|
84
|
-
SuperwallExpoModule.handleDeepLink(event.url)
|
|
107
|
+
SuperwallExpoModule.handleDeepLink(event.url).catch((error) => {
|
|
108
|
+
console.debug("Superwall: Non-Superwall deep link ignored", event.url, error);
|
|
109
|
+
});
|
|
85
110
|
}
|
|
86
111
|
});
|
|
87
112
|
};
|
|
88
|
-
handleDeepLink()
|
|
113
|
+
handleDeepLink().catch((error) => {
|
|
114
|
+
console.error("Superwall: Deep link setup failed", error);
|
|
115
|
+
});
|
|
89
116
|
return () => {
|
|
90
117
|
if (deepLinkEventHandlerRef.current) {
|
|
91
118
|
deepLinkEventHandlerRef.current.remove();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SuperwallProvider.js","sourceRoot":"","sources":["../../src/SuperwallProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkB,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AACzD,OAAO,EAA4B,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAA;AAChF,OAAO,mBAAmB,MAAM,uBAAuB,CAAA;AAEvD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"SuperwallProvider.js","sourceRoot":"","sources":["../../src/SuperwallProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkB,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AACzD,OAAO,EAA4B,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAA;AAChF,OAAO,mBAAmB,MAAM,uBAAuB,CAAA;AAEvD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAuBpE;;;;;;GAMG;AACH,MAAM,cAAc,GAAG,CAAC,GAAW,EAAW,EAAE;IAC9C,MAAM,EAAE,GAAG,gCAAgC,CAAA;IAC3C,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACrB,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,iBAAiB,GAAG,CAAC,GAAW,EAAW,EAAE;IACjD,MAAM,EAAE,GAAG,oCAAoC,CAAA;IAC/C,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACrB,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAChC,OAAO,EACP,OAAO,EACP,QAAQ,EACR,oBAAoB,GACG;IACvB,MAAM,uBAAuB,GAAG,MAAM,CAAsB,IAAI,CAAC,CAAA;IACjE,MAAM,+BAA+B,GAAG,CAAC,CAAC,2BAA2B,EAAE,CAAA;IAEvE,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,kBAAkB,EAAE,GAAG,iBAAiB,CAClF,UAAU,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACrB,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;KAC7C,CAAC,CAAC,CACJ,CAAA;IAED,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,YAAY,IAAI,CAAC,SAAS,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACvD,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,EAA0B,CAAC,CAAA;YAC3D,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,oCAAoC,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAA;gBAC1E,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAA;gBAClD,oBAAoB,EAAE,CAAC,KAAK,CAAC,CAAA;gBAC7B,OAAM;YACR,CAAC;YAED,SAAS,CAAC,MAAM,EAAE;gBAChB,GAAG,OAAO;gBACV,wBAAwB,EAAE,+BAA+B;aAC1D,CAAC,CAAA;QACJ,CAAC;IACH,CAAC,EAAE;QACD,YAAY;QACZ,+BAA+B;QAC/B,SAAS;QACT,kBAAkB;QAClB,OAAO;QACP,OAAO;QACP,SAAS;QACT,oBAAoB;KACrB,CAAC,CAAA;IAEF,mDAAmD;IACnD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,kBAAkB,IAAI,oBAAoB,EAAE,CAAC;YAC/C,oBAAoB,CAAC,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAA;QACrD,CAAC;IACH,CAAC,EAAE,CAAC,kBAAkB,EAAE,oBAAoB,CAAC,CAAC,CAAA;IAE9C,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,OAAO,GAAG,iBAAiB,CAAC,QAAQ,EAAE,CAAC,cAAc,EAAE,CAAA;QAE7D,OAAO,OAAO,CAAA;IAChB,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,cAAc,GAAG,KAAK,IAAI,EAAE;YAChC,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,aAAa,EAAE,CAAA;gBACzC,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC3D,mBAAmB,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;wBACtD,OAAO,CAAC,KAAK,CAAC,4CAA4C,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;oBACzE,CAAC,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,KAAK,CAAC,CAAA;YAC9D,CAAC;YAED,uBAAuB,CAAC,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE;gBAC1E,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;oBAChE,mBAAmB,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;wBAC5D,OAAO,CAAC,KAAK,CAAC,4CAA4C,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;oBAC/E,CAAC,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC,CAAC,CAAA;QACJ,CAAC,CAAA;QAED,cAAc,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YAC/B,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAA;QAC3D,CAAC,CAAC,CAAA;QAEF,OAAO,GAAG,EAAE;YACV,IAAI,uBAAuB,CAAC,OAAO,EAAE,CAAC;gBACpC,uBAAuB,CAAC,OAAO,CAAC,MAAM,EAAE,CAAA;YAC1C,CAAC;QACH,CAAC,CAAA;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAA;AACvF,CAAC","sourcesContent":["import { type ReactNode, useEffect, useRef } from \"react\"\nimport { type EmitterSubscription, Linking, Platform } from \"react-native\"\nimport { useShallow } from \"zustand/shallow\"\nimport { useCustomPurchaseController } from \"./CustomPurchaseControllerProvider\"\nimport SuperwallExpoModule from \"./SuperwallExpoModule\"\nimport type { SuperwallOptions } from \"./SuperwallOptions\"\nimport { SuperwallContext, useSuperwallStore } from \"./useSuperwall\"\n\ninterface SuperwallProviderProps {\n /** Your Superwall API key */\n apiKeys: {\n android?: string\n ios?: string\n }\n /** Optional configuration options passed to the native SDK */\n options?: Partial<SuperwallOptions> & {\n /** @deprecated Use manualPurchaseManagement instead */\n manualPurchaseManagment?: boolean\n }\n /** App content to render once configured */\n children: ReactNode\n /**\n * Optional callback invoked when SDK configuration fails.\n * Use this to track errors, show custom UI, or implement retry logic.\n * @param error - The error that occurred during configuration\n */\n onConfigurationError?: (error: Error) => void\n}\n\n/**\n * Checks if a URL is an Expo deep link scheme.\n * Matches expo://, exp://, or exp+{slug}:// schemes.\n *\n * @param url - The URL string to check\n * @returns true if the URL is an Expo deep link scheme, false otherwise\n */\nconst isExpoDeepLink = (url: string): boolean => {\n const re = /^(?:expo|exp\\+[^:]+|exp):\\/\\//i\n return re.test(url)\n}\n\n/**\n * Checks if a URL is an Expo platform URL (expo.dev domain).\n *\n * @param url - The URL string to check\n * @returns true if the URL is an Expo platform URL, false otherwise\n */\nconst isExpoPlatformUrl = (url: string): boolean => {\n const re = /^https?:\\/\\/(?:www\\.)?expo\\.dev\\//i\n return re.test(url)\n}\n\n/**\n * @category Providers\n * @since 0.0.15\n * Main provider component for the Superwall SDK.\n *\n * This component initializes the Superwall SDK with your API key and configuration options.\n * It should wrap the root of your application or the part of your app that requires Superwall functionality.\n * It also sets up necessary event listeners for the SDK.\n *\n * @param props - The properties for the SuperwallProvider.\n * @param props.apiKeys - An object containing your Superwall API keys for Android and iOS.\n * @param props.options - Optional configuration options to pass to the native Superwall SDK.\n * @param props.children - The child components of your application that will have access to Superwall features.\n *\n * Example:\n * ```tsx\n * <SuperwallProvider apiKeys={{ ios: \"YOUR_IOS_API_KEY\", android: \"YOUR_ANDROID_API_KEY\" }}>\n * <App />\n * </SuperwallProvider>\n * ```\n */\nexport function SuperwallProvider({\n apiKeys,\n options,\n children,\n onConfigurationError,\n}: SuperwallProviderProps) {\n const deepLinkEventHandlerRef = useRef<EmitterSubscription>(null)\n const isUsingCustomPurchaseController = !!useCustomPurchaseController()\n\n const { isConfigured, isLoading, configure, configurationError } = useSuperwallStore(\n useShallow((state) => ({\n isConfigured: state.isConfigured,\n isLoading: state.isLoading,\n configure: state.configure,\n configurationError: state.configurationError,\n })),\n )\n\n useEffect(() => {\n if (!isConfigured && !isLoading && !configurationError) {\n const apiKey = apiKeys[Platform.OS as keyof typeof apiKeys]\n if (!apiKey) {\n const error = new Error(`No API key provided for platform ${Platform.OS}`)\n console.error(\"Superwall configure failed\", error)\n onConfigurationError?.(error)\n return\n }\n\n configure(apiKey, {\n ...options,\n manualPurchaseManagement: isUsingCustomPurchaseController,\n })\n }\n }, [\n isConfigured,\n isUsingCustomPurchaseController,\n isLoading,\n configurationError,\n apiKeys,\n options,\n configure,\n onConfigurationError,\n ])\n\n // Notify callback when configuration error changes\n useEffect(() => {\n if (configurationError && onConfigurationError) {\n onConfigurationError(new Error(configurationError))\n }\n }, [configurationError, onConfigurationError])\n\n useEffect(() => {\n const cleanup = useSuperwallStore.getState()._initListeners()\n\n return cleanup\n }, [])\n\n useEffect(() => {\n const handleDeepLink = async () => {\n try {\n const url = await Linking.getInitialURL()\n if (url && !isExpoDeepLink(url) && !isExpoPlatformUrl(url)) {\n SuperwallExpoModule.handleDeepLink(url).catch((error) => {\n console.debug(\"Superwall: Non-Superwall deep link ignored\", url, error)\n })\n }\n } catch (error) {\n console.debug(\"Superwall: Failed to get initial URL\", error)\n }\n\n deepLinkEventHandlerRef.current = Linking.addEventListener(\"url\", (event) => {\n if (!isExpoDeepLink(event.url) && !isExpoPlatformUrl(event.url)) {\n SuperwallExpoModule.handleDeepLink(event.url).catch((error) => {\n console.debug(\"Superwall: Non-Superwall deep link ignored\", event.url, error)\n })\n }\n })\n }\n\n handleDeepLink().catch((error) => {\n console.error(\"Superwall: Deep link setup failed\", error)\n })\n\n return () => {\n if (deepLinkEventHandlerRef.current) {\n deepLinkEventHandlerRef.current.remove()\n }\n }\n }, [])\n\n return <SuperwallContext.Provider value={true}>{children}</SuperwallContext.Provider>\n}\n"]}
|
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
* while the Superwall SDK is initializing. Once Superwall is configured and
|
|
8
8
|
* no longer in a loading state, this component will render `null`.
|
|
9
9
|
*
|
|
10
|
+
* Note: This will not render if there's a configuration error. Use `SuperwallError`
|
|
11
|
+
* to handle error states.
|
|
12
|
+
*
|
|
10
13
|
* @param props - The properties for the SuperwallLoading component.
|
|
11
14
|
* @param props.children - The content to render while Superwall is loading.
|
|
12
15
|
* @returns The children if Superwall is loading/not configured, otherwise `null`.
|
|
@@ -30,4 +33,40 @@ export declare const SuperwallLoading: ({ children }: {
|
|
|
30
33
|
export declare const SuperwallLoaded: ({ children }: {
|
|
31
34
|
children: React.ReactNode;
|
|
32
35
|
}) => import("react").ReactNode;
|
|
36
|
+
/**
|
|
37
|
+
* @category Components
|
|
38
|
+
* @since 0.1.0
|
|
39
|
+
* A component that renders its children only when Superwall configuration has failed.
|
|
40
|
+
*
|
|
41
|
+
* This component can be used to display an error message or fallback UI
|
|
42
|
+
* when the Superwall SDK fails to initialize. The children can be either
|
|
43
|
+
* static React nodes or a render function that receives the error message.
|
|
44
|
+
*
|
|
45
|
+
* @param props - The properties for the SuperwallError component.
|
|
46
|
+
* @param props.children - The content to render when Superwall has an error.
|
|
47
|
+
* Can be static React nodes or a function that receives the error message string.
|
|
48
|
+
* @returns The children if Superwall has failed, otherwise `null`.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```tsx
|
|
52
|
+
* // Static error UI
|
|
53
|
+
* <SuperwallError>
|
|
54
|
+
* <Text>Failed to load Superwall</Text>
|
|
55
|
+
* </SuperwallError>
|
|
56
|
+
*
|
|
57
|
+
* // Dynamic error UI with error message
|
|
58
|
+
* <SuperwallError>
|
|
59
|
+
* {(error) => (
|
|
60
|
+
* <View>
|
|
61
|
+
* <Text>Failed to initialize Superwall</Text>
|
|
62
|
+
* <Text>{error}</Text>
|
|
63
|
+
* <Button title="Retry" onPress={handleRetry} />
|
|
64
|
+
* </View>
|
|
65
|
+
* )}
|
|
66
|
+
* </SuperwallError>
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export declare const SuperwallError: ({ children, }: {
|
|
70
|
+
children: React.ReactNode | ((error: string) => React.ReactNode);
|
|
71
|
+
}) => import("react").ReactNode;
|
|
33
72
|
//# sourceMappingURL=SuperwallLoading.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SuperwallLoading.d.ts","sourceRoot":"","sources":["../../../src/components/SuperwallLoading.tsx"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"SuperwallLoading.d.ts","sourceRoot":"","sources":["../../../src/components/SuperwallLoading.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,gBAAgB,GAAI,cAAc;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,8BAW3E,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,GAAI,cAAc;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,8BAW1E,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,cAAc,GAAI,eAE5B;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC,CAAA;CACjE,8BAQA,CAAA"}
|
|
@@ -8,13 +8,19 @@ import { useSuperwall } from "../useSuperwall";
|
|
|
8
8
|
* while the Superwall SDK is initializing. Once Superwall is configured and
|
|
9
9
|
* no longer in a loading state, this component will render `null`.
|
|
10
10
|
*
|
|
11
|
+
* Note: This will not render if there's a configuration error. Use `SuperwallError`
|
|
12
|
+
* to handle error states.
|
|
13
|
+
*
|
|
11
14
|
* @param props - The properties for the SuperwallLoading component.
|
|
12
15
|
* @param props.children - The content to render while Superwall is loading.
|
|
13
16
|
* @returns The children if Superwall is loading/not configured, otherwise `null`.
|
|
14
17
|
*/
|
|
15
18
|
export const SuperwallLoading = ({ children }) => {
|
|
16
|
-
const isLoaded = useSuperwall((state) =>
|
|
17
|
-
|
|
19
|
+
const { isLoaded, hasError } = useSuperwall((state) => ({
|
|
20
|
+
isLoaded: !state.isLoading && state.isConfigured,
|
|
21
|
+
hasError: state.configurationError !== null,
|
|
22
|
+
}));
|
|
23
|
+
if (isLoaded || hasError) {
|
|
18
24
|
return null;
|
|
19
25
|
}
|
|
20
26
|
return children;
|
|
@@ -33,10 +39,53 @@ export const SuperwallLoading = ({ children }) => {
|
|
|
33
39
|
* @returns The children if Superwall is loaded/configured, otherwise `null`.
|
|
34
40
|
*/
|
|
35
41
|
export const SuperwallLoaded = ({ children }) => {
|
|
36
|
-
const isLoaded = useSuperwall((state) =>
|
|
37
|
-
|
|
42
|
+
const { isLoaded, hasError } = useSuperwall((state) => ({
|
|
43
|
+
isLoaded: !state.isLoading && state.isConfigured,
|
|
44
|
+
hasError: state.configurationError !== null,
|
|
45
|
+
}));
|
|
46
|
+
if (!isLoaded || hasError) {
|
|
38
47
|
return null;
|
|
39
48
|
}
|
|
40
49
|
return children;
|
|
41
50
|
};
|
|
51
|
+
/**
|
|
52
|
+
* @category Components
|
|
53
|
+
* @since 0.1.0
|
|
54
|
+
* A component that renders its children only when Superwall configuration has failed.
|
|
55
|
+
*
|
|
56
|
+
* This component can be used to display an error message or fallback UI
|
|
57
|
+
* when the Superwall SDK fails to initialize. The children can be either
|
|
58
|
+
* static React nodes or a render function that receives the error message.
|
|
59
|
+
*
|
|
60
|
+
* @param props - The properties for the SuperwallError component.
|
|
61
|
+
* @param props.children - The content to render when Superwall has an error.
|
|
62
|
+
* Can be static React nodes or a function that receives the error message string.
|
|
63
|
+
* @returns The children if Superwall has failed, otherwise `null`.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```tsx
|
|
67
|
+
* // Static error UI
|
|
68
|
+
* <SuperwallError>
|
|
69
|
+
* <Text>Failed to load Superwall</Text>
|
|
70
|
+
* </SuperwallError>
|
|
71
|
+
*
|
|
72
|
+
* // Dynamic error UI with error message
|
|
73
|
+
* <SuperwallError>
|
|
74
|
+
* {(error) => (
|
|
75
|
+
* <View>
|
|
76
|
+
* <Text>Failed to initialize Superwall</Text>
|
|
77
|
+
* <Text>{error}</Text>
|
|
78
|
+
* <Button title="Retry" onPress={handleRetry} />
|
|
79
|
+
* </View>
|
|
80
|
+
* )}
|
|
81
|
+
* </SuperwallError>
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export const SuperwallError = ({ children, }) => {
|
|
85
|
+
const error = useSuperwall((state) => state.configurationError);
|
|
86
|
+
if (!error) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
return typeof children === "function" ? children(error) : children;
|
|
90
|
+
};
|
|
42
91
|
//# sourceMappingURL=SuperwallLoading.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SuperwallLoading.js","sourceRoot":"","sources":["../../../src/components/SuperwallLoading.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAE9C
|
|
1
|
+
{"version":3,"file":"SuperwallLoading.js","sourceRoot":"","sources":["../../../src/components/SuperwallLoading.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAE9C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,EAAE,QAAQ,EAAiC,EAAE,EAAE;IAC9E,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,YAAY,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACtD,QAAQ,EAAE,CAAC,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,YAAY;QAChD,QAAQ,EAAE,KAAK,CAAC,kBAAkB,KAAK,IAAI;KAC5C,CAAC,CAAC,CAAA;IAEH,IAAI,QAAQ,IAAI,QAAQ,EAAE,CAAC;QACzB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAAE,QAAQ,EAAiC,EAAE,EAAE;IAC7E,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,YAAY,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACtD,QAAQ,EAAE,CAAC,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,YAAY;QAChD,QAAQ,EAAE,KAAK,CAAC,kBAAkB,KAAK,IAAI;KAC5C,CAAC,CAAC,CAAA;IAEH,IAAI,CAAC,QAAQ,IAAI,QAAQ,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAC7B,QAAQ,GAGT,EAAE,EAAE;IACH,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAA;IAE/D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAA;AACpE,CAAC,CAAA","sourcesContent":["import { useSuperwall } from \"../useSuperwall\"\n\n/**\n * @category Components\n * @since 0.0.15\n * A component that renders its children only when Superwall is loading or not yet configured.\n *\n * This component can be used to display a loading indicator or a placeholder\n * while the Superwall SDK is initializing. Once Superwall is configured and\n * no longer in a loading state, this component will render `null`.\n *\n * Note: This will not render if there's a configuration error. Use `SuperwallError`\n * to handle error states.\n *\n * @param props - The properties for the SuperwallLoading component.\n * @param props.children - The content to render while Superwall is loading.\n * @returns The children if Superwall is loading/not configured, otherwise `null`.\n */\nexport const SuperwallLoading = ({ children }: { children: React.ReactNode }) => {\n const { isLoaded, hasError } = useSuperwall((state) => ({\n isLoaded: !state.isLoading && state.isConfigured,\n hasError: state.configurationError !== null,\n }))\n\n if (isLoaded || hasError) {\n return null\n }\n\n return children\n}\n\n/**\n * @category Components\n * @since 0.0.15\n * A component that renders its children only when Superwall has finished loading and is configured.\n *\n * This component is useful for conditionally rendering parts of your UI that\n * depend on Superwall being ready. If Superwall is still loading or has not\n * been configured, this component will render `null`.\n *\n * @param props - The properties for the SuperwallLoaded component.\n * @param props.children - The content to render once Superwall is loaded and configured.\n * @returns The children if Superwall is loaded/configured, otherwise `null`.\n */\nexport const SuperwallLoaded = ({ children }: { children: React.ReactNode }) => {\n const { isLoaded, hasError } = useSuperwall((state) => ({\n isLoaded: !state.isLoading && state.isConfigured,\n hasError: state.configurationError !== null,\n }))\n\n if (!isLoaded || hasError) {\n return null\n }\n\n return children\n}\n\n/**\n * @category Components\n * @since 0.1.0\n * A component that renders its children only when Superwall configuration has failed.\n *\n * This component can be used to display an error message or fallback UI\n * when the Superwall SDK fails to initialize. The children can be either\n * static React nodes or a render function that receives the error message.\n *\n * @param props - The properties for the SuperwallError component.\n * @param props.children - The content to render when Superwall has an error.\n * Can be static React nodes or a function that receives the error message string.\n * @returns The children if Superwall has failed, otherwise `null`.\n *\n * @example\n * ```tsx\n * // Static error UI\n * <SuperwallError>\n * <Text>Failed to load Superwall</Text>\n * </SuperwallError>\n *\n * // Dynamic error UI with error message\n * <SuperwallError>\n * {(error) => (\n * <View>\n * <Text>Failed to initialize Superwall</Text>\n * <Text>{error}</Text>\n * <Button title=\"Retry\" onPress={handleRetry} />\n * </View>\n * )}\n * </SuperwallError>\n * ```\n */\nexport const SuperwallError = ({\n children,\n}: {\n children: React.ReactNode | ((error: string) => React.ReactNode)\n}) => {\n const error = useSuperwall((state) => state.configurationError)\n\n if (!error) {\n return null\n }\n\n return typeof children === \"function\" ? children(error) : children\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { EntitlementsInfo, IntegrationAttributes, SubscriptionStatus } from "./SuperwallExpoModule.types";
|
|
2
2
|
import type { SuperwallOptions } from "./SuperwallOptions";
|
|
3
3
|
/**
|
|
4
4
|
* @category Models
|
|
@@ -42,6 +42,11 @@ export interface SuperwallStore {
|
|
|
42
42
|
isLoading: boolean;
|
|
43
43
|
/** Indicates whether the native event listeners have been initialized. */
|
|
44
44
|
listenersInitialized: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Contains error message if SDK configuration failed, `null` otherwise.
|
|
47
|
+
* When this is set, the SDK is not configured and app should show error UI.
|
|
48
|
+
*/
|
|
49
|
+
configurationError: string | null;
|
|
45
50
|
/**
|
|
46
51
|
* The current user's attributes.
|
|
47
52
|
* `null` if no user is identified or after `reset` is called.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSuperwall.d.ts","sourceRoot":"","sources":["../../src/useSuperwall.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"useSuperwall.d.ts","sourceRoot":"","sources":["../../src/useSuperwall.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,25 +14,37 @@ export const useSuperwallStore = create((set, get) => ({
|
|
|
14
14
|
isConfigured: false,
|
|
15
15
|
isLoading: false,
|
|
16
16
|
listenersInitialized: false,
|
|
17
|
+
configurationError: null,
|
|
17
18
|
user: null,
|
|
18
19
|
subscriptionStatus: {
|
|
19
20
|
status: "UNKNOWN",
|
|
20
21
|
},
|
|
21
22
|
/* -------------------- Actions -------------------- */
|
|
22
23
|
configure: async (apiKey, options) => {
|
|
23
|
-
set({ isLoading: true });
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
24
|
+
set({ isLoading: true, configurationError: null });
|
|
25
|
+
try {
|
|
26
|
+
const { manualPurchaseManagement, manualPurchaseManagment, ...restOptions } = options || {};
|
|
27
|
+
// Support both spellings for backward compatibility
|
|
28
|
+
const isManualPurchaseManagement = manualPurchaseManagement ?? manualPurchaseManagment ?? false;
|
|
29
|
+
await SuperwallExpoModule.configure(apiKey, restOptions, isManualPurchaseManagement, pkg.version);
|
|
30
|
+
const currentUser = await SuperwallExpoModule.getUserAttributes();
|
|
31
|
+
const subscriptionStatus = await SuperwallExpoModule.getSubscriptionStatus();
|
|
32
|
+
set({
|
|
33
|
+
isConfigured: true,
|
|
34
|
+
isLoading: false,
|
|
35
|
+
configurationError: null,
|
|
36
|
+
user: currentUser,
|
|
37
|
+
subscriptionStatus,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
42
|
+
set({
|
|
43
|
+
isLoading: false,
|
|
44
|
+
configurationError: errorMessage,
|
|
45
|
+
});
|
|
46
|
+
// Don't throw - let developers handle via state or callback
|
|
47
|
+
}
|
|
36
48
|
},
|
|
37
49
|
identify: async (userId, options) => {
|
|
38
50
|
await SuperwallExpoModule.identify(userId, options);
|
|
@@ -108,11 +120,24 @@ export const useSuperwallStore = create((set, get) => ({
|
|
|
108
120
|
subscriptions.push(SuperwallExpoModule.addListener("subscriptionStatusDidChange", ({ to }) => {
|
|
109
121
|
set({ subscriptionStatus: to });
|
|
110
122
|
}));
|
|
123
|
+
// Listen for configuration events
|
|
124
|
+
subscriptions.push(SuperwallExpoModule.addListener("handleSuperwallEvent", ({ eventInfo }) => {
|
|
125
|
+
if (eventInfo.event.event === "configFail") {
|
|
126
|
+
set({
|
|
127
|
+
configurationError: "Failed to load Superwall configuration",
|
|
128
|
+
isLoading: false,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
else if (eventInfo.event.event === "configRefresh") {
|
|
132
|
+
// Clear any previous errors on successful refresh
|
|
133
|
+
set({ configurationError: null });
|
|
134
|
+
}
|
|
135
|
+
}));
|
|
111
136
|
set({ listenersInitialized: true });
|
|
112
137
|
console.log("Initialized listeners", subscriptions.length);
|
|
113
138
|
return () => {
|
|
114
139
|
console.log("Cleaning up listeners", subscriptions.length);
|
|
115
|
-
// biome-ignore lint/suspicious/useIterableCallbackReturn:
|
|
140
|
+
// biome-ignore lint/suspicious/useIterableCallbackReturn: forEach is used for side effects only
|
|
116
141
|
subscriptions.forEach((s) => s.remove());
|
|
117
142
|
// Reset the state on cleanup
|
|
118
143
|
set({ listenersInitialized: false });
|
|
@@ -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 SuperwallExpoModule from \"./SuperwallExpoModule\"\nimport type { SubscriptionStatus, IntegrationAttributes, EntitlementsInfo } from \"./SuperwallExpoModule.types\"\nimport type { SuperwallOptions } from \"./SuperwallOptions\"\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\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 * 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?: Partial<SuperwallOptions> & {\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: (placement: string, params?: Record<string, any>) => Promise<any>\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>) => 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\n user: null,\n subscriptionStatus: {\n status: \"UNKNOWN\",\n },\n\n /* -------------------- Actions -------------------- */\n configure: async (apiKey, options) => {\n set({ isLoading: true })\n const { manualPurchaseManagement, manualPurchaseManagment, ...restOptions } = options || {}\n\n // Support both spellings for backward compatibility\n const isManualPurchaseManagement = manualPurchaseManagement ?? manualPurchaseManagment ?? false\n\n await SuperwallExpoModule.configure(\n apiKey,\n restOptions,\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 user: currentUser as UserAttributes,\n subscriptionStatus,\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 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(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(\"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 set({ listenersInitialized: true })\n console.log(\"Initialized listeners\", subscriptions.length)\n\n return (): void => {\n console.log(\"Cleaning up listeners\", subscriptions.length)\n // biome-ignore lint/suspicious/useIterableCallbackReturn: <explanation>\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 SuperwallExpoModule from \"./SuperwallExpoModule\"\nimport type {\n EntitlementsInfo,\n IntegrationAttributes,\n SubscriptionStatus,\n} from \"./SuperwallExpoModule.types\"\nimport type { SuperwallOptions } from \"./SuperwallOptions\"\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\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?: Partial<SuperwallOptions> & {\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: (placement: string, params?: Record<string, any>) => Promise<any>\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>) => 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, ...restOptions } = options || {}\n\n // Support both spellings for backward compatibility\n const isManualPurchaseManagement =\n manualPurchaseManagement ?? manualPurchaseManagment ?? false\n\n await SuperwallExpoModule.configure(\n apiKey,\n restOptions,\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 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(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(\"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(\"Initialized listeners\", subscriptions.length)\n\n return (): void => {\n console.log(\"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"]}
|